xref: /aosp_15_r20/external/bcc/libbpf-tools/core_fixes.bpf.h (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 /* Copyright (c) 2021 Hengqi Chen */
3 
4 #ifndef __CORE_FIXES_BPF_H
5 #define __CORE_FIXES_BPF_H
6 
7 #include <vmlinux.h>
8 #include <bpf/bpf_core_read.h>
9 
10 /**
11  * commit 2f064a59a1 ("sched: Change task_struct::state") changes
12  * the name of task_struct::state to task_struct::__state
13  * see:
14  *     https://github.com/torvalds/linux/commit/2f064a59a1
15  */
16 struct task_struct___o {
17 	volatile long int state;
18 } __attribute__((preserve_access_index));
19 
20 struct task_struct___x {
21 	unsigned int __state;
22 } __attribute__((preserve_access_index));
23 
get_task_state(void * task)24 static __always_inline __s64 get_task_state(void *task)
25 {
26 	struct task_struct___x *t = task;
27 
28 	if (bpf_core_field_exists(t->__state))
29 		return BPF_CORE_READ(t, __state);
30 	return BPF_CORE_READ((struct task_struct___o *)task, state);
31 }
32 
33 /**
34  * commit 309dca309fc3 ("block: store a block_device pointer in struct bio")
35  * adds a new member bi_bdev which is a pointer to struct block_device
36  * see:
37  *     https://github.com/torvalds/linux/commit/309dca309fc3
38  */
39 struct bio___o {
40 	struct gendisk *bi_disk;
41 } __attribute__((preserve_access_index));
42 
43 struct bio___x {
44 	struct block_device *bi_bdev;
45 } __attribute__((preserve_access_index));
46 
get_gendisk(void * bio)47 static __always_inline struct gendisk *get_gendisk(void *bio)
48 {
49 	struct bio___x *b = bio;
50 
51 	if (bpf_core_field_exists(b->bi_bdev))
52 		return BPF_CORE_READ(b, bi_bdev, bd_disk);
53 	return BPF_CORE_READ((struct bio___o *)bio, bi_disk);
54 }
55 
56 /**
57  * commit d5869fdc189f ("block: introduce block_rq_error tracepoint")
58  * adds a new tracepoint block_rq_error and it shares the same arguments
59  * with tracepoint block_rq_complete. As a result, the kernel BTF now has
60  * a `struct trace_event_raw_block_rq_completion` instead of
61  * `struct trace_event_raw_block_rq_complete`.
62  * see:
63  *     https://github.com/torvalds/linux/commit/d5869fdc189f
64  */
65 struct trace_event_raw_block_rq_complete___x {
66 	dev_t dev;
67 	sector_t sector;
68 	unsigned int nr_sector;
69 } __attribute__((preserve_access_index));
70 
71 struct trace_event_raw_block_rq_completion___x {
72 	dev_t dev;
73 	sector_t sector;
74 	unsigned int nr_sector;
75 } __attribute__((preserve_access_index));
76 
has_block_rq_completion()77 static __always_inline bool has_block_rq_completion()
78 {
79 	if (bpf_core_type_exists(struct trace_event_raw_block_rq_completion___x))
80 		return true;
81 	return false;
82 }
83 
84 /**
85  * commit d152c682f03c ("block: add an explicit ->disk backpointer to the
86  * request_queue") and commit f3fa33acca9f ("block: remove the ->rq_disk
87  * field in struct request") make some changes to `struct request` and
88  * `struct request_queue`. Now, to get the `struct gendisk *` field in a CO-RE
89  * way, we need both `struct request` and `struct request_queue`.
90  * see:
91  *     https://github.com/torvalds/linux/commit/d152c682f03c
92  *     https://github.com/torvalds/linux/commit/f3fa33acca9f
93  */
94 struct request_queue___x {
95 	struct gendisk *disk;
96 } __attribute__((preserve_access_index));
97 
98 struct request___x {
99 	struct request_queue___x *q;
100 	struct gendisk *rq_disk;
101 } __attribute__((preserve_access_index));
102 
get_disk(void * request)103 static __always_inline struct gendisk *get_disk(void *request)
104 {
105 	struct request___x *r = request;
106 
107 	if (bpf_core_field_exists(r->rq_disk))
108 		return BPF_CORE_READ(r, rq_disk);
109 	return BPF_CORE_READ(r, q, disk);
110 }
111 
112 /**
113  * commit 6521f8917082("namei: prepare for idmapped mounts") add `struct
114  * user_namespace *mnt_userns` as vfs_create() and vfs_unlink() first argument.
115  * At the same time, struct renamedata {} add `struct user_namespace
116  * *old_mnt_userns` item. Now, to kprobe vfs_create()/vfs_unlink() in a CO-RE
117  * way, determine whether there is a `old_mnt_userns` field for `struct
118  * renamedata` to decide which input parameter of the vfs_create() to use as
119  * `dentry`.
120  * commit abf08576afe3("fs: port vfs_*() helpers to struct mnt_idmap") use
121  * `struct mnt_idmap *new_mnt_idmap` instead of `struct user_namespace *
122  * old_mnt_userns`.
123  * see:
124  *     https://github.com/torvalds/linux/commit/6521f8917082
125  *     https://github.com/torvalds/linux/commit/abf08576afe3
126  */
127 struct renamedata___x {
128 	struct user_namespace *old_mnt_userns;
129 	struct new_mnt_idmap *new_mnt_idmap;
130 } __attribute__((preserve_access_index));
131 
renamedata_has_old_mnt_userns_field(void)132 static __always_inline bool renamedata_has_old_mnt_userns_field(void)
133 {
134 	if (bpf_core_field_exists(struct renamedata___x, old_mnt_userns))
135 		return true;
136 	return false;
137 }
138 
renamedata_has_new_mnt_idmap_field(void)139 static __always_inline bool renamedata_has_new_mnt_idmap_field(void)
140 {
141 	if (bpf_core_field_exists(struct renamedata___x, new_mnt_idmap))
142 		return true;
143 	return false;
144 }
145 
146 /**
147  * commit 3544de8ee6e4("mm, tracing: record slab name for kmem_cache_free()")
148  * replaces `trace_event_raw_kmem_free` with `trace_event_raw_kfree` and adds
149  * `tracepoint_kmem_cache_free` to enhance the information recorded for
150  * `kmem_cache_free`.
151  * see:
152  *     https://github.com/torvalds/linux/commit/3544de8ee6e4
153  */
154 
155 struct trace_event_raw_kmem_free___x {
156 	const void *ptr;
157 } __attribute__((preserve_access_index));
158 
159 struct trace_event_raw_kfree___x {
160 	const void *ptr;
161 } __attribute__((preserve_access_index));
162 
163 struct trace_event_raw_kmem_cache_free___x {
164 	const void *ptr;
165 } __attribute__((preserve_access_index));
166 
has_kfree()167 static __always_inline bool has_kfree()
168 {
169 	if (bpf_core_type_exists(struct trace_event_raw_kfree___x))
170 		return true;
171 	return false;
172 }
173 
has_kmem_cache_free()174 static __always_inline bool has_kmem_cache_free()
175 {
176 	if (bpf_core_type_exists(struct trace_event_raw_kmem_cache_free___x))
177 		return true;
178 	return false;
179 }
180 
181 /**
182  * commit 11e9734bcb6a("mm/slab_common: unify NUMA and UMA version of
183  * tracepoints") drops kmem_alloc event class, rename kmem_alloc_node to
184  * kmem_alloc, so `trace_event_raw_kmem_alloc_node` is not existed any more.
185  * see:
186  *    https://github.com/torvalds/linux/commit/11e9734bcb6a
187  */
188 struct trace_event_raw_kmem_alloc_node___x {
189 	const void *ptr;
190 	size_t bytes_alloc;
191 } __attribute__((preserve_access_index));
192 
has_kmem_alloc_node(void)193 static __always_inline bool has_kmem_alloc_node(void)
194 {
195 	if (bpf_core_type_exists(struct trace_event_raw_kmem_alloc_node___x))
196 		return true;
197 	return false;
198 }
199 
200 /**
201  * commit 2c1d697fb8ba("mm/slab_common: drop kmem_alloc & avoid dereferencing
202  * fields when not using") drops kmem_alloc event class. As a result,
203  * `trace_event_raw_kmem_alloc` is removed, `trace_event_raw_kmalloc` and
204  * `trace_event_raw_kmem_cache_alloc` are added.
205  * see:
206  *    https://github.com/torvalds/linux/commit/2c1d697fb8ba
207  */
208 struct trace_event_raw_kmem_alloc___x {
209 	const void *ptr;
210 	size_t bytes_alloc;
211 } __attribute__((preserve_access_index));
212 
213 struct trace_event_raw_kmalloc___x {
214 	const void *ptr;
215 	size_t bytes_alloc;
216 } __attribute__((preserve_access_index));
217 
218 struct trace_event_raw_kmem_cache_alloc___x {
219 	const void *ptr;
220 	size_t bytes_alloc;
221 } __attribute__((preserve_access_index));
222 
has_kmem_alloc(void)223 static __always_inline bool has_kmem_alloc(void)
224 {
225 	if (bpf_core_type_exists(struct trace_event_raw_kmem_alloc___x))
226 		return true;
227 	return false;
228 }
229 
230 /**
231  * The bpf_get_socket_cookie helper is landed since kernel v4.12,
232  * but only available for tracing programs since kernel v5.12
233  * via commit c5dbb89fc2ac("bpf: Expose bpf_get_socket_cookie to tracing programs").
234  * Since the helper is used to provide a unique socket identifier,
235  * we could use the sock itself as the identifier if the helper is not available.
236  * Here, we use BPF_FUNC_check_mtu to check the availability of the helper
237  * since they are both introduced in v5.12.
238  *
239  * see:
240  *    https://github.com/torvalds/linux/commit/91b8270f2a4d
241  *    https://github.com/torvalds/linux/commit/c5dbb89fc2ac
242  *    https://github.com/torvalds/linux/commit/34b2021cc616
243  */
get_sock_ident(struct sock * sk)244 static __always_inline __u64 get_sock_ident(struct sock *sk)
245 {
246 	if (bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_check_mtu)) {
247 		return bpf_get_socket_cookie(sk);
248 	}
249 	return (__u64)sk;
250 }
251 
252 #endif /* __CORE_FIXES_BPF_H */
253