diff --git a/bpf/process/string_maps.h b/bpf/process/string_maps.h index a27d6eff0de..e1f9b6e10d7 100644 --- a/bpf/process/string_maps.h +++ b/bpf/process/string_maps.h @@ -32,19 +32,30 @@ * 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. * * 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 5 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) +#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) + +#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 +135,83 @@ 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"); + +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"); + 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..667533286f9 100644 --- a/bpf/process/types/basic.h +++ b/bpf/process/types/basic.h @@ -192,7 +192,7 @@ 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 +#define MAX_STRING 4096 #ifdef __MULTI_KPROBE static inline __attribute__((always_inline)) __u32 get_index(void *ctx) @@ -470,7 +470,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 +705,99 @@ 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; + 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; +} + +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; + } + 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; +} + +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); + case 6: + return map_lookup_elem(&string_maps_6, &map_idx); + case 7: + return map_lookup_elem(&string_maps_7, &map_idx); + 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); + } + 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) + if (orig_len > STRING_MAPS_SIZE_10 - 2 || !orig_len) return 0; - 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 +806,35 @@ 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 - heap[0] = len; + // Copy string to heap, preceded by length - + // u8 for first 6 maps; u16 for latter 5 maps + if (index <= 5) + heap[0] = len; + else { + *(u16 *)heap = len; + } - asm volatile("%[len] &= 0xff;\n" + asm volatile("%[len] &= %1;\n" : [len] "+r"(len) - :); - probe_read(&heap[1], len, arg_str); + : "i"(STRING_MAPS_HEAP_MASK)); + if (index <= 5) + probe_read(&heap[1], len, arg_str); + else + probe_read(&heap[2], len, arg_str); // 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)); + 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); } // 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/pkg/selectors/selectors.go b/pkg/selectors/selectors.go index a17fb7faf71..20cc63901ba 100644 --- a/pkg/selectors/selectors.go +++ b/pkg/selectors/selectors.go @@ -30,19 +30,41 @@ type ValueReader interface { const ( stringMapsKeyIncSize = 24 - StringMapsNumSubMaps = 6 - MaxStringMapsSize = 6*stringMapsKeyIncSize + 1 + StringMapsNumSubMaps = 11 + 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 ) 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 +305,32 @@ 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 s <= stringMapSize7-2 { + return stringMapSize7 - 2 + } + if s <= stringMapSize8-2 { + return stringMapSize8 - 2 + } + if s <= stringMapSize9-2 { + return stringMapSize9 - 2 + } + return stringMapSize10 - 2 +} + func ArgStringSelectorValue(v string, removeNul bool) ([MaxStringMapsSize]byte, int, error) { if removeNul { // Remove any trailing nul characters ("\0" or 0x00) @@ -293,23 +341,28 @@ func ArgStringSelectorValue(v string, removeNul bool) ([MaxStringMapsSize]byte, ret := [MaxStringMapsSize]byte{} b := []byte(v) s := len(b) - if s >= MaxStringMapsSize { + if s > MaxStringMapsSize-2 { 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 5. + 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 +412,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/tracing/generickprobe.go b/pkg/sensors/tracing/generickprobe.go index 4964a6505c5..7bb7a4b5a13 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" @@ -369,7 +368,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 +1011,7 @@ 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 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/kprobe_test.go b/pkg/sensors/tracing/kprobe_test.go index f49a8399316..ef59204ba78 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,96 @@ func TestKprobeStringMatchHash5Max(t *testing.T) { testKprobeStringMatch(t, readHook, getOpenatChecker(t, dir), dir) } +func TestKprobeStringMatchHash6Min(t *testing.T) { + 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) { + 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) { + 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) { + pidStr := strconv.Itoa(int(observertesthelper.GetMyPid())) + pathLen := 512 + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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 +1434,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 +1589,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 +1639,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 +4326,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..d6417dcdb04 100644 --- a/pkg/sensors/tracing/selectors.go +++ b/pkg/sensors/tracing/selectors.go @@ -90,6 +90,36 @@ func selectorsMaploads(ks *selectors.KernelSelectorState, pinPathPrefix string, Load: func(outerMap *ebpf.Map, index uint32) error { return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 5) }, + }, { + Index: 0, + Name: "string_maps_6", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 6) + }, + }, { + Index: 0, + Name: "string_maps_7", + Load: func(outerMap *ebpf.Map, index uint32) error { + return populateStringFilterMaps(ks, pinPathPrefix, outerMap, 7) + }, + }, { + 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) + }, }, { Index: 0, Name: "string_prefix_maps",