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

Linux 6.18.37 · BPF

BPF_PROG_TYPE_CGROUP_SYSCTL

Cgroup sysctl hook의 attach type, context, return code, name/value helper, 숫자 변환과 보안상 제한을 설명합니다.

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

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

1. 요약·해설

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

요약과 해설

prog_cgroup_sysctl.rst:1-125

이 program type은 cgroup process의 `/proc/sys` read/write를 관찰하고 제한하거나, 쓰려는 string value를 변경할 수 있습니다. `write`는 접근 방향을, `file_pos`는 value 접근 시작 위치를 나타냅니다.

Helper는 sysctl name, 현재 value, 새 value의 조회와 새 value 교체를 담당합니다. Value는 string으로 노출되므로 integer policy에는 `bpf_strtol()` 또는 `bpf_strtoul()` 변환이 필요합니다.

Hook은 trusted root 환경의 monitoring과 sanity checking 용도입니다. Open 시점과 read/write 시점의 process 및 cgroup이 다를 수 있어 sysctl 권한을 강제하는 보안 경계로 사용하면 안 됩니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2
3 ===========================
4 BPF_PROG_TYPE_CGROUP_SYSCTL
5 ===========================
6
7 This document describes ``BPF_PROG_TYPE_CGROUP_SYSCTL`` program type that
8 provides cgroup-bpf hook for sysctl.
9
10 The hook has to be attached to a cgroup and will be called every time a
11 process inside that cgroup tries to read from or write to sysctl knob in proc.
12
13 1. Attach type
14 **************
15
16 ``BPF_CGROUP_SYSCTL`` attach type has to be used to attach
17 ``BPF_PROG_TYPE_CGROUP_SYSCTL`` program to a cgroup.
18
19 2. Context
20 **********
21
22 ``BPF_PROG_TYPE_CGROUP_SYSCTL`` provides access to the following context from
23 BPF program::
24
25 struct bpf_sysctl {
26 __u32 write;
27 __u32 file_pos;
28 };
29
30 * ``write`` indicates whether sysctl value is being read (``0``) or written
31 (``1``). This field is read-only.
32
33 * ``file_pos`` indicates file position sysctl is being accessed at, read
34 or written. This field is read-write. Writing to the field sets the starting
35 position in sysctl proc file ``read(2)`` will be reading from or ``write(2)``
36 will be writing to. Writing zero to the field can be used e.g. to override
37 whole sysctl value by ``bpf_sysctl_set_new_value()`` on ``write(2)`` even
38 when it's called by user space on ``file_pos > 0``. Writing non-zero
39 value to the field can be used to access part of sysctl value starting from
40 specified ``file_pos``. Not all sysctl support access with ``file_pos !=
41 0``, e.g. writes to numeric sysctl entries must always be at file position
42 ``0``. See also ``kernel.sysctl_writes_strict`` sysctl.
43
44 See `linux/bpf.h`_ for more details on how context field can be accessed.
45
46 3. Return code
47 **************
48
49 ``BPF_PROG_TYPE_CGROUP_SYSCTL`` program must return one of the following
50 return codes:
51
52 * ``0`` means "reject access to sysctl";
53 * ``1`` means "proceed with access".
54
55 If program returns ``0`` user space will get ``-1`` from ``read(2)`` or
56 ``write(2)`` and ``errno`` will be set to ``EPERM``.
57
58 4. Helpers
59 **********
60
61 Since sysctl knob is represented by a name and a value, sysctl specific BPF
62 helpers focus on providing access to these properties:
63
64 * ``bpf_sysctl_get_name()`` to get sysctl name as it is visible in
65 ``/proc/sys`` into provided by BPF program buffer;
66
67 * ``bpf_sysctl_get_current_value()`` to get string value currently held by
68 sysctl into provided by BPF program buffer. This helper is available on both
69 ``read(2)`` from and ``write(2)`` to sysctl;
70
71 * ``bpf_sysctl_get_new_value()`` to get new string value currently being
72 written to sysctl before actual write happens. This helper can be used only
73 on ``ctx->write == 1``;
74
75 * ``bpf_sysctl_set_new_value()`` to override new string value currently being
76 written to sysctl before actual write happens. Sysctl value will be
77 overridden starting from the current ``ctx->file_pos``. If the whole value
78 has to be overridden BPF program can set ``file_pos`` to zero before calling
79 to the helper. This helper can be used only on ``ctx->write == 1``. New
80 string value set by the helper is treated and verified by kernel same way as
81 an equivalent string passed by user space.
82
83 BPF program sees sysctl value same way as user space does in proc filesystem,
84 i.e. as a string. Since many sysctl values represent an integer or a vector
85 of integers, the following helpers can be used to get numeric value from the
86 string:
87
88 * ``bpf_strtol()`` to convert initial part of the string to long integer
89 similar to user space `strtol(3)`_;
90 * ``bpf_strtoul()`` to convert initial part of the string to unsigned long
91 integer similar to user space `strtoul(3)`_;
92
93 See `linux/bpf.h`_ for more details on helpers described here.
94
95 5. Examples
96 ***********
97
98 See `test_sysctl_prog.c`_ for an example of BPF program in C that access
99 sysctl name and value, parses string value to get vector of integers and uses
100 the result to make decision whether to allow or deny access to sysctl.
101
102 6. Notes
103 ********
104
105 ``BPF_PROG_TYPE_CGROUP_SYSCTL`` is intended to be used in **trusted** root
106 environment, for example to monitor sysctl usage or catch unreasonable values
107 an application, running as root in a separate cgroup, is trying to set.
108
109 Since `task_dfl_cgroup(current)` is called at `sys_read` / `sys_write` time it
110 may return results different from that at `sys_open` time, i.e. process that
111 opened sysctl file in proc filesystem may differ from process that is trying
112 to read from / write to it and two such processes may run in different
113 cgroups, what means ``BPF_PROG_TYPE_CGROUP_SYSCTL`` should not be used as a
114 security mechanism to limit sysctl usage.
115
116 As with any cgroup-bpf program additional care should be taken if an
117 application running as root in a cgroup should not be allowed to
118 detach/replace BPF program attached by administrator.
119
120 .. Links
121 .. _linux/bpf.h: ../../include/uapi/linux/bpf.h
122 .. _strtol(3): http://man7.org/linux/man-pages/man3/strtol.3p.html
123 .. _strtoul(3): http://man7.org/linux/man-pages/man3/strtoul.3p.html
124 .. _test_sysctl_prog.c:
125 ../../tools/testing/selftests/bpf/progs/test_sysctl_prog.c
126

3. 한국어 전문 번역

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

Program type과 attach type

1-18

`BPF_PROG_TYPE_CGROUP_SYSCTL` 문서는 `(LGPL-2.1 OR BSD-2-Clause)` 라이선스를 사용합니다. 이 program type은 sysctl을 위한 cgroup-bpf hook을 제공합니다.

Hook은 cgroup에 attach해야 하며, 해당 cgroup 안의 process가 proc의 sysctl knob를 읽거나 쓰려고 할 때마다 호출됩니다.

`BPF_PROG_TYPE_CGROUP_SYSCTL` program을 cgroup에 attach할 때는 `BPF_CGROUP_SYSCTL` attach type을 사용해야 합니다.

struct bpf_sysctl context

19-45

`BPF_PROG_TYPE_CGROUP_SYSCTL`은 BPF program에 다음 context를 제공합니다.

struct bpf_sysctl {
    __u32 write;
    __u32 file_pos;
};
  • `write`: sysctl value를 읽는 중이면 `0`, 쓰는 중이면 `1`입니다. 이 field는 read-only입니다.
  • `file_pos`: sysctl을 읽거나 쓰는 file position이며 read-write입니다. 이 field에 쓴 값은 sysctl proc file에서 `read(2)` 또는 `write(2)`가 시작할 위치를 정합니다.

`write(2)`가 user space에서 `file_pos > 0`으로 호출되었더라도 `file_pos`에 0을 쓰고 `bpf_sysctl_set_new_value()`를 호출하면 sysctl value 전체를 덮어쓸 수 있습니다. 0이 아닌 값을 쓰면 지정한 `file_pos`부터 sysctl value 일부에 접근할 수 있습니다.

모든 sysctl이 `file_pos != 0` 접근을 지원하지는 않습니다. 예를 들어 numeric sysctl entry에 대한 write는 항상 file position `0`에서 시작해야 합니다. `kernel.sysctl_writes_strict` sysctl도 함께 참고하십시오.

Context field 접근 방법의 자세한 내용은 `linux/bpf.h`를 참고하십시오.

Return code

46-57

`BPF_PROG_TYPE_CGROUP_SYSCTL` program은 다음 return code 중 하나를 반환해야 합니다.

  • `0`: sysctl 접근을 reject합니다.
  • `1`: 접근을 계속 진행합니다.

Program이 `0`을 반환하면 user space의 `read(2)` 또는 `write(2)`는 `-1`을 받고 `errno`는 `EPERM`으로 설정됩니다.

Sysctl name, value와 숫자 변환 helper

58-94

Sysctl knob은 name과 value로 표현되므로 sysctl 전용 BPF helper는 이 두 property에 대한 접근을 제공합니다.

  • `bpf_sysctl_get_name()`: `/proc/sys`에서 보이는 sysctl name을 BPF program이 제공한 buffer로 가져옵니다.
  • `bpf_sysctl_get_current_value()`: sysctl이 현재 보유한 string value를 BPF program buffer로 가져옵니다. Sysctl의 `read(2)`와 `write(2)` 양쪽에서 사용할 수 있습니다.
  • `bpf_sysctl_get_new_value()`: 실제 write 전에 sysctl에 쓰려는 새 string value를 가져옵니다. `ctx->write == 1`일 때만 사용할 수 있습니다.
  • `bpf_sysctl_set_new_value()`: 실제 write 전에 새 string value를 덮어씁니다. 현재 `ctx->file_pos`부터 value가 교체되며, 전체 value를 덮으려면 helper 호출 전에 `file_pos`를 0으로 설정할 수 있습니다. `ctx->write == 1`일 때만 사용할 수 있습니다.

`bpf_sysctl_set_new_value()`가 설정한 새 string은 user space가 같은 string을 전달했을 때와 동일한 방식으로 kernel에서 처리되고 검증됩니다.

BPF program은 proc filesystem의 user space와 똑같이 sysctl value를 string으로 봅니다. 많은 sysctl value가 integer 또는 integer vector를 나타내므로 다음 helper로 string에서 numeric value를 얻을 수 있습니다.

  • `bpf_strtol()`: user space `strtol(3)`과 비슷하게 string의 앞부분을 long integer로 변환합니다.
  • `bpf_strtoul()`: user space `strtoul(3)`과 비슷하게 string의 앞부분을 unsigned long integer로 변환합니다.

이 helper들의 자세한 내용도 `linux/bpf.h`에 있습니다.

Policy example

95-101

`test_sysctl_prog.c`에는 sysctl name과 value에 접근하고, string value를 parse해 integer vector를 얻은 뒤, 그 결과로 sysctl 접근 허용 또는 거부를 결정하는 C BPF program 예제가 있습니다.

신뢰 환경과 보안상 제한

102-125

`BPF_PROG_TYPE_CGROUP_SYSCTL`은 trusted root environment에서 사용하기 위한 것입니다. 예를 들어 sysctl 사용을 monitor하거나, 별도 cgroup에서 root로 실행되는 application이 비합리적인 값을 설정하려는 상황을 포착할 수 있습니다.

`task_dfl_cgroup(current)`은 `sys_open` 시점이 아니라 `sys_read` 또는 `sys_write` 시점에 호출되므로 서로 다른 결과를 반환할 수 있습니다. Proc filesystem의 sysctl file을 연 process와 실제 read/write를 시도하는 process가 다를 수 있고, 두 process가 서로 다른 cgroup에서 실행될 수도 있습니다.

따라서 `BPF_PROG_TYPE_CGROUP_SYSCTL`을 sysctl 사용을 제한하는 security mechanism으로 사용해서는 안 됩니다.

다른 cgroup-bpf program과 마찬가지로 cgroup 안에서 root로 실행되는 application이 administrator가 attach한 BPF program을 detach하거나 replace하지 못해야 한다면 추가 주의가 필요합니다.

원문이 연결하는 header, man page, selftest 자료는 다음과 같습니다.

  • [../../include/uapi/linux/bpf.h](../../include/uapi/linux/bpf.h)
  • [http://man7.org/linux/man-pages/man3/strtol.3p.html](http://man7.org/linux/man-pages/man3/strtol.3p.html)
  • [http://man7.org/linux/man-pages/man3/strtoul.3p.html](http://man7.org/linux/man-pages/man3/strtoul.3p.html)
  • [../../tools/testing/selftests/bpf/progs/test_sysctl_prog.c](../../tools/testing/selftests/bpf/progs/test_sysctl_prog.c)