printf: Remove unused 'bprintf'
[drm/drm-misc.git] / Documentation / bpf / prog_cgroup_sockopt.rst
blob1226a94af07a886b8d562ee2241c2bfc43ef2f54
1 .. SPDX-License-Identifier: GPL-2.0
3 ============================
4 BPF_PROG_TYPE_CGROUP_SOCKOPT
5 ============================
7 ``BPF_PROG_TYPE_CGROUP_SOCKOPT`` program type can be attached to two
8 cgroup hooks:
10 * ``BPF_CGROUP_GETSOCKOPT`` - called every time process executes ``getsockopt``
11   system call.
12 * ``BPF_CGROUP_SETSOCKOPT`` - called every time process executes ``setsockopt``
13   system call.
15 The context (``struct bpf_sockopt``) has associated socket (``sk``) and
16 all input arguments: ``level``, ``optname``, ``optval`` and ``optlen``.
18 BPF_CGROUP_SETSOCKOPT
19 =====================
21 ``BPF_CGROUP_SETSOCKOPT`` is triggered *before* the kernel handling of
22 sockopt and it has writable context: it can modify the supplied arguments
23 before passing them down to the kernel. This hook has access to the cgroup
24 and socket local storage.
26 If BPF program sets ``optlen`` to -1, the control will be returned
27 back to the userspace after all other BPF programs in the cgroup
28 chain finish (i.e. kernel ``setsockopt`` handling will *not* be executed).
30 Note, that ``optlen`` can not be increased beyond the user-supplied
31 value. It can only be decreased or set to -1. Any other value will
32 trigger ``EFAULT``.
34 Return Type
35 -----------
37 * ``0`` - reject the syscall, ``EPERM`` will be returned to the userspace.
38 * ``1`` - success, continue with next BPF program in the cgroup chain.
40 BPF_CGROUP_GETSOCKOPT
41 =====================
43 ``BPF_CGROUP_GETSOCKOPT`` is triggered *after* the kernel handing of
44 sockopt. The BPF hook can observe ``optval``, ``optlen`` and ``retval``
45 if it's interested in whatever kernel has returned. BPF hook can override
46 the values above, adjust ``optlen`` and reset ``retval`` to 0. If ``optlen``
47 has been increased above initial ``getsockopt`` value (i.e. userspace
48 buffer is too small), ``EFAULT`` is returned.
50 This hook has access to the cgroup and socket local storage.
52 Note, that the only acceptable value to set to ``retval`` is 0 and the
53 original value that the kernel returned. Any other value will trigger
54 ``EFAULT``.
56 Return Type
57 -----------
59 * ``0`` - reject the syscall, ``EPERM`` will be returned to the userspace.
60 * ``1`` - success: copy ``optval`` and ``optlen`` to userspace, return
61   ``retval`` from the syscall (note that this can be overwritten by
62   the BPF program from the parent cgroup).
64 Cgroup Inheritance
65 ==================
67 Suppose, there is the following cgroup hierarchy where each cgroup
68 has ``BPF_CGROUP_GETSOCKOPT`` attached at each level with
69 ``BPF_F_ALLOW_MULTI`` flag::
71   A (root, parent)
72    \
73     B (child)
75 When the application calls ``getsockopt`` syscall from the cgroup B,
76 the programs are executed from the bottom up: B, A. First program
77 (B) sees the result of kernel's ``getsockopt``. It can optionally
78 adjust ``optval``, ``optlen`` and reset ``retval`` to 0. After that
79 control will be passed to the second (A) program which will see the
80 same context as B including any potential modifications.
82 Same for ``BPF_CGROUP_SETSOCKOPT``: if the program is attached to
83 A and B, the trigger order is B, then A. If B does any changes
84 to the input arguments (``level``, ``optname``, ``optval``, ``optlen``),
85 then the next program in the chain (A) will see those changes,
86 *not* the original input ``setsockopt`` arguments. The potentially
87 modified values will be then passed down to the kernel.
89 Large optval
90 ============
91 When the ``optval`` is greater than the ``PAGE_SIZE``, the BPF program
92 can access only the first ``PAGE_SIZE`` of that data. So it has to options:
94 * Set ``optlen`` to zero, which indicates that the kernel should
95   use the original buffer from the userspace. Any modifications
96   done by the BPF program to the ``optval`` are ignored.
97 * Set ``optlen`` to the value less than ``PAGE_SIZE``, which
98   indicates that the kernel should use BPF's trimmed ``optval``.
100 When the BPF program returns with the ``optlen`` greater than
101 ``PAGE_SIZE``, the userspace will receive original kernel
102 buffers without any modifications that the BPF program might have
103 applied.
105 Example
106 =======
108 Recommended way to handle BPF programs is as follows:
110 .. code-block:: c
112         SEC("cgroup/getsockopt")
113         int getsockopt(struct bpf_sockopt *ctx)
114         {
115                 /* Custom socket option. */
116                 if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) {
117                         ctx->retval = 0;
118                         optval[0] = ...;
119                         ctx->optlen = 1;
120                         return 1;
121                 }
123                 /* Modify kernel's socket option. */
124                 if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) {
125                         ctx->retval = 0;
126                         optval[0] = ...;
127                         ctx->optlen = 1;
128                         return 1;
129                 }
131                 /* optval larger than PAGE_SIZE use kernel's buffer. */
132                 if (ctx->optlen > PAGE_SIZE)
133                         ctx->optlen = 0;
135                 return 1;
136         }
138         SEC("cgroup/setsockopt")
139         int setsockopt(struct bpf_sockopt *ctx)
140         {
141                 /* Custom socket option. */
142                 if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) {
143                         /* do something */
144                         ctx->optlen = -1;
145                         return 1;
146                 }
148                 /* Modify kernel's socket option. */
149                 if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) {
150                         optval[0] = ...;
151                         return 1;
152                 }
154                 /* optval larger than PAGE_SIZE use kernel's buffer. */
155                 if (ctx->optlen > PAGE_SIZE)
156                         ctx->optlen = 0;
158                 return 1;
159         }
161 See ``tools/testing/selftests/bpf/progs/sockopt_sk.c`` for an example
162 of BPF program that handles socket options.