Skip to content

Commit

Permalink
WIP start of pkt hook
Browse files Browse the repository at this point in the history
WIP packet: track hooks that this packet triggers

hooks: set flow_start hook in packet

detect: pack prefilter engine struct

For future expansion of the fields.

detect/prefilter: put pkt mask in struct

In preparation for adding more pkt fields.

WIP detect: implement pkt:flow_start hook

SQUASH detect flow start hook
  • Loading branch information
victorjulien committed Feb 21, 2025
1 parent e1ceb67 commit 81ab9fa
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 18 deletions.
5 changes: 5 additions & 0 deletions src/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,13 @@ typedef struct Packet_
/* coccinelle: Packet:flowflags:FLOW_PKT_ */

uint8_t app_update_direction; // enum StreamUpdateDir

/** sig mask flags this packet has, used in signature matching */
SignatureMask sig_mask;

/** bit flags of SignatureHookPkt values this packet should trigger */
uint16_t pkt_hooks;

/* Pkt Flags */
uint32_t flags;

Expand Down
12 changes: 12 additions & 0 deletions src/detect-engine-build.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ static bool SignatureInspectsBuffers(const Signature *s)
*/
int SignatureIsIPOnly(DetectEngineCtx *de_ctx, const Signature *s)
{
/* explicit hook means no IP-only */
if (s->init_data->hook.type != SIGNATURE_HOOK_TYPE_NOT_SET)
return 0;

if (s->alproto != ALPROTO_UNKNOWN)
return 0;

Expand Down Expand Up @@ -276,6 +280,10 @@ int SignatureIsIPOnly(DetectEngineCtx *de_ctx, const Signature *s)
*/
static int SignatureIsPDOnly(const DetectEngineCtx *de_ctx, const Signature *s)
{
/* explicit hook means no PD-only */
if (s->init_data->hook.type != SIGNATURE_HOOK_TYPE_NOT_SET)
return 0;

if (s->alproto != ALPROTO_UNKNOWN)
return 0;

Expand Down Expand Up @@ -354,6 +362,10 @@ static int SignatureIsInspectingPayload(DetectEngineCtx *de_ctx, const Signature
*/
static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, const Signature *s)
{
/* explicit hook means no DE-only */
if (s->init_data->hook.type != SIGNATURE_HOOK_TYPE_NOT_SET)
SCReturnInt(0);

if (s->alproto != ALPROTO_UNKNOWN) {
SCReturnInt(0);
}
Expand Down
8 changes: 5 additions & 3 deletions src/detect-engine-prefilter-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ static int SetupEngineForPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh
SCLogDebug("%s: ctx %p extra type %u extra value %u, sig cnt %u",
sigmatch_table[sm_type].name, ctx, ctx->type, ctx->value,
ctx->sigs_cnt);
PrefilterAppendEngine(
de_ctx, sgh, Match, mask, ctx, PrefilterPacketHeaderFree, sigmatch_table[sm_type].name);
enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
PrefilterAppendEngine(de_ctx, sgh, Match, mask, hook, ctx, PrefilterPacketHeaderFree,
sigmatch_table[sm_type].name);
return 0;
}

Expand Down Expand Up @@ -245,7 +246,8 @@ static int SetupEngineForPacketHeaderPrefilterPacketU8HashCtx(DetectEngineCtx *d
}

if (cnt) {
PrefilterAppendEngine(de_ctx, sgh, Match, mask, ctx, PrefilterPacketU8HashCtxFree,
enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
PrefilterAppendEngine(de_ctx, sgh, Match, mask, hook, ctx, PrefilterPacketU8HashCtxFree,
sigmatch_table[sm_type].name);
} else {
PrefilterPacketU8HashCtxFree(ctx);
Expand Down
115 changes: 108 additions & 7 deletions src/detect-engine-prefilter.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2016-2021 Open Information Security Foundation
/* Copyright (C) 2016-2025 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -168,7 +168,12 @@ void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *
/* run packet engines */
PrefilterEngine *engine = sgh->pkt_engines;
do {
if ((engine->ctx.pkt_mask & mask) == engine->ctx.pkt_mask) {
/* run engine if:
* mask matches
* no hook is used OR hook matches
*/
if (((engine->ctx.pkt.mask & mask) == engine->ctx.pkt.mask) &&
(engine->ctx.pkt.hook == 0 || (p->pkt_hooks & BIT_U16(engine->ctx.pkt.hook)))) {
PREFILTER_PROFILING_START(det_ctx);
engine->cb.Prefilter(det_ctx, p, engine->pectx);
PREFILTER_PROFILING_END(det_ctx, engine->gid);
Expand Down Expand Up @@ -211,7 +216,8 @@ void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *
}

int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc,
SignatureMask mask, void *pectx, void (*FreeFunc)(void *pectx), const char *name)
SignatureMask mask, enum SignatureHookPkt hook, void *pectx, void (*FreeFunc)(void *pectx),
const char *name)
{
if (sgh == NULL || PrefilterFunc == NULL || pectx == NULL)
return -1;
Expand All @@ -221,10 +227,14 @@ int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterP
return -1;
memset(e, 0x00, sizeof(*e));

// TODO right now we represent the hook in a u8 in the prefilter engine for space reasons.
BUG_ON(hook >= 8);

e->Prefilter = PrefilterFunc;
e->pectx = pectx;
e->Free = FreeFunc;
e->pkt_mask = mask;
e->pkt_hook = hook;

if (sgh->init->pkt_engines == NULL) {
sgh->init->pkt_engines = e;
Expand Down Expand Up @@ -535,6 +545,14 @@ static void PrefilterPktNonPF(DetectEngineThreadCtx *det_ctx, Packet *p, const v
}
}

static void PrefilterPktNonPFHookFlowStart(
DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
{
if (p->flowflags & (FLOW_PKT_TOSERVER_FIRST | FLOW_PKT_TOCLIENT_FIRST)) {
PrefilterPktNonPF(det_ctx, p, pectx);
}
}

/** \internal
* \brief engine to select the non-prefilter rules for frames
* Checks the alproto and type as well.
Expand Down Expand Up @@ -631,10 +649,22 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
}
uint32_t frame_non_pf_array_size = 0;

struct PrefilterNonPFDataSig *pkt_hook_flow_start_non_pf_array =
SCCalloc(max_sids, sizeof(*pkt_hook_flow_start_non_pf_array));
if (pkt_hook_flow_start_non_pf_array == NULL) {
SCFree(pkt_non_pf_array);
SCFree(frame_non_pf_array);
return -1;
}
uint32_t pkt_hook_flow_start_non_pf_array_size = 0;
SignatureMask pkt_hook_flow_start_mask = 0;
bool pkt_hook_flow_start_mask_init = false;

HashListTable *tx_engines_hash =
HashListTableInit(256, TxNonPFHash, TxNonPFCompare, TxNonPFFree);
if (tx_engines_hash == NULL) {
SCFree(pkt_non_pf_array);
SCFree(pkt_hook_flow_start_non_pf_array);
SCFree(frame_non_pf_array);
return -1;
}
Expand All @@ -644,6 +674,7 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
HashTableInit(512, NonPFNamesHash, NonPFNamesCompare, NonPFNamesFree);
if (de_ctx->non_pf_engine_names == NULL) {
SCFree(pkt_non_pf_array);
SCFree(pkt_hook_flow_start_non_pf_array);
SCFree(frame_non_pf_array);
HashListTableFree(tx_engines_hash);
return -1;
Expand Down Expand Up @@ -676,6 +707,44 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
bool tx_non_pf = false;
bool frame_non_pf = false;
bool pkt_non_pf = false;

if (s->init_data->hook.type == SIGNATURE_HOOK_TYPE_PKT &&
s->init_data->hook.t.pkt.ph == SIGNATURE_HOOK_PKT_FLOW_START) {
// TODO code duplication with regular pkt case below

/* for pkt non prefilter, we have some space in the structure,
* so we can squeeze another filter */
uint8_t type;
uint16_t value;
if ((s->flags & SIG_FLAG_DSIZE) && s->dsize_mode == DETECT_UINT_EQ) {
SCLogDebug("dsize extra match");
type = 2;
value = s->dsize_low;
} else if (s->dp != NULL && s->dp->next == NULL && s->dp->port == s->dp->port2) {
type = 1;
value = s->dp->port;
} else {
type = 0;
value = s->alproto;
}
pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].sid = s->num;
pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].value = value;
pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].type = type;
pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].pkt.sig_mask =
s->mask;
pkt_hook_flow_start_non_pf_array_size++;

if (pkt_hook_flow_start_mask_init) {
pkt_hook_flow_start_mask &= s->mask;
} else {
pkt_hook_flow_start_mask = s->mask;
pkt_hook_flow_start_mask_init = true;
}

SCLogDebug("flow_start hook");
continue; // done for this sig
}

for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
const int list_id = s->init_data->buffers[x].id;
const DetectBufferType *buf = DetectEngineBufferTypeGetById(de_ctx, list_id);
Expand Down Expand Up @@ -896,12 +965,32 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
data->size = pkt_non_pf_array_size;
memcpy((uint8_t *)&data->array, pkt_non_pf_array,
pkt_non_pf_array_size * sizeof(data->array[0]));
if (PrefilterAppendEngine(de_ctx, sgh, PrefilterPktNonPF, pkt_mask, (void *)data,
enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
if (PrefilterAppendEngine(de_ctx, sgh, PrefilterPktNonPF, pkt_mask, hook, (void *)data,
PrefilterNonPFDataFree, "packet:non_pf") < 0) {
SCFree(data);
goto error;
}
}
if (pkt_hook_flow_start_non_pf_array_size) {
struct PrefilterNonPFData *data = SCCalloc(
1, sizeof(*data) + pkt_hook_flow_start_non_pf_array_size * sizeof(data->array[0]));
if (data == NULL)
goto error;
data->size = pkt_hook_flow_start_non_pf_array_size;
memcpy((uint8_t *)&data->array, pkt_hook_flow_start_non_pf_array,
pkt_hook_flow_start_non_pf_array_size * sizeof(data->array[0]));
SCLogDebug("packet:flow_start:non_pf added with %u rules", data->size);
enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_FLOW_START;
if (PrefilterAppendEngine(de_ctx, sgh,
PrefilterPktNonPFHookFlowStart, // TODO no longer needed to have a dedicated
// callback
pkt_hook_flow_start_mask, hook, (void *)data, PrefilterNonPFDataFree,
"packet:flow_start:non_pf") < 0) {
SCFree(data);
goto error;
}
}
if (frame_non_pf_array_size) {
SCLogDebug("%u frame non-pf sigs", frame_non_pf_array_size);
struct PrefilterNonPFData *data =
Expand All @@ -918,6 +1007,8 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
}
}

SCFree(pkt_hook_flow_start_non_pf_array);
pkt_hook_flow_start_non_pf_array = NULL;
SCFree(pkt_non_pf_array);
pkt_non_pf_array = NULL;
SCFree(frame_non_pf_array);
Expand All @@ -928,6 +1019,7 @@ static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
if (tx_engines_hash) {
HashListTableFree(tx_engines_hash);
}
SCFree(pkt_hook_flow_start_non_pf_array);
SCFree(pkt_non_pf_array);
SCFree(frame_non_pf_array);
return -1;
Expand Down Expand Up @@ -973,7 +1065,11 @@ int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
for (el = sgh->init->pkt_engines ; el != NULL; el = el->next) {
e->local_id = el->id;
e->cb.Prefilter = el->Prefilter;
e->ctx.pkt_mask = el->pkt_mask;
e->ctx.pkt.mask = el->pkt_mask;
// TODO right now we represent the hook in a u8 in the prefilter engine for space
// reasons.
BUG_ON(el->pkt_hook >= 8);
e->ctx.pkt.hook = (uint8_t)el->pkt_hook;
e->pectx = el->pectx;
el->pectx = NULL; // e now owns the ctx
e->gid = el->gid;
Expand All @@ -998,7 +1094,11 @@ int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
for (el = sgh->init->payload_engines ; el != NULL; el = el->next) {
e->local_id = el->id;
e->cb.Prefilter = el->Prefilter;
e->ctx.pkt_mask = el->pkt_mask;
e->ctx.pkt.mask = el->pkt_mask;
// TODO right now we represent the hook in a u8 in the prefilter engine for space
// reasons.
BUG_ON(el->pkt_hook >= 8);
e->ctx.pkt.hook = (uint8_t)el->pkt_hook;
e->pectx = el->pectx;
el->pectx = NULL; // e now owns the ctx
e->gid = el->gid;
Expand Down Expand Up @@ -1404,8 +1504,9 @@ int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, M
pectx->mpm_ctx = mpm_ctx;
pectx->transforms = &mpm_reg->transforms;

enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
int r = PrefilterAppendEngine(
de_ctx, sgh, PrefilterMpmPkt, 0, pectx, PrefilterMpmPktFree, mpm_reg->pname);
de_ctx, sgh, PrefilterMpmPkt, 0, hook, pectx, PrefilterMpmPktFree, mpm_reg->pname);
if (r != 0) {
SCFree(pectx);
}
Expand Down
3 changes: 2 additions & 1 deletion src/detect-engine-prefilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ void Prefilter(DetectEngineThreadCtx *, const SigGroupHead *, Packet *p, const u
const SignatureMask mask);

int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc,
SignatureMask mask, void *pectx, void (*FreeFunc)(void *pectx), const char *name);
SignatureMask mask, enum SignatureHookPkt hook, void *pectx, void (*FreeFunc)(void *pectx),
const char *name);
int PrefilterAppendPayloadEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
PrefilterPktFn PrefilterFunc, void *pectx, void (*FreeFunc)(void *pectx), const char *name);
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
Expand Down
Loading

0 comments on commit 81ab9fa

Please sign in to comment.