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
This commit is contained in:
Коммит
1de4f2ef21
|
@ -1540,8 +1540,13 @@ static int do_umount(struct mount *mnt, int flags)
|
||||||
|
|
||||||
namespace_lock();
|
namespace_lock();
|
||||||
lock_mount_hash();
|
lock_mount_hash();
|
||||||
event++;
|
|
||||||
|
|
||||||
|
/* Recheck MNT_LOCKED with the locks held */
|
||||||
|
retval = -EINVAL;
|
||||||
|
if (mnt->mnt.mnt_flags & MNT_LOCKED)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
event++;
|
||||||
if (flags & MNT_DETACH) {
|
if (flags & MNT_DETACH) {
|
||||||
if (!list_empty(&mnt->mnt_list))
|
if (!list_empty(&mnt->mnt_list))
|
||||||
umount_tree(mnt, UMOUNT_PROPAGATE);
|
umount_tree(mnt, UMOUNT_PROPAGATE);
|
||||||
|
@ -1555,6 +1560,7 @@ static int do_umount(struct mount *mnt, int flags)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
namespace_unlock();
|
namespace_unlock();
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -1645,7 +1651,7 @@ int ksys_umount(char __user *name, int flags)
|
||||||
goto dput_and_out;
|
goto dput_and_out;
|
||||||
if (!check_mnt(mnt))
|
if (!check_mnt(mnt))
|
||||||
goto dput_and_out;
|
goto dput_and_out;
|
||||||
if (mnt->mnt.mnt_flags & MNT_LOCKED)
|
if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
|
||||||
goto dput_and_out;
|
goto dput_and_out;
|
||||||
retval = -EPERM;
|
retval = -EPERM;
|
||||||
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
|
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
|
||||||
|
@ -1728,9 +1734,15 @@ 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)) {
|
||||||
|
if (s->mnt.mnt_flags & MNT_LOCKED) {
|
||||||
|
/* Both unbindable and locked. */
|
||||||
|
q = ERR_PTR(-EPERM);
|
||||||
|
goto out;
|
||||||
|
} else {
|
||||||
s = skip_mnt_tree(s);
|
s = skip_mnt_tree(s);
|
||||||
continue;
|
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)) {
|
||||||
s = skip_mnt_tree(s);
|
s = skip_mnt_tree(s);
|
||||||
|
@ -1782,7 +1794,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
|
||||||
{
|
{
|
||||||
namespace_lock();
|
namespace_lock();
|
||||||
lock_mount_hash();
|
lock_mount_hash();
|
||||||
umount_tree(real_mount(mnt), UMOUNT_SYNC);
|
umount_tree(real_mount(mnt), 0);
|
||||||
unlock_mount_hash();
|
unlock_mount_hash();
|
||||||
namespace_unlock();
|
namespace_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||||
if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
|
if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = sort_idmaps(&new_map);
|
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = -EPERM;
|
ret = -EPERM;
|
||||||
/* Map the lower ids from the parent user namespace to the
|
/* Map the lower ids from the parent user namespace to the
|
||||||
* kernel global id space.
|
* kernel global id space.
|
||||||
|
@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||||
e->lower_first = lower_first;
|
e->lower_first = lower_first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we want to use binary search for lookup, this clones the extent
|
||||||
|
* array and sorts both copies.
|
||||||
|
*/
|
||||||
|
ret = sort_idmaps(&new_map);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Install the map */
|
/* Install the map */
|
||||||
if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
|
if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
|
||||||
memcpy(map->extent, new_map.extent,
|
memcpy(map->extent, new_map.extent,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче