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