xref: /linux/Documentation/filesystems/failfs.rst (revision cd051cfe1e35a471fc2cdf6d32fae6ee23305ecb)
1*a45a6605SChristian Brauner.. SPDX-License-Identifier: GPL-2.0
2*a45a6605SChristian Brauner
3*a45a6605SChristian Brauner======
4*a45a6605SChristian Braunerfailfs
5*a45a6605SChristian Brauner======
6*a45a6605SChristian Brauner
7*a45a6605SChristian Braunerfailfs is a kernel-internal filesystem that fails every operation
8*a45a6605SChristian Braunerreaching it with ``EOPNOTSUPP``. It is the counterpart to nullfs. Where
9*a45a6605SChristian Braunernullfs is permanently empty, failfs means "nothing is supported here".
10*a45a6605SChristian BraunerIt cannot be mounted from userspace, nothing can be mounted on top of
11*a45a6605SChristian Braunerit. It cannot be cloned.
12*a45a6605SChristian Brauner
13*a45a6605SChristian BraunerThe only way into it is the ``FD_FAILFS_ROOT`` file descriptor sentinel which
14*a45a6605SChristian Brauneris understood by ``fchdir(2)`` and ``fchroot(2)``.
15*a45a6605SChristian Brauner
16*a45a6605SChristian BraunerSemantics
17*a45a6605SChristian Brauner=========
18*a45a6605SChristian Brauner
19*a45a6605SChristian BraunerEvery path walk of a component through failfs fails with
20*a45a6605SChristian Brauner``EOPNOTSUPP`` before that component is parsed, including ``.``.
21*a45a6605SChristian Brauner
22*a45a6605SChristian BraunerNo path lookup can open the root, not even with ``O_PATH``.
23*a45a6605SChristian Brauner
24*a45a6605SChristian BraunerA process with its working directory in failfs fails every
25*a45a6605SChristian Brauner``AT_FDCWD``-relative lookup. As with any working directory that is
26*a45a6605SChristian Braunerunreachable from the process root, the ``getcwd(2)`` system call returns
27*a45a6605SChristian Braunera path prefixed with ``(unreachable)``.
28*a45a6605SChristian Brauner
29*a45a6605SChristian BraunerA process with its root directory in failfs fails every absolute path
30*a45a6605SChristian Braunerlookup including absolute symlinks and the interpreter of dynamically
31*a45a6605SChristian Braunerlinked binaries. In other words, this fails exec.
32*a45a6605SChristian Brauner
33*a45a6605SChristian BraunerLookups anchored at explicit directory file descriptors keep working. It
34*a45a6605SChristian Brauneris the ``fs_struct`` equivalent of ``RESOLVE_BENEATH``. The process must
35*a45a6605SChristian Brauneranchor every lookup at a file descriptor it explicitly holds.
36*a45a6605SChristian Brauner
37*a45a6605SChristian BraunerEntering
38*a45a6605SChristian Brauner========
39*a45a6605SChristian Brauner
40*a45a6605SChristian Brauner``fchroot(FD_FAILFS_ROOT, 0)`` requires ``CAP_SYS_CHROOT`` in the
41*a45a6605SChristian Braunercaller's user namespace, mirroring ``chroot(2)``. Unprivileged callers
42*a45a6605SChristian Braunermay enter if all of the following hold:
43*a45a6605SChristian Brauner
44*a45a6605SChristian Brauner* ``no_new_privs`` is set: setuid binaries on regular mounts remain
45*a45a6605SChristian Brauner  reachable via inherited directory file descriptors and executing them
46*a45a6605SChristian Brauner  with an unusable root directory is the classic confused deputy.
47*a45a6605SChristian Brauner
48*a45a6605SChristian Brauner* The caller is not already chrooted: the root directory is what
49*a45a6605SChristian Brauner  confines ``..`` resolution and the failfs root can never be reached by
50*a45a6605SChristian Brauner  walking up a real mount tree, so moving the root of a chrooted task to
51*a45a6605SChristian Brauner  failfs would allow it to escape its chroot via ``openat(fd, "..")``.
52*a45a6605SChristian Brauner
53*a45a6605SChristian Brauner* The caller does not share its ``fs_struct``: ``no_new_privs`` is
54*a45a6605SChristian Brauner  checked on the calling thread, but the root lives in the ``fs_struct``.
55*a45a6605SChristian Brauner  A ``CLONE_FS`` sibling without ``no_new_privs`` could otherwise execute
56*a45a6605SChristian Brauner  a setuid binary with the failfs root, so entry requires ``fs->users ==
57*a45a6605SChristian Brauner  1``, the same restriction ``setns(2)`` applies for the mount and user
58*a45a6605SChristian Brauner  namespaces.
59*a45a6605SChristian Brauner
60*a45a6605SChristian BraunerLeaving
61*a45a6605SChristian Brauner=======
62*a45a6605SChristian Brauner
63*a45a6605SChristian BraunerBacking out is currently hard, but this is a property of the current
64*a45a6605SChristian Braunerimplementation, not a guaranteed interface, and may be loosened later.
65*a45a6605SChristian BraunerFor now a process that entered failfs counts as chrooted, so it cannot
66*a45a6605SChristian Braunercreate user namespaces to regain ``CAP_SYS_CHROOT``, and ``chroot(2)``
67*a45a6605SChristian Brauneror ``fchroot(2)`` back out require ``CAP_SYS_CHROOT``. The remaining way
68*a45a6605SChristian Braunerout today is ``setns(2)`` with a mount namespace file descriptor, which
69*a45a6605SChristian Braunerrequires ``CAP_SYS_ADMIN`` over the target mount namespace as well as
70*a45a6605SChristian Brauner``CAP_SYS_CHROOT`` and ``CAP_SYS_ADMIN`` in the caller's user namespace
71*a45a6605SChristian Braunerand resets both root and working directory. A process that holds no such
72*a45a6605SChristian Braunerfile descriptor and restricts ``*chdir()``/``*chroot()``/``setns()`` via
73*a45a6605SChristian Braunerseccomp cannot currently get back out.
74