Project

General

Profile

Feature #9363

Updated by Jason Ish about 10 hours ago

Keywords Keyword Setup callbacks implemented in plugins or in Rust can't access the @Signature@, @Signature@ and @SigMatch@ and @sigmatch_table@ internals that built-in keywords use when they are registered and when their during rule options are set up, parsing, because those types are opaque to them and their layout changes with build options (for example @--enable-profiling-rules@). Three Two common things such a keyword Setup callback needs are therefore impossible without calling unexported functions or mirroring struct offsets: 

 # *Packet match callback:* @SCDetectHelperKeywordRegister()@ takes an @SCSigTableAppLiteElmt@, which only has an app-layer transaction match callback. A packet keyword has to write its @Match@ callback into @sigmatch_table@ directly. 
 # *Negation:* keywords registered with @SIGMATCH_HANDLE_NEGATION@ get the leading @!@ stripped by the rule parser, which records it in @Signature::init_data@. The flag is already exposed to Rust, but there is no way to read the result. 
 # *Earlier instances of the same keyword:* keywords like @app-layer-protocol@ and @ipproto@ walk the signature's packet match list to reject duplicate or conflicting options, reading each earlier instance's context. @SCDetectGetLastSMFromLists()@ is not a substitute: it only returns the last match, gives no access to its context, and ignores the packet match list once a sticky buffer is active in the rule. 

 h2. Proposal 

 Add functions accessors to the detect API, exposed through the generated Rust bindings: 

 * @SCDetectHelperKeywordPacketMatchRegister(kwid, Match)@: install a packet match callback for a keyword registered with @SCDetectHelperKeywordRegister()@, without changing the @SCSigTableAppLiteElmt@ layout 
 * @SCDetectSignatureIsNegated(s)@: whether the option being set up was negated 
 * @SCDetectSignatureGetLastSMByType(s, list_id, type)@: last SigMatch of a keyword in one of the static lists (e.g. @DETECT_SM_LIST_MATCH@) 
 * @SCSigMatchGetPrevByType(sm, type)@: previous SigMatch of the same keyword 
 * @SCSigMatchGetCtx(sm)@: the keyword context of a SigMatch 

 The lookup is limited to the static lists from @DetectSigmatchListEnum@. That enum is moved to @detect-engine-register.h@ and allowlisted in the Rust bindings, so Rust keywords can use @DETECT_SM_LIST_MATCH@ instead of hardcoding it. 

 h2. Users 

 * The in-tree nDPI plugin is converted to register the accessors for its @ndpi-protocol@ and @ndpi-risk@ keywords through the helpers, and to use the accessors for their negation and conflict checks, so it no longer touches @sigmatch_table@, @Signature@ or @SigMatch@ internals. checks. 
 * An external nDPI plugin written in Rust uses them in place of writing into @sigmatch_table@ through a probed struct layout, calling the unexported @DetectGetLastSMByListId()@, @DetectGetLastSMByListId()@ and walking @SigMatch@ through mirrored struct offsets. 
 * The @flowbits@ and @ipproto@ keywords use the SigMatch lookup as in-tree examples, and unit tests in @src/tests/util-plugin.c@ cover the patterns from a keyword registered the way a plugin does it. 

 h2. Related 

 * #7499 tracking: rust/plugins: first class support for rust plugins 
 * #8632 plugins(ndpi): add flow accessors for opaque usage of flow

Back