doc: ReSTify no_new_privs.txt
This updates no_new_privs documentation to ReST markup and adds it to the user-space API documentation. Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
This commit is contained in:
parent
c061f33f35
commit
40fde647cc
2 changed files with 26 additions and 19 deletions
|
@ -16,6 +16,7 @@ place where this information is gathered.
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
no_new_privs
|
||||
seccomp_filter
|
||||
unshare
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
======================
|
||||
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
|
||||
|
@ -5,53 +9,55 @@ 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
|
||||
- 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
|
||||
``/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
|
||||
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
|
||||
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).
|
||||
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
|
||||
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.
|
||||
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:
|
||||
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.
|
||||
if ``no_new_privs`` is set.
|
||||
|
||||
- By itself, no_new_privs can be used to reduce the attack surface
|
||||
- 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
|
||||
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.
|
||||
``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
|
||||
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.
|
Loading…
Reference in a new issue