← Documents Documentation/bpf/kfuncs.rst GitHub 원문 ↗

Linux 6.18.37 · BPF

BPF Kernel Functions (kfuncs)

Kfunc 정의·parameter annotation·verifier flag·등록·lifecycle과 core task/cgroup/cpumask kfunc를 설명합니다.

Source pathDocumentation/bpf/kfuncs.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

kfuncs.rst:1-712

Kfunc는 kernel function을 BPF program에 노출하는 유연한 kernel 내부 API입니다. Wrapper의 extern linkage와 `__bpf_kfunc`, `__sz`·`__k`·`__uninit`·`__opt`·`__str`·`__prog` parameter annotation으로 verifier가 call contract를 이해하게 합니다.

`KF_ACQUIRE`, `KF_RELEASE`, `KF_RET_NULL`, `KF_TRUSTED_ARGS`, `KF_RCU`, `KF_RCU_PROTECTED` 등은 reference lifetime과 pointer validity를 강제합니다. Kfunc set은 BTF ID와 flag를 묶어 BPF program type별로 등록합니다.

Kfunc는 UAPI와 달리 hard stability guarantee가 없습니다. 일반적으로 `KF_DEPRECATED`와 kernel-doc을 통한 migration 기간을 제공하지만 subsystem maintainer는 기술적으로 필요하면 변경하거나 제거할 수 있으므로 out-of-tree user의 upstream 소통이 중요합니다.

Core kfunc 예제는 `task_struct`와 `cgroup` reference의 acquire·release, RCU read-side 접근, PID·ID lookup, cgroup ancestor 조회를 실제 BPF code로 보여 줍니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 .. _kfuncs-header-label:
4
5 =============================
6 BPF Kernel Functions (kfuncs)
7 =============================
8
9 1. Introduction
10 ===============
11
12 BPF Kernel Functions or more commonly known as kfuncs are functions in the Linux
13 kernel which are exposed for use by BPF programs. Unlike normal BPF helpers,
14 kfuncs do not have a stable interface and can change from one kernel release to
15 another. Hence, BPF programs need to be updated in response to changes in the
16 kernel. See :ref:`BPF_kfunc_lifecycle_expectations` for more information.
17
18 2. Defining a kfunc
19 ===================
20
21 There are two ways to expose a kernel function to BPF programs, either make an
22 existing function in the kernel visible, or add a new wrapper for BPF. In both
23 cases, care must be taken that BPF program can only call such function in a
24 valid context. To enforce this, visibility of a kfunc can be per program type.
25
26 If you are not creating a BPF wrapper for existing kernel function, skip ahead
27 to :ref:`BPF_kfunc_nodef`.
28
29 2.1 Creating a wrapper kfunc
30 ----------------------------
31
32 When defining a wrapper kfunc, the wrapper function should have extern linkage.
33 This prevents the compiler from optimizing away dead code, as this wrapper kfunc
34 is not invoked anywhere in the kernel itself. It is not necessary to provide a
35 prototype in a header for the wrapper kfunc.
36
37 An example is given below::
38
39 /* Disables missing prototype warnings */
40 __bpf_kfunc_start_defs();
41
42 __bpf_kfunc struct task_struct *bpf_find_get_task_by_vpid(pid_t nr)
43 {
44 return find_get_task_by_vpid(nr);
45 }
46
47 __bpf_kfunc_end_defs();
48
49 A wrapper kfunc is often needed when we need to annotate parameters of the
50 kfunc. Otherwise one may directly make the kfunc visible to the BPF program by
51 registering it with the BPF subsystem. See :ref:`BPF_kfunc_nodef`.
52
53 2.2 Annotating kfunc parameters
54 -------------------------------
55
56 Similar to BPF helpers, there is sometime need for additional context required
57 by the verifier to make the usage of kernel functions safer and more useful.
58 Hence, we can annotate a parameter by suffixing the name of the argument of the
59 kfunc with a __tag, where tag may be one of the supported annotations.
60
61 2.2.1 __sz Annotation
62 ---------------------
63
64 This annotation is used to indicate a memory and size pair in the argument list.
65 An example is given below::
66
67 __bpf_kfunc void bpf_memzero(void *mem, int mem__sz)
68 {
69 ...
70 }
71
72 Here, the verifier will treat first argument as a PTR_TO_MEM, and second
73 argument as its size. By default, without __sz annotation, the size of the type
74 of the pointer is used. Without __sz annotation, a kfunc cannot accept a void
75 pointer.
76
77 2.2.2 __k Annotation
78 --------------------
79
80 This annotation is only understood for scalar arguments, where it indicates that
81 the verifier must check the scalar argument to be a known constant, which does
82 not indicate a size parameter, and the value of the constant is relevant to the
83 safety of the program.
84
85 An example is given below::
86
87 __bpf_kfunc void *bpf_obj_new(u32 local_type_id__k, ...)
88 {
89 ...
90 }
91
92 Here, bpf_obj_new uses local_type_id argument to find out the size of that type
93 ID in program's BTF and return a sized pointer to it. Each type ID will have a
94 distinct size, hence it is crucial to treat each such call as distinct when
95 values don't match during verifier state pruning checks.
96
97 Hence, whenever a constant scalar argument is accepted by a kfunc which is not a
98 size parameter, and the value of the constant matters for program safety, __k
99 suffix should be used.
100
101 2.2.3 __uninit Annotation
102 -------------------------
103
104 This annotation is used to indicate that the argument will be treated as
105 uninitialized.
106
107 An example is given below::
108
109 __bpf_kfunc int bpf_dynptr_from_skb(..., struct bpf_dynptr_kern *ptr__uninit)
110 {
111 ...
112 }
113
114 Here, the dynptr will be treated as an uninitialized dynptr. Without this
115 annotation, the verifier will reject the program if the dynptr passed in is
116 not initialized.
117
118 2.2.4 __opt Annotation
119 -------------------------
120
121 This annotation is used to indicate that the buffer associated with an __sz or __szk
122 argument may be null. If the function is passed a nullptr in place of the buffer,
123 the verifier will not check that length is appropriate for the buffer. The kfunc is
124 responsible for checking if this buffer is null before using it.
125
126 An example is given below::
127
128 __bpf_kfunc void *bpf_dynptr_slice(..., void *buffer__opt, u32 buffer__szk)
129 {
130 ...
131 }
132
133 Here, the buffer may be null. If buffer is not null, it at least of size buffer_szk.
134 Either way, the returned buffer is either NULL, or of size buffer_szk. Without this
135 annotation, the verifier will reject the program if a null pointer is passed in with
136 a nonzero size.
137
138 2.2.5 __str Annotation
139 ----------------------------
140 This annotation is used to indicate that the argument is a constant string.
141
142 An example is given below::
143
144 __bpf_kfunc bpf_get_file_xattr(..., const char *name__str, ...)
145 {
146 ...
147 }
148
149 In this case, ``bpf_get_file_xattr()`` can be called as::
150
151 bpf_get_file_xattr(..., "xattr_name", ...);
152
153 Or::
154
155 const char name[] = "xattr_name"; /* This need to be global */
156 int BPF_PROG(...)
157 {
158 ...
159 bpf_get_file_xattr(..., name, ...);
160 ...
161 }
162
163 2.2.6 __prog Annotation
164 ---------------------------
165 This annotation is used to indicate that the argument needs to be fixed up to
166 the bpf_prog_aux of the caller BPF program. Any value passed into this argument
167 is ignored, and rewritten by the verifier.
168
169 An example is given below::
170
171 __bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
172 int (callback_fn)(void *map, int *key, void *value),
173 unsigned int flags,
174 void *aux__prog)
175 {
176 struct bpf_prog_aux *aux = aux__prog;
177 ...
178 }
179
180 .. _BPF_kfunc_nodef:
181
182 2.3 Using an existing kernel function
183 -------------------------------------
184
185 When an existing function in the kernel is fit for consumption by BPF programs,
186 it can be directly registered with the BPF subsystem. However, care must still
187 be taken to review the context in which it will be invoked by the BPF program
188 and whether it is safe to do so.
189
190 2.4 Annotating kfuncs
191 ---------------------
192
193 In addition to kfuncs' arguments, verifier may need more information about the
194 type of kfunc(s) being registered with the BPF subsystem. To do so, we define
195 flags on a set of kfuncs as follows::
196
197 BTF_KFUNCS_START(bpf_task_set)
198 BTF_ID_FLAGS(func, bpf_get_task_pid, KF_ACQUIRE | KF_RET_NULL)
199 BTF_ID_FLAGS(func, bpf_put_pid, KF_RELEASE)
200 BTF_KFUNCS_END(bpf_task_set)
201
202 This set encodes the BTF ID of each kfunc listed above, and encodes the flags
203 along with it. Ofcourse, it is also allowed to specify no flags.
204
205 kfunc definitions should also always be annotated with the ``__bpf_kfunc``
206 macro. This prevents issues such as the compiler inlining the kfunc if it's a
207 static kernel function, or the function being elided in an LTO build as it's
208 not used in the rest of the kernel. Developers should not manually add
209 annotations to their kfunc to prevent these issues. If an annotation is
210 required to prevent such an issue with your kfunc, it is a bug and should be
211 added to the definition of the macro so that other kfuncs are similarly
212 protected. An example is given below::
213
214 __bpf_kfunc struct task_struct *bpf_get_task_pid(s32 pid)
215 {
216 ...
217 }
218
219 2.4.1 KF_ACQUIRE flag
220 ---------------------
221
222 The KF_ACQUIRE flag is used to indicate that the kfunc returns a pointer to a
223 refcounted object. The verifier will then ensure that the pointer to the object
224 is eventually released using a release kfunc, or transferred to a map using a
225 referenced kptr (by invoking bpf_kptr_xchg). If not, the verifier fails the
226 loading of the BPF program until no lingering references remain in all possible
227 explored states of the program.
228
229 2.4.2 KF_RET_NULL flag
230 ----------------------
231
232 The KF_RET_NULL flag is used to indicate that the pointer returned by the kfunc
233 may be NULL. Hence, it forces the user to do a NULL check on the pointer
234 returned from the kfunc before making use of it (dereferencing or passing to
235 another helper). This flag is often used in pairing with KF_ACQUIRE flag, but
236 both are orthogonal to each other.
237
238 2.4.3 KF_RELEASE flag
239 ---------------------
240
241 The KF_RELEASE flag is used to indicate that the kfunc releases the pointer
242 passed in to it. There can be only one referenced pointer that can be passed
243 in. All copies of the pointer being released are invalidated as a result of
244 invoking kfunc with this flag. KF_RELEASE kfuncs automatically receive the
245 protection afforded by the KF_TRUSTED_ARGS flag described below.
246
247 2.4.4 KF_TRUSTED_ARGS flag
248 --------------------------
249
250 The KF_TRUSTED_ARGS flag is used for kfuncs taking pointer arguments. It
251 indicates that the all pointer arguments are valid, and that all pointers to
252 BTF objects have been passed in their unmodified form (that is, at a zero
253 offset, and without having been obtained from walking another pointer, with one
254 exception described below).
255
256 There are two types of pointers to kernel objects which are considered "valid":
257
258 1. Pointers which are passed as tracepoint or struct_ops callback arguments.
259 2. Pointers which were returned from a KF_ACQUIRE kfunc.
260
261 Pointers to non-BTF objects (e.g. scalar pointers) may also be passed to
262 KF_TRUSTED_ARGS kfuncs, and may have a non-zero offset.
263
264 The definition of "valid" pointers is subject to change at any time, and has
265 absolutely no ABI stability guarantees.
266
267 As mentioned above, a nested pointer obtained from walking a trusted pointer is
268 no longer trusted, with one exception. If a struct type has a field that is
269 guaranteed to be valid (trusted or rcu, as in KF_RCU description below) as long
270 as its parent pointer is valid, the following macros can be used to express
271 that to the verifier:
272
273 * ``BTF_TYPE_SAFE_TRUSTED``
274 * ``BTF_TYPE_SAFE_RCU``
275 * ``BTF_TYPE_SAFE_RCU_OR_NULL``
276
277 For example,
278
279 .. code-block:: c
280
281 BTF_TYPE_SAFE_TRUSTED(struct socket) {
282 struct sock *sk;
283 };
284
285 or
286
287 .. code-block:: c
288
289 BTF_TYPE_SAFE_RCU(struct task_struct) {
290 const cpumask_t *cpus_ptr;
291 struct css_set __rcu *cgroups;
292 struct task_struct __rcu *real_parent;
293 struct task_struct *group_leader;
294 };
295
296 In other words, you must:
297
298 1. Wrap the valid pointer type in a ``BTF_TYPE_SAFE_*`` macro.
299
300 2. Specify the type and name of the valid nested field. This field must match
301 the field in the original type definition exactly.
302
303 A new type declared by a ``BTF_TYPE_SAFE_*`` macro also needs to be emitted so
304 that it appears in BTF. For example, ``BTF_TYPE_SAFE_TRUSTED(struct socket)``
305 is emitted in the ``type_is_trusted()`` function as follows:
306
307 .. code-block:: c
308
309 BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct socket));
310
311
312 2.4.5 KF_SLEEPABLE flag
313 -----------------------
314
315 The KF_SLEEPABLE flag is used for kfuncs that may sleep. Such kfuncs can only
316 be called by sleepable BPF programs (BPF_F_SLEEPABLE).
317
318 2.4.6 KF_DESTRUCTIVE flag
319 --------------------------
320
321 The KF_DESTRUCTIVE flag is used to indicate functions calling which is
322 destructive to the system. For example such a call can result in system
323 rebooting or panicking. Due to this additional restrictions apply to these
324 calls. At the moment they only require CAP_SYS_BOOT capability, but more can be
325 added later.
326
327 2.4.7 KF_RCU flag
328 -----------------
329
330 The KF_RCU flag is a weaker version of KF_TRUSTED_ARGS. The kfuncs marked with
331 KF_RCU expect either PTR_TRUSTED or MEM_RCU arguments. The verifier guarantees
332 that the objects are valid and there is no use-after-free. The pointers are not
333 NULL, but the object's refcount could have reached zero. The kfuncs need to
334 consider doing refcnt != 0 check, especially when returning a KF_ACQUIRE
335 pointer. Note as well that a KF_ACQUIRE kfunc that is KF_RCU should very likely
336 also be KF_RET_NULL.
337
338 2.4.8 KF_RCU_PROTECTED flag
339 ---------------------------
340
341 The KF_RCU_PROTECTED flag is used to indicate that the kfunc must be invoked in
342 an RCU critical section. This is assumed by default in non-sleepable programs,
343 and must be explicitly ensured by calling ``bpf_rcu_read_lock`` for sleepable
344 ones.
345
346 If the kfunc returns a pointer value, this flag also enforces that the returned
347 pointer is RCU protected, and can only be used while the RCU critical section is
348 active.
349
350 The flag is distinct from the ``KF_RCU`` flag, which only ensures that its
351 arguments are at least RCU protected pointers. This may transitively imply that
352 RCU protection is ensured, but it does not work in cases of kfuncs which require
353 RCU protection but do not take RCU protected arguments.
354
355 .. _KF_deprecated_flag:
356
357 2.4.9 KF_DEPRECATED flag
358 ------------------------
359
360 The KF_DEPRECATED flag is used for kfuncs which are scheduled to be
361 changed or removed in a subsequent kernel release. A kfunc that is
362 marked with KF_DEPRECATED should also have any relevant information
363 captured in its kernel doc. Such information typically includes the
364 kfunc's expected remaining lifespan, a recommendation for new
365 functionality that can replace it if any is available, and possibly a
366 rationale for why it is being removed.
367
368 Note that while on some occasions, a KF_DEPRECATED kfunc may continue to be
369 supported and have its KF_DEPRECATED flag removed, it is likely to be far more
370 difficult to remove a KF_DEPRECATED flag after it's been added than it is to
371 prevent it from being added in the first place. As described in
372 :ref:`BPF_kfunc_lifecycle_expectations`, users that rely on specific kfuncs are
373 encouraged to make their use-cases known as early as possible, and participate
374 in upstream discussions regarding whether to keep, change, deprecate, or remove
375 those kfuncs if and when such discussions occur.
376
377 2.5 Registering the kfuncs
378 --------------------------
379
380 Once the kfunc is prepared for use, the final step to making it visible is
381 registering it with the BPF subsystem. Registration is done per BPF program
382 type. An example is shown below::
383
384 BTF_KFUNCS_START(bpf_task_set)
385 BTF_ID_FLAGS(func, bpf_get_task_pid, KF_ACQUIRE | KF_RET_NULL)
386 BTF_ID_FLAGS(func, bpf_put_pid, KF_RELEASE)
387 BTF_KFUNCS_END(bpf_task_set)
388
389 static const struct btf_kfunc_id_set bpf_task_kfunc_set = {
390 .owner = THIS_MODULE,
391 .set = &bpf_task_set,
392 };
393
394 static int init_subsystem(void)
395 {
396 return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_task_kfunc_set);
397 }
398 late_initcall(init_subsystem);
399
400 2.6 Specifying no-cast aliases with ___init
401 --------------------------------------------
402
403 The verifier will always enforce that the BTF type of a pointer passed to a
404 kfunc by a BPF program, matches the type of pointer specified in the kfunc
405 definition. The verifier, does, however, allow types that are equivalent
406 according to the C standard to be passed to the same kfunc arg, even if their
407 BTF_IDs differ.
408
409 For example, for the following type definition:
410
411 .. code-block:: c
412
413 struct bpf_cpumask {
414 cpumask_t cpumask;
415 refcount_t usage;
416 };
417
418 The verifier would allow a ``struct bpf_cpumask *`` to be passed to a kfunc
419 taking a ``cpumask_t *`` (which is a typedef of ``struct cpumask *``). For
420 instance, both ``struct cpumask *`` and ``struct bpf_cpmuask *`` can be passed
421 to bpf_cpumask_test_cpu().
422
423 In some cases, this type-aliasing behavior is not desired. ``struct
424 nf_conn___init`` is one such example:
425
426 .. code-block:: c
427
428 struct nf_conn___init {
429 struct nf_conn ct;
430 };
431
432 The C standard would consider these types to be equivalent, but it would not
433 always be safe to pass either type to a trusted kfunc. ``struct
434 nf_conn___init`` represents an allocated ``struct nf_conn`` object that has
435 *not yet been initialized*, so it would therefore be unsafe to pass a ``struct
436 nf_conn___init *`` to a kfunc that's expecting a fully initialized ``struct
437 nf_conn *`` (e.g. ``bpf_ct_change_timeout()``).
438
439 In order to accommodate such requirements, the verifier will enforce strict
440 PTR_TO_BTF_ID type matching if two types have the exact same name, with one
441 being suffixed with ``___init``.
442
443 .. _BPF_kfunc_lifecycle_expectations:
444
445 3. kfunc lifecycle expectations
446 ===============================
447
448 kfuncs provide a kernel <-> kernel API, and thus are not bound by any of the
449 strict stability restrictions associated with kernel <-> user UAPIs. This means
450 they can be thought of as similar to EXPORT_SYMBOL_GPL, and can therefore be
451 modified or removed by a maintainer of the subsystem they're defined in when
452 it's deemed necessary.
453
454 Like any other change to the kernel, maintainers will not change or remove a
455 kfunc without having a reasonable justification. Whether or not they'll choose
456 to change a kfunc will ultimately depend on a variety of factors, such as how
457 widely used the kfunc is, how long the kfunc has been in the kernel, whether an
458 alternative kfunc exists, what the norm is in terms of stability for the
459 subsystem in question, and of course what the technical cost is of continuing
460 to support the kfunc.
461
462 There are several implications of this:
463
464 a) kfuncs that are widely used or have been in the kernel for a long time will
465 be more difficult to justify being changed or removed by a maintainer. In
466 other words, kfuncs that are known to have a lot of users and provide
467 significant value provide stronger incentives for maintainers to invest the
468 time and complexity in supporting them. It is therefore important for
469 developers that are using kfuncs in their BPF programs to communicate and
470 explain how and why those kfuncs are being used, and to participate in
471 discussions regarding those kfuncs when they occur upstream.
472
473 b) Unlike regular kernel symbols marked with EXPORT_SYMBOL_GPL, BPF programs
474 that call kfuncs are generally not part of the kernel tree. This means that
475 refactoring cannot typically change callers in-place when a kfunc changes,
476 as is done for e.g. an upstreamed driver being updated in place when a
477 kernel symbol is changed.
478
479 Unlike with regular kernel symbols, this is expected behavior for BPF
480 symbols, and out-of-tree BPF programs that use kfuncs should be considered
481 relevant to discussions and decisions around modifying and removing those
482 kfuncs. The BPF community will take an active role in participating in
483 upstream discussions when necessary to ensure that the perspectives of such
484 users are taken into account.
485
486 c) A kfunc will never have any hard stability guarantees. BPF APIs cannot and
487 will not ever hard-block a change in the kernel purely for stability
488 reasons. That being said, kfuncs are features that are meant to solve
489 problems and provide value to users. The decision of whether to change or
490 remove a kfunc is a multivariate technical decision that is made on a
491 case-by-case basis, and which is informed by data points such as those
492 mentioned above. It is expected that a kfunc being removed or changed with
493 no warning will not be a common occurrence or take place without sound
494 justification, but it is a possibility that must be accepted if one is to
495 use kfuncs.
496
497 3.1 kfunc deprecation
498 ---------------------
499
500 As described above, while sometimes a maintainer may find that a kfunc must be
501 changed or removed immediately to accommodate some changes in their subsystem,
502 usually kfuncs will be able to accommodate a longer and more measured
503 deprecation process. For example, if a new kfunc comes along which provides
504 superior functionality to an existing kfunc, the existing kfunc may be
505 deprecated for some period of time to allow users to migrate their BPF programs
506 to use the new one. Or, if a kfunc has no known users, a decision may be made
507 to remove the kfunc (without providing an alternative API) after some
508 deprecation period so as to provide users with a window to notify the kfunc
509 maintainer if it turns out that the kfunc is actually being used.
510
511 It's expected that the common case will be that kfuncs will go through a
512 deprecation period rather than being changed or removed without warning. As
513 described in :ref:`KF_deprecated_flag`, the kfunc framework provides the
514 KF_DEPRECATED flag to kfunc developers to signal to users that a kfunc has been
515 deprecated. Once a kfunc has been marked with KF_DEPRECATED, the following
516 procedure is followed for removal:
517
518 1. Any relevant information for deprecated kfuncs is documented in the kfunc's
519 kernel docs. This documentation will typically include the kfunc's expected
520 remaining lifespan, a recommendation for new functionality that can replace
521 the usage of the deprecated function (or an explanation as to why no such
522 replacement exists), etc.
523
524 2. The deprecated kfunc is kept in the kernel for some period of time after it
525 was first marked as deprecated. This time period will be chosen on a
526 case-by-case basis, and will typically depend on how widespread the use of
527 the kfunc is, how long it has been in the kernel, and how hard it is to move
528 to alternatives. This deprecation time period is "best effort", and as
529 described :ref:`above<BPF_kfunc_lifecycle_expectations>`, circumstances may
530 sometimes dictate that the kfunc be removed before the full intended
531 deprecation period has elapsed.
532
533 3. After the deprecation period the kfunc will be removed. At this point, BPF
534 programs calling the kfunc will be rejected by the verifier.
535
536 4. Core kfuncs
537 ==============
538
539 The BPF subsystem provides a number of "core" kfuncs that are potentially
540 applicable to a wide variety of different possible use cases and programs.
541 Those kfuncs are documented here.
542
543 4.1 struct task_struct * kfuncs
544 -------------------------------
545
546 There are a number of kfuncs that allow ``struct task_struct *`` objects to be
547 used as kptrs:
548
549 .. kernel-doc:: kernel/bpf/helpers.c
550 :identifiers: bpf_task_acquire bpf_task_release
551
552 These kfuncs are useful when you want to acquire or release a reference to a
553 ``struct task_struct *`` that was passed as e.g. a tracepoint arg, or a
554 struct_ops callback arg. For example:
555
556 .. code-block:: c
557
558 /**
559 * A trivial example tracepoint program that shows how to
560 * acquire and release a struct task_struct * pointer.
561 */
562 SEC("tp_btf/task_newtask")
563 int BPF_PROG(task_acquire_release_example, struct task_struct *task, u64 clone_flags)
564 {
565 struct task_struct *acquired;
566
567 acquired = bpf_task_acquire(task);
568 if (acquired)
569 /*
570 * In a typical program you'd do something like store
571 * the task in a map, and the map will automatically
572 * release it later. Here, we release it manually.
573 */
574 bpf_task_release(acquired);
575 return 0;
576 }
577
578
579 References acquired on ``struct task_struct *`` objects are RCU protected.
580 Therefore, when in an RCU read region, you can obtain a pointer to a task
581 embedded in a map value without having to acquire a reference:
582
583 .. code-block:: c
584
585 #define private(name) SEC(".data." #name) __hidden __attribute__((aligned(8)))
586 private(TASK) static struct task_struct *global;
587
588 /**
589 * A trivial example showing how to access a task stored
590 * in a map using RCU.
591 */
592 SEC("tp_btf/task_newtask")
593 int BPF_PROG(task_rcu_read_example, struct task_struct *task, u64 clone_flags)
594 {
595 struct task_struct *local_copy;
596
597 bpf_rcu_read_lock();
598 local_copy = global;
599 if (local_copy)
600 /*
601 * We could also pass local_copy to kfuncs or helper functions here,
602 * as we're guaranteed that local_copy will be valid until we exit
603 * the RCU read region below.
604 */
605 bpf_printk("Global task %s is valid", local_copy->comm);
606 else
607 bpf_printk("No global task found");
608 bpf_rcu_read_unlock();
609
610 /* At this point we can no longer reference local_copy. */
611
612 return 0;
613 }
614
615 ----
616
617 A BPF program can also look up a task from a pid. This can be useful if the
618 caller doesn't have a trusted pointer to a ``struct task_struct *`` object that
619 it can acquire a reference on with bpf_task_acquire().
620
621 .. kernel-doc:: kernel/bpf/helpers.c
622 :identifiers: bpf_task_from_pid
623
624 Here is an example of it being used:
625
626 .. code-block:: c
627
628 SEC("tp_btf/task_newtask")
629 int BPF_PROG(task_get_pid_example, struct task_struct *task, u64 clone_flags)
630 {
631 struct task_struct *lookup;
632
633 lookup = bpf_task_from_pid(task->pid);
634 if (!lookup)
635 /* A task should always be found, as %task is a tracepoint arg. */
636 return -ENOENT;
637
638 if (lookup->pid != task->pid) {
639 /* bpf_task_from_pid() looks up the task via its
640 * globally-unique pid from the init_pid_ns. Thus,
641 * the pid of the lookup task should always be the
642 * same as the input task.
643 */
644 bpf_task_release(lookup);
645 return -EINVAL;
646 }
647
648 /* bpf_task_from_pid() returns an acquired reference,
649 * so it must be dropped before returning from the
650 * tracepoint handler.
651 */
652 bpf_task_release(lookup);
653 return 0;
654 }
655
656 4.2 struct cgroup * kfuncs
657 --------------------------
658
659 ``struct cgroup *`` objects also have acquire and release functions:
660
661 .. kernel-doc:: kernel/bpf/helpers.c
662 :identifiers: bpf_cgroup_acquire bpf_cgroup_release
663
664 These kfuncs are used in exactly the same manner as bpf_task_acquire() and
665 bpf_task_release() respectively, so we won't provide examples for them.
666
667 ----
668
669 Other kfuncs available for interacting with ``struct cgroup *`` objects are
670 bpf_cgroup_ancestor() and bpf_cgroup_from_id(), allowing callers to access
671 the ancestor of a cgroup and find a cgroup by its ID, respectively. Both
672 return a cgroup kptr.
673
674 .. kernel-doc:: kernel/bpf/helpers.c
675 :identifiers: bpf_cgroup_ancestor
676
677 .. kernel-doc:: kernel/bpf/helpers.c
678 :identifiers: bpf_cgroup_from_id
679
680 Eventually, BPF should be updated to allow this to happen with a normal memory
681 load in the program itself. This is currently not possible without more work in
682 the verifier. bpf_cgroup_ancestor() can be used as follows:
683
684 .. code-block:: c
685
686 /**
687 * Simple tracepoint example that illustrates how a cgroup's
688 * ancestor can be accessed using bpf_cgroup_ancestor().
689 */
690 SEC("tp_btf/cgroup_mkdir")
691 int BPF_PROG(cgrp_ancestor_example, struct cgroup *cgrp, const char *path)
692 {
693 struct cgroup *parent;
694
695 /* The parent cgroup resides at the level before the current cgroup's level. */
696 parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
697 if (!parent)
698 return -ENOENT;
699
700 bpf_printk("Parent id is %d", parent->self.id);
701
702 /* Return the parent cgroup that was acquired above. */
703 bpf_cgroup_release(parent);
704 return 0;
705 }
706
707 4.3 struct cpumask * kfuncs
708 ---------------------------
709
710 BPF provides a set of kfuncs that can be used to query, allocate, mutate, and
711 destroy struct cpumask * objects. Please refer to :ref:`cpumasks-header-label`
712 for more details.
713

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

BPF kernel function 소개

1-17

이 문서는 `GPL-2.0` license를 따르며 `kfuncs-header-label` anchor에서 BPF Kernel Functions (kfuncs)를 설명합니다.

BPF Kernel Function, 더 흔히 kfunc라고 부르는 function은 BPF program이 사용할 수 있도록 노출한 Linux kernel function입니다.

일반 BPF helper와 달리 kfunc는 stable interface가 아니며 kernel release 사이에 바뀔 수 있습니다. 따라서 kernel 변경에 맞춰 BPF program도 갱신해야 합니다. 자세한 내용은 `BPF_kfunc_lifecycle_expectations`를 참조합니다.

Kfunc를 정의하는 두 방법

18-28

Kernel function을 BPF program에 노출하는 방법은 기존 kernel function을 visible하게 만드는 방법과 BPF용 새 wrapper를 추가하는 방법 두 가지입니다.

어느 경우든 BPF program이 valid context에서만 function을 호출하도록 주의해야 합니다. 이를 강제하기 위해 kfunc visibility를 program type별로 지정할 수 있습니다.

기존 kernel function의 BPF wrapper를 만들지 않는다면 `BPF_kfunc_nodef` 절로 건너갑니다.

Wrapper kfunc 작성

29-52

Wrapper kfunc를 정의할 때 wrapper function은 extern linkage를 가져야 합니다. Kernel 자체에서는 이 wrapper kfunc를 호출하지 않으므로, 이렇게 해야 compiler가 dead code로 최적화해 없애지 않습니다. Wrapper kfunc prototype을 header에 둘 필요는 없습니다.

/* Disables missing prototype warnings */
__bpf_kfunc_start_defs();

__bpf_kfunc struct task_struct *bpf_find_get_task_by_vpid(pid_t nr)
{
        return find_get_task_by_vpid(nr);
}

__bpf_kfunc_end_defs();

Kfunc parameter에 annotation이 필요할 때 wrapper kfunc가 흔히 필요합니다. 그렇지 않다면 BPF subsystem에 등록해 kfunc를 BPF program에 직접 노출할 수 있습니다. `BPF_kfunc_nodef` 절을 참조합니다.

Kfunc parameter annotation

53-60

BPF helper와 마찬가지로 verifier가 kernel function을 더 안전하고 유용하게 사용하도록 추가 context가 필요한 경우가 있습니다.

Kfunc argument 이름 끝에 `__tag`를 붙여 parameter를 annotate할 수 있으며, tag에는 지원되는 annotation 중 하나를 사용합니다.

__sz annotation

61-76

`__sz` annotation은 argument list의 memory와 size pair를 나타냅니다.

__bpf_kfunc void bpf_memzero(void *mem, int mem__sz)
{
...
}

Verifier는 첫 argument를 `PTR_TO_MEM`으로, 둘째 argument를 그 memory의 size로 취급합니다. 기본적으로 `__sz` annotation이 없으면 pointer가 가리키는 type의 size를 사용합니다. `__sz`가 없으면 kfunc는 void pointer를 받을 수 없습니다.

__k annotation

77-100

`__k` annotation은 scalar argument에만 적용됩니다. 이는 verifier가 해당 scalar를 알려진 constant인지 확인해야 하고, 그 argument가 size parameter는 아니지만 constant value가 program safety에 중요함을 나타냅니다.

__bpf_kfunc void *bpf_obj_new(u32 local_type_id__k, ...)
{
...
}

`bpf_obj_new`는 `local_type_id` argument로 program BTF에서 해당 type ID의 size를 알아낸 뒤 그 size를 가진 pointer를 반환합니다. Type ID마다 size가 다르므로 verifier state pruning에서 value가 일치하지 않을 때 각 call을 별개의 call로 취급하는 것이 중요합니다.

따라서 kfunc가 size parameter가 아닌 constant scalar argument를 받고 그 constant value가 program safety에 중요하면 `__k` suffix를 사용해야 합니다.

__uninit annotation

101-117

`__uninit` annotation은 argument를 uninitialized 상태로 취급함을 나타냅니다.

__bpf_kfunc int bpf_dynptr_from_skb(..., struct bpf_dynptr_kern *ptr__uninit)
{
...
}

이 예제에서는 dynptr를 uninitialized dynptr로 취급합니다. 이 annotation이 없으면 전달된 dynptr가 initialize되지 않았을 때 verifier가 program을 reject합니다.

__opt annotation

118-137

`__opt` annotation은 `__sz` 또는 `__szk` argument와 연결된 buffer가 null일 수 있음을 나타냅니다. Buffer 대신 nullptr를 전달하면 verifier는 length가 buffer에 적절한지 확인하지 않습니다. Kfunc는 buffer를 사용하기 전에 null인지 직접 확인해야 합니다.

__bpf_kfunc void *bpf_dynptr_slice(..., void *buffer__opt, u32 buffer__szk)
{
...
}

이 예제에서 buffer는 null일 수 있습니다. Null이 아니면 적어도 `buffer__szk` size입니다. 반환된 buffer도 NULL이거나 `buffer__szk` size입니다. 이 annotation이 없으면 nonzero size와 함께 null pointer를 전달한 program을 verifier가 reject합니다.

__str annotation

138-162

`__str` annotation은 argument가 constant string임을 나타냅니다.

__bpf_kfunc bpf_get_file_xattr(..., const char *name__str, ...)
{
...
}

이 경우 `bpf_get_file_xattr()`는 string literal로 호출할 수 있습니다.

bpf_get_file_xattr(..., "xattr_name", ...);

또는 global이어야 하는 constant character array를 정의해 전달할 수 있습니다.

const char name[] = "xattr_name";  /* This need to be global */
int BPF_PROG(...)
{
        ...
        bpf_get_file_xattr(..., name, ...);
        ...
}

__prog annotation

163-179

`__prog` annotation은 argument를 caller BPF program의 `bpf_prog_aux`로 fix up해야 함을 나타냅니다. 이 argument에 전달한 값은 무시되고 verifier가 다시 씁니다.

__bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
                                         int (callback_fn)(void *map, int *key, void *value),
                                         unsigned int flags,
                                         void *aux__prog)
 {
        struct bpf_prog_aux *aux = aux__prog;
        ...
 }

기존 kernel function 사용

180-189

`BPF_kfunc_nodef` anchor 절입니다. 기존 kernel function이 BPF program에서 사용하기 적합하면 BPF subsystem에 직접 등록할 수 있습니다.

그래도 BPF program이 어떤 context에서 호출할지와 그 호출이 안전한지는 반드시 검토해야 합니다.

Kfunc flag annotation

190-218

Verifier는 kfunc argument 외에도 BPF subsystem에 등록하는 kfunc type에 관한 정보가 더 필요할 수 있습니다. 이를 위해 kfunc set에 flag를 정의합니다.

BTF_KFUNCS_START(bpf_task_set)
BTF_ID_FLAGS(func, bpf_get_task_pid, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_put_pid, KF_RELEASE)
BTF_KFUNCS_END(bpf_task_set)

이 set은 나열한 각 kfunc의 BTF ID와 flag를 함께 encode합니다. Flag를 지정하지 않아도 됩니다.

Kfunc definition에는 항상 `__bpf_kfunc` macro도 붙여야 합니다. 이는 static kernel function인 kfunc를 compiler가 inline하거나, kernel의 다른 곳에서 사용되지 않는 function을 LTO build가 제거하는 문제를 막습니다.

Developer가 이 문제를 막으려고 kfunc에 annotation을 수동으로 추가해서는 안 됩니다. 특정 annotation이 필요하다면 그것은 bug이며 다른 kfunc도 보호받도록 macro definition에 추가해야 합니다.

__bpf_kfunc struct task_struct *bpf_get_task_pid(s32 pid)
{
...
}

KF_ACQUIRE flag

219-228

`KF_ACQUIRE`는 kfunc가 refcounted object pointer를 반환함을 나타냅니다. Verifier는 release kfunc로 pointer를 최종 release하거나 `bpf_kptr_xchg`를 호출해 referenced kptr로 map에 이전하도록 강제합니다.

Program의 가능한 모든 explored state에 남은 reference가 없어질 때까지 이 조건을 만족하지 않으면 verifier가 BPF program load를 실패시킵니다.

KF_RET_NULL flag

229-237

`KF_RET_NULL`은 kfunc가 반환한 pointer가 NULL일 수 있음을 나타냅니다. 따라서 user는 pointer를 dereference하거나 다른 helper에 넘기기 전에 NULL check를 해야 합니다.

이 flag는 흔히 `KF_ACQUIRE`와 함께 사용하지만 두 flag는 서로 orthogonal합니다.

KF_RELEASE flag

238-246

`KF_RELEASE`는 kfunc가 전달받은 pointer를 release함을 나타냅니다. Referenced pointer는 하나만 전달할 수 있고, 이 flag를 가진 kfunc를 호출하면 release된 pointer의 모든 copy가 invalidate됩니다.

`KF_RELEASE` kfunc는 아래에서 설명하는 `KF_TRUSTED_ARGS` flag의 보호를 자동으로 받습니다.

KF_TRUSTED_ARGS와 valid pointer

247-278

`KF_TRUSTED_ARGS`는 pointer argument를 받는 kfunc에 사용합니다. 모든 pointer argument가 valid하고, BTF object pointer는 수정되지 않은 형태, 즉 zero offset이고 다른 pointer를 따라가 얻은 것이 아닌 형태로 전달됐음을 나타냅니다. 아래에 한 가지 예외가 있습니다.

Valid한 kernel object pointer는 두 종류입니다.

  • Tracepoint 또는 `struct_ops` callback argument로 전달된 pointer
  • `KF_ACQUIRE` kfunc가 반환한 pointer

Non-BTF object pointer, 예를 들어 scalar pointer도 `KF_TRUSTED_ARGS` kfunc에 전달할 수 있으며 non-zero offset을 가질 수 있습니다.

"Valid" pointer의 정의는 언제든 바뀔 수 있고 ABI stability를 전혀 보장하지 않습니다.

Trusted pointer를 따라가 얻은 nested pointer는 더 이상 trusted하지 않지만 예외가 하나 있습니다. Parent pointer가 valid한 동안 valid(trusted 또는 아래 `KF_RCU`에서 말하는 rcu)하다고 보장되는 field가 struct type에 있다면 다음 macro로 verifier에 이를 표현할 수 있습니다.

  • `BTF_TYPE_SAFE_TRUSTED`
  • `BTF_TYPE_SAFE_RCU`
  • `BTF_TYPE_SAFE_RCU_OR_NULL`

안전한 nested field type 선언

279-311

Trusted nested field 선언 예제입니다.

BTF_TYPE_SAFE_TRUSTED(struct socket) {
        struct sock *sk;
};

RCU-protected nested field 선언 예제입니다.

BTF_TYPE_SAFE_RCU(struct task_struct) {
        const cpumask_t *cpus_ptr;
        struct css_set __rcu *cgroups;
        struct task_struct __rcu *real_parent;
        struct task_struct *group_leader;
};

즉 다음 두 조건을 지켜야 합니다.

  • Valid pointer type을 `BTF_TYPE_SAFE_*` macro로 감쌉니다.
  • Valid nested field의 type과 name을 지정합니다. 이 field는 original type definition의 field와 정확히 일치해야 합니다.

`BTF_TYPE_SAFE_*` macro가 선언한 새 type은 BTF에 나타나도록 emit해야 합니다. 예를 들어 `BTF_TYPE_SAFE_TRUSTED(struct socket)`은 `type_is_trusted()` function에서 다음과 같이 emit합니다.

BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct socket));

KF_SLEEPABLE과 KF_DESTRUCTIVE

312-326

`KF_SLEEPABLE`은 sleep할 수 있는 kfunc에 사용합니다. 이런 kfunc는 sleepable BPF program(`BPF_F_SLEEPABLE`)에서만 호출할 수 있습니다.

`KF_DESTRUCTIVE`는 호출하면 system에 파괴적인 영향을 주는 function을 나타냅니다. 예를 들어 system reboot나 panic을 일으킬 수 있으므로 추가 제약을 적용합니다. 현재는 `CAP_SYS_BOOT` capability만 요구하지만 이후 더 추가될 수 있습니다.

KF_RCU와 KF_RCU_PROTECTED

327-354

`KF_RCU`는 `KF_TRUSTED_ARGS`보다 약한 형태입니다. `KF_RCU` kfunc는 `PTR_TRUSTED` 또는 `MEM_RCU` argument를 기대합니다. Verifier는 object가 valid하고 use-after-free가 없음을 보장합니다.

Pointer는 NULL이 아니지만 object refcount는 0에 도달했을 수 있습니다. 특히 `KF_ACQUIRE` pointer를 반환할 때 kfunc는 `refcnt != 0` check를 고려해야 합니다. `KF_ACQUIRE`이면서 `KF_RCU`인 kfunc는 거의 항상 `KF_RET_NULL`도 함께 가져야 합니다.

`KF_RCU_PROTECTED`는 kfunc를 RCU critical section 안에서 호출해야 함을 나타냅니다. Non-sleepable program에서는 기본적으로 이를 가정하고, sleepable program에서는 `bpf_rcu_read_lock`을 호출해 명시적으로 보장해야 합니다.

Kfunc가 pointer를 반환하면 이 flag는 반환 pointer도 RCU-protected임을 강제하며 RCU critical section이 active한 동안에만 사용할 수 있습니다.

이 flag는 argument가 적어도 RCU-protected pointer임만 보장하는 `KF_RCU`와 구별됩니다. Argument 특성상 RCU protection을 transitive하게 암시할 수 있지만, RCU-protected argument를 받지 않으면서 RCU protection을 요구하는 kfunc에는 적용되지 않습니다.

KF_DEPRECATED flag

355-376

`KF_deprecated_flag` anchor 절입니다. `KF_DEPRECATED`는 다음 kernel release에서 변경하거나 제거할 예정인 kfunc에 사용합니다.

이 flag를 붙인 kfunc의 kernel doc에는 예상되는 남은 lifespan, 사용 가능한 대체 기능에 대한 권고, 제거 이유 같은 관련 정보를 담아야 합니다.

때로는 deprecated kfunc 지원을 계속하고 flag를 제거할 수도 있지만, 한번 추가한 `KF_DEPRECATED`를 제거하기는 처음부터 붙이지 않는 것보다 훨씬 어렵습니다.

`BPF_kfunc_lifecycle_expectations`에서 설명하듯 특정 kfunc에 의존하는 user는 use case를 가능한 한 일찍 알리고, 해당 kfunc의 유지·변경·deprecate·제거를 논의하는 upstream discussion에 참여하는 것이 좋습니다.

Kfunc set 등록

377-399

Kfunc를 사용할 준비가 끝나면 마지막 단계는 BPF subsystem에 등록해 visible하게 만드는 것입니다. 등록은 BPF program type별로 수행합니다.

BTF_KFUNCS_START(bpf_task_set)
BTF_ID_FLAGS(func, bpf_get_task_pid, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func, bpf_put_pid, KF_RELEASE)
BTF_KFUNCS_END(bpf_task_set)

static const struct btf_kfunc_id_set bpf_task_kfunc_set = {
        .owner = THIS_MODULE,
        .set   = &bpf_task_set,
};

static int init_subsystem(void)
{
        return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_task_kfunc_set);
}
late_initcall(init_subsystem);

예제는 `bpf_task_set`에 acquire/release flag를 encode하고 `btf_kfunc_id_set`의 owner와 set을 지정한 뒤 `register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, ...)`로 tracing program type에 등록합니다.

___init no-cast alias

400-442

Verifier는 BPF program이 kfunc에 전달한 pointer의 BTF type이 kfunc definition의 pointer type과 일치하도록 항상 강제합니다. 다만 BTF ID가 달라도 C standard상 equivalent한 type은 같은 kfunc argument로 허용합니다.

다음 type definition을 예로 듭니다.

struct bpf_cpumask {
        cpumask_t cpumask;
        refcount_t usage;
};

Verifier는 `struct bpf_cpumask *`를 `cpumask_t *`(`struct cpumask *` typedef)를 받는 kfunc에 전달하도록 허용합니다. 예를 들어 `struct cpumask *`와 `struct bpf_cpmuask *` 모두 `bpf_cpumask_test_cpu()`에 전달할 수 있습니다.

이 type aliasing 동작을 원하지 않는 경우도 있습니다. `struct nf_conn___init`가 그런 예입니다.

struct nf_conn___init {
        struct nf_conn ct;
};

C standard는 이 type들을 equivalent하게 보지만 trusted kfunc에 둘 중 어느 type이나 전달하는 것이 항상 안전하지는 않습니다. `struct nf_conn___init`는 allocate됐지만 아직 initialize되지 않은 `struct nf_conn` object를 나타냅니다.

따라서 완전히 initialize된 `struct nf_conn *`을 기대하는 `bpf_ct_change_timeout()` 같은 kfunc에 `struct nf_conn___init *`을 넘기면 안전하지 않습니다.

이 요구를 지원하기 위해 이름이 정확히 같고 한쪽에 `___init` suffix가 붙은 두 type에는 verifier가 strict `PTR_TO_BTF_ID` type matching을 강제합니다.

Kfunc lifecycle과 안정성 기대

443-461

`BPF_kfunc_lifecycle_expectations` anchor 절입니다. Kfunc는 kernel과 kernel 사이의 API이므로 kernel과 user 사이 UAPI에 적용되는 엄격한 stability 제약을 받지 않습니다.

따라서 `EXPORT_SYMBOL_GPL`과 비슷하게 생각할 수 있으며, 필요하다고 판단하면 kfunc가 정의된 subsystem maintainer가 수정하거나 제거할 수 있습니다.

다른 kernel 변경과 마찬가지로 maintainer는 합리적 정당화 없이 kfunc를 바꾸거나 제거하지 않습니다. 결정은 사용 범위, kernel에 존재한 기간, 대체 kfunc 유무, 해당 subsystem의 stability 관행, 계속 지원하는 기술적 비용 등 여러 요인에 좌우됩니다.

사용자가 많은 kfunc와 upstream 소통

462-472

a) 널리 사용되거나 kernel에 오래 존재한 kfunc는 maintainer가 변경이나 제거를 정당화하기 더 어렵습니다. User가 많고 큰 가치를 제공한다고 알려진 kfunc는 maintainer가 지원에 시간과 복잡성을 투자할 동기를 강화합니다.

따라서 BPF program에서 kfunc를 사용하는 developer는 그 kfunc를 어떻게, 왜 사용하는지 알리고 설명하며 관련 upstream discussion에 참여하는 것이 중요합니다.

Out-of-tree BPF caller 고려

473-485

b) `EXPORT_SYMBOL_GPL`로 표시한 일반 kernel symbol과 달리 kfunc를 호출하는 BPF program은 대개 kernel tree 밖에 있습니다. 따라서 kfunc가 바뀔 때 upstream driver caller를 함께 고치듯 refactoring으로 caller를 제자리에서 일괄 변경할 수 없습니다.

이는 BPF symbol에서 예상되는 동작입니다. Kfunc를 사용하는 out-of-tree BPF program도 kfunc 수정·제거 discussion과 decision에서 관련 user로 간주해야 합니다. BPF community는 필요할 때 upstream discussion에 적극 참여해 이 user들의 관점을 고려하도록 합니다.

Hard stability guarantee는 없음

486-496

c) Kfunc에는 hard stability guarantee가 결코 없습니다. BPF API는 순전히 stability를 이유로 kernel change를 hard-block할 수 없고 앞으로도 그러지 않습니다.

그렇더라도 kfunc는 문제를 해결하고 user에게 가치를 제공하려는 feature입니다. 변경·제거 여부는 앞의 data point를 고려한 다변수 기술 decision이며 case-by-case로 결정합니다.

경고 없이 kfunc를 제거하거나 변경하는 일이 흔하거나 충분한 정당화 없이 일어나지는 않을 것으로 기대하지만, kfunc를 사용하려면 그런 가능성을 받아들여야 합니다.

Kfunc deprecation 과정

497-517

Subsystem 변경 때문에 kfunc를 즉시 바꾸거나 제거해야 할 때도 있지만, 보통은 더 길고 신중한 deprecation process를 적용할 수 있습니다.

새 kfunc가 기존 kfunc보다 우수한 기능을 제공하면 user가 BPF program을 새 API로 migrate할 기간을 주기 위해 기존 kfunc를 일정 기간 deprecate할 수 있습니다.

알려진 user가 없는 kfunc라면 일정 deprecation period 후 대체 API 없이 제거하기로 결정할 수도 있습니다. 실제 user가 있다면 그 기간에 maintainer에게 알릴 수 있습니다.

일반적으로 kfunc는 경고 없이 변경·제거되기보다 deprecation period를 거칠 것으로 기대합니다. `KF_deprecated_flag` 절의 `KF_DEPRECATED` flag로 developer가 deprecated 상태를 알리며, 그 뒤 다음 제거 절차를 따릅니다.

Deprecated kfunc 제거 절차

518-535
  • 1. Deprecated kfunc 관련 정보를 kernel docs에 기록합니다. 일반적으로 예상되는 남은 lifespan, deprecated function을 대신할 새 기능에 대한 권고 또는 대체가 없는 이유 등을 포함합니다.
  • 2. 처음 deprecated로 표시한 뒤 일정 기간 kernel에 유지합니다. 기간은 case-by-case로 정하며 보통 사용 범위, kernel에 존재한 기간, 대체 기능으로 이동하기 어려운 정도에 따라 달라집니다. 이 기간은 best effort이므로 상황에 따라 의도한 기간이 모두 지나기 전에 제거할 수도 있습니다.
  • 3. Deprecation period가 끝나면 kfunc를 제거합니다. 이때 해당 kfunc를 호출하는 BPF program은 verifier가 reject합니다.

Core kfunc

536-542

BPF subsystem은 매우 다양한 use case와 program에 적용할 수 있는 여러 "core" kfunc를 제공합니다. 이 절에서 그 kfunc를 설명합니다.

struct task_struct reference acquire와 release

543-578

`struct task_struct *` object를 kptr로 사용할 수 있게 하는 여러 kfunc가 있습니다. `kernel/bpf/helpers.c`의 kernel-doc에서 `bpf_task_acquire`와 `bpf_task_release`를 가져옵니다.

Tracepoint argument나 `struct_ops` callback argument로 받은 `struct task_struct *` reference를 acquire하거나 release할 때 유용합니다.

/**
 * A trivial example tracepoint program that shows how to
 * acquire and release a struct task_struct * pointer.
 */
SEC("tp_btf/task_newtask")
int BPF_PROG(task_acquire_release_example, struct task_struct *task, u64 clone_flags)
{
        struct task_struct *acquired;

        acquired = bpf_task_acquire(task);
        if (acquired)
                /*
                 * In a typical program you'd do something like store
                 * the task in a map, and the map will automatically
                 * release it later. Here, we release it manually.
                 */
                bpf_task_release(acquired);
        return 0;
}

RCU로 map의 task pointer 접근

579-616

`struct task_struct *` object에서 acquire한 reference는 RCU-protected입니다. 따라서 RCU read region 안에서는 reference를 acquire하지 않고도 map value에 embedded된 task pointer를 얻을 수 있습니다.

#define private(name) SEC(".data." #name) __hidden __attribute__((aligned(8)))
private(TASK) static struct task_struct *global;

/**
 * A trivial example showing how to access a task stored
 * in a map using RCU.
 */
SEC("tp_btf/task_newtask")
int BPF_PROG(task_rcu_read_example, struct task_struct *task, u64 clone_flags)
{
        struct task_struct *local_copy;

        bpf_rcu_read_lock();
        local_copy = global;
        if (local_copy)
                /*
                 * We could also pass local_copy to kfuncs or helper functions here,
                 * as we're guaranteed that local_copy will be valid until we exit
                 * the RCU read region below.
                 */
                bpf_printk("Global task %s is valid", local_copy->comm);
        else
                bpf_printk("No global task found");
        bpf_rcu_read_unlock();

        /* At this point we can no longer reference local_copy. */

        return 0;
}

예제는 `bpf_rcu_read_lock()`과 `bpf_rcu_read_unlock()` 사이에서 global task pointer를 local copy로 읽고 사용합니다. RCU read region을 벗어난 뒤에는 `local_copy`를 더 이상 참조할 수 없습니다.

PID로 task lookup

617-655

BPF program은 PID로 task를 lookup할 수도 있습니다. Caller에게 `bpf_task_acquire()`로 reference를 acquire할 trusted `struct task_struct *` pointer가 없을 때 유용합니다.

`kernel/bpf/helpers.c`의 kernel-doc에서 `bpf_task_from_pid`를 가져옵니다.

SEC("tp_btf/task_newtask")
int BPF_PROG(task_get_pid_example, struct task_struct *task, u64 clone_flags)
{
        struct task_struct *lookup;

        lookup = bpf_task_from_pid(task->pid);
        if (!lookup)
                /* A task should always be found, as %task is a tracepoint arg. */
                return -ENOENT;

        if (lookup->pid != task->pid) {
                /* bpf_task_from_pid() looks up the task via its
                 * globally-unique pid from the init_pid_ns. Thus,
                 * the pid of the lookup task should always be the
                 * same as the input task.
                 */
                bpf_task_release(lookup);
                return -EINVAL;
        }

        /* bpf_task_from_pid() returns an acquired reference,
         * so it must be dropped before returning from the
         * tracepoint handler.
         */
        bpf_task_release(lookup);
        return 0;
}

`bpf_task_from_pid()`는 init PID namespace의 globally unique PID로 task를 찾고 acquired reference를 반환하므로 tracepoint handler가 return하기 전에 `bpf_task_release()`로 반드시 drop해야 합니다.

struct cgroup acquire와 release

656-668

`struct cgroup *` object에도 acquire와 release function이 있습니다. `kernel/bpf/helpers.c`의 kernel-doc에서 `bpf_cgroup_acquire`와 `bpf_cgroup_release`를 가져옵니다.

이 kfunc는 각각 `bpf_task_acquire()`와 `bpf_task_release()`와 정확히 같은 방식으로 사용하므로 별도 예제를 제공하지 않습니다.

Cgroup ancestor와 ID lookup

669-706

`struct cgroup *` object와 상호 작용하는 다른 kfunc에는 `bpf_cgroup_ancestor()`와 `bpf_cgroup_from_id()`가 있습니다. 각각 cgroup ancestor에 접근하고 ID로 cgroup을 찾으며 둘 다 cgroup kptr를 반환합니다.

`kernel/bpf/helpers.c`의 kernel-doc에서 `bpf_cgroup_ancestor`와 `bpf_cgroup_from_id`를 가져옵니다.

궁극적으로 BPF program 자체의 일반 memory load로 이 작업을 허용해야 하지만 현재는 verifier에 추가 작업이 필요합니다. `bpf_cgroup_ancestor()` 사용 예제는 다음과 같습니다.

/**
 * Simple tracepoint example that illustrates how a cgroup's
 * ancestor can be accessed using bpf_cgroup_ancestor().
 */
SEC("tp_btf/cgroup_mkdir")
int BPF_PROG(cgrp_ancestor_example, struct cgroup *cgrp, const char *path)
{
        struct cgroup *parent;

        /* The parent cgroup resides at the level before the current cgroup's level. */
        parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
        if (!parent)
                return -ENOENT;

        bpf_printk("Parent id is %d", parent->self.id);

        /* Return the parent cgroup that was acquired above. */
        bpf_cgroup_release(parent);
        return 0;
}

struct cpumask kfunc

707-712

BPF는 `struct cpumask *` object를 query, allocate, mutate, destroy하는 kfunc 집합을 제공합니다. 자세한 내용은 `cpumasks-header-label` 절을 참조합니다.