| .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | 
 |  | 
 | =========================== | 
 | BPF_PROG_TYPE_CGROUP_SYSCTL | 
 | =========================== | 
 |  | 
 | This document describes ``BPF_PROG_TYPE_CGROUP_SYSCTL`` program type that | 
 | provides cgroup-bpf hook for sysctl. | 
 |  | 
 | The hook has to be attached to a cgroup and will be called every time a | 
 | process inside that cgroup tries to read from or write to sysctl knob in proc. | 
 |  | 
 | 1. Attach type | 
 | ************** | 
 |  | 
 | ``BPF_CGROUP_SYSCTL`` attach type has to be used to attach | 
 | ``BPF_PROG_TYPE_CGROUP_SYSCTL`` program to a cgroup. | 
 |  | 
 | 2. Context | 
 | ********** | 
 |  | 
 | ``BPF_PROG_TYPE_CGROUP_SYSCTL`` provides access to the following context from | 
 | BPF program:: | 
 |  | 
 |     struct bpf_sysctl { | 
 |         __u32 write; | 
 |         __u32 file_pos; | 
 |     }; | 
 |  | 
 | * ``write`` indicates whether sysctl value is being read (``0``) or written | 
 |   (``1``). This field is read-only. | 
 |  | 
 | * ``file_pos`` indicates file position sysctl is being accessed at, read | 
 |   or written. This field is read-write. Writing to the field sets the starting | 
 |   position in sysctl proc file ``read(2)`` will be reading from or ``write(2)`` | 
 |   will be writing to. Writing zero to the field can be used e.g. to override | 
 |   whole sysctl value by ``bpf_sysctl_set_new_value()`` on ``write(2)`` even | 
 |   when it's called by user space on ``file_pos > 0``. Writing non-zero | 
 |   value to the field can be used to access part of sysctl value starting from | 
 |   specified ``file_pos``. Not all sysctl support access with ``file_pos != | 
 |   0``, e.g. writes to numeric sysctl entries must always be at file position | 
 |   ``0``. See also ``kernel.sysctl_writes_strict`` sysctl. | 
 |  | 
 | See `linux/bpf.h`_ for more details on how context field can be accessed. | 
 |  | 
 | 3. Return code | 
 | ************** | 
 |  | 
 | ``BPF_PROG_TYPE_CGROUP_SYSCTL`` program must return one of the following | 
 | return codes: | 
 |  | 
 | * ``0`` means "reject access to sysctl"; | 
 | * ``1`` means "proceed with access". | 
 |  | 
 | If program returns ``0`` user space will get ``-1`` from ``read(2)`` or | 
 | ``write(2)`` and ``errno`` will be set to ``EPERM``. | 
 |  | 
 | 4. Helpers | 
 | ********** | 
 |  | 
 | Since sysctl knob is represented by a name and a value, sysctl specific BPF | 
 | helpers focus on providing access to these properties: | 
 |  | 
 | * ``bpf_sysctl_get_name()`` to get sysctl name as it is visible in | 
 |   ``/proc/sys`` into provided by BPF program buffer; | 
 |  | 
 | * ``bpf_sysctl_get_current_value()`` to get string value currently held by | 
 |   sysctl into provided by BPF program buffer. This helper is available on both | 
 |   ``read(2)`` from and ``write(2)`` to sysctl; | 
 |  | 
 | * ``bpf_sysctl_get_new_value()`` to get new string value currently being | 
 |   written to sysctl before actual write happens. This helper can be used only | 
 |   on ``ctx->write == 1``; | 
 |  | 
 | * ``bpf_sysctl_set_new_value()`` to override new string value currently being | 
 |   written to sysctl before actual write happens. Sysctl value will be | 
 |   overridden starting from the current ``ctx->file_pos``. If the whole value | 
 |   has to be overridden BPF program can set ``file_pos`` to zero before calling | 
 |   to the helper. This helper can be used only on ``ctx->write == 1``. New | 
 |   string value set by the helper is treated and verified by kernel same way as | 
 |   an equivalent string passed by user space. | 
 |  | 
 | BPF program sees sysctl value same way as user space does in proc filesystem, | 
 | i.e. as a string. Since many sysctl values represent an integer or a vector | 
 | of integers, the following helpers can be used to get numeric value from the | 
 | string: | 
 |  | 
 | * ``bpf_strtol()`` to convert initial part of the string to long integer | 
 |   similar to user space `strtol(3)`_; | 
 | * ``bpf_strtoul()`` to convert initial part of the string to unsigned long | 
 |   integer similar to user space `strtoul(3)`_; | 
 |  | 
 | See `linux/bpf.h`_ for more details on helpers described here. | 
 |  | 
 | 5. Examples | 
 | *********** | 
 |  | 
 | See `test_sysctl_prog.c`_ for an example of BPF program in C that access | 
 | sysctl name and value, parses string value to get vector of integers and uses | 
 | the result to make decision whether to allow or deny access to sysctl. | 
 |  | 
 | 6. Notes | 
 | ******** | 
 |  | 
 | ``BPF_PROG_TYPE_CGROUP_SYSCTL`` is intended to be used in **trusted** root | 
 | environment, for example to monitor sysctl usage or catch unreasonable values | 
 | an application, running as root in a separate cgroup, is trying to set. | 
 |  | 
 | Since `task_dfl_cgroup(current)` is called at `sys_read` / `sys_write` time it | 
 | may return results different from that at `sys_open` time, i.e. process that | 
 | opened sysctl file in proc filesystem may differ from process that is trying | 
 | to read from / write to it and two such processes may run in different | 
 | cgroups, what means ``BPF_PROG_TYPE_CGROUP_SYSCTL`` should not be used as a | 
 | security mechanism to limit sysctl usage. | 
 |  | 
 | As with any cgroup-bpf program additional care should be taken if an | 
 | application running as root in a cgroup should not be allowed to | 
 | detach/replace BPF program attached by administrator. | 
 |  | 
 | .. Links | 
 | .. _linux/bpf.h: ../../include/uapi/linux/bpf.h | 
 | .. _strtol(3): http://man7.org/linux/man-pages/man3/strtol.3p.html | 
 | .. _strtoul(3): http://man7.org/linux/man-pages/man3/strtoul.3p.html | 
 | .. _test_sysctl_prog.c: | 
 |    ../../tools/testing/selftests/bpf/progs/test_sysctl_prog.c |