Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2026-99170

Gravedad:
Pendiente de análisis
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
28/10/2026
Última modificación:
28/10/2026

Descripción

*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> namespace: a mount that copy_tree() leaves out can&amp;#39;t take over a lock<br /> <br /> Since commit c62a4766937e ("move_mount: transfer MNT_LOCKED") a mount<br /> can be moved beneath a locked mount. The lock moves from the old cover<br /> to the new mount which takes over the job of hiding what&amp;#39;s under it and<br /> the old cover can be unmounted. That works as long as the new mount<br /> stays. But the caller picks the new mount and copy_tree() leaves a<br /> mount of a mount namespace file out of every copy made without<br /> CL_COPY_MNT_NS_FILE, together with everything mounted on it, and never<br /> looks at MNT_LOCKED. unshare(CLONE_NEWNS) and mount propagation make<br /> such copies.<br /> <br /> So a task that is root in its own user namespace gets rid of a locked<br /> cover on a file without a race and without touching the filesystem<br /> below it. It makes a child with a mount namespace of its own, binds the<br /> child&amp;#39;s /proc//ns/mnt beneath the cover with MOVE_MOUNT_BENEATH,<br /> which hands the lock to that bind, and calls unshare(CLONE_NEWNS). The<br /> new mount namespace has nothing on the file. That&amp;#39;s the usual way to<br /> mask a single file, a bind of /dev/null or of an empty file. With a<br /> bind of an ordinary file the file stays covered.<br /> <br /> copy_tree() already refuses to leave out a locked unbindable mount with<br /> -EPERM since commit df7342b24018 ("mount: Don&amp;#39;t allow copying<br /> MNT_UNBINDABLE|MNT_LOCKED mounts"). Do the same for a locked mount of a<br /> mount namespace file. That also covers a tree copied with<br /> CL_COPY_MNT_NS_FILE and attached into a mount namespace of another user<br /> namespace where lock_mnt_tree() locks it. Note that unshare(CLONE_NEWNS)<br /> and clone(CLONE_NEWNS) fail with EPERM from such a mount namespace from<br /> then on. The mount can&amp;#39;t be left out and it can&amp;#39;t be unmounted.<br /> <br /> And refuse to move a mount of a mount namespace file beneath a locked<br /> mount in the first place. Otherwise the task ends up with a mount it<br /> can&amp;#39;t unmount and an unshare() that fails for good.<br /> <br /> Chris also found a second mount that goes away by itself, a clone of an<br /> automounted mount that shrink_submounts() took along with its parent.<br /> Commit f78ddcc87224 ("namespace: never expire a locked mount") took<br /> care of that one.<br /> <br /> Chris&amp;#39;s reproducer is appended. Mode nsfile reads SECRET after the<br /> unshare() on 7.3-rc7, with this patch the move_mount() fails with<br /> EINVAL and the file stays covered. nsfile-control uses an ordinary file<br /> and reads MASK both ways.<br /> <br /> // SPDX-License-Identifier: GPL-2.0<br /> /*<br /> * Get rid of a locked cover with MOVE_MOUNT_BENEATH.<br /> *<br /> * The "admin" (root) makes a tmpfs W:<br /> * W/D file, holds SECRET, covered by a bind of a file with MASK<br /> * W/Dd/inner file, holds SECRET, Dd is covered by a bind of a directory<br /> * whose "inner" holds MASK<br /> * W/own directory of uid 1000 with the file "mine" and the<br /> * directory "minedir", whose "inner" holds MINE<br /> * W/dbg debugfs, mode 755. dbg/tracing is an automount point<br /> * The "attacker" is uid 1000. It enters a new user namespace with a new mount<br /> * namespace, so W and both covers are locked there.<br /> *<br /> * usage: prog MODE<br /> * plain put a bind of own/mine beneath the cover of D, unmount the cover<br /> * nsfile put a bind of the mount namespace file of a child beneath the<br /> * cover of D, then unshare(CLONE_NEWNS)<br /> * nsfile-control the same with a bind of own/mine<br /> * shrink put a bind of the automounted tracefs beneath the cover of Dd,<br /> * unmount the cover, put a tmpfs beneath W, call umount(W), which fails<br /> * shrink-control the same with a bind of own/minedir<br /> * The environment variable AUTOMOUNT_DIR names another automount point for "shrink".<br /> */<br /> #define _GNU_SOURCE<br /> #include <br /> #include <br /> #include <br /> #include <br /> #include <br /> #include <br /> #include <br /> #include <br /> #include <br /> <br /> ---truncated---

Impacto