-
Notifications
You must be signed in to change notification settings - Fork 426
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
Data filter in kernel #4324
Data filter in kernel #4324
Conversation
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.
This is just a first pass (skimming) review.
Tested and working with:
sudo ./dist/tracee -e security_file_open.data.pathname=/etc/passwd
sudo ./dist/tracee -e security_file_open.data.pathname='/etc/passwd*'
sudo ./dist/tracee -e security_file_open.data.pathname='*passwd-'
Amazing, @rscampos! 👏🏼
ca7b783
to
5187326
Compare
@geyslan I've pushed some changes to how we retrieve the string from args in args_buffer_t. To make it work, I added a field to args_buffer_t and modified the save_str_to_buf function. |
295957e
to
4b53fe8
Compare
This is important, it could have been a security vulnerability. |
Thank you for commenting on this, @itaysk. If filtering in the kernel isn't possible, I'll definitely try this solution. |
4b53fe8
to
20842f5
Compare
f82b46d
to
a600fb5
Compare
There is no need to filter in userspace for such a corner case. It is possible to define the result of the longest prefix match to contain the results of the policies with the sub strings as well, since the return value of the map is matched policies (or matched rules in the future) |
e491453
to
c87ab81
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 Raphael!
I did a first review on this draft, looking forward to see it merged
0cf3a5d
to
9097b76
Compare
c6469ce
to
86b4d0f
Compare
86b4d0f
to
88809d1
Compare
d5d64b3
to
bd095ca
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.
LGTM
Great work @rscampos !
7ee86fe
to
83551f0
Compare
de8e0a5
to
b498708
Compare
b498708
to
7192fb7
Compare
- function load_str_from_buf created to retrieve str value based on index; - function reverse_string created to revert an string in order to enable suffix; - function evaluate_data_filters/match_data_filters created to apply: exact, prefix and suffix match; - eBPF maps for exact, prefix and suffix. eBPF map for hold temporary LPM TRI key; - extend event_config to have data filter config per event: used for exact, prefix and suffix match; - save offset at the specified index in the function save_str_to_buf.
- how to enable data filter in the eBPF program using the function evaluate_data_filters.
- eBPF map definition for exact, prefix, suffix match; - create updateDataFilterLPMBPF and updateDataFilterBPF to populate eBPF maps; - config map fields for exact, prefix and suffix; - Create the function createNewDataFilterMapsVersion in order to create the inner maps based on version and event id.
- method equalities created for data filter; - method computeDataFilterEqualities created for kernel data filter; - handle corner case when one policy uses a substring (path) of another policy; - disable data filter (only pathname) for selected events; - Kernel data filters restrict pathnames to 255 characters and disallow 'contains' filters - added functions to enforce that.
- Add MatchTypes{} and KernelDataFilter{} in cmp.AllowUnexported; - Kernel data filters restrict pathnames to 255 characters and disallow 'contains' filters; unit tests have been added to validate these restrictions; - Integration tests for specific events added, covering three filter types with "equal" and "not equal" conditions.
- Add the restrictions applicable when the kernel-space data filter is available for an event field.
7192fb7
to
03b6b4d
Compare
/fast-forward |
Folks @yanivagman @geyslan, Thank you for all the feedbacks! Learned a lot of good things during this work! |
Congrats for this amazing new feature! 🚀🥳 |
1. Explain what the PR does
03b6b4d docs(filters): add restrictions when kernel data filter is used
97dd25f test(filters): kernel data filter
4030594 feat(filters): equalities for kernel data filter
0d98252 feat(filters): eBPF management for kernel data filter
0c31dbe feat(ebpf): enable kernel data filter in eBPF program
86ac860 feat(ebpf): kernel data filter logic
a499bc1 feat(ebpf): Enable BPF_F_NO_PREALLOC for LPM TRIE
03b6b4d docs(filters): add restrictions when kernel data filter is used
97dd25f test(filters): kernel data filter
4030594 feat(filters): equalities for kernel data filter
0d98252 feat(filters): eBPF management for kernel data filter
0c31dbe feat(ebpf): enable kernel data filter in eBPF program
86ac860 feat(ebpf): kernel data filter logic
2. Explain how to test it
The method for defining data filters in Tracee remains the same. However, for the
security_file_open
andmagic_write
events, if the pathname is used as a filter, the event is now filtered at the eBPF data plane, preventing it from being sent to user space for filtering.Notes for the reviewer: The following sections contain commands I used to test with policies. The results for each test group are also included. Both the policies and results are located in the zip file provided in each section. The results of some tests may vary depending on the Linux version and libraries, especially when the "not equal" operator is used.
Only exact match
Tracee
Maps
Cmds
The results of each of the following lines are in the JSON file (results_exact.json):
exactly_policies_results.zip
Only prefix match
Tracee
Maps
Cmds
The results of each of the following lines are in the JSON file (results_prefix.json):
prefix_policies_results.zip
Only suffix match
Tracee
Maps
Cmds
The results of each of the following lines are in the JSON file (results_suffix.json):
suffix_policies_results.zip
Mixed (exact/prefix/suffix) match
In this section, you can see all string matches working together. The command
cat /etc/netconfig
triggers three policies simultaneously, while the commandcat /etc/host.conf
triggers two policies.Tracee
Maps
Cmds
The results of each of the following lines are in the JSON file (results_mixed.json):
mixed_policies_results.zip
Mixed (exact/prefix/suffix) match (same policy)
In this section, you can see all string matches working together in the same policy. The command
more /etc/netconfig
triggers three policies simultaneously.Tracee
Maps
Cmds
The results of each of the following lines are in the JSON file (results_mixed_same_policy.json):
Results: results_mixed_same_policy.json
results_mixed_same_policy_results.zip
Ensuring Multiple Policy Matches when LPM Trie is used - Prefix
Corner case description: When using the LPM Trie, it always returns the longest matching string. A corner case arises when one policy (e.g., policy1) uses a substring of another policy (e.g., policy2). For instance, if policy1 covers
/etc/net*
and policy2 covers/etc/netconf*
, a lookup for/etc/netconfig
currently only returns policy2 because it is the longest match. However, it should return both policy1 and policy2.A potential solution (implemented): If one suffix or prefix overlaps with another, we can simply combine their bitmaps in user space. No additional logic is required in kernel space to handle this corner case.
Tracee
Maps
Note: Policy 4 includes lines to exclude library entries from the output. These lines are solely for cleaning up the output to simplify the testing in this section.
Policy 2 (prefix /etc/net) overlaps with Policy 1 (prefix /etc/n), as /etc/n is a substring of /etc/net. This is why the key with the path "/etc/net" has equality_set_in_scopes=3, indicating that both Policy 1 and Policy 2 are part of the same equality set. Additionally, equal_in_scopes=3 shows that Policy 1 and Policy 2 are considered equal in their scopes.
Policy 3 (prefix /etc/network) encompasses both Policy 1 (prefix /etc/n) and Policy 2 (prefix /etc/net). Consequently, the key with the path "/etc/network" has equality_set_in_scopes=7, which signifies that all three policies are present within the same scope. Similarly, equal_in_scopes=7 indicates that Policy 1, Policy 2, and Policy 3 are equal in scopes.
Policy 4 (prefix /etc/netconf) also includes both Policy 1 (prefix /etc/n) and Policy 2 (prefix /etc/net). Therefore, the key with the path "/etc/netconf" has equality_set_in_scopes=11, which means that Policy 1, Policy 2, and Policy 4 are all part of the same scope. However, because Policy 4 was defined with the condition data.pathname!=/etc/netconf, equal_in_scopes=3, meaning that only Policy 1 and Policy 2 are considered equal in scopes, while Policy 4 is excluded from that equality.
In summary, Policy 2, Policy 3, and Policy 4 derive bits from other policies, reflecting their interdependencies and overlaps in scope.
Cmds
The results of each of the following lines are in the JSON file (results_corner_case_prefix.json):
cc_prefix_policies_results.zip
Ensuring Multiple Policy Matches when LPM Trie is used - Suffix
Tracee
Maps
Note: Policy 3 includes lines to exclude library entries from the output. These lines are solely for cleaning up the output to simplify the testing in this section.
Policy 1 (suffix netconfig) overlaps with Policy 2 (suffix config), as config is a substring of netconfig. This is why the key with the path "gifnocten" (which is a reversed representation of netconfig) has equality_set_in_scopes=3 and this indicates that both Policy 1 and Policy 2 are contained within the same scope. However, equal_in_scopes=3 shows that Policy 1 and Policy 2 are equal in scopes.
Policy 2 (suffix config) only contains the bitmap of Policy 2 (equality_set_in_scopes=2 and equal_in_scopes=2).
Policy 3 (suffix etc/netconfig) contains both Policy 1 (suffix netconfig) and Policy 2 (suffix config). Therefore, the key with the path "gifnocten/cte" (representing the reverse of etc/netconfig) has equality_set_in_scopes=7. This value indicates that all three policies are present within the scope. However, equal_in_scopes=3 shows that only Policy 1 and Policy 2 are equal in scopes, whereas Policy 3 is disabled in this scope because it was defined using data.pathname!=etc/netconfig.
Cmds
The results of each of the following lines are in the JSON file (results_corner_case_suffix.json):
cc_suffix_policies_results.zip
Performance results
To measure performance, the
bpftool
tool was used to collect and exportbpf_program_runtime_ns
andbpf_program_amount
metrics to Grafana for analyzing eBPF program latency. Exporting this data to Grafana allows for measuring latency within a specific time window using the following logic:Improvements in eBPF Latency for Some Events (Compared to the Old Version of Tracee):
security_file_open: ~80% improvement (both with and without stress).
security_mmap_file: 74% improvement without stress and 48% with stress.
magic_write: 54% improvement without stress and 0% with stress.
Improvements in Lost Events:
security_file_open: ~97.65% improvement.
security_mmap_file: ~95.04% improvement.
magic_write: ~99.40% improvement.
By applying filters in the eBPF plane, fewer events are placed in the perf buffer, which significantly reduces eBPF latency. The primary benefit of performing filtering in the kernel is the reduction in the number of events added to the perf buffer, leading to improved overall performance.
3. Other comments
TODO
First Phase:
save_str_to_buf()
, add the argument offset based on its index to facilitate direct access for theload_str_from_buf()
function./etc/net*
and policy2 covers/etc/netconf*
, a lookup for/etc/netconfig
currently only returns policy2 because it is the longest match. However, it should return both policy1 and policy2. A potential solution (work in progress) is to combine equality when such a corner case is detected.Second Phase:
security_file_open
,magic_write
, andsecurity_mmap_file
. Extend support to other events.