diff --git a/bpf/Makefile b/bpf/Makefile index 2e1ce7f86a7..b8947f5d262 100644 --- a/bpf/Makefile +++ b/bpf/Makefile @@ -20,6 +20,11 @@ PROCESS = bpf_execve_event.o bpf_execve_event_v53.o bpf_fork.o bpf_exit.o bpf_ge bpf_generic_tracepoint_v61.o \ bpf_multi_kprobe_v61.o bpf_multi_retkprobe_v61.o \ bpf_generic_uprobe_v61.o \ + bpf_execve_event_v511.o \ + bpf_generic_kprobe_v511.o bpf_generic_retkprobe_v511.o \ + bpf_generic_tracepoint_v511.o \ + bpf_multi_kprobe_v511.o bpf_multi_retkprobe_v511.o \ + bpf_generic_uprobe_v511.o \ bpf_loader.o \ bpf_killer.o bpf_multi_killer.o bpf_fmodret_killer.o @@ -66,6 +71,7 @@ endef # Generic build targets for each sub-dir $(eval $(call DEFINE_VARIANT,v53)) +$(eval $(call DEFINE_VARIANT,v511)) $(eval $(call DEFINE_VARIANT,v61)) # ALIGNCHECKER @@ -117,13 +123,22 @@ $(DEPSDIR)%_v53.d: $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -MM -MP -MT $(patsubst $(DEPSDIR)%.d, $(OBJSDIR)%.ll, $@) $< > $@ objs/bpf_multi_kprobe_v61.ll objs/bpf_multi_retkprobe_v61.ll: - $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__V61_BPF_PROG -D__MULTI_KPROBE -c $< -o $@ + $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -D__V61_BPF_PROG -D__MULTI_KPROBE -c $< -o $@ objs/%_v61.ll: - $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__V61_BPF_PROG -c $< -o $@ + $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -D__V61_BPF_PROG -c $< -o $@ $(DEPSDIR)%_v61.d: - $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__V61_BPF_PROG -MM -MP -MT $(patsubst $(DEPSDIR)%.d, $(OBJSDIR)%.ll, $@) $< > $@ + $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -D__V61_BPF_PROG -MM -MP -MT $(patsubst $(DEPSDIR)%.d, $(OBJSDIR)%.ll, $@) $< > $@ + +objs/bpf_multi_kprobe_v511.ll objs/bpf_multi_retkprobe_v511.ll: + $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -D__MULTI_KPROBE -c $< -o $@ + +objs/%_v511.ll: + $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -c $< -o $@ + +$(DEPSDIR)%_v511.d: + $(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -MM -MP -MT $(patsubst $(DEPSDIR)%.d, $(OBJSDIR)%.ll, $@) $< > $@ # BPFTESTDIR objs/%.ll: $(BPFTESTDIR)%.c diff --git a/bpf/process/string_maps.h b/bpf/process/string_maps.h index a27d6eff0de..a91cc7e4e59 100644 --- a/bpf/process/string_maps.h +++ b/bpf/process/string_maps.h @@ -32,19 +32,35 @@ * up are equally padded to the smallest key size that can accommodate them, and then * looked up in the related map. * - * The chosen key sizes are 25, 49, 73, 97, 121, 145 (6 maps). + * The chosen key sizes are 25, 49, 73, 97, 121, 145, 258, 514, 1026, 2050, 4098 (11 maps). + * The first 6 are sized for common uses and to minimise the hashing of empty bytes. The + * following 5 maps notionally double in size, with lengths equal to 2^k + 2. On kernels + * <5.11, the last four maps are replaced with a single map with key size 512. This is due + * to key size limitations on kernels <5.11. * * In order to distinguish between character buffers that end in 0s and similar buffers * that are padded with 0s, each string will be prefixed by its length stored in a - * single byte. + * single byte (for first 6 maps) or as a little endian u16 (latter maps). */ #define STRING_MAPS_KEY_INC_SIZE 24 -#define STRING_MAPS_SIZE_0 1 * STRING_MAPS_KEY_INC_SIZE + 1 -#define STRING_MAPS_SIZE_1 2 * STRING_MAPS_KEY_INC_SIZE + 1 -#define STRING_MAPS_SIZE_2 3 * STRING_MAPS_KEY_INC_SIZE + 1 -#define STRING_MAPS_SIZE_3 4 * STRING_MAPS_KEY_INC_SIZE + 1 -#define STRING_MAPS_SIZE_4 5 * STRING_MAPS_KEY_INC_SIZE + 1 -#define STRING_MAPS_SIZE_5 6 * STRING_MAPS_KEY_INC_SIZE + 1 +#define STRING_MAPS_SIZE_0 (1 * STRING_MAPS_KEY_INC_SIZE + 1) +#define STRING_MAPS_SIZE_1 (2 * STRING_MAPS_KEY_INC_SIZE + 1) +#define STRING_MAPS_SIZE_2 (3 * STRING_MAPS_KEY_INC_SIZE + 1) +#define STRING_MAPS_SIZE_3 (4 * STRING_MAPS_KEY_INC_SIZE + 1) +#define STRING_MAPS_SIZE_4 (5 * STRING_MAPS_KEY_INC_SIZE + 1) +#define STRING_MAPS_SIZE_5 (6 * STRING_MAPS_KEY_INC_SIZE + 1) +#define STRING_MAPS_SIZE_6 (256 + 2) +#ifdef __LARGE_MAP_KEYS +#define STRING_MAPS_SIZE_7 (512 + 2) +#define STRING_MAPS_SIZE_8 (1024 + 2) +#define STRING_MAPS_SIZE_9 (2048 + 2) +#define STRING_MAPS_SIZE_10 (4096 + 2) +#else +#define STRING_MAPS_SIZE_7 (512) +#endif +#define STRING_MAPS_HEAP_SIZE 16384 +#define STRING_MAPS_HEAP_MASK (8192 - 1) +#define STRING_MAPS_COPY_MASK 4095 struct { __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); @@ -124,18 +140,85 @@ struct { }); } string_maps_5 SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); + __uint(max_entries, STRING_MAPS_OUTER_MAX_ENTRIES); + __uint(key_size, sizeof(__u32)); + __array( + values, struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u8[STRING_MAPS_SIZE_6]); + __type(value, __u8); + }); +} string_maps_6 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); + __uint(max_entries, STRING_MAPS_OUTER_MAX_ENTRIES); + __uint(key_size, sizeof(__u32)); + __array( + values, struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u8[STRING_MAPS_SIZE_7]); + __type(value, __u8); + }); +} string_maps_7 SEC(".maps"); + +#ifdef __LARGE_MAP_KEYS +struct { + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); + __uint(max_entries, STRING_MAPS_OUTER_MAX_ENTRIES); + __uint(key_size, sizeof(__u32)); + __array( + values, struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u8[STRING_MAPS_SIZE_8]); + __type(value, __u8); + }); +} string_maps_8 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); + __uint(max_entries, STRING_MAPS_OUTER_MAX_ENTRIES); + __uint(key_size, sizeof(__u32)); + __array( + values, struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u8[STRING_MAPS_SIZE_9]); + __type(value, __u8); + }); +} string_maps_9 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); + __uint(max_entries, STRING_MAPS_OUTER_MAX_ENTRIES); + __uint(key_size, sizeof(__u32)); + __array( + values, struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u8[STRING_MAPS_SIZE_10]); + __type(value, __u8); + }); +} string_maps_10 SEC(".maps"); +#endif + struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __uint(max_entries, 1); __uint(key_size, sizeof(__u32)); - __uint(value_size, 512); + __uint(value_size, STRING_MAPS_HEAP_SIZE); } string_maps_heap SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __uint(max_entries, 1); __uint(key_size, sizeof(__u32)); - __uint(value_size, 512); + __uint(value_size, STRING_MAPS_HEAP_SIZE); } string_maps_ro_zero SEC(".maps"); #define STRING_PREFIX_MAX_LENGTH 256 diff --git a/bpf/process/types/basic.h b/bpf/process/types/basic.h index 5513fa58848..62dd8bfa6c4 100644 --- a/bpf/process/types/basic.h +++ b/bpf/process/types/basic.h @@ -192,7 +192,15 @@ struct event_config { * we will need to resize. TBD would be to size these at compile time using * buffer size information. */ -#define MAX_STRING 1024 +#ifdef __LARGE_BPF_PROG +#ifdef __LARGE_MAP_KEYS +#define MAX_STRING (STRING_MAPS_SIZE_10 - 2) +#else +#define MAX_STRING (STRING_MAPS_SIZE_7 - 2) +#endif +#else +#define MAX_STRING (STRING_MAPS_SIZE_5 - 1) +#endif #ifdef __MULTI_KPROBE static inline __attribute__((always_inline)) __u32 get_index(void *ctx) @@ -470,7 +478,9 @@ copy_strings(char *args, unsigned long arg) long size; // probe_read_str() always nul-terminates the string. - size = probe_read_str(&args[4], MAX_STRING, (char *)arg); + // So add one to the length to allow for it. This should + // result in us honouring our MAX_STRING correctly. + size = probe_read_str(&args[4], MAX_STRING + 1, (char *)arg); if (size <= 1) return invalid_ty; // Remove the nul character from end. @@ -703,31 +713,131 @@ copy_char_buf(void *ctx, long off, unsigned long arg, int argm, return __copy_char_buf(ctx, off, arg, bytes, has_max_data(argm), e, data_heap); } +static inline __attribute__((always_inline)) u16 +string_padded_len(u16 len) +{ + u16 padded_len = len; + + if (len < STRING_MAPS_SIZE_5) { + if (len % STRING_MAPS_KEY_INC_SIZE != 0) + padded_len = ((len / STRING_MAPS_KEY_INC_SIZE) + 1) * STRING_MAPS_KEY_INC_SIZE; + return padded_len; + } + if (len <= STRING_MAPS_SIZE_6 - 2) + return STRING_MAPS_SIZE_6 - 2; +#ifdef __LARGE_BPF_PROG +#ifdef __LARGE_MAP_KEYS + if (len <= STRING_MAPS_SIZE_7 - 2) + return STRING_MAPS_SIZE_7 - 2; + if (len <= STRING_MAPS_SIZE_8 - 2) + return STRING_MAPS_SIZE_8 - 2; + if (len <= STRING_MAPS_SIZE_9 - 2) + return STRING_MAPS_SIZE_9 - 2; + return STRING_MAPS_SIZE_10 - 2; +#else + return STRING_MAPS_SIZE_7 - 2; +#endif +#else + return STRING_MAPS_SIZE_5 - 1; +#endif +} + +static inline __attribute__((always_inline)) int +string_map_index(u16 padded_len) +{ + if (padded_len < STRING_MAPS_SIZE_5) + return (padded_len / STRING_MAPS_KEY_INC_SIZE) - 1; + +#ifdef __LARGE_BPF_PROG +#ifdef __LARGE_MAP_KEYS + switch (padded_len) { + case STRING_MAPS_SIZE_6 - 2: + return 6; + case STRING_MAPS_SIZE_7 - 2: + return 7; + case STRING_MAPS_SIZE_8 - 2: + return 8; + case STRING_MAPS_SIZE_9 - 2: + return 9; + } + return 10; +#else + if (padded_len == STRING_MAPS_SIZE_6 - 2) + return 6; + return 7; +#endif +#else + return 5; +#endif +} + +static inline __attribute__((always_inline)) void * +get_string_map(int index, __u32 map_idx) +{ + switch (index) { + case 0: + return map_lookup_elem(&string_maps_0, &map_idx); + case 1: + return map_lookup_elem(&string_maps_1, &map_idx); + case 2: + return map_lookup_elem(&string_maps_2, &map_idx); + case 3: + return map_lookup_elem(&string_maps_3, &map_idx); + case 4: + return map_lookup_elem(&string_maps_4, &map_idx); + case 5: + return map_lookup_elem(&string_maps_5, &map_idx); +#ifdef __LARGE_BPF_PROG + case 6: + return map_lookup_elem(&string_maps_6, &map_idx); + case 7: + return map_lookup_elem(&string_maps_7, &map_idx); +#ifdef __LARGE_MAP_KEYS + case 8: + return map_lookup_elem(&string_maps_8, &map_idx); + case 9: + return map_lookup_elem(&string_maps_9, &map_idx); + case 10: + return map_lookup_elem(&string_maps_10, &map_idx); +#endif +#endif + } + return 0; +} + static inline __attribute__((always_inline)) long filter_char_buf_equal(struct selector_arg_filter *filter, char *arg_str, uint orig_len) { __u32 *map_ids = (__u32 *)&filter->value; + char *heap, *zero_heap; void *string_map; + __u16 padded_len; __u32 map_idx; - __u8 len; - __u8 padded_len; - int index; - char *heap, *zero_heap; int zero = 0; + __u16 len; + int index; - if (orig_len >= STRING_MAPS_SIZE_5 || !orig_len) +#ifdef __LARGE_BPF_PROG +#ifdef __LARGE_MAP_KEYS + if (orig_len > STRING_MAPS_SIZE_10 - 2 || !orig_len) + return 0; +#else + if (orig_len > STRING_MAPS_SIZE_7 - 2 || !orig_len) + return 0; +#endif +#else + if (orig_len > STRING_MAPS_SIZE_5 - 1 || !orig_len) return 0; +#endif - len = (__u8)orig_len; + len = (__u16)orig_len; // Calculate padded string length - padded_len = len; - if (len % STRING_MAPS_KEY_INC_SIZE != 0) - padded_len = ((len / STRING_MAPS_KEY_INC_SIZE) + 1) * STRING_MAPS_KEY_INC_SIZE; + padded_len = string_padded_len(len); // Check if we have entries for this padded length. // Do this before we copy data for efficiency. - index = (padded_len / STRING_MAPS_KEY_INC_SIZE) - 1; - map_idx = map_ids[index & 0x7]; + index = string_map_index(padded_len); + map_idx = map_ids[index & 0xf]; if (map_idx == 0xffffffff) return 0; @@ -736,46 +846,46 @@ filter_char_buf_equal(struct selector_arg_filter *filter, char *arg_str, uint or if (!heap || !zero_heap) return 0; - // Copy string to heap, preceded by length + // Copy string to heap, preceded by length - + // u8 for first 6 maps; u16 for latter maps +#ifdef __LARGE_BPF_PROG + if (index <= 5) + heap[0] = len; + else + *(u16 *)heap = len; +#else heap[0] = len; +#endif - asm volatile("%[len] &= 0xff;\n" + asm volatile("%[len] &= %1;\n" : [len] "+r"(len) - :); + : "i"(STRING_MAPS_HEAP_MASK)); +#ifdef __LARGE_BPF_PROG + if (index <= 5) + probe_read(&heap[1], len, arg_str); + else + probe_read(&heap[2], len, arg_str); +#else probe_read(&heap[1], len, arg_str); +#endif // Pad string to multiple of key increment size if (padded_len > len) { - asm volatile("%[len] &= 0xff;\n" + asm volatile("%[len] &= %1;\n" : [len] "+r"(len) - :); - probe_read(heap + len + 1, (padded_len - len) & 0xff, zero_heap); + : "i"(STRING_MAPS_HEAP_MASK)); +#ifdef __LARGE_BPF_PROG + if (index <= 5) + probe_read(heap + len + 1, (padded_len - len) & STRING_MAPS_COPY_MASK, zero_heap); + else + probe_read(heap + len + 2, (padded_len - len) & STRING_MAPS_COPY_MASK, zero_heap); +#else + probe_read(heap + len + 1, (padded_len - len) & STRING_MAPS_COPY_MASK, zero_heap); +#endif } // Get map for this string length - switch (index) { - case 0: - string_map = map_lookup_elem(&string_maps_0, &map_idx); - break; - case 1: - string_map = map_lookup_elem(&string_maps_1, &map_idx); - break; - case 2: - string_map = map_lookup_elem(&string_maps_2, &map_idx); - break; - case 3: - string_map = map_lookup_elem(&string_maps_3, &map_idx); - break; - case 4: - string_map = map_lookup_elem(&string_maps_4, &map_idx); - break; - case 5: - string_map = map_lookup_elem(&string_maps_5, &map_idx); - break; - default: - return 0; - } - + string_map = get_string_map(index, map_idx); if (!string_map) return 0; diff --git a/contrib/verify/verify.sh b/contrib/verify/verify.sh index d5858d191cb..3f17a3e6fed 100755 --- a/contrib/verify/verify.sh +++ b/contrib/verify/verify.sh @@ -68,6 +68,11 @@ for obj in "$TETRAGONDIR"/*.o; do continue fi + # Skip v5.11 objects check for kernel < 5.11 + if [[ "$B" == *511.o && $(echo "$KERNEL < 5.11" | bc) == 1 ]]; then + continue + fi + # Skip bpf_loader for kernel < 5.19 if [[ "$B" == bpf_loader* && $(echo "$KERNEL < 5.19" | bc) == 1 ]]; then continue diff --git a/pkg/kernels/kernels.go b/pkg/kernels/kernels.go index 53ad548ed44..c85070f8d0b 100644 --- a/pkg/kernels/kernels.go +++ b/pkg/kernels/kernels.go @@ -155,6 +155,8 @@ func IsKernelVersionLessThan(version string) bool { func GenericKprobeObjs() (string, string) { if EnableV61Progs() { return "bpf_generic_kprobe_v61.o", "bpf_generic_retkprobe_v61.o" + } else if MinKernelVersion("5.11") { + return "bpf_generic_kprobe_v511.o", "bpf_generic_retkprobe_v511.o" } else if EnableLargeProgs() { return "bpf_generic_kprobe_v53.o", "bpf_generic_retkprobe_v53.o" } diff --git a/pkg/selectors/kernel.go b/pkg/selectors/kernel.go index 2eb91e221e6..be669001ab2 100644 --- a/pkg/selectors/kernel.go +++ b/pkg/selectors/kernel.go @@ -728,8 +728,18 @@ func writeMatchStrings(k *KernelSelectorState, values []string, ty uint32) error if err != nil { return fmt.Errorf("MatchArgs value %s invalid: %w", v, err) } - for sizeIdx := 0; sizeIdx < StringMapsNumSubMaps; sizeIdx++ { - if size == StringMapsSizes[sizeIdx] { + numSubMaps := StringMapsNumSubMaps + if !kernels.MinKernelVersion("5.11") { + numSubMaps = StringMapsNumSubMapsSmall + } + + for sizeIdx := 0; sizeIdx < numSubMaps; sizeIdx++ { + stringMapSize := StringMapsSizes[sizeIdx] + if sizeIdx == 7 && !kernels.MinKernelVersion("5.11") { + stringMapSize = StringMapSize7a + } + + if size == stringMapSize { maps[sizeIdx][value] = struct{}{} break } diff --git a/pkg/selectors/kernel_test.go b/pkg/selectors/kernel_test.go index 909af89f6d1..05824be58c9 100644 --- a/pkg/selectors/kernel_test.go +++ b/pkg/selectors/kernel_test.go @@ -231,7 +231,7 @@ func TestParseMatchArg(t *testing.T) { expected1 := []byte{ 0x01, 0x00, 0x00, 0x00, // Index == 1 0x03, 0x00, 0x00, 0x00, // operator == equal - 32, 0x00, 0x00, 0x00, // length == 32 + 52, 0x00, 0x00, 0x00, // length == 32 0x06, 0x00, 0x00, 0x00, // value type == string 0x00, 0x00, 0x00, 0x00, // map ID for strings <25 0xff, 0xff, 0xff, 0xff, // map ID for strings 25-48 @@ -239,6 +239,11 @@ func TestParseMatchArg(t *testing.T) { 0xff, 0xff, 0xff, 0xff, // map ID for strings 73-96 0xff, 0xff, 0xff, 0xff, // map ID for strings 97-120 0xff, 0xff, 0xff, 0xff, // map ID for strings 121-144 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 145-256 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 257-512 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 513-1024 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 1025-2048 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 2049-4096 } if err := ParseMatchArg(k, arg1, sig); err != nil || bytes.Equal(expected1, d.e[0:d.off]) == false { t.Errorf("parseMatchArg: error %v expected:\n%v\nbytes:\n%v\nparsing %v\n", err, expected1, d.e[0:d.off], arg1) @@ -314,9 +319,9 @@ func TestParseMatchArg(t *testing.T) { if kernels.EnableLargeProgs() { // multiple match args are supported only in kernels >= 5.4 length := []byte{ - 88, 0x00, 0x00, 0x00, + 108, 0x00, 0x00, 0x00, 24, 0x00, 0x00, 0x00, - 64, 0x00, 0x00, 0x00, + 84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -595,11 +600,11 @@ func TestInitKernelSelectors(t *testing.T) { } expected_selsize_small := []byte{ - 0xfc, 0x00, 0x00, 0x00, // size = pids + args + actions + namespaces + capabilities + 4 + 0x10, 0x01, 0x00, 0x00, // size = pids + args + actions + namespaces + capabilities + 4 } expected_selsize_large := []byte{ - 0x30, 0x01, 0x00, 0x00, // size = pids + args + actions + namespaces + namespacesChanges + capabilities + capabilityChanges + 4 + 0x44, 0x01, 0x00, 0x00, // size = pids + args + actions + namespaces + namespacesChanges + capabilities + capabilityChanges + 4 } expected_filters := []byte{ @@ -684,17 +689,17 @@ func TestInitKernelSelectors(t *testing.T) { expected_last_large := []byte{ // arg header - 88, 0x00, 0x00, 0x00, // size = sizeof(arg2) + sizeof(arg1) + 24 + 108, 0x00, 0x00, 0x00, // size = sizeof(arg2) + sizeof(arg1) + 24 24, 0x00, 0x00, 0x00, // arg[0] offset - 64, 0x00, 0x00, 0x00, // arg[1] offset + 84, 0x00, 0x00, 0x00, // arg[1] offset 0x00, 0x00, 0x00, 0x00, // arg[2] offset 0x00, 0x00, 0x00, 0x00, // arg[3] offset 0x00, 0x00, 0x00, 0x00, // arg[4] offset - //arg1 size = 40 + //arg1 size = 60 0x01, 0x00, 0x00, 0x00, // Index == 1 0x03, 0x00, 0x00, 0x00, // operator == equal - 32, 0x00, 0x00, 0x00, // length == 32 + 52, 0x00, 0x00, 0x00, // length == 32 0x06, 0x00, 0x00, 0x00, // value type == string 0x00, 0x00, 0x00, 0x00, // map ID for strings <25 0xff, 0xff, 0xff, 0xff, // map ID for strings 25-48 @@ -702,6 +707,11 @@ func TestInitKernelSelectors(t *testing.T) { 0xff, 0xff, 0xff, 0xff, // map ID for strings 73-96 0xff, 0xff, 0xff, 0xff, // map ID for strings 97-120 0xff, 0xff, 0xff, 0xff, // map ID for strings 121-144 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 145-256 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 257-512 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 513-1024 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 1025-2048 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 2049-4096 //arg2 size = 24 0x02, 0x00, 0x00, 0x00, // Index == 2 @@ -724,17 +734,17 @@ func TestInitKernelSelectors(t *testing.T) { expected_last_small := []byte{ // arg header - 64, 0x00, 0x00, 0x00, // size = sizeof(arg2) + sizeof(arg1) + 32 + 84, 0x00, 0x00, 0x00, // size = sizeof(arg1) + 24 24, 0x00, 0x00, 0x00, // arg[0] offset 0x00, 0x00, 0x00, 0x00, // arg[1] offset 0x00, 0x00, 0x00, 0x00, // arg[2] offset 0x00, 0x00, 0x00, 0x00, // arg[3] offset 0x00, 0x00, 0x00, 0x00, // arg[4] offset - //arg1 size = 40 + //arg1 size = 60 0x01, 0x00, 0x00, 0x00, // Index == 1 0x03, 0x00, 0x00, 0x00, // operator == equal - 32, 0x00, 0x00, 0x00, // length == 32 + 52, 0x00, 0x00, 0x00, // length == 32 0x06, 0x00, 0x00, 0x00, // value type == string 0x00, 0x00, 0x00, 0x00, // map ID for strings <25 0xff, 0xff, 0xff, 0xff, // map ID for strings 25-48 @@ -742,6 +752,11 @@ func TestInitKernelSelectors(t *testing.T) { 0xff, 0xff, 0xff, 0xff, // map ID for strings 73-96 0xff, 0xff, 0xff, 0xff, // map ID for strings 97-120 0xff, 0xff, 0xff, 0xff, // map ID for strings 121-144 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 145-256 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 257-512 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 513-1024 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 1025-2048 + 0xff, 0xff, 0xff, 0xff, // map ID for strings 2049-4096 // actions header 32, 0x00, 0x00, 0x00, // size = (4 * sizeof(uint32) * number of actions) + args + 4 diff --git a/pkg/selectors/selectors.go b/pkg/selectors/selectors.go index a17fb7faf71..27bd49fd82b 100644 --- a/pkg/selectors/selectors.go +++ b/pkg/selectors/selectors.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/cilium/tetragon/pkg/api/processapi" + "github.com/cilium/tetragon/pkg/kernels" ) type KernelLPMTrie4 struct { @@ -29,20 +30,45 @@ type ValueReader interface { } const ( - stringMapsKeyIncSize = 24 - StringMapsNumSubMaps = 6 - MaxStringMapsSize = 6*stringMapsKeyIncSize + 1 - StringPrefixMaxLength = 256 - StringPostfixMaxLength = 128 + stringMapsKeyIncSize = 24 + StringMapsNumSubMaps = 11 + StringMapsNumSubMapsSmall = 8 + MaxStringMapsSize = 4096 + 2 + StringPrefixMaxLength = 256 + StringPostfixMaxLength = 128 + + // Maps with key string length <256 only require a single byte + // to store string length. Maps with key string length >=256 + // require two bytes to store string length. + stringMapSize0 = 1*stringMapsKeyIncSize + 1 + stringMapSize1 = 2*stringMapsKeyIncSize + 1 + stringMapSize2 = 3*stringMapsKeyIncSize + 1 + stringMapSize3 = 4*stringMapsKeyIncSize + 1 + stringMapSize4 = 5*stringMapsKeyIncSize + 1 + stringMapSize5 = 6*stringMapsKeyIncSize + 1 + stringMapSize6 = 256 + 2 + stringMapSize7 = 512 + 2 + stringMapSize8 = 1024 + 2 + stringMapSize9 = 2048 + 2 + stringMapSize10 = 4096 + 2 + + StringMapSize7a = 512 ) var ( - StringMapsSizes = [StringMapsNumSubMaps]int{1*stringMapsKeyIncSize + 1, - 2*stringMapsKeyIncSize + 1, - 3*stringMapsKeyIncSize + 1, - 4*stringMapsKeyIncSize + 1, - 5*stringMapsKeyIncSize + 1, - 6*stringMapsKeyIncSize + 1} + StringMapsSizes = [StringMapsNumSubMaps]int{ + stringMapSize0, + stringMapSize1, + stringMapSize2, + stringMapSize3, + stringMapSize4, + stringMapSize5, + stringMapSize6, + stringMapSize7, + stringMapSize8, + stringMapSize9, + stringMapSize10, + } ) type StringMapLists [StringMapsNumSubMaps][]map[[MaxStringMapsSize]byte]struct{} @@ -283,6 +309,35 @@ func ArgSelectorValue(v string) ([]byte, uint32) { return b, uint32(len(b)) } +func stringPaddedLen(s int) int { + paddedLen := s + + if s <= 6*stringMapsKeyIncSize { + if s%stringMapsKeyIncSize != 0 { + paddedLen = ((s / stringMapsKeyIncSize) + 1) * stringMapsKeyIncSize + } + return paddedLen + } + // The '-2' is to reduce the key size to the key string size - + // the key includes a string length that is 2 bytes long. + if s <= stringMapSize6-2 { + return stringMapSize6 - 2 + } + if kernels.MinKernelVersion("5.11") { + if s <= stringMapSize7-2 { + return stringMapSize7 - 2 + } + if s <= stringMapSize8-2 { + return stringMapSize8 - 2 + } + if s <= stringMapSize9-2 { + return stringMapSize9 - 2 + } + return stringMapSize10 - 2 + } + return StringMapSize7a - 2 +} + func ArgStringSelectorValue(v string, removeNul bool) ([MaxStringMapsSize]byte, int, error) { if removeNul { // Remove any trailing nul characters ("\0" or 0x00) @@ -293,23 +348,38 @@ func ArgStringSelectorValue(v string, removeNul bool) ([MaxStringMapsSize]byte, ret := [MaxStringMapsSize]byte{} b := []byte(v) s := len(b) - if s >= MaxStringMapsSize { - return ret, 0, fmt.Errorf("string is too long") + if kernels.MinKernelVersion("5.11") { + if s > MaxStringMapsSize-2 { + return ret, 0, fmt.Errorf("string is too long") + } + } else if kernels.MinKernelVersion("5.4") { + if s > StringMapSize7a-2 { + return ret, 0, fmt.Errorf("string is too long") + } + } else { + if s > stringMapSize5-1 { + return ret, 0, fmt.Errorf("string is too long") + } } if s == 0 { return ret, 0, fmt.Errorf("string is empty") } - paddedLen := s // Calculate length of string padded to next multiple of key increment size - if s%stringMapsKeyIncSize != 0 { - paddedLen = ((s / stringMapsKeyIncSize) + 1) * stringMapsKeyIncSize + paddedLen := stringPaddedLen(s) + + // Add real length to start and padding to end. + // u8 for first 6 maps and u16 little endian for latter maps. + if paddedLen <= 6*stringMapsKeyIncSize { + ret[0] = byte(s) + copy(ret[1:], b) + // Total length is padded string len + prefixed length byte. + return ret, paddedLen + 1, nil } - - // Add real length to start and padding to end - ret[0] = byte(s) - copy(ret[1:], b) - // Total length is padded string len + prefixed length byte. - return ret, paddedLen + 1, nil + ret[0] = byte(s % 0x100) + ret[1] = byte(s / 0x100) + copy(ret[2:], b) + // Total length is padded string len + prefixed length half word. + return ret, paddedLen + 2, nil } func ArgPostfixSelectorValue(v string, removeNul bool) ([]byte, uint32) { @@ -359,21 +429,26 @@ func (k *KernelSelectorState) createStringMaps() SelectorStringMaps { {}, {}, {}, + {}, + {}, + {}, + {}, + {}, } } -// In BPF, the string "equal" operator uses six hash maps, each stored within a matching array. +// In BPF, the string "equal" operator uses 11 hash maps, each stored within a matching array. // For each kprobe there could be multiple string match selectors. Each of these selectors has -// up to six hash maps (of different sizes) that hold potential matches. Each kprobe could have +// up to 11 hash maps (of different sizes) that hold potential matches. Each kprobe could have // multiple string match selectors (for different parameters, and/or different actions). Arrays // of hash maps can only hold hash maps of a singular type; e.g. an array of hash maps with a // key size of 25 can only hold hash maps that have that key size – it can't hold hash maps with // different key sizes. // -// As we have six different key sizes (to facilitate faster look ups for shorter strings), each -// selector can potentially have six hash maps to look up the string in. And as each kprobe +// As we have 11 different key sizes (to facilitate faster look ups for shorter strings), each +// selector can potentially have 11 hash maps to look up the string in. And as each kprobe // could have multiple string match selectors, each kprobe could potentially have multiple hash -// maps for each key size. Each kprobe therefore has six arrays of hash maps to hold these hash +// maps for each key size. Each kprobe therefore has 11 arrays of hash maps to hold these hash // maps. // // In golang we create a list of hash maps for each key size. Each of these is inserted into the diff --git a/pkg/sensors/base/base.go b/pkg/sensors/base/base.go index 441e5ac9121..d6afd579b54 100644 --- a/pkg/sensors/base/base.go +++ b/pkg/sensors/base/base.go @@ -140,6 +140,8 @@ func GetInitialSensor() *sensors.Sensor { func ExecObj() string { if kernels.EnableV61Progs() { return "bpf_execve_event_v61.o" + } else if kernels.MinKernelVersion("5.11") { + return "bpf_execve_event_v511.o" } else if kernels.EnableLargeProgs() { return "bpf_execve_event_v53.o" } diff --git a/pkg/sensors/tracing/args.go b/pkg/sensors/tracing/args.go index 1d345f50d26..847c46b0951 100644 --- a/pkg/sensors/tracing/args.go +++ b/pkg/sensors/tracing/args.go @@ -15,6 +15,7 @@ import ( api "github.com/cilium/tetragon/pkg/api/tracingapi" gt "github.com/cilium/tetragon/pkg/generictypes" "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1" + "github.com/cilium/tetragon/pkg/kernels" "github.com/cilium/tetragon/pkg/logger" "github.com/cilium/tetragon/pkg/observer" "github.com/cilium/tetragon/pkg/reader/network" @@ -519,7 +520,13 @@ func parseString(r io.Reader) (string, error) { } // limit the size of the string to avoid huge memory allocation and OOM kill in case of issue - if size > maxStringSize { + maxStrLen := int32(maxStringSize) + if !kernels.MinKernelVersion("5.4") { + maxStrLen = maxStringSizeTiny + } else if !kernels.MinKernelVersion("5.11") { + maxStrLen = maxStringSizeSmall + } + if size > maxStrLen { return "", fmt.Errorf("string size too large: %d, max size is %d", size, maxStringSize) } stringBuffer := make([]byte, size) diff --git a/pkg/sensors/tracing/generickprobe.go b/pkg/sensors/tracing/generickprobe.go index 4964a6505c5..d2f5cd1b28f 100644 --- a/pkg/sensors/tracing/generickprobe.go +++ b/pkg/sensors/tracing/generickprobe.go @@ -21,7 +21,6 @@ import ( "github.com/cilium/tetragon/pkg/arch" "github.com/cilium/tetragon/pkg/bpf" "github.com/cilium/tetragon/pkg/btf" - cachedbtf "github.com/cilium/tetragon/pkg/btf" "github.com/cilium/tetragon/pkg/eventhandler" "github.com/cilium/tetragon/pkg/grpc/tracing" "github.com/cilium/tetragon/pkg/idtable" @@ -211,7 +210,12 @@ func filterMaps(load *program.Program, pinPath string, kprobeEntry *genericKprob maps = append(maps, addr6FilterMaps) var stringFilterMap [selectors.StringMapsNumSubMaps]*program.Map - for string_map_index := 0; string_map_index < selectors.StringMapsNumSubMaps; string_map_index++ { + numSubMaps := selectors.StringMapsNumSubMaps + if !kernels.MinKernelVersion("5.11") { + numSubMaps = selectors.StringMapsNumSubMapsSmall + } + + for string_map_index := 0; string_map_index < numSubMaps; string_map_index++ { stringFilterMap[string_map_index] = program.MapBuilderPin(fmt.Sprintf("string_maps_%d", string_map_index), sensors.PathJoin(pinPath, fmt.Sprintf("string_maps_%d", string_map_index)), load) if state != nil && !kernels.MinKernelVersion("5.9") { @@ -264,6 +268,9 @@ func createMultiKprobeSensor(sensorPath string, multiIDs []idtable.EntryID) ([]* if kernels.EnableV61Progs() { loadProgName = "bpf_multi_kprobe_v61.o" loadProgRetName = "bpf_multi_retkprobe_v61.o" + } else if kernels.MinKernelVersion("5.11") { + loadProgName = "bpf_multi_kprobe_v511.o" + loadProgRetName = "bpf_multi_retkprobe_v511.o" } pinPath := multiKprobePinPath(sensorPath) @@ -369,7 +376,7 @@ func preValidateKprobes(name string, kprobes []v1alpha1.KProbeSpec, lists []v1al } if len(option.Config.KMods) > 0 { - btfobj, err = cachedbtf.AddModulesToSpec(btfobj, option.Config.KMods) + btfobj, err = btf.AddModulesToSpec(btfobj, option.Config.KMods) if err != nil { return fmt.Errorf("adding modules to spec failed: %w", err) } @@ -1012,7 +1019,9 @@ func loadGenericKprobeSensor(bpfDir, mapDir string, load *program.Program, verbo var errParseStringSize = errors.New("error parsing string size from binary") // this is from bpf/process/types/basic.h 'MAX_STRING' -const maxStringSize = 1024 +const maxStringSize = 4096 +const maxStringSizeSmall = 510 +const maxStringSizeTiny = 144 func getUrl(url string) { // We fire and forget URLs, and we don't care if they hit or not. diff --git a/pkg/sensors/tracing/generictracepoint.go b/pkg/sensors/tracing/generictracepoint.go index 7a3c281b669..ca5c8c8aa95 100644 --- a/pkg/sensors/tracing/generictracepoint.go +++ b/pkg/sensors/tracing/generictracepoint.go @@ -366,6 +366,8 @@ func createGenericTracepointSensor( progName := "bpf_generic_tracepoint.o" if kernels.EnableV61Progs() { progName = "bpf_generic_tracepoint_v61.o" + } else if kernels.MinKernelVersion("5.11") { + progName = "bpf_generic_tracepoint_v511.o" } else if kernels.EnableLargeProgs() { progName = "bpf_generic_tracepoint_v53.o" } @@ -428,7 +430,11 @@ func createGenericTracepointSensor( } maps = append(maps, addr6FilterMaps) - for string_map_index := 0; string_map_index < selectors.StringMapsNumSubMaps; string_map_index++ { + numSubMaps := selectors.StringMapsNumSubMaps + if !kernels.MinKernelVersion("5.11") { + numSubMaps = selectors.StringMapsNumSubMapsSmall + } + for string_map_index := 0; string_map_index < numSubMaps; string_map_index++ { stringFilterMap := program.MapBuilderPin(fmt.Sprintf("string_maps_%d", string_map_index), sensors.PathJoin(pinPath, fmt.Sprintf("string_maps_%d", string_map_index)), prog0) if !kernels.MinKernelVersion("5.9") { diff --git a/pkg/sensors/tracing/kprobe_test.go b/pkg/sensors/tracing/kprobe_test.go index f49a8399316..0454e5a7236 100644 --- a/pkg/sensors/tracing/kprobe_test.go +++ b/pkg/sensors/tracing/kprobe_test.go @@ -23,7 +23,6 @@ import ( "github.com/cilium/ebpf" "github.com/cilium/ebpf/asm" "github.com/cilium/tetragon/api/v1/tetragon" - "github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker" ec "github.com/cilium/tetragon/api/v1/tetragon/codegen/eventchecker" "github.com/cilium/tetragon/pkg/arch" "github.com/cilium/tetragon/pkg/bpf" @@ -901,6 +900,129 @@ func TestKprobeStringMatchHash5Max(t *testing.T) { testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) } +func TestKprobeStringMatchHash6Min(t *testing.T) { + if !kernels.MinKernelVersion("5.4") { + t.Skip("Test requires kernel 5.4+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 145 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash6Max(t *testing.T) { + if !kernels.MinKernelVersion("5.4") { + t.Skip("Test requires kernel 5.4+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 256 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash7Min(t *testing.T) { + if !kernels.MinKernelVersion("5.4") { + t.Skip("Test requires kernel 5.4+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 257 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash7Max(t *testing.T) { + if !kernels.MinKernelVersion("5.4") { + t.Skip("Test requires kernel 5.4+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 512 + if !kernels.MinKernelVersion("5.11") { + pathLen = 510 + } + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash8Min(t *testing.T) { + if !kernels.MinKernelVersion("5.11") { + t.Skip("Test requires kernel 5.11+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 513 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash8Max(t *testing.T) { + if !kernels.MinKernelVersion("5.11") { + t.Skip("Test requires kernel 5.11+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 1024 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash9Min(t *testing.T) { + if !kernels.MinKernelVersion("5.11") { + t.Skip("Test requires kernel 5.11+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 1025 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash9Max(t *testing.T) { + if !kernels.MinKernelVersion("5.11") { + t.Skip("Test requires kernel 5.11+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 2048 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash10Min(t *testing.T) { + if !kernels.MinKernelVersion("5.11") { + t.Skip("Test requires kernel 5.11+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 2049 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + +func TestKprobeStringMatchHash10Max(t *testing.T) { + if !kernels.MinKernelVersion("5.11") { + t.Skip("Test requires kernel 5.11+") + } + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 4096 + fileLen := len("/testfile") + dir := strings.Repeat("A", pathLen-fileLen) + readHook := testKprobeStringMatchHook(pidStr, dir) + testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) +} + func testKprobeObjectMultiValueOpenHook(pidStr string, path string) string { return ` apiVersion: cilium.io/v1alpha1 @@ -1345,7 +1467,7 @@ func testKprobeObjectFilterModeOpenHook(pidStr string, mode int, valueFmt string func testKprobeObjectFilterModeOpenMatch(t *testing.T, valueFmt string, modeCreate, modeCheck int) { pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) - checker := func(dir string) *eventchecker.UnorderedEventChecker { + checker := func(dir string) *ec.UnorderedEventChecker { return ec.NewUnorderedEventChecker( ec.NewProcessKprobeChecker(""). WithFunctionName(sm.Full(arch.AddSyscallPrefixTestHelper(t, "sys_openat"))). @@ -1500,7 +1622,7 @@ func TestKprobeObjectFilterReturnValueGTOk(t *testing.T) { path := dir + "/testfile" openHook := testKprobeObjectFilterReturnValueGTHook(pidStr, path) - checker := func(dir string) *eventchecker.UnorderedEventChecker { + checker := func(dir string) *ec.UnorderedEventChecker { return ec.NewUnorderedEventChecker( ec.NewProcessKprobeChecker(""). WithFunctionName(sm.Full(arch.AddSyscallPrefixTestHelper(t, "sys_openat"))). @@ -1550,7 +1672,7 @@ func TestKprobeObjectFilterReturnValueLTOk(t *testing.T) { path := dir + "/testfile" openHook := testKprobeObjectFilterReturnValueLTHook(pidStr, path) - checker := func(dir string) *eventchecker.UnorderedEventChecker { + checker := func(dir string) *ec.UnorderedEventChecker { return ec.NewUnorderedEventChecker( ec.NewProcessKprobeChecker(""). WithFunctionName(sm.Full(arch.AddSyscallPrefixTestHelper(t, "sys_openat"))). @@ -4237,7 +4359,7 @@ spec: t.Logf("got error (as expected): %s", err) } -func testMaxData(t *testing.T, data []byte, checker *eventchecker.UnorderedEventChecker, configHook string, fd int) { +func testMaxData(t *testing.T, data []byte, checker *ec.UnorderedEventChecker, configHook string, fd int) { var doneWG, readyWG sync.WaitGroup defer doneWG.Wait() diff --git a/pkg/sensors/tracing/selectors.go b/pkg/sensors/tracing/selectors.go index 43c6cc0a23d..cdf4992c4e9 100644 --- a/pkg/sensors/tracing/selectors.go +++ b/pkg/sensors/tracing/selectors.go @@ -17,7 +17,7 @@ import ( func selectorsMaploads(ks *selectors.KernelSelectorState, pinPathPrefix string, index uint32) []*program.MapLoad { selBuff := ks.Buffer() - return []*program.MapLoad{ + maps := []*program.MapLoad{ { Index: index, Name: "filter_map", @@ -54,6 +54,18 @@ func selectorsMaploads(ks *selectors.KernelSelectorState, pinPathPrefix string, Load: func(outerMap *ebpf.Map, index uint32) error { return populateMatchBinariesPathsMaps(ks, pinPathPrefix, outerMap) }, + }, { + Index: 0, + Name: "string_prefix_maps", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringPrefixFilterMaps(ks, pinPathPrefix, outerMap) + }, + }, { + Index: 0, + Name: "string_postfix_maps", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringPostfixFilterMaps(ks, pinPathPrefix, outerMap) + }, }, { Index: 0, Name: "string_maps_0", @@ -92,18 +104,42 @@ func selectorsMaploads(ks *selectors.KernelSelectorState, pinPathPrefix string, }, }, { Index: 0, - Name: "string_prefix_maps", + Name: "string_maps_6", Load: func(outerMap *ebpf.Map, index uint32) error { - return populateStringPrefixFilterMaps(ks, pinPathPrefix, outerMap) + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 6) }, }, { Index: 0, - Name: "string_postfix_maps", + Name: "string_maps_7", Load: func(outerMap *ebpf.Map, index uint32) error { - return populateStringPostfixFilterMaps(ks, pinPathPrefix, outerMap) + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 7) }, }, } + if kernels.MinKernelVersion("5.11") { + maps = append(maps, []*program.MapLoad{ + { + Index: 0, + Name: "string_maps_8", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 8) + }, + }, { + Index: 0, + Name: "string_maps_9", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 9) + }, + }, { + Index: 0, + Name: "string_maps_10", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 10) + }, + }, + }...) + } + return maps } func populateArgFilterMaps( @@ -315,11 +351,15 @@ func populateStringFilterMap( innerData map[[selectors.MaxStringMapsSize]byte]struct{}, maxEntries uint32, ) error { + mapKeySize := selectors.StringMapsSizes[subMap] + if subMap == 7 && !kernels.MinKernelVersion("5.11") { + mapKeySize = selectors.StringMapSize7a + } innerName := fmt.Sprintf("string_maps_%d_%d", subMap, innerID) innerSpec := &ebpf.MapSpec{ Name: innerName, Type: ebpf.Hash, - KeySize: uint32(selectors.StringMapsSizes[subMap]), + KeySize: uint32(mapKeySize), ValueSize: uint32(1), MaxEntries: maxEntries, } @@ -333,7 +373,7 @@ func populateStringFilterMap( one := uint8(1) for rawVal := range innerData { - val := rawVal[:selectors.StringMapsSizes[subMap]] + val := rawVal[:mapKeySize] err := innerMap.Update(val, one, 0) if err != nil { return fmt.Errorf("failed to insert value into %s: %w", innerName, err)