Skip to content

tetragon: add support for substring operators#4393

Merged
olsajiri merged 4 commits intomainfrom
pr/olsajiri/substring
Feb 9, 2026
Merged

tetragon: add support for substring operators#4393
olsajiri merged 4 commits intomainfrom
pr/olsajiri/substring

Conversation

@olsajiri
Copy link
Copy Markdown
Contributor

@olsajiri olsajiri commented Nov 29, 2025

Adding support for SubString/IgnCase operators for matchArg selector, to be used on top of strings like:

    data:
    - index: 0
      type: "string"
      source: "pt_regs"
      resolve: "rdi"
    selectors:
    - matchData:
      - index: 0
        operator: "SubString"
        values:
        - "_3_"

The SubString matches exact string, SubStringIgnCase matches string regardless the case.

On top of #4489

@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch 2 times, most recently from f00dc92 to 3a44fed Compare December 23, 2025 15:10
@netlify
Copy link
Copy Markdown

netlify Bot commented Dec 23, 2025

Deploy Preview for tetragon ready!

Name Link
🔨 Latest commit c82a8b7
🔍 Latest deploy log https://app.netlify.com/projects/tetragon/deploys/6985f9e7326ae700088df0d5
😎 Deploy Preview https://deploy-preview-4393--tetragon.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch 3 times, most recently from 3a56bab to 5325dd0 Compare December 25, 2025 18:22
@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch 4 times, most recently from e2f69d8 to d618baf Compare January 20, 2026 11:33
@olsajiri olsajiri added the release-note/minor This PR introduces a minor user-visible change label Jan 20, 2026
@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch 2 times, most recently from c4a1da0 to 08b325c Compare January 20, 2026 15:35
@olsajiri olsajiri changed the title Pr/olsajiri/substring tetragon: add support for substring operators Jan 20, 2026
@olsajiri olsajiri marked this pull request as ready for review January 20, 2026 15:39
@olsajiri olsajiri requested a review from a team as a code owner January 20, 2026 15:39
// a pointer to the map. The rest of the argument code might do
// some arithmetics on it which would fail for pointer, but it's
// always using probe_read, so it's safe.
probe_read(&arg, sizeof(arg), &arg);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a problem: just surprised probe_read can have @arg as source and dest! I will borrow this myself.

Copy link
Copy Markdown
Contributor

@kevsecurity kevsecurity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

return m.Update(uint32(0), selector.Buffer(), ebpf.UpdateAny)
},
})
mapLoad = append(mapLoad, selectorsMaploads(selector, 0)...)
Copy link
Copy Markdown
Contributor

@andrewstrohman andrewstrohman Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause the selector maps to be included in a program.Program's MapLoad. A collectionLoader's maps is populated by a CollectionSpec's maps. CollectionSpec's maps are determined by the elf file.

Maps found in a program.Program's MapLoad will be loaded if they are also found in the ebpf.Collection's Maps. ebpf.Collection Maps is populated by collectionLoader's maps. So, just adding this is enough to load the maps.

However, when we create the sensor, we are not including the selector maps in the sensors.Sensor's Maps member. As such, we are not doing the max entry logic, like how we do for kprobes. See here and here for how I was thinking about handling this.

What do you think? My WIP does not prevent duplicates of the "filter_map" program.MapLoad like yours does. Also, there isn't an exact match between maps taken care of in selectorsMaploads vs my filterMaps function, but despite these shortcomings, it demonstrates the idea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so kprobe has that HasSelector condition for selector maps.. are you suggestion something similar for uprobe?

why do you keep the filter_map load in b8d7d4c ? it's part of selectorsMaploads right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you keep the filter_map load in b8d7d4c ? it's part of selectorsMaploads right?

Yes, that's a problem with my WIP. I agree that I shouldn't do that. I would fix that if we decided the overall approach makes sense.

so kprobe has that HasSelector condition for selector maps.. are you suggestion something similar for uprobe?

Yes, that seems like a good way to conditionally load the selector maps based on whether they are needed.

But what I'm really getting at here is that we are loading the maps without configuring the max entries. So, I think we need to address that. It looks like the logic of loading selector maps would be the same across all hook point types. So, I'm proposing that we create a unified way to do this.

We already have selectorsMaploads, a unified way for creating program.MapLoad. I think we should have the equivalent for generating program.Map. Then all hook types could reuse the same code for generating both program.MapLoad and program.Map for selector maps.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, that sounds good.. let's see how it looks like wrt that each sensor needs slightly different maps, but I think it would be good to have something like that

Comment thread pkg/selectors/kernel.go Outdated
func writeMatchSubString(k *KernelSelectorState, values []string) error {
for _, v := range values {
id := len(k.subStrs)
if id >= SubstringMapEntries-1 {
Copy link
Copy Markdown
Contributor

@andrewstrohman andrewstrohman Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is off by one.

I think it should instead be: if id >= SubstringMapEntries

Consider the following example. SubstringMapEntries is 100. It's used to set the max number of entries in the map. So the number of subStrs should not exceed 100.

If we want to add exactly 100 subStrs, on the last iteration, id will be 99.
99 >= (100 - 1), is true, so we return error. But we could add that last entry without going over the map's capacity.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, thanks

@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch 5 times, most recently from 319e3db to 1d3388f Compare January 25, 2026 09:49
@olsajiri
Copy link
Copy Markdown
Contributor Author

I changed the code to use core instead of the CONFIG variables, it's simpler

Copy link
Copy Markdown
Contributor

@kkourt kkourt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really cool! Thanks!

I have some minor nits (see below).

Comment thread pkg/selectors/kernel.go Outdated
if id >= SubstringMapEntries {
return fmt.Errorf("substring error: Only %d substrings allowed", SubstringMapEntries)
}
if len(v) >= 100 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a constant for this, ideally with a comment pointing to the corresponding BPF value.

Comment thread pkg/selectors/kernel.go
for _, a := range slices.Concat(s.MatchArgs, s.MatchData, s.MatchReturnArgs) {
argOp, err := SelectorOp(a.Operator)
if err != nil {
return false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we continue looking at the other selectors instead of returning here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that means the selector operator is wrong and the selector should already fail or we fail shortly.. so I think there's no point to continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, in that case, shouldn't we return an error?

Comment thread pkg/sensors/tracing/genericuprobe.go Outdated

if has.substring {
substringMap := program.MapBuilderSensor("substring_map", load)
substringMap.SetMaxEntries(selectors.SubstringMapEntries)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just size this to the number of entries in the selector?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, will change, thanks

@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch 2 times, most recently from a20078d to 0934840 Compare February 4, 2026 09:15
…lector

Adding support for SubString/IgnCase operators for matchArg selector,
to be used on top of strings like:

    data:
    - index: 0
      type: "string"
      source: "pt_regs"
      resolve: "rdi"
    selectors:
    - matchData:
      - index: 0
        operator: "SubString"
        values:
        - "_3_"

The SubString matches exact string, SubStringIgnCase matches
string regardless the case.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
  $ make generate codegen
  $ make -C docs tracing-policy-docs

Plus CustomResourceDefinitionSchemaVersion update.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Adding several tests for substring match on preloaded string.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Adding several tests for substring match on preloaded string
that results with overladed regs.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
@olsajiri olsajiri force-pushed the pr/olsajiri/substring branch from 0934840 to c82a8b7 Compare February 6, 2026 14:25
@olsajiri
Copy link
Copy Markdown
Contributor Author

olsajiri commented Feb 6, 2026

note the ci failure is just syntax false alarm

@olsajiri olsajiri merged commit b2c22fc into main Feb 9, 2026
62 of 63 checks passed
@olsajiri olsajiri deleted the pr/olsajiri/substring branch February 9, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/minor This PR introduces a minor user-visible change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants