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