xref: /linux/tools/testing/selftests/bpf/progs/kmem_cache_iter.c (revision e626a13f6fbb4697f8734333432dca577628d09a)
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