-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add dynamic extraction of a parameter attribute #3143
base: main
Are you sure you want to change the base?
Add dynamic extraction of a parameter attribute #3143
Conversation
9a9d21f
to
ce33ec7
Compare
✅ Deploy Preview for tetragon ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
ce33ec7
to
5ebb3e0
Compare
e3117d7
to
ba048b3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it, left some comments
thanks for splitting the code in multiple logical changes, it's rare ;-)
we were originally thinking of using C expression parsing (there's some go lib for that) but I think that can be done later if it's ever needed, the basic parsing you did should be fine
please add tests, would be great to have some framework where we could easily add various 'ExtractParam' expressions for testing
ba048b3
to
1fb7dbc
Compare
753fd10
to
2b1153f
Compare
2b1153f
to
a04e634
Compare
058c828
to
391c5a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great, I left some comments, thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been pulled-in for the docs change, here's a review. Thanks for adding docs!
391c5a8
to
dac4d2e
Compare
@olsajiri The CI tests are still crashing on all kernel versions. I ran my tests on a 6.6 kernel, and everything worked fine. I'll investigate further to figure out the issue and update you soon. EDIT : The tests were failing because EDIT 2 : CI fails on |
e279770
to
3a85916
Compare
060882a
to
10e0ee3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good, one comment left, but could be fixed later if needed, thanks
This commit introduces the `struct config_btf_arg_depth`. It appends `btf_argN` to `struct event_config` as an array. This array stores the path to the searched data. Any `btf_argN` can have a list of elements as follow : file->f_path is 152 bytes, so the array will look like [{ offset: 152, is_pointer: 0, is_initialized: 1 }, ...]. The max value `MAX_BTF_ARG_DEPTH` as been set arbitrary as the verifier need a fixed size. In config_btf_arg, is_pointer and is_initialized are u16 because it must match padding of 64 bits long structure Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
…_argN This commit introduces the “extract_arg_depth” function and loops over it to move into the “arg” buffer of config->btf_argN[i]->offset by iteration. The goal is to reach the requiered data by overwriting over arg with the new value. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
This commit checks if btf.Type exists in Tetragon existing types. For instance: `struct file` with btf is called `file` and also exists in `GenericStringToType` with the same alias. However, the attribute `name` in `struct qstr` has a returned type `unsigned char` wich does not exist yet in `GenericStringToType`. The same thing happened with `linux_binprm->filename` as the type is `char` Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
ResolveBtfPath function recursively searches in a btf structure in order to find a specific path until it reaches the target or fails. The function also searches in embedded anonymous structures or unions to cover as much use cases as possible. For instance, mm_struct has 2 fields; anonymous struct and another type. But you are still able to look into the anonymous struct by specifying a path like "mm.pgd.pgd". For instance, if the search is in the linux_binprm structure and the path is `file.f_path.dentry.d_name.name`, the following actions will be done. - Look for the variable name `file` inside `linux_binprm`. - If it matches, it stores the offset from linux_binprm where the `file` variable could be found. - Then it takes the btf type `file` and searches for a parameter named `f_path`. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
In order to read the data properly on BPF side, integer/long values must use `bpf_probe_read`. So now, every time the latest type retrieved is defined as an integer, it will be safely read before accessing the data. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
I've noticed that unit tests load differently the btf file than locally. So when using `NewBTF()` locally it worked, but during the pipeline it crashes. To avoid this behaviour, `LoadBTF` is added and ensure the btf file path is set before trying to load it. Otherwise, it run the `InitCachedBtf()`. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
The function `FindBtfFuncParamFromHook` has been added to identify the exact BTF type of the hook's parameters. This allows us to handle cases where the hook has parameters that include multiple pointers to structures. With those information, we will be able to dereference correctly any parameters until we reach the data Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
This commit adds a new parameter to give the ability to the user to search for a specific attribute following a "path" as follow: ```yml ... - hook: "bprm_check_security" args: - index: 0 # index 0 is struct linux_binprm type: "string" resolve: "file.f_path.dentry.d_name.name" ... ``` The above config can be used to extract a specific attribute from the structure at index 0. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
Searches if every user defined type with Resolve exists as a BTF type and stores its corresponding offset in ConfigBtfArg. This function does a basic split on `Resolve` to obtain the "path" to the required data. Then, the array is given to `btf.ResolveBtfPath` to find the offset of each element until we reach the required data. The output is stored in EventConfig to keep the normal behaviour. For example, if the arg 0 is `struct linux_binprm` and Resolve is set to `file.f_path.dentry.d_name.name`, the output will give an array of all the offsets from their parents as follows : [{ offset: 96, is_pointer: 0 }, { offset: 152, is_pointer: 1 }, ...] Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
This commit updates `addLsm` function to use the new `arg.Resolve` option in order to look for the attributes in BTF structure. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
Since the Resolve attribute feature uses the hook name to retrieve the hook parameters, if the LSM hook does not exist inside the BTF file, it is not possible to resolve attributes correctly. The feature that allows this was added to the kernel in v5.8 with the patch below: https://lore.kernel.org/bpf/20200329004356.27286-4-kpsingh@chromium.org/ After this patch, LSM hooks can be retrieved in the BTF file with this format: `bpf_lsm_<hook_name>` Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
As BTF types are not defined for Uprobes, their offsets can't be found in BTF file. Thus, if the user defines Resolve, an error is returned Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
Add very similar code as in `genericlsm.go` file to handle Resolve feature. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
…licy `TestResolveBtfArgFromKprobePolicy` is introduced. It aims to test the access to the requested attribute with no errors and assert that the very last type corresponds to the requested policy type (string/int/etc). 3 different cases are handled: - Test a classic hook - Test resolve from double pointer parameter - Assert an error is raised when the resolve path is too long Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
This test ensures 4 things : - It can retrieve correctly the parameter of an kprobe hook. - Is raises an error when btf.Type could not be found - It raises an error when the type found is not a function. - It raises an error when the requested parameter index is out of range for the FuncProto.Params array. Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
This commit adds 3 tests for ResolveBtfPath algorithm : - `testAssertEqualBtfPath` to assert that a specific path has the exact same btfConfig as expected. - `testAssertPathIsAccessible` tries to reach the path and asserts that no errors are raised. - `testAssertErrorOnInvalidPath` asserts that the error messages raised if the path is incorrect. The chosen test cases have embed union/anonymous structs. To Test locally : ``` go test -exec "sudo" ./pkg/btf/ ``` Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
Signed-off-by: Tristan d'Audibert <tristan.daudibert@orange.com>
10e0ee3
to
3a883bb
Compare
The discussion for this PR can be found here #3142
Take this PR in the today state as a proof of concept for dynamic parameter extraction. I will continue to work on this PR until the below checks are done.
At the current state, the PR is able to
Description
This PR introduce the dynamic extraction of a custom attribute
Test the PR
You can use the following config
Release-note