Skip to content

Tx sub states/v2#15827

Open
victorjulien wants to merge 43 commits into
OISF:mainfrom
victorjulien:tx-sub-states/v2
Open

Tx sub states/v2#15827
victorjulien wants to merge 43 commits into
OISF:mainfrom
victorjulien:tx-sub-states/v2

Conversation

@victorjulien

@victorjulien victorjulien commented Jul 8, 2026

Copy link
Copy Markdown
Member

Foundational tx sub state support, with app transactions able to have their own type and state machines (hence sub states). Implemented here for HTTP2/DOH2 with a stream and global type.

SV_BRANCH=OISF/suricata-verify#3168

It's not perfect yet, with some known issues:

  • general polish
  • docs
  • doh2 could also move into a tx type instead of a pseudo app-layer

Would like to get this in and work more incrementally from here.

https://redmine.openinfosecfoundation.org/issues/8386

Allow registration of per substate progress name mappings.

Implement logic for getting sub-state names, id's.

Add transaction type and end of progress values to AppLayerTxData.

Introduce helpers to keep logic clean.
Support for per transaction sub states: different state machines per
transaction type.

Skip engines not belonging to our substate.

Store tx_type in DetectTransaction.

Each protocol supporting sub states will register states from 1 and up.

To support:

Ticket: OISF#8386.
Split into 2 sub-states:
- stream, which has the "HTTP" requests and responses, including DOH2
- global, which has the settings and other global or control handling

Introduce a simpler progress tracking for the global sub state:
- HTTP2ProgGlobalStart and HTTP2ProgGlobalComplete.

The stream sub state uses the same state machine as before.

Ticket: OISF#8386.
Each keyword supporting DOH2 must register explicitly
Now that DNS keywords are no longer registered for DOH2, the keywords
need to manually registered for DOH2.
Now that HTTP keywords are no longer automatically registered for
HTTP/2, register them manually.
DNS/HTTP2 no longer automatically registers all keywords also for DOH2.

Instead, the DNS keywords and HTTP/2 stream keywords are registered for
DOH2 explicitly as well.

- flow alproto DOH2 + engine DOH2  -> inspect inner DNS
- flow alproto DOH2 + engine HTTP2 -> inspect outer HTTP/2
- flow alproto DOH2 + engine UNKNOWN -> inspect outer HTTP/2
For the most part hard coded for HTTP/2 for now.
Register a generic list for each sub state / progress combo.
Otherwise we'd have to re-register the relevant callbacks.
With substate support the fixed table approach for policies was no
longer a good fit, so convert to a hash table. The policies are stored
per alproto, sub_state, progress and direction.
Now that there is a policy hash, make the alert signature object a
member of that to avoid another hash table lookup.
Check that sub state handling is correct.
In preparation of being able to log it.
http2 states were not yet supported even if the built-in states could
already work. Clearly error out on a hook w/o substate.
In firewall mode the alproto logic when building prefilter and rule
engines is strict, but was out of sync between prefilter and rule app
inspect engines.

For SIGNATURE_HOOK_TYPE_APP rules the logic is strict, with an exception
for HTTP/2 and DOH2. DOH2 is not a full protocol implementation, but
rather HTTP/2 with a different alproto.

Fixes: d64954a ("detect: don't register unrelated inspect engines")
This is to make the hook use names consistent with the default
hooks and other protocols.
DOH2 depends on HTTP/2, so it makes no sense to enable it separately.

It would also put the sub state handling in a weird state, as the DOH2
side reuses the registered HTTP/2 callbacks.
When building the per signature app_inspect list, only add engines
that match the sub state specified in the hook.
Register HTTP/2 and DOH2 this way.
@suricata-qa

Copy link
Copy Markdown

WARNING:

field baseline test %
SURI_TLPR1_stats_chk
.app_layer.flow.ftp_data 604 656 108.61%
.app_layer.error.ftp.parser 17 0 -

Pipeline = 32497

@victorjulien victorjulien marked this pull request as ready for review July 8, 2026 17:49
@victorjulien victorjulien requested review from a team, catenacyber and jasonish as code owners July 8, 2026 17:49
@jasonish

jasonish commented Jul 8, 2026

Copy link
Copy Markdown
Member

Given this rule:

alert http2:global:request_started any any -> any any (msg:"http2 global hook with stream-scoped http.uri"; http.uri; content:"x"; sid:1; rev:1;)

ASAN throws a memory leak error on test, for example:

[jason@desktop] …/dev/suricata/review  tx-sub-states/v2 ❯ ./src/suricata -S repro/substate-null-app-inspect/substate-null-app-inspect.rules -l . -T
Notice: suricata: This is Suricata version 9.0.0-dev (2dc3e09ebc 2026-07-08) running in SYSTEM mode [LogVersion:suricata.c:1248]
Notice: suricata: Configuration provided was successfully loaded. Exiting. [SuricataInit:suricata.c:3177]

=================================================================
==375284==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x7f1a8cd2bea9 in calloc (/usr/lib/libasan.so.8+0x12bea9) (BuildId: b28f87d70f4aadfdfe6abce3776c226f5569bd6a)
    #1 0x563e8765b06d in SCCallocFunc /home/jason/oisf/dev/suricata/review/src/util-mem.c:60
    #2 0x563e87c0ca5e in SigMatchList2DataArray /home/jason/oisf/dev/suricata/review/src/detect-parse.c:2603
    #3 0x563e879a62c2 in DetectEngineAppInspectionEngine2Signature /home/jason/oisf/dev/suricata/review/src/detect-engine.c:983
    #4 0x563e878ef540 in SigMatchPrepare /home/jason/oisf/dev/suricata/review/src/detect-engine-build.c:2226
    #5 0x563e878f03bd in SigGroupBuild /home/jason/oisf/dev/suricata/review/src/detect-engine-build.c:2339
    #6 0x563e879057c4 in SigLoadSignatures /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:515
    #7 0x563e875e69f9 in LoadSignatures /home/jason/oisf/dev/suricata/review/src/suricata.c:2581
    #8 0x563e875e783a in PostConfLoadedDetectSetup /home/jason/oisf/dev/suricata/review/src/suricata.c:2732
    #9 0x563e875e9e4b in SuricataInit /home/jason/oisf/dev/suricata/review/src/suricata.c:3173
    #10 0x563e875d7f43 in main /home/jason/oisf/dev/suricata/review/src/main.c:57
    #11 0x7f1a8ba27740  (/usr/lib/libc.so.6+0x27740) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #12 0x7f1a8ba27878 in __libc_start_main (/usr/lib/libc.so.6+0x27878) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #13 0x563e875d7d94 in _start (/home/jason/oisf/dev/suricata/review/src/suricata+0x9d4d94) (BuildId: c1cb9c0324113f477bd9178bdb8f6a61899f6364)

Indirect leak of 1000 byte(s) in 1 object(s) allocated from:
    #0 0x7f1a8cd2c0c1 in malloc (/usr/lib/libasan.so.8+0x12c0c1) (BuildId: b28f87d70f4aadfdfe6abce3776c226f5569bd6a)
    #1 0x563e8765ab1f in SCMallocFunc /home/jason/oisf/dev/suricata/review/src/util-mem.c:31
    #2 0x563e87669aff in SCHSMalloc /home/jason/oisf/dev/suricata/review/src/util-mpm-hs.c:93
    #3 0x7f1a8be6d0db  (/usr/lib/libhs.so.5+0x6d0db) (BuildId: 7a7deeea5ae453c96e314b13ebc639d9194a1c12)
    #4 0x7f1a8be68c80  (/usr/lib/libhs.so.5+0x68c80) (BuildId: 7a7deeea5ae453c96e314b13ebc639d9194a1c12)
    #5 0x7f1a8be697d4 in hs_compile (/usr/lib/libhs.so.5+0x697d4) (BuildId: 7a7deeea5ae453c96e314b13ebc639d9194a1c12)
    #6 0x563e876c10bf in HSBuildDatabase /home/jason/oisf/dev/suricata/review/src/util-spm-hs.c:80
    #7 0x563e876c1507 in HSInitCtx /home/jason/oisf/dev/suricata/review/src/util-spm-hs.c:125
    #8 0x563e876afd7c in SpmInitCtx /home/jason/oisf/dev/suricata/review/src/util-spm.c:189
    #9 0x563e878a1c1c in DetectContentParse /home/jason/oisf/dev/suricata/review/src/detect-content.c:230
    #10 0x563e878a2da2 in DetectContentSetup /home/jason/oisf/dev/suricata/review/src/detect-content.c:325
    #11 0x563e87c021e8 in SigParseOptions /home/jason/oisf/dev/suricata/review/src/detect-parse.c:1074
    #12 0x563e87c0929d in SigParse /home/jason/oisf/dev/suricata/review/src/detect-parse.c:2125
    #13 0x563e87c13966 in SigInitHelper /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3222
    #14 0x563e87c14dc3 in SigInitDo /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3369
    #15 0x563e87c151cf in SigInit /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3412
    #16 0x563e87c16c66 in DetectEngineAppendSig /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3759
    #17 0x563e87902df2 in DetectLoadSigFile /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:186
    #18 0x563e87903864 in ProcessSigFiles /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:280
    #19 0x563e87904fc2 in SigLoadSignatures /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:453
    #20 0x563e875e69f9 in LoadSignatures /home/jason/oisf/dev/suricata/review/src/suricata.c:2581
    #21 0x563e875e783a in PostConfLoadedDetectSetup /home/jason/oisf/dev/suricata/review/src/suricata.c:2732
    #22 0x563e875e9e4b in SuricataInit /home/jason/oisf/dev/suricata/review/src/suricata.c:3173
    #23 0x563e875d7f43 in main /home/jason/oisf/dev/suricata/review/src/main.c:57
    #24 0x7f1a8ba27740  (/usr/lib/libc.so.6+0x27740) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #25 0x7f1a8ba27878 in __libc_start_main (/usr/lib/libc.so.6+0x27878) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #26 0x563e875d7d94 in _start (/home/jason/oisf/dev/suricata/review/src/suricata+0x9d4d94) (BuildId: c1cb9c0324113f477bd9178bdb8f6a61899f6364)

Indirect leak of 57 byte(s) in 1 object(s) allocated from:
    #0 0x7f1a8cd2bea9 in calloc (/usr/lib/libasan.so.8+0x12bea9) (BuildId: b28f87d70f4aadfdfe6abce3776c226f5569bd6a)
    #1 0x563e8765b06d in SCCallocFunc /home/jason/oisf/dev/suricata/review/src/util-mem.c:60
    #2 0x563e878a1aad in DetectContentParse /home/jason/oisf/dev/suricata/review/src/detect-content.c:219
    #3 0x563e878a2da2 in DetectContentSetup /home/jason/oisf/dev/suricata/review/src/detect-content.c:325
    #4 0x563e87c021e8 in SigParseOptions /home/jason/oisf/dev/suricata/review/src/detect-parse.c:1074
    #5 0x563e87c0929d in SigParse /home/jason/oisf/dev/suricata/review/src/detect-parse.c:2125
    #6 0x563e87c13966 in SigInitHelper /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3222
    #7 0x563e87c14dc3 in SigInitDo /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3369
    #8 0x563e87c151cf in SigInit /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3412
    #9 0x563e87c16c66 in DetectEngineAppendSig /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3759
    #10 0x563e87902df2 in DetectLoadSigFile /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:186
    #11 0x563e87903864 in ProcessSigFiles /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:280
    #12 0x563e87904fc2 in SigLoadSignatures /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:453
    #13 0x563e875e69f9 in LoadSignatures /home/jason/oisf/dev/suricata/review/src/suricata.c:2581
    #14 0x563e875e783a in PostConfLoadedDetectSetup /home/jason/oisf/dev/suricata/review/src/suricata.c:2732
    #15 0x563e875e9e4b in SuricataInit /home/jason/oisf/dev/suricata/review/src/suricata.c:3173
    #16 0x563e875d7f43 in main /home/jason/oisf/dev/suricata/review/src/main.c:57
    #17 0x7f1a8ba27740  (/usr/lib/libc.so.6+0x27740) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #18 0x7f1a8ba27878 in __libc_start_main (/usr/lib/libc.so.6+0x27878) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #19 0x563e875d7d94 in _start (/home/jason/oisf/dev/suricata/review/src/suricata+0x9d4d94) (BuildId: c1cb9c0324113f477bd9178bdb8f6a61899f6364)

Indirect leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x7f1a8cd2bea9 in calloc (/usr/lib/libasan.so.8+0x12bea9) (BuildId: b28f87d70f4aadfdfe6abce3776c226f5569bd6a)
    #1 0x563e8765b06d in SCCallocFunc /home/jason/oisf/dev/suricata/review/src/util-mem.c:60
    #2 0x563e876c13cb in HSInitCtx /home/jason/oisf/dev/suricata/review/src/util-spm-hs.c:110
    #3 0x563e876afd7c in SpmInitCtx /home/jason/oisf/dev/suricata/review/src/util-spm.c:189
    #4 0x563e878a1c1c in DetectContentParse /home/jason/oisf/dev/suricata/review/src/detect-content.c:230
    #5 0x563e878a2da2 in DetectContentSetup /home/jason/oisf/dev/suricata/review/src/detect-content.c:325
    #6 0x563e87c021e8 in SigParseOptions /home/jason/oisf/dev/suricata/review/src/detect-parse.c:1074
    #7 0x563e87c0929d in SigParse /home/jason/oisf/dev/suricata/review/src/detect-parse.c:2125
    #8 0x563e87c13966 in SigInitHelper /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3222
    #9 0x563e87c14dc3 in SigInitDo /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3369
    #10 0x563e87c151cf in SigInit /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3412
    #11 0x563e87c16c66 in DetectEngineAppendSig /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3759
    #12 0x563e87902df2 in DetectLoadSigFile /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:186
    #13 0x563e87903864 in ProcessSigFiles /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:280
    #14 0x563e87904fc2 in SigLoadSignatures /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:453
    #15 0x563e875e69f9 in LoadSignatures /home/jason/oisf/dev/suricata/review/src/suricata.c:2581
    #16 0x563e875e783a in PostConfLoadedDetectSetup /home/jason/oisf/dev/suricata/review/src/suricata.c:2732
    #17 0x563e875e9e4b in SuricataInit /home/jason/oisf/dev/suricata/review/src/suricata.c:3173
    #18 0x563e875d7f43 in main /home/jason/oisf/dev/suricata/review/src/main.c:57
    #19 0x7f1a8ba27740  (/usr/lib/libc.so.6+0x27740) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #20 0x7f1a8ba27878 in __libc_start_main (/usr/lib/libc.so.6+0x27878) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #21 0x563e875d7d94 in _start (/home/jason/oisf/dev/suricata/review/src/suricata+0x9d4d94) (BuildId: c1cb9c0324113f477bd9178bdb8f6a61899f6364)

Indirect leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x7f1a8cd2bea9 in calloc (/usr/lib/libasan.so.8+0x12bea9) (BuildId: b28f87d70f4aadfdfe6abce3776c226f5569bd6a)
    #1 0x563e8765b06d in SCCallocFunc /home/jason/oisf/dev/suricata/review/src/util-mem.c:60
    #2 0x563e876c145e in HSInitCtx /home/jason/oisf/dev/suricata/review/src/util-spm-hs.c:117
    #3 0x563e876afd7c in SpmInitCtx /home/jason/oisf/dev/suricata/review/src/util-spm.c:189
    #4 0x563e878a1c1c in DetectContentParse /home/jason/oisf/dev/suricata/review/src/detect-content.c:230
    #5 0x563e878a2da2 in DetectContentSetup /home/jason/oisf/dev/suricata/review/src/detect-content.c:325
    #6 0x563e87c021e8 in SigParseOptions /home/jason/oisf/dev/suricata/review/src/detect-parse.c:1074
    #7 0x563e87c0929d in SigParse /home/jason/oisf/dev/suricata/review/src/detect-parse.c:2125
    #8 0x563e87c13966 in SigInitHelper /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3222
    #9 0x563e87c14dc3 in SigInitDo /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3369
    #10 0x563e87c151cf in SigInit /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3412
    #11 0x563e87c16c66 in DetectEngineAppendSig /home/jason/oisf/dev/suricata/review/src/detect-parse.c:3759
    #12 0x563e87902df2 in DetectLoadSigFile /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:186
    #13 0x563e87903864 in ProcessSigFiles /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:280
    #14 0x563e87904fc2 in SigLoadSignatures /home/jason/oisf/dev/suricata/review/src/detect-engine-loader.c:453
    #15 0x563e875e69f9 in LoadSignatures /home/jason/oisf/dev/suricata/review/src/suricata.c:2581
    #16 0x563e875e783a in PostConfLoadedDetectSetup /home/jason/oisf/dev/suricata/review/src/suricata.c:2732
    #17 0x563e875e9e4b in SuricataInit /home/jason/oisf/dev/suricata/review/src/suricata.c:3173
    #18 0x563e875d7f43 in main /home/jason/oisf/dev/suricata/review/src/main.c:57
    #19 0x7f1a8ba27740  (/usr/lib/libc.so.6+0x27740) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #20 0x7f1a8ba27878 in __libc_start_main (/usr/lib/libc.so.6+0x27878) (BuildId: d8ceb52a8c6e1fefece4ca75f7396d1d5bffc565)
    #21 0x563e875d7d94 in _start (/home/jason/oisf/dev/suricata/review/src/suricata+0x9d4d94) (BuildId: c1cb9c0324113f477bd9178bdb8f6a61899f6364)

SUMMARY: AddressSanitizer: 1105 byte(s) leaked in 5 allocation(s).

Similar leak if you convert the rule to an accept:hook and load as a firewall rule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants