Commit e985ccc9 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Khalid Elmously

mount: Don't allow copying MNT_UNBINDABLE|MNT_LOCKED mounts

BugLink: https://launchpad.net/bugs/1789161

Jonathan Calmels from NVIDIA reported that he's able to bypass the
mount visibility security check in place in the Linux kernel by using
a combination of the unbindable property along with the private mount
propagation option to allow a unprivileged user to see a path which
was purposefully hidden by the root user.

Reproducer:
  # Hide a path to all users using a tmpfs
  root@castiana:~# mount -t tmpfs tmpfs /sys/devices/
  root@castiana:~#

  # As an unprivileged user, unshare user namespace and mount namespace
  stgraber@castiana:~$ unshare -U -m -r

  # Confirm the path is still not accessible
  root@castiana:~# ls /sys/devices/

  # Make /sys recursively unbindable and private
  root@castiana:~# mount --make-runbindable /sys
  root@castiana:~# mount --make-private /sys

  # Recursively bind-mount the rest of /sys over to /mnnt
  root@castiana:~# mount --rbind /sys/ /mnt

  # Access our hidden /sys/device as an unprivileged user
  root@castiana:~# ls /mnt/devices/
  breakpoint cpu cstate_core cstate_pkg i915 intel_pt isa kprobe
  LNXSYSTM:00 msr pci0000:00 platform pnp0 power software system
  tracepoint uncore_arb uncore_cbox_0 uncore_cbox_1 uprobe virtual

Solve this by teaching copy_tree to fail if a mount turns out to be
both unbindable and locked.

Cc: stable@vger.kernel.org
Fixes: 5ff9d8a6 ("vfs: Lock in place mounts from more privileged users")
Reported-by: default avatarJonathan Calmels <jcalmels@nvidia.com>
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
(cherry picked from commit df7342b2)
Signed-off-by: default avatarTyler Hicks <tyhicks@canonical.com>
Acked-by: default avatarColin King <colin.king@canonical.com>
Acked-by: default avatarThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Signed-off-by: default avatarThadeu Lima de Souza Cascardo <cascardo@canonical.com>
parent e5ee4c31
...@@ -1781,8 +1781,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, ...@@ -1781,8 +1781,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
for (s = r; s; s = next_mnt(s, r)) { for (s = r; s; s = next_mnt(s, r)) {
if (!(flag & CL_COPY_UNBINDABLE) && if (!(flag & CL_COPY_UNBINDABLE) &&
IS_MNT_UNBINDABLE(s)) { IS_MNT_UNBINDABLE(s)) {
s = skip_mnt_tree(s); if (s->mnt.mnt_flags & MNT_LOCKED) {
continue; /* Both unbindable and locked. */
q = ERR_PTR(-EPERM);
goto out;
} else {
s = skip_mnt_tree(s);
continue;
}
} }
if (!(flag & CL_COPY_MNT_NS_FILE) && if (!(flag & CL_COPY_MNT_NS_FILE) &&
is_mnt_ns_file(s->mnt.mnt_root)) { is_mnt_ns_file(s->mnt.mnt_root)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment