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&#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&#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&#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&#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&#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&#39;t be left out and it can&#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&#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&#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---


