1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2024 Google */ 3 #include <vmlinux.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_tracing.h> 6 7 char _license[] SEC("license") = "GPL"; 8 9 #define SLAB_NAME_MAX 32 10 11 struct kmem_cache_result { 12 char name[SLAB_NAME_MAX]; 13 long obj_size; 14 }; 15 16 struct { 17 __uint(type, BPF_MAP_TYPE_HASH); 18 __uint(key_size, sizeof(void *)); 19 __uint(value_size, SLAB_NAME_MAX); 20 __uint(max_entries, 1); 21 } slab_hash SEC(".maps"); 22 23 struct { 24 __uint(type, BPF_MAP_TYPE_ARRAY); 25 __uint(key_size, sizeof(int)); 26 __uint(value_size, sizeof(struct kmem_cache_result)); 27 __uint(max_entries, 1024); 28 } slab_result SEC(".maps"); 29 30 extern struct kmem_cache *bpf_get_kmem_cache(u64 addr) __ksym; 31 32 /* Result, will be checked by userspace */ 33 int task_struct_found; 34 int kmem_cache_seen; 35 36 SEC("iter/kmem_cache") 37 int slab_info_collector(struct bpf_iter__kmem_cache *ctx) 38 { 39 struct seq_file *seq = ctx->meta->seq; 40 struct kmem_cache *s = ctx->s; 41 struct kmem_cache_result *r; 42 int idx; 43 44 if (s) { 45 /* To make sure if the slab_iter implements the seq interface 46 * properly and it's also useful for debugging. 47 */ 48 BPF_SEQ_PRINTF(seq, "%s: %u\n", s->name, s->size); 49 50 idx = kmem_cache_seen; 51 r = bpf_map_lookup_elem(&slab_result, &idx); 52 if (r == NULL) 53 return 0; 54 55 kmem_cache_seen++; 56 57 /* Save name and size to match /proc/slabinfo */ 58 bpf_probe_read_kernel_str(r->name, sizeof(r->name), s->name); 59 r->obj_size = s->size; 60 61 if (!bpf_strncmp(r->name, 11, "task_struct")) 62 bpf_map_update_elem(&slab_hash, &s, r->name, BPF_NOEXIST); 63 } 64 65 return 0; 66 } 67 68 SEC("raw_tp/bpf_test_finish") 69 int BPF_PROG(check_task_struct) 70 { 71 u64 curr = bpf_get_current_task(); 72 struct kmem_cache *s; 73 char *name; 74 75 s = bpf_get_kmem_cache(curr); 76 if (s == NULL) { 77 task_struct_found = -1; 78 return 0; 79 } 80 name = bpf_map_lookup_elem(&slab_hash, &s); 81 if (name && !bpf_strncmp(name, 11, "task_struct")) 82 task_struct_found = 1; 83 else 84 task_struct_found = -2; 85 return 0; 86 } 87