요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
======================
No New Privileges Flag
======================
The execve system call can grant a newly-started program privileges that
its parent did not have. The most obvious examples are setuid/setgid
programs and file capabilities. To prevent the parent program from
gaining these privileges as well, the kernel and user code must be
careful to prevent the parent from doing anything that could subvert the
child. For example:
- The dynamic loader handles ``LD_*`` environment variables differently if
a program is setuid.
- chroot is disallowed to unprivileged processes, since it would allow
``/etc/passwd`` to be replaced from the point of view of a process that
inherited chroot.
- The exec code has special handling for ptrace.
These are all ad-hoc fixes. The ``no_new_privs`` bit (since Linux 3.5) is a
new, generic mechanism to make it safe for a process to modify its
execution environment in a manner that persists across execve. Any task
can set ``no_new_privs``. Once the bit is set, it is inherited across fork,
clone, and execve and cannot be unset. With ``no_new_privs`` set, ``execve()``
promises not to grant the privilege to do anything that could not have
been done without the execve call. For example, the setuid and setgid
bits will no longer change the uid or gid; file capabilities will not
add to the permitted set, and LSMs will not relax constraints after
execve.
To set ``no_new_privs``, use::
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
Be careful, though: LSMs might also not tighten constraints on exec
in ``no_new_privs`` mode. (This means that setting up a general-purpose
service launcher to set ``no_new_privs`` before execing daemons may
interfere with LSM-based sandboxing.)
Note that ``no_new_privs`` does not prevent privilege changes that do not
involve ``execve()``. An appropriately privileged task can still call
``setuid(2)`` and receive SCM_RIGHTS datagrams.
There are two main use cases for ``no_new_privs`` so far:
- Filters installed for the seccomp mode 2 sandbox persist across
execve and can change the behavior of newly-executed programs.
Unprivileged users are therefore only allowed to install such filters
if ``no_new_privs`` is set.
- By itself, ``no_new_privs`` can be used to reduce the attack surface
available to an unprivileged user. If everything running with a
given uid has ``no_new_privs`` set, then that uid will be unable to
escalate its privileges by directly attacking setuid, setgid, and
fcap-using binaries; it will need to compromise something without the
``no_new_privs`` bit set first.
In the future, other potentially dangerous kernel features could become
available to unprivileged tasks if ``no_new_privs`` is set. In principle,
several options to ``unshare(2)`` and ``clone(2)`` would be safe when
``no_new_privs`` is set, and ``no_new_privs`` + ``chroot`` is considerable less
dangerous than chroot by itself.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
execve 권한 상승과 기존 방어
1-20`execve` 시스템 호출은 새로 시작하는 프로그램에 부모가 갖지 않았던 권한을 부여할 수 있습니다. 대표적인 예는 setuid/setgid 프로그램과 파일 capability입니다. 부모가 이 권한을 함께 얻지 못하게 하려면 커널과 사용자 공간 코드가 부모의 자식 실행 환경 교란을 막아야 합니다.
각 하위 시스템이 특수한 경우를 개별적으로 처리해 왔습니다.
======================
No New Privileges Flag
======================
The execve system call can grant a newly-started program privileges that
its parent did not have. The most obvious examples are setuid/setgid
programs and file capabilities. To prevent the parent program from
gaining these privileges as well, the kernel and user code must be
careful to prevent the parent from doing anything that could subvert the
child. For example:
- The dynamic loader handles ``LD_*`` environment variables differently if
a program is setuid.
- chroot is disallowed to unprivileged processes, since it would allow
``/etc/passwd`` to be replaced from the point of view of a process that
inherited chroot.
- The exec code has special handling for ptrace.
no_new_privs의 보장과 설정
21-35이러한 처리는 모두 임시방편입니다. Linux 3.5부터 제공되는 `no_new_privs` 비트는 프로세스가 `execve` 뒤에도 유지되는 실행 환경을 안전하게 변경하도록 하는 일반 메커니즘입니다.
어떤 태스크든 `no_new_privs`를 설정할 수 있습니다. 한 번 설정하면 fork, clone, execve를 거쳐 상속되며 해제할 수 없습니다.
`no_new_privs`가 설정된 상태에서 `execve()`는 호출 전에는 할 수 없었던 일을 가능하게 하는 권한을 부여하지 않겠다고 보장합니다. setuid와 setgid 비트는 uid나 gid를 바꾸지 않고, 파일 capability는 permitted 집합에 권한을 추가하지 않으며, LSM도 execve 뒤에 제약을 완화하지 않습니다.
다음 `prctl()` 호출로 플래그를 설정합니다.
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
These are all ad-hoc fixes. The ``no_new_privs`` bit (since Linux 3.5) is a
new, generic mechanism to make it safe for a process to modify its
execution environment in a manner that persists across execve. Any task
can set ``no_new_privs``. Once the bit is set, it is inherited across fork,
clone, and execve and cannot be unset. With ``no_new_privs`` set, ``execve()``
promises not to grant the privilege to do anything that could not have
been done without the execve call. For example, the setuid and setgid
bits will no longer change the uid or gid; file capabilities will not
add to the permitted set, and LSMs will not relax constraints after
execve.
To set ``no_new_privs``, use::
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
LSM과 execve 밖의 권한 변경
36-44주의할 점은 `no_new_privs` 모드에서 LSM이 exec 시 제약을 더 강화하지 않을 수도 있다는 것입니다. 범용 서비스 실행기가 데몬을 exec하기 전에 `no_new_privs`를 설정하면 LSM 기반 샌드박스와 충돌할 수 있습니다.
`no_new_privs`는 `execve()`가 관여하지 않는 권한 변경을 막지 않습니다. 필요한 권한을 가진 태스크는 여전히 `setuid(2)`를 호출할 수 있고 SCM_RIGHTS 데이터그램으로 파일 디스크립터를 받을 수 있습니다.
Be careful, though: LSMs might also not tighten constraints on exec
in ``no_new_privs`` mode. (This means that setting up a general-purpose
service launcher to set ``no_new_privs`` before execing daemons may
interfere with LSM-based sandboxing.)
Note that ``no_new_privs`` does not prevent privilege changes that do not
involve ``execve()``. An appropriately privileged task can still call
``setuid(2)`` and receive SCM_RIGHTS datagrams.
현재 용도와 확장 가능성
45-63현재 `no_new_privs`의 주요 용도는 두 가지입니다.
플래그는 execve를 가로지르는 정책의 안전 조건이 됩니다.
앞으로는 `no_new_privs`를 조건으로 잠재적으로 위험한 다른 커널 기능을 비특권 태스크에 허용할 수도 있습니다. 원칙적으로 `unshare(2)`와 `clone(2)`의 일부 옵션은 이 조건에서 안전해질 수 있고, `no_new_privs`와 결합한 `chroot`는 chroot 단독 사용보다 훨씬 덜 위험합니다.
There are two main use cases for ``no_new_privs`` so far:
- Filters installed for the seccomp mode 2 sandbox persist across
execve and can change the behavior of newly-executed programs.
Unprivileged users are therefore only allowed to install such filters
if ``no_new_privs`` is set.
- By itself, ``no_new_privs`` can be used to reduce the attack surface
available to an unprivileged user. If everything running with a
given uid has ``no_new_privs`` set, then that uid will be unable to
escalate its privileges by directly attacking setuid, setgid, and
fcap-using binaries; it will need to compromise something without the
``no_new_privs`` bit set first.
In the future, other potentially dangerous kernel features could become
available to unprivileged tasks if ``no_new_privs`` is set. In principle,
several options to ``unshare(2)`` and ``clone(2)`` would be safe when
``no_new_privs`` is set, and ``no_new_privs`` + ``chroot`` is considerable less
dangerous than chroot by itself.
요약·해설
no_new_privs.rst:1-63`no_new_privs`는 샌드박스 자체가 아니라 execve를 통한 권한 상승을 차단하는 단방향 프로세스 속성입니다. 상속되고 해제할 수 없다는 점, LSM이 exec에서 제약을 더 강화하지 않을 수도 있다는 점, execve 밖의 권한 변경은 막지 않는다는 점을 함께 고려해야 합니다.