aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-11-10 14:27:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-11-10 14:27:58 -0500
commit1de4f2ef216dade3b5bd5f5247c4c750a953f51c (patch)
tree7be22ffabcb98c2aeeb0df644a32a06328154c2f
parenta1aa42f1d8c00a0767afee28d17caafd2a4dd8ff (diff)
parent9c8e0a1b683525464a2abe9fb4b54404a50ed2b4 (diff)
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
-rw-r--r--fs/namespace.c22
-rw-r--r--kernel/user_namespace.c12
2 files changed, 25 insertions, 9 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 98d27da43304..74f64294a410 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1540,8 +1540,13 @@ static int do_umount(struct mount *mnt, int flags)
1540 1540
1541 namespace_lock(); 1541 namespace_lock();
1542 lock_mount_hash(); 1542 lock_mount_hash();
1543 event++;
1544 1543
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++;
1545 if (flags & MNT_DETACH) { 1550 if (flags & MNT_DETACH) {
1546 if (!list_empty(&mnt->mnt_list)) 1551 if (!list_empty(&mnt->mnt_list))
1547 umount_tree(mnt, UMOUNT_PROPAGATE); 1552 umount_tree(mnt, UMOUNT_PROPAGATE);
@@ -1555,6 +1560,7 @@ static int do_umount(struct mount *mnt, int flags)
1555 retval = 0; 1560 retval = 0;
1556 } 1561 }
1557 } 1562 }
1563out:
1558 unlock_mount_hash(); 1564 unlock_mount_hash();
1559 namespace_unlock(); 1565 namespace_unlock();
1560 return retval; 1566 return retval;
@@ -1645,7 +1651,7 @@ int ksys_umount(char __user *name, int flags)
1645 goto dput_and_out; 1651 goto dput_and_out;
1646 if (!check_mnt(mnt)) 1652 if (!check_mnt(mnt))
1647 goto dput_and_out; 1653 goto dput_and_out;
1648 if (mnt->mnt.mnt_flags & MNT_LOCKED) 1654 if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
1649 goto dput_and_out; 1655 goto dput_and_out;
1650 retval = -EPERM; 1656 retval = -EPERM;
1651 if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) 1657 if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
@@ -1728,8 +1734,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
1728 for (s = r; s; s = next_mnt(s, r)) { 1734 for (s = r; s; s = next_mnt(s, r)) {
1729 if (!(flag & CL_COPY_UNBINDABLE) && 1735 if (!(flag & CL_COPY_UNBINDABLE) &&
1730 IS_MNT_UNBINDABLE(s)) { 1736 IS_MNT_UNBINDABLE(s)) {
1731 s = skip_mnt_tree(s); 1737 if (s->mnt.mnt_flags & MNT_LOCKED) {
1732 continue; 1738 /* Both unbindable and locked. */
1739 q = ERR_PTR(-EPERM);
1740 goto out;
1741 } else {
1742 s = skip_mnt_tree(s);
1743 continue;
1744 }
1733 } 1745 }
1734 if (!(flag & CL_COPY_MNT_NS_FILE) && 1746 if (!(flag & CL_COPY_MNT_NS_FILE) &&
1735 is_mnt_ns_file(s->mnt.mnt_root)) { 1747 is_mnt_ns_file(s->mnt.mnt_root)) {
@@ -1782,7 +1794,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
1782{ 1794{
1783 namespace_lock(); 1795 namespace_lock();
1784 lock_mount_hash(); 1796 lock_mount_hash();
1785 umount_tree(real_mount(mnt), UMOUNT_SYNC); 1797 umount_tree(real_mount(mnt), 0);
1786 unlock_mount_hash(); 1798 unlock_mount_hash();
1787 namespace_unlock(); 1799 namespace_unlock();
1788} 1800}
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index e5222b5fb4fe..923414a246e9 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
974 if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) 974 if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
975 goto out; 975 goto out;
976 976
977 ret = sort_idmaps(&new_map);
978 if (ret < 0)
979 goto out;
980
981 ret = -EPERM; 977 ret = -EPERM;
982 /* Map the lower ids from the parent user namespace to the 978 /* Map the lower ids from the parent user namespace to the
983 * kernel global id space. 979 * kernel global id space.
@@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf,
1004 e->lower_first = lower_first; 1000 e->lower_first = lower_first;
1005 } 1001 }
1006 1002
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
1007 /* Install the map */ 1011 /* Install the map */
1008 if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) { 1012 if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
1009 memcpy(map->extent, new_map.extent, 1013 memcpy(map->extent, new_map.extent,