From 6d174d0f29b122a7f4bfee22bdc572a6cc242a67 Mon Sep 17 00:00:00 2001 From: Yaniv Agman Date: Wed, 6 Nov 2024 17:24:03 +0200 Subject: [PATCH] refactor: improve clarity of filter matching logic --- pkg/ebpf/c/common/filtering.h | 220 ++++++++++++++++---------------- pkg/ebpf/c/tracee.bpf.c | 2 +- pkg/ebpf/c/types.h | 67 +++++----- pkg/filters/binary.go | 2 +- pkg/filters/bool.go | 2 +- pkg/filters/bool_test.go | 8 +- pkg/filters/processtree.go | 2 +- pkg/filters/processtree_test.go | 10 +- pkg/filters/string.go | 2 +- pkg/filters/string_test.go | 10 +- pkg/filters/uint.go | 2 +- pkg/policy/ebpf.go | 152 +++++++++++----------- pkg/policy/equality.go | 14 +- 13 files changed, 249 insertions(+), 244 deletions(-) diff --git a/pkg/ebpf/c/common/filtering.h b/pkg/ebpf/c/common/filtering.h index f36e82d5d2d0..7ece14b1dc18 100644 --- a/pkg/ebpf/c/common/filtering.h +++ b/pkg/ebpf/c/common/filtering.h @@ -34,36 +34,38 @@ statfunc void *get_filter_map(void *outer_map, u16 version) } statfunc u64 -uint_filter_range_matches(u64 filter_out_scopes, void *filter_map, u64 value, u64 max, u64 min) +uint_filter_range_matches(u64 match_if_key_missing, void *filter_map, u64 value, u64 max, u64 min) { // check equality_filter_matches() for more info - u64 equal_in_scopes = 0; - u64 equality_set_in_scopes = 0; + u64 equals_in_policies = 0; + u64 key_used_in_policies = 0; if (filter_map) { eq_t *equality = bpf_map_lookup_elem(filter_map, &value); if (equality != NULL) { - equal_in_scopes = equality->equal_in_scopes; - equality_set_in_scopes = equality->equality_set_in_scopes; + equals_in_policies = equality->equals_in_policies; + key_used_in_policies = equality->key_used_in_policies; } } if ((max != FILTER_MAX_NOT_SET) && (value >= max)) - return equal_in_scopes; + return equals_in_policies; if ((min != FILTER_MIN_NOT_SET) && (value <= min)) - return equal_in_scopes; + return equals_in_policies; - return equal_in_scopes | (filter_out_scopes & ~equality_set_in_scopes); + return equals_in_policies | (match_if_key_missing & ~key_used_in_policies); } -statfunc u64 binary_filter_matches(u64 filter_out_scopes, void *filter_map, proc_info_t *proc_info) +statfunc u64 binary_filter_matches(u64 match_if_key_missing, + void *filter_map, + proc_info_t *proc_info) { // check equality_filter_matches() for more info - u64 equal_in_scopes = 0; - u64 equality_set_in_scopes = 0; + u64 equals_in_policies = 0; + u64 key_used_in_policies = 0; if (filter_map) { eq_t *equality = bpf_map_lookup_elem(filter_map, proc_info->binary.path); @@ -72,23 +74,23 @@ statfunc u64 binary_filter_matches(u64 filter_out_scopes, void *filter_map, proc equality = bpf_map_lookup_elem(filter_map, &proc_info->binary); } if (equality != NULL) { - equal_in_scopes = equality->equal_in_scopes; - equality_set_in_scopes = equality->equality_set_in_scopes; + equals_in_policies = equality->equals_in_policies; + key_used_in_policies = equality->key_used_in_policies; } } - return equal_in_scopes | (filter_out_scopes & ~equality_set_in_scopes); + return equals_in_policies | (match_if_key_missing & ~key_used_in_policies); } -statfunc u64 equality_filter_matches(u64 filter_out_scopes, void *filter_map, void *key) +statfunc u64 equality_filter_matches(u64 match_if_key_missing, void *filter_map, void *key) { - // check compute_scopes() for initial info + // check match_scope_filters() for initial info // // policy 2: comm=who // policy 3: comm=ping // policy 4: comm!=who // - // filter_out_scopes = 0000 1000, since scope 4 has "not equal" for comm filter + // match_if_key_missing = 0000 1000, since policy 4 has "not equal" for comm filter // filter_map = comm_filter // key = "who" | "ping" // @@ -96,71 +98,74 @@ statfunc u64 equality_filter_matches(u64 filter_out_scopes, void *filter_map, vo // // considering an event from "who" command // - // equal_in_scopes = 0000 0010, since scope 2 has "equal" for comm filter - // equality_set_in_scopes = 0000 1010, since scope 2 and 4 are set for comm filter + // equals_in_policies = 0000 0010, since policy 2 has "equal" for comm filter + // key_used_in_policies = 0000 1010, since policy 2 and 4 are using the key "who" // - // return = equal_in_scopes | (filter_out_scopes & equality_set_in_scopes) + // return = equals_in_policies | (match_if_key_missing & ~key_used_in_policies) // 0000 0010 | // (0000 1000 & 1111 0101) -> 0000 0000 // // 0000 0010 | // 0000 0000 // --------- - // 0000 0010 = (scope 2 matched) + // 0000 0010 = (policy 2 matched) // // considering an event from "ping" command // - // equal_in_scopes = 0000 0100, since scope 3 has "equal" for comm filter - // equality_set_in_scopes = 0000 0100, since scope 3 is set for comm filter + // equals_in_policies = 0000 0100, since policy 3 has "equal" for comm filter + // key_used_in_policies = 0000 0100, since policy 3 is set for comm filter // - // return = equal_in_scopes | (filter_out_scopes & ~equality_set_in_scopes) + // return = equals_in_policies | (match_if_key_missing & ~key_used_in_policies) // 0000 0100 | - // (0000 1000 & 0000 0100) -> 0000 0000 + // (0000 1000 & 1111 1011) -> 0000 1000 // // 0000 0100 | - // 0000 0000 + // 0000 1000 // --------- - // 0000 0100 = (scope 3 matched) + // 0000 1100 = (policy 3 and 4 matched) - u64 equal_in_scopes = 0; - u64 equality_set_in_scopes = 0; + u64 equals_in_policies = 0; + u64 key_used_in_policies = 0; if (filter_map) { eq_t *equality = bpf_map_lookup_elem(filter_map, key); if (equality != NULL) { - equal_in_scopes = equality->equal_in_scopes; - equality_set_in_scopes = equality->equality_set_in_scopes; + equals_in_policies = equality->equals_in_policies; + key_used_in_policies = equality->key_used_in_policies; } } - return equal_in_scopes | (filter_out_scopes & ~equality_set_in_scopes); + // match if: + // 1. key is used and equality matches (equals_in_policies) + // 2. key is NOT used and the default action is to match + return equals_in_policies | (match_if_key_missing & ~key_used_in_policies); } -statfunc u64 bool_filter_matches(u64 filter_out_scopes, bool val) +statfunc u64 bool_filter_matches(u64 match_bitmap, bool bool_value) { - // check compute_scopes() for initial info + // check match_scope_filters() for initial info // // policy 5: container=true // // considering an event from a container // - // filter_out_scopes = 0000 0000 - // val = true - // return = 0000 0000 ^ - // 1111 1111 <- ~0ULL - // --------- - // 1111 1111 + // match_bitmap = 0000 0000 + // val = true + // return = 0000 0000 ^ + // 1111 1111 <- ~0ULL + // --------- + // 1111 1111 // // considering an event not from a container // - // filter_out_scopes = 0000 0000 - // val = false - // return = 0000 0000 ^ - // 0000 0000 - // --------- - // 0000 0000 - - return filter_out_scopes ^ (val ? ~0ULL : 0); + // match_bitmap = 0000 0000 + // val = false + // return = 0000 0000 ^ + // 0000 0000 + // --------- + // 0000 0000 + + return match_bitmap ^ (bool_value ? ~0ULL : 0); } statfunc u64 match_scope_filters(program_data_t *p) @@ -179,33 +184,33 @@ statfunc u64 match_scope_filters(program_data_t *p) // boolean filters (not using versioned filter maps) // - if (policies_cfg->cont_filter_enabled_scopes) { + if (policies_cfg->cont_filter_enabled) { bool is_container = false; u8 state = p->task_info->container_state; if (state == CONTAINER_STARTED || state == CONTAINER_EXISTED) is_container = true; - u64 filter_out_scopes = policies_cfg->cont_filter_out_scopes; - u64 mask = ~policies_cfg->cont_filter_enabled_scopes; + u64 match_bitmap = policies_cfg->cont_filter_match_if_key_missing; + u64 mask = ~policies_cfg->cont_filter_enabled; - // For scopes which has this filter disabled we want to set the matching bits using 'mask' - res &= bool_filter_matches(filter_out_scopes, is_container) | mask; + // For policies that have this filter disabled we want to set the matching bits using 'mask' + res &= bool_filter_matches(match_bitmap, is_container) | mask; } - if (policies_cfg->new_cont_filter_enabled_scopes) { + if (policies_cfg->new_cont_filter_enabled) { bool is_new_container = false; if (p->task_info->container_state == CONTAINER_STARTED) is_new_container = true; - u64 filter_out_scopes = policies_cfg->new_cont_filter_out_scopes; - u64 mask = ~policies_cfg->new_cont_filter_enabled_scopes; + u64 match_bitmap = policies_cfg->new_cont_filter_match_if_key_missing; + u64 mask = ~policies_cfg->new_cont_filter_enabled; - res &= bool_filter_matches(filter_out_scopes, is_new_container) | mask; + res &= bool_filter_matches(match_bitmap, is_new_container) | mask; } - if (policies_cfg->new_pid_filter_enabled_scopes) { - u64 filter_out_scopes = policies_cfg->new_pid_filter_out_scopes; - u64 mask = ~policies_cfg->new_pid_filter_enabled_scopes; + if (policies_cfg->new_pid_filter_enabled) { + u64 match_bitmap = policies_cfg->new_pid_filter_match_if_key_missing; + u64 mask = ~policies_cfg->new_pid_filter_enabled; - res &= bool_filter_matches(filter_out_scopes, proc_info->new_proc) | mask; + res &= bool_filter_matches(match_bitmap, proc_info->new_proc) | mask; } // @@ -215,112 +220,113 @@ statfunc u64 match_scope_filters(program_data_t *p) u16 version = p->event->context.policies_version; void *filter_map = NULL; - if (policies_cfg->pid_filter_enabled_scopes) { - u64 filter_out_scopes = policies_cfg->pid_filter_out_scopes; - u64 mask = ~policies_cfg->pid_filter_enabled_scopes; + if (policies_cfg->pid_filter_enabled) { + u64 match_if_key_missing = policies_cfg->pid_filter_match_if_key_missing; + u64 mask = ~policies_cfg->pid_filter_enabled; u64 max = policies_cfg->pid_max; u64 min = policies_cfg->pid_min; filter_map = get_filter_map(&pid_filter_version, version); // the user might have given us a tid - check for it too - res &= - uint_filter_range_matches(filter_out_scopes, filter_map, context->host_pid, max, min) | - uint_filter_range_matches(filter_out_scopes, filter_map, context->host_tid, max, min) | - mask; + res &= uint_filter_range_matches( + match_if_key_missing, filter_map, context->host_pid, max, min) | + uint_filter_range_matches( + match_if_key_missing, filter_map, context->host_tid, max, min) | + mask; } - if (policies_cfg->uid_filter_enabled_scopes) { + if (policies_cfg->uid_filter_enabled) { context->uid = bpf_get_current_uid_gid(); - u64 filter_out_scopes = policies_cfg->uid_filter_out_scopes; - u64 mask = ~policies_cfg->uid_filter_enabled_scopes; + u64 match_if_key_missing = policies_cfg->uid_filter_match_if_key_missing; + u64 mask = ~policies_cfg->uid_filter_enabled; u64 max = policies_cfg->uid_max; u64 min = policies_cfg->uid_min; filter_map = get_filter_map(&uid_filter_version, version); - res &= - uint_filter_range_matches(filter_out_scopes, filter_map, context->uid, max, min) | mask; + res &= uint_filter_range_matches(match_if_key_missing, filter_map, context->uid, max, min) | + mask; } - if (policies_cfg->mnt_ns_filter_enabled_scopes) { + if (policies_cfg->mnt_ns_filter_enabled) { context->mnt_id = get_task_mnt_ns_id(p->event->task); - u64 filter_out_scopes = policies_cfg->mnt_ns_filter_out_scopes; - u64 mask = ~policies_cfg->mnt_ns_filter_enabled_scopes; + u64 match_if_key_missing = policies_cfg->mnt_ns_filter_match_if_key_missing; + u64 mask = ~policies_cfg->mnt_ns_filter_enabled; filter_map = get_filter_map(&mnt_ns_filter_version, version); - res &= equality_filter_matches(filter_out_scopes, filter_map, &context->mnt_id) | mask; + res &= equality_filter_matches(match_if_key_missing, filter_map, &context->mnt_id) | mask; } - if (policies_cfg->pid_ns_filter_enabled_scopes) { + if (policies_cfg->pid_ns_filter_enabled) { context->pid_id = get_task_pid_ns_id(p->event->task); - u64 filter_out_scopes = policies_cfg->pid_ns_filter_out_scopes; - u64 mask = ~policies_cfg->pid_ns_filter_enabled_scopes; + u64 match_if_key_missing = policies_cfg->pid_ns_filter_match_if_key_missing; + u64 mask = ~policies_cfg->pid_ns_filter_enabled; filter_map = get_filter_map(&pid_ns_filter_version, version); - res &= equality_filter_matches(filter_out_scopes, filter_map, &context->pid_id) | mask; + res &= equality_filter_matches(match_if_key_missing, filter_map, &context->pid_id) | mask; } - if (policies_cfg->uts_ns_filter_enabled_scopes) { + if (policies_cfg->uts_ns_filter_enabled) { char *uts_name = get_task_uts_name(p->event->task); if (uts_name) bpf_probe_read_kernel_str(&context->uts_name, TASK_COMM_LEN, uts_name); - u64 filter_out_scopes = policies_cfg->uts_ns_filter_out_scopes; - u64 mask = ~policies_cfg->uts_ns_filter_enabled_scopes; + u64 match_if_key_missing = policies_cfg->uts_ns_filter_match_if_key_missing; + u64 mask = ~policies_cfg->uts_ns_filter_enabled; filter_map = get_filter_map(&uts_ns_filter_version, version); - res &= equality_filter_matches(filter_out_scopes, filter_map, &context->uts_name) | mask; + res &= equality_filter_matches(match_if_key_missing, filter_map, &context->uts_name) | mask; } - if (policies_cfg->comm_filter_enabled_scopes) { + if (policies_cfg->comm_filter_enabled) { bpf_get_current_comm(&context->comm, sizeof(context->comm)); - u64 filter_out_scopes = policies_cfg->comm_filter_out_scopes; - u64 mask = ~policies_cfg->comm_filter_enabled_scopes; + u64 match_if_key_missing = policies_cfg->comm_filter_match_if_key_missing; + u64 mask = ~policies_cfg->comm_filter_enabled; filter_map = get_filter_map(&comm_filter_version, version); - res &= equality_filter_matches(filter_out_scopes, filter_map, &context->comm) | mask; + res &= equality_filter_matches(match_if_key_missing, filter_map, &context->comm) | mask; } - if (policies_cfg->cgroup_id_filter_enabled_scopes) { + if (policies_cfg->cgroup_id_filter_enabled) { u32 cgroup_id_lsb = context->cgroup_id; - u64 filter_out_scopes = policies_cfg->cgroup_id_filter_out_scopes; - u64 mask = ~policies_cfg->cgroup_id_filter_enabled_scopes; + u64 match_if_key_missing = policies_cfg->cgroup_id_filter_match_if_key_missing; + u64 mask = ~policies_cfg->cgroup_id_filter_enabled; filter_map = get_filter_map(&cgroup_id_filter_version, version); - res &= equality_filter_matches(filter_out_scopes, filter_map, &cgroup_id_lsb) | mask; + res &= equality_filter_matches(match_if_key_missing, filter_map, &cgroup_id_lsb) | mask; } - if (policies_cfg->proc_tree_filter_enabled_scopes) { - u64 filter_out_scopes = policies_cfg->proc_tree_filter_out_scopes; - u64 mask = ~policies_cfg->proc_tree_filter_enabled_scopes; + if (policies_cfg->proc_tree_filter_enabled) { + u64 match_if_key_missing = policies_cfg->proc_tree_filter_match_if_key_missing; + u64 mask = ~policies_cfg->proc_tree_filter_enabled; filter_map = get_filter_map(&process_tree_map_version, version); - res &= equality_filter_matches(filter_out_scopes, filter_map, &context->host_pid) | mask; + res &= equality_filter_matches(match_if_key_missing, filter_map, &context->host_pid) | mask; } - if (policies_cfg->bin_path_filter_enabled_scopes) { - u64 filter_out_scopes = policies_cfg->bin_path_filter_out_scopes; - u64 mask = ~policies_cfg->bin_path_filter_enabled_scopes; + if (policies_cfg->bin_path_filter_enabled) { + u64 match_if_key_missing = policies_cfg->bin_path_filter_match_if_key_missing; + u64 mask = ~policies_cfg->bin_path_filter_enabled; filter_map = get_filter_map(&binary_filter_version, version); - res &= binary_filter_matches(filter_out_scopes, filter_map, proc_info) | mask; + res &= binary_filter_matches(match_if_key_missing, filter_map, proc_info) | mask; } // // follow filter // - if (policies_cfg->follow_filter_enabled_scopes) { + if (policies_cfg->follow_filter_enabled) { // trace this proc anyway if follow was set by a scope - res |= proc_info->follow_in_scopes & policies_cfg->follow_filter_enabled_scopes; + res |= proc_info->follow_in_scopes & policies_cfg->follow_filter_enabled; } - // Make sure only enabled scopes are set in the bitmask (other bits are invalid) - return res & policies_cfg->enabled_scopes; + // Make sure only enabled policies are set in the bitmap (other bits are invalid) + return res & policies_cfg->enabled_policies; } statfunc bool evaluate_scope_filters(program_data_t *p) { - u64 matched_scopes = match_scope_filters(p); - p->event->context.matched_policies &= matched_scopes; + u64 matched_policies = match_scope_filters(p); + p->event->context.matched_policies &= matched_policies; return p->event->context.matched_policies != 0; } diff --git a/pkg/ebpf/c/tracee.bpf.c b/pkg/ebpf/c/tracee.bpf.c index 0e480035f656..5dc6b2f0fa9e 100644 --- a/pkg/ebpf/c/tracee.bpf.c +++ b/pkg/ebpf/c/tracee.bpf.c @@ -640,7 +640,7 @@ int tracepoint__sched__sched_process_fork(struct bpf_raw_tracepoint_args *ctx) policies_config_t *policies_cfg = &p.event->policies_config; - if (policies_cfg->proc_tree_filter_enabled_scopes) { + if (policies_cfg->proc_tree_filter_enabled) { u16 version = p.event->context.policies_version; // Give the compiler a hint about the map type, otherwise libbpf will complain // about missing type information. i.e.: "can't determine value size for type". diff --git a/pkg/ebpf/c/types.h b/pkg/ebpf/c/types.h index b6822b92add6..186d91f5e2db 100644 --- a/pkg/ebpf/c/types.h +++ b/pkg/ebpf/c/types.h @@ -294,43 +294,42 @@ typedef struct ksym_name { } ksym_name_t; typedef struct equality { - // bitmask with scopes on which a equal '=' filter is set - // its bit value will depend on the filter's equality precedence order - u64 equal_in_scopes; - // bitmask with scopes on which a filter equality is set - u64 equality_set_in_scopes; + // bitmap indicating which policies have a filter that uses the '=' operator (0 means '!=') + u64 equals_in_policies; + // bitmap indicating which policies have a filter that utilize the provided key + u64 key_used_in_policies; } eq_t; typedef struct policies_config { - // enabled scopes bitmask per filter - u64 uid_filter_enabled_scopes; - u64 pid_filter_enabled_scopes; - u64 mnt_ns_filter_enabled_scopes; - u64 pid_ns_filter_enabled_scopes; - u64 uts_ns_filter_enabled_scopes; - u64 comm_filter_enabled_scopes; - u64 cgroup_id_filter_enabled_scopes; - u64 cont_filter_enabled_scopes; - u64 new_cont_filter_enabled_scopes; - u64 new_pid_filter_enabled_scopes; - u64 proc_tree_filter_enabled_scopes; - u64 bin_path_filter_enabled_scopes; - u64 follow_filter_enabled_scopes; - // filter_out bitmask per filter - u64 uid_filter_out_scopes; - u64 pid_filter_out_scopes; - u64 mnt_ns_filter_out_scopes; - u64 pid_ns_filter_out_scopes; - u64 uts_ns_filter_out_scopes; - u64 comm_filter_out_scopes; - u64 cgroup_id_filter_out_scopes; - u64 cont_filter_out_scopes; - u64 new_cont_filter_out_scopes; - u64 new_pid_filter_out_scopes; - u64 proc_tree_filter_out_scopes; - u64 bin_path_filter_out_scopes; - // bitmask with scopes that have at least one filter enabled - u64 enabled_scopes; + // bitmap indicating which policies have the filter enabled + u64 uid_filter_enabled; + u64 pid_filter_enabled; + u64 mnt_ns_filter_enabled; + u64 pid_ns_filter_enabled; + u64 uts_ns_filter_enabled; + u64 comm_filter_enabled; + u64 cgroup_id_filter_enabled; + u64 cont_filter_enabled; + u64 new_cont_filter_enabled; + u64 new_pid_filter_enabled; + u64 proc_tree_filter_enabled; + u64 bin_path_filter_enabled; + u64 follow_filter_enabled; + // bitmap indicating whether to match a rule if the key is missing from its filter map + u64 uid_filter_match_if_key_missing; + u64 pid_filter_match_if_key_missing; + u64 mnt_ns_filter_match_if_key_missing; + u64 pid_ns_filter_match_if_key_missing; + u64 uts_ns_filter_match_if_key_missing; + u64 comm_filter_match_if_key_missing; + u64 cgroup_id_filter_match_if_key_missing; + u64 cont_filter_match_if_key_missing; + u64 new_cont_filter_match_if_key_missing; + u64 new_pid_filter_match_if_key_missing; + u64 proc_tree_filter_match_if_key_missing; + u64 bin_path_filter_match_if_key_missing; + // bitmap with policies that have at least one filter enabled + u64 enabled_policies; // global min max u64 uid_max; u64 uid_min; diff --git a/pkg/filters/binary.go b/pkg/filters/binary.go index 7886dc8dc75b..79ac768052f5 100644 --- a/pkg/filters/binary.go +++ b/pkg/filters/binary.go @@ -130,7 +130,7 @@ func (f *BinaryFilter) Enabled() bool { return f.enabled } -func (f *BinaryFilter) FilterOut() bool { +func (f *BinaryFilter) MatchIfKeyMissing() bool { if len(f.equal) > 0 && len(f.notEqual) == 0 { return false } diff --git a/pkg/filters/bool.go b/pkg/filters/bool.go index 9952724b2b8b..452795c4065b 100644 --- a/pkg/filters/bool.go +++ b/pkg/filters/bool.go @@ -144,7 +144,7 @@ func (f *BoolFilter) Value() bool { return f.trueEnabled } -func (f *BoolFilter) FilterOut() bool { +func (f *BoolFilter) MatchIfKeyMissing() bool { return !f.Value() } diff --git a/pkg/filters/bool_test.go b/pkg/filters/bool_test.go index f2e294b7f344..ba04e0731cf7 100644 --- a/pkg/filters/bool_test.go +++ b/pkg/filters/bool_test.go @@ -91,21 +91,21 @@ func TestBoolFilterParse(t *testing.T) { } } -func TestBoolFilterFilterOut(t *testing.T) { +func TestBoolFilterMatchIfKeyMissing(t *testing.T) { t.Parallel() bf1 := NewBoolFilter() bf1.Parse("=true") - assert.False(t, bf1.FilterOut()) + assert.False(t, bf1.MatchIfKeyMissing()) bf3 := NewBoolFilter() bf3.Parse("=true") bf3.Parse("=false") - assert.False(t, bf3.FilterOut()) + assert.False(t, bf3.MatchIfKeyMissing()) bf2 := NewBoolFilter() bf2.Parse("=false") - assert.True(t, bf2.FilterOut()) + assert.True(t, bf2.MatchIfKeyMissing()) } func TestBoolFilterClone(t *testing.T) { diff --git a/pkg/filters/processtree.go b/pkg/filters/processtree.go index 03c612445a04..bd6f3d453ee4 100644 --- a/pkg/filters/processtree.go +++ b/pkg/filters/processtree.go @@ -80,7 +80,7 @@ func (f *ProcessTreeFilter) Parse(operatorAndValues string) error { return nil } -func (f *ProcessTreeFilter) FilterOut() bool { +func (f *ProcessTreeFilter) MatchIfKeyMissing() bool { if len(f.equal) > 0 && len(f.notEqual) == 0 { return false } diff --git a/pkg/filters/processtree_test.go b/pkg/filters/processtree_test.go index fdfd8e06c729..ce3367778b0b 100644 --- a/pkg/filters/processtree_test.go +++ b/pkg/filters/processtree_test.go @@ -113,32 +113,32 @@ func TestProcessTreeFilterParse(t *testing.T) { } } -func TestProcessTreeFilterFilterOut(t *testing.T) { +func TestProcessTreeFilterMatchIfKeyMissing(t *testing.T) { t.Parallel() ptf1 := NewProcessTreeFilter() ptf1.Parse("=0") ptf1.Parse("=1") ptf1.Parse("=2") - assert.False(t, ptf1.FilterOut()) + assert.False(t, ptf1.MatchIfKeyMissing()) ptf2 := NewProcessTreeFilter() ptf2.Parse("=0") ptf2.Parse("!=1") ptf2.Parse("=2") - assert.True(t, ptf2.FilterOut()) + assert.True(t, ptf2.MatchIfKeyMissing()) ptf3 := NewProcessTreeFilter() ptf3.Parse("!=0") ptf3.Parse("=1") ptf3.Parse("!=2") - assert.True(t, ptf3.FilterOut()) + assert.True(t, ptf3.MatchIfKeyMissing()) ptf4 := NewProcessTreeFilter() ptf4.Parse("!=0") ptf4.Parse("!=1") ptf4.Parse("!=2") - assert.True(t, ptf4.FilterOut()) + assert.True(t, ptf4.MatchIfKeyMissing()) } func TestProcessTreeFilterClone(t *testing.T) { diff --git a/pkg/filters/string.go b/pkg/filters/string.go index 470540a75a5e..71388caea281 100644 --- a/pkg/filters/string.go +++ b/pkg/filters/string.go @@ -230,7 +230,7 @@ func (f *StringFilter) NotEqual() []string { return res } -func (f *StringFilter) FilterOut() bool { +func (f *StringFilter) MatchIfKeyMissing() bool { if len(f.Equal()) > 0 && len(f.NotEqual()) == 0 { return false } diff --git a/pkg/filters/string_test.go b/pkg/filters/string_test.go index 35863492b14d..fcfd6c0282bc 100644 --- a/pkg/filters/string_test.go +++ b/pkg/filters/string_test.go @@ -151,7 +151,7 @@ func TestStringFilterParse(t *testing.T) { } } -func TestStringFilterFilterOut(t *testing.T) { +func TestStringFilterMatchIfKeyMissing(t *testing.T) { t.Parallel() sf1 := NewStringFilter(nil) @@ -163,7 +163,7 @@ func TestStringFilterFilterOut(t *testing.T) { err = sf1.Parse("=here") require.NoError(t, err) - assert.False(t, sf1.FilterOut()) + assert.False(t, sf1.MatchIfKeyMissing()) sf2 := NewStringFilter(nil) @@ -174,7 +174,7 @@ func TestStringFilterFilterOut(t *testing.T) { err = sf2.Parse("=here") require.NoError(t, err) - assert.True(t, sf2.FilterOut()) + assert.True(t, sf2.MatchIfKeyMissing()) sf3 := NewStringFilter(nil) @@ -185,7 +185,7 @@ func TestStringFilterFilterOut(t *testing.T) { err = sf3.Parse("!=here") require.NoError(t, err) - assert.True(t, sf3.FilterOut()) + assert.True(t, sf3.MatchIfKeyMissing()) sf4 := NewStringFilter(nil) @@ -196,7 +196,7 @@ func TestStringFilterFilterOut(t *testing.T) { err = sf4.Parse("!=here") require.NoError(t, err) - assert.True(t, sf4.FilterOut()) + assert.True(t, sf4.MatchIfKeyMissing()) } func TestStringFilterClone(t *testing.T) { diff --git a/pkg/filters/uint.go b/pkg/filters/uint.go index b9a785046782..f5b3b2138220 100644 --- a/pkg/filters/uint.go +++ b/pkg/filters/uint.go @@ -212,7 +212,7 @@ func (f *UIntFilter[T]) Parse(operatorAndValues string) error { return nil } -func (f *UIntFilter[T]) FilterOut() bool { +func (f *UIntFilter[T]) MatchIfKeyMissing() bool { if len(f.equal) > 0 && len(f.notEqual) == 0 && f.min == MinNotSetUInt && f.max == MaxNotSetUInt { return false } diff --git a/pkg/policy/ebpf.go b/pkg/policy/ebpf.go index a732cb6099d2..1b76f65cfdc4 100644 --- a/pkg/policy/ebpf.go +++ b/pkg/policy/ebpf.go @@ -218,8 +218,8 @@ func (ps *policies) updateUIntFilterBPF(uintEqualities map[uint64]equality, inne eqVal := make([]byte, equalityValueSize) valuePointer := unsafe.Pointer(&eqVal[0]) - binary.LittleEndian.PutUint64(eqVal[0:8], v.equalInPolicies) - binary.LittleEndian.PutUint64(eqVal[8:16], v.equalitySetInPolicies) + binary.LittleEndian.PutUint64(eqVal[0:8], v.equalsInPolicies) + binary.LittleEndian.PutUint64(eqVal[8:16], v.keyUsedInPolicies) bpfMap, ok := ps.bpfInnerMaps[innerMapName] if !ok { @@ -251,8 +251,8 @@ func (ps *policies) updateStringFilterBPF(strEqualities map[string]equality, inn eqVal := make([]byte, equalityValueSize) valuePointer := unsafe.Pointer(&eqVal[0]) - binary.LittleEndian.PutUint64(eqVal[0:8], v.equalInPolicies) - binary.LittleEndian.PutUint64(eqVal[8:16], v.equalitySetInPolicies) + binary.LittleEndian.PutUint64(eqVal[0:8], v.equalsInPolicies) + binary.LittleEndian.PutUint64(eqVal[8:16], v.keyUsedInPolicies) bpfMap, ok := ps.bpfInnerMaps[innerMapName] if !ok { @@ -278,8 +278,8 @@ func (ps *policies) updateProcTreeFilterBPF(procTreeEqualities map[uint32]equali eqVal := make([]byte, equalityValueSize) valuePointer := unsafe.Pointer(&eqVal[0]) - binary.LittleEndian.PutUint64(eqVal[0:8], v.equalInPolicies) - binary.LittleEndian.PutUint64(eqVal[8:16], v.equalitySetInPolicies) + binary.LittleEndian.PutUint64(eqVal[0:8], v.equalsInPolicies) + binary.LittleEndian.PutUint64(eqVal[8:16], v.keyUsedInPolicies) bpfMap, ok := ps.bpfInnerMaps[innerMapName] if !ok { @@ -383,8 +383,8 @@ func (ps *policies) updateBinaryFilterBPF(binEqualities map[filters.NSBinary]equ eqVal := make([]byte, equalityValueSize) valuePointer := unsafe.Pointer(&eqVal[0]) - binary.LittleEndian.PutUint64(eqVal[0:8], v.equalInPolicies) - binary.LittleEndian.PutUint64(eqVal[8:16], v.equalitySetInPolicies) + binary.LittleEndian.PutUint64(eqVal[0:8], v.equalsInPolicies) + binary.LittleEndian.PutUint64(eqVal[8:16], v.keyUsedInPolicies) bpfMap, ok := ps.bpfInnerMaps[innerMapName] if !ok { @@ -571,34 +571,34 @@ func (ps *policies) createNewPoliciesConfigMap(bpfModule *bpf.Module) error { // Order of fields is important, as it is used as a value for // the PoliciesConfigMap BPF map. type PoliciesConfig struct { - UIDFilterEnabledScopes uint64 - PIDFilterEnabledScopes uint64 - MntNsFilterEnabledScopes uint64 - PidNsFilterEnabledScopes uint64 - UtsNsFilterEnabledScopes uint64 - CommFilterEnabledScopes uint64 - CgroupIdFilterEnabledScopes uint64 - ContFilterEnabledScopes uint64 - NewContFilterEnabledScopes uint64 - NewPidFilterEnabledScopes uint64 - ProcTreeFilterEnabledScopes uint64 - BinPathFilterEnabledScopes uint64 - FollowFilterEnabledScopes uint64 - - UIDFilterOutScopes uint64 - PIDFilterOutScopes uint64 - MntNsFilterOutScopes uint64 - PidNsFilterOutScopes uint64 - UtsNsFilterOutScopes uint64 - CommFilterOutScopes uint64 - CgroupIdFilterOutScopes uint64 - ContFilterOutScopes uint64 - NewContFilterOutScopes uint64 - NewPidFilterOutScopes uint64 - ProcTreeFilterOutScopes uint64 - BinPathFilterOutScopes uint64 - - EnabledScopes uint64 + UIDFilterEnabled uint64 + PIDFilterEnabled uint64 + MntNsFilterEnabled uint64 + PidNsFilterEnabled uint64 + UtsNsFilterEnabled uint64 + CommFilterEnabled uint64 + CgroupIdFilterEnabled uint64 + ContFilterEnabled uint64 + NewContFilterEnabled uint64 + NewPidFilterEnabled uint64 + ProcTreeFilterEnabled uint64 + BinPathFilterEnabled uint64 + FollowFilterEnabled uint64 + + UIDFilterMatchIfKeyMissing uint64 + PIDFilterMatchIfKeyMissing uint64 + MntNsFilterMatchIfKeyMissing uint64 + PidNsFilterMatchIfKeyMissing uint64 + UtsNsFilterMatchIfKeyMissing uint64 + CommFilterMatchIfKeyMissing uint64 + CgroupIdFilterMatchIfKeyMissing uint64 + ContFilterMatchIfKeyMissing uint64 + NewContFilterMatchIfKeyMissing uint64 + NewPidFilterMatchIfKeyMissing uint64 + ProcTreeFilterMatchIfKeyMissing uint64 + BinPathFilterMatchIfKeyMissing uint64 + + EnabledPolicies uint64 UidMax uint64 UidMin uint64 @@ -626,86 +626,86 @@ func (ps *policies) computePoliciesConfig() *PoliciesConfig { for _, p := range ps.allFromMap() { offset := p.ID - // filter enabled policies bitmap + // bitmap indicating which policies have filters enabled if p.UIDFilter.Enabled() { - cfg.UIDFilterEnabledScopes |= 1 << offset + cfg.UIDFilterEnabled |= 1 << offset } if p.PIDFilter.Enabled() { - cfg.PIDFilterEnabledScopes |= 1 << offset + cfg.PIDFilterEnabled |= 1 << offset } if p.MntNSFilter.Enabled() { - cfg.MntNsFilterEnabledScopes |= 1 << offset + cfg.MntNsFilterEnabled |= 1 << offset } if p.PidNSFilter.Enabled() { - cfg.PidNsFilterEnabledScopes |= 1 << offset + cfg.PidNsFilterEnabled |= 1 << offset } if p.UTSFilter.Enabled() { - cfg.UtsNsFilterEnabledScopes |= 1 << offset + cfg.UtsNsFilterEnabled |= 1 << offset } if p.CommFilter.Enabled() { - cfg.CommFilterEnabledScopes |= 1 << offset + cfg.CommFilterEnabled |= 1 << offset } if p.ContIDFilter.Enabled() { - cfg.CgroupIdFilterEnabledScopes |= 1 << offset + cfg.CgroupIdFilterEnabled |= 1 << offset } if p.ContFilter.Enabled() { - cfg.ContFilterEnabledScopes |= 1 << offset + cfg.ContFilterEnabled |= 1 << offset } if p.NewContFilter.Enabled() { - cfg.NewContFilterEnabledScopes |= 1 << offset + cfg.NewContFilterEnabled |= 1 << offset } if p.NewPidFilter.Enabled() { - cfg.NewPidFilterEnabledScopes |= 1 << offset + cfg.NewPidFilterEnabled |= 1 << offset } if p.ProcessTreeFilter.Enabled() { - cfg.ProcTreeFilterEnabledScopes |= 1 << offset + cfg.ProcTreeFilterEnabled |= 1 << offset } if p.BinaryFilter.Enabled() { - cfg.BinPathFilterEnabledScopes |= 1 << offset + cfg.BinPathFilterEnabled |= 1 << offset } if p.Follow { - cfg.FollowFilterEnabledScopes |= 1 << offset + cfg.FollowFilterEnabled |= 1 << offset } - // filter out scopes bitmap - if p.UIDFilter.FilterOut() { - cfg.UIDFilterOutScopes |= 1 << offset + // bitmap indicating whether to match a rule if the key is missing from its filter map + if p.UIDFilter.MatchIfKeyMissing() { + cfg.UIDFilterMatchIfKeyMissing |= 1 << offset } - if p.PIDFilter.FilterOut() { - cfg.PIDFilterOutScopes |= 1 << offset + if p.PIDFilter.MatchIfKeyMissing() { + cfg.PIDFilterMatchIfKeyMissing |= 1 << offset } - if p.MntNSFilter.FilterOut() { - cfg.MntNsFilterOutScopes |= 1 << offset + if p.MntNSFilter.MatchIfKeyMissing() { + cfg.MntNsFilterMatchIfKeyMissing |= 1 << offset } - if p.PidNSFilter.FilterOut() { - cfg.PidNsFilterOutScopes |= 1 << offset + if p.PidNSFilter.MatchIfKeyMissing() { + cfg.PidNsFilterMatchIfKeyMissing |= 1 << offset } - if p.UTSFilter.FilterOut() { - cfg.UtsNsFilterOutScopes |= 1 << offset + if p.UTSFilter.MatchIfKeyMissing() { + cfg.UtsNsFilterMatchIfKeyMissing |= 1 << offset } - if p.CommFilter.FilterOut() { - cfg.CommFilterOutScopes |= 1 << offset + if p.CommFilter.MatchIfKeyMissing() { + cfg.CommFilterMatchIfKeyMissing |= 1 << offset } - if p.ContIDFilter.FilterOut() { - cfg.CgroupIdFilterOutScopes |= 1 << offset + if p.ContIDFilter.MatchIfKeyMissing() { + cfg.CgroupIdFilterMatchIfKeyMissing |= 1 << offset } - if p.ContFilter.FilterOut() { - cfg.ContFilterOutScopes |= 1 << offset + if p.ContFilter.MatchIfKeyMissing() { + cfg.ContFilterMatchIfKeyMissing |= 1 << offset } - if p.NewContFilter.FilterOut() { - cfg.NewContFilterOutScopes |= 1 << offset + if p.NewContFilter.MatchIfKeyMissing() { + cfg.NewContFilterMatchIfKeyMissing |= 1 << offset } - if p.NewPidFilter.FilterOut() { - cfg.NewPidFilterOutScopes |= 1 << offset + if p.NewPidFilter.MatchIfKeyMissing() { + cfg.NewPidFilterMatchIfKeyMissing |= 1 << offset } - if p.ProcessTreeFilter.FilterOut() { - cfg.ProcTreeFilterOutScopes |= 1 << offset + if p.ProcessTreeFilter.MatchIfKeyMissing() { + cfg.ProcTreeFilterMatchIfKeyMissing |= 1 << offset } - if p.BinaryFilter.FilterOut() { - cfg.BinPathFilterOutScopes |= 1 << offset + if p.BinaryFilter.MatchIfKeyMissing() { + cfg.BinPathFilterMatchIfKeyMissing |= 1 << offset } - cfg.EnabledScopes |= 1 << offset + cfg.EnabledPolicies |= 1 << offset } cfg.UidMax = ps.uidFilterMax diff --git a/pkg/policy/equality.go b/pkg/policy/equality.go index ffd2d1d17929..ac2efd1c3281 100644 --- a/pkg/policy/equality.go +++ b/pkg/policy/equality.go @@ -10,12 +10,12 @@ import ( // equality mirrors the C struct equality (eq_t). // Check it for more info. type equality struct { - equalInPolicies uint64 - equalitySetInPolicies uint64 + equalsInPolicies uint64 + keyUsedInPolicies uint64 } const ( - // 8 bytes for equalInPolicies and 8 bytes for equalitySetInPolicies + // 8 bytes for equalsInPolicies and 8 bytes for keyUsedInPolicies equalityValueSize = 16 ) @@ -45,15 +45,15 @@ type equalityUpdater func(eq *equality, policyID uint) // notEqualUpdate updates the equality as not equal with the given policyID. func notEqualUpdate(eq *equality, policyID uint) { // NotEqual == 0, so clear n bitmap bit - utils.ClearBit(&eq.equalInPolicies, policyID) - utils.SetBit(&eq.equalitySetInPolicies, policyID) + utils.ClearBit(&eq.equalsInPolicies, policyID) + utils.SetBit(&eq.keyUsedInPolicies, policyID) } // equalUpdate updates the equality as equal with the given policyID. func equalUpdate(eq *equality, policyID uint) { // Equal == 1, so set n bitmap bit - utils.SetBit(&eq.equalInPolicies, policyID) - utils.SetBit(&eq.equalitySetInPolicies, policyID) + utils.SetBit(&eq.equalsInPolicies, policyID) + utils.SetBit(&eq.keyUsedInPolicies, policyID) } // updateEqualities updates the equalities map with the given filter equalities