提交 45b4b782 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace

Pull namespace fixes from Eric Biederman:
 "While reading through the code of detach_mounts I realized the code
  was slightly off.  Testing it revealed two buggy corner cases that can
  send the code of detach_mounts into an infinite loop.

  Fixing the code to do the right thing removes the possibility of these
  user triggered infinite loops in the code"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  mnt: In detach_mounts detach the appropriate unmounted mount
  mnt: Clarify and correct the disconnect logic in umount_tree
...@@ -1361,6 +1361,36 @@ enum umount_tree_flags { ...@@ -1361,6 +1361,36 @@ enum umount_tree_flags {
UMOUNT_PROPAGATE = 2, UMOUNT_PROPAGATE = 2,
UMOUNT_CONNECTED = 4, UMOUNT_CONNECTED = 4,
}; };
static bool disconnect_mount(struct mount *mnt, enum umount_tree_flags how)
{
/* Leaving mounts connected is only valid for lazy umounts */
if (how & UMOUNT_SYNC)
return true;
/* A mount without a parent has nothing to be connected to */
if (!mnt_has_parent(mnt))
return true;
/* Because the reference counting rules change when mounts are
* unmounted and connected, umounted mounts may not be
* connected to mounted mounts.
*/
if (!(mnt->mnt_parent->mnt.mnt_flags & MNT_UMOUNT))
return true;
/* Has it been requested that the mount remain connected? */
if (how & UMOUNT_CONNECTED)
return false;
/* Is the mount locked such that it needs to remain connected? */
if (IS_MNT_LOCKED(mnt))
return false;
/* By default disconnect the mount */
return true;
}
/* /*
* mount_lock must be held * mount_lock must be held
* namespace_sem must be held for write * namespace_sem must be held for write
...@@ -1398,10 +1428,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how) ...@@ -1398,10 +1428,7 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
if (how & UMOUNT_SYNC) if (how & UMOUNT_SYNC)
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
disconnect = !(((how & UMOUNT_CONNECTED) && disconnect = disconnect_mount(p, how);
mnt_has_parent(p) &&
(p->mnt_parent->mnt.mnt_flags & MNT_UMOUNT)) ||
IS_MNT_LOCKED_AND_LAZY(p));
pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
disconnect ? &unmounted : NULL); disconnect ? &unmounted : NULL);
...@@ -1538,11 +1565,8 @@ void __detach_mounts(struct dentry *dentry) ...@@ -1538,11 +1565,8 @@ void __detach_mounts(struct dentry *dentry)
while (!hlist_empty(&mp->m_list)) { while (!hlist_empty(&mp->m_list)) {
mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
if (mnt->mnt.mnt_flags & MNT_UMOUNT) { if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
struct mount *p, *tmp; hlist_add_head(&mnt->mnt_umount.s_list, &unmounted);
list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) { umount_mnt(mnt);
hlist_add_head(&p->mnt_umount.s_list, &unmounted);
umount_mnt(p);
}
} }
else umount_tree(mnt, UMOUNT_CONNECTED); else umount_tree(mnt, UMOUNT_CONNECTED);
} }
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED) #define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED)
#define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED) #define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED)
#define IS_MNT_LOCKED(m) ((m)->mnt.mnt_flags & MNT_LOCKED) #define IS_MNT_LOCKED(m) ((m)->mnt.mnt_flags & MNT_LOCKED)
#define IS_MNT_LOCKED_AND_LAZY(m) \
(((m)->mnt.mnt_flags & (MNT_LOCKED|MNT_SYNC_UMOUNT)) == MNT_LOCKED)
#define CL_EXPIRE 0x01 #define CL_EXPIRE 0x01
#define CL_SLAVE 0x02 #define CL_SLAVE 0x02
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册