Skip to content

Commit 1de4f2e

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull namespace fixes from Eric Biederman: "I believe all of these are simple obviously correct bug fixes. These fall into two groups: - Fixing the implementation of MNT_LOCKED which prevents lesser privileged users from seeing unders mounts created by more privileged users. - Fixing the extended uid and group mapping in user namespaces. As well as ensuring the code looks correct I have spot tested these changes as well and in my testing the fixes are working" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: mount: Prevent MNT_DETACH from disconnecting locked mounts mount: Don't allow copying MNT_UNBINDABLE|MNT_LOCKED mounts mount: Retest MNT_LOCKED in do_umount userns: also map extents in the reverse map to kernel IDs
2 parents a1aa42f + 9c8e0a1 commit 1de4f2e

File tree

2 files changed

+25
-9
lines changed

2 files changed

+25
-9
lines changed

fs/namespace.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,8 +1540,13 @@ static int do_umount(struct mount *mnt, int flags)
15401540

15411541
namespace_lock();
15421542
lock_mount_hash();
1543-
event++;
15441543

1544+
/* Recheck MNT_LOCKED with the locks held */
1545+
retval = -EINVAL;
1546+
if (mnt->mnt.mnt_flags & MNT_LOCKED)
1547+
goto out;
1548+
1549+
event++;
15451550
if (flags & MNT_DETACH) {
15461551
if (!list_empty(&mnt->mnt_list))
15471552
umount_tree(mnt, UMOUNT_PROPAGATE);
@@ -1555,6 +1560,7 @@ static int do_umount(struct mount *mnt, int flags)
15551560
retval = 0;
15561561
}
15571562
}
1563+
out:
15581564
unlock_mount_hash();
15591565
namespace_unlock();
15601566
return retval;
@@ -1645,7 +1651,7 @@ int ksys_umount(char __user *name, int flags)
16451651
goto dput_and_out;
16461652
if (!check_mnt(mnt))
16471653
goto dput_and_out;
1648-
if (mnt->mnt.mnt_flags & MNT_LOCKED)
1654+
if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
16491655
goto dput_and_out;
16501656
retval = -EPERM;
16511657
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
@@ -1728,8 +1734,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
17281734
for (s = r; s; s = next_mnt(s, r)) {
17291735
if (!(flag & CL_COPY_UNBINDABLE) &&
17301736
IS_MNT_UNBINDABLE(s)) {
1731-
s = skip_mnt_tree(s);
1732-
continue;
1737+
if (s->mnt.mnt_flags & MNT_LOCKED) {
1738+
/* Both unbindable and locked. */
1739+
q = ERR_PTR(-EPERM);
1740+
goto out;
1741+
} else {
1742+
s = skip_mnt_tree(s);
1743+
continue;
1744+
}
17331745
}
17341746
if (!(flag & CL_COPY_MNT_NS_FILE) &&
17351747
is_mnt_ns_file(s->mnt.mnt_root)) {
@@ -1782,7 +1794,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
17821794
{
17831795
namespace_lock();
17841796
lock_mount_hash();
1785-
umount_tree(real_mount(mnt), UMOUNT_SYNC);
1797+
umount_tree(real_mount(mnt), 0);
17861798
unlock_mount_hash();
17871799
namespace_unlock();
17881800
}

kernel/user_namespace.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
974974
if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
975975
goto out;
976976

977-
ret = sort_idmaps(&new_map);
978-
if (ret < 0)
979-
goto out;
980-
981977
ret = -EPERM;
982978
/* Map the lower ids from the parent user namespace to the
983979
* kernel global id space.
@@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf,
10041000
e->lower_first = lower_first;
10051001
}
10061002

1003+
/*
1004+
* If we want to use binary search for lookup, this clones the extent
1005+
* array and sorts both copies.
1006+
*/
1007+
ret = sort_idmaps(&new_map);
1008+
if (ret < 0)
1009+
goto out;
1010+
10071011
/* Install the map */
10081012
if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
10091013
memcpy(map->extent, new_map.extent,

0 commit comments

Comments
 (0)