linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ram <linuxram@us.ibm.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	Andrew Morton <akpm@osdl.org>,
	viro@parcelfarce.linux.theplanet.co.uk, jamie@shareable.org
Subject: Re: [RFC][PATCH] rbind across namespaces
Date: Mon, 23 May 2005 00:24:08 -0700	[thread overview]
Message-ID: <1116833048.4397.137.camel@localhost> (raw)
In-Reply-To: <E1Da5BO-00027F-00@dorka.pomaz.szeredi.hu>

[-- Attachment #1: Type: text/plain, Size: 518 bytes --]

On Sun, 2005-05-22 at 22:08, Miklos Szeredi wrote:
> > The patch failed rbinds in some cases. Fixed it. The enclosed patch
> > has a high chance of being bug free.
> 
> Except not setting mnt_namespace corretly, it does seem to be ok.

yes done. enclosed the patch.

But seems like this patch opens up questions like:

Should mounts/umounts/remounts/pivot_root in foreign namespaces 
be allowed? Probably check_mnt() can simply go, and the correct
semaphores have to be held in each of the functions.

RP

> 
> Miklos

[-- Attachment #2: rbind_across_namespace5.patch --]
[-- Type: text/x-patch, Size: 5372 bytes --]

Summary:

Allows rbinds across any two namespaces.  NOTE: currenly bind from foriegn
namespace to current namespace is allowed. This patch now allows:

1. binds/rbinds from any namespace to any other namespace, under the assumption
   that if a process has access to a namespace, it ought to have permission to
   manipulate that namespace. 
2. bind/rbind to detached mounts are disallowed.
3. rbind from detached mount is treated as bind.

The patch incorporates ideas from Miklos and Jamie, and is dependent on
Miklos's "fix race in mark_mounts_for_expiry" patch to function correctly. Also
it depends on Miklos's "fix bind mount from foreign namespace" patch, because
without that patch umounts would fail.

--- /home/linux/views/linux-2.6.12-rc4/fs/namespace.c	2005-05-06 23:22:29.000000000 -0700
+++ linux-2.6.12-rc4/fs/namespace.c	2005-05-23 00:20:39.000000000 -0700
@@ -148,7 +148,7 @@ static struct vfsmount *next_mnt(struct 
 }
 
 static struct vfsmount *
-clone_mnt(struct vfsmount *old, struct dentry *root)
+clone_mnt(struct vfsmount *old, struct dentry *root, struct namespace *ns)
 {
 	struct super_block *sb = old->mnt_sb;
 	struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
@@ -160,7 +160,7 @@ clone_mnt(struct vfsmount *old, struct d
 		mnt->mnt_root = dget(root);
 		mnt->mnt_mountpoint = mnt->mnt_root;
 		mnt->mnt_parent = mnt;
-		mnt->mnt_namespace = old->mnt_namespace;
+		mnt->mnt_namespace = ns;
 
 		/* stick the duplicate mount on the same expiry list
 		 * as the original if that was on one */
@@ -533,13 +533,14 @@ lives_below_in_same_fs(struct dentry *d,
 	}
 }
 
-static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
+static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
+				  struct namespace *ns)
 {
 	struct vfsmount *res, *p, *q, *r, *s;
 	struct list_head *h;
 	struct nameidata nd;
 
-	res = q = clone_mnt(mnt, dentry);
+	res = q = clone_mnt(mnt, dentry, ns);
 	if (!q)
 		goto Enomem;
 	q->mnt_mountpoint = mnt->mnt_mountpoint;
@@ -558,7 +559,7 @@ static struct vfsmount *copy_tree(struct
 			p = s;
 			nd.mnt = q;
 			nd.dentry = p->mnt_mountpoint;
-			q = clone_mnt(p, p->mnt_root);
+			q = clone_mnt(p, p->mnt_root, ns);
 			if (!q)
 				goto Enomem;
 			spin_lock(&vfsmount_lock);
@@ -616,11 +617,14 @@ out_unlock:
 }
 
 /*
- * do loopback mount.
+ * do loopback mount.  The loopback mount can be done from any namespace to any
+ * other namespace including the current namespace, as long as the task acquired 
+ * rights to manipulate them.
  */
 static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
 {
 	struct nameidata old_nd;
+	struct namespace *mntpt_ns, *old_ns;
 	struct vfsmount *mnt = NULL;
 	int err = mount_is_safe(nd);
 	if (err)
@@ -631,16 +635,58 @@ static int do_loopback(struct nameidata 
 	if (err)
 		return err;
 
-	down_write(&current->namespace->sem);
 	err = -EINVAL;
-	if (check_mnt(nd->mnt) && (!recurse || check_mnt(old_nd.mnt))) {
-		err = -ENOMEM;
-		if (recurse)
-			mnt = copy_tree(old_nd.mnt, old_nd.dentry);
-		else
-			mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+	spin_lock(&vfsmount_lock);
+
+	/* 
+	 * Disallow bind/rbind mounts to detached mounts and treat rbind from
+	 * detached mount as normal bind.
+	 */
+	mntpt_ns = nd->mnt->mnt_namespace;
+	old_ns = old_nd.mnt->mnt_namespace;
+	if (!mntpt_ns || !mntpt_ns->root) {
+		spin_unlock(&vfsmount_lock);
+		goto out;
 	}
 
+	if (!old_ns || !old_ns->root)
+		recurse = 0;
+
+	get_namespace(mntpt_ns);
+	if (recurse && old_ns != mntpt_ns)
+		get_namespace(old_ns);
+
+	spin_unlock(&vfsmount_lock);
+
+	/* 
+	 * make sure we don't race with some other thread manipulating the
+	 * namespaces.
+	 */
+	if (recurse && (old_ns < mntpt_ns))
+		down_write(&old_ns->sem);
+	down_write(&mntpt_ns->sem);
+	if (recurse && (old_ns > mntpt_ns))
+		down_write(&old_ns->sem);
+
+
+	/* 
+	 * well... mounts might have detached while we acquired
+	 * the semaphores. Revalidate that the destination mount 
+	 * is still attached. 
+	 */
+	if (!nd->mnt->mnt_namespace)
+		goto error_out;
+
+	/* 
+	 * and if the source mount is detached, than just do
+	 * a bind, instead of a rbind
+	 */
+	err = -ENOMEM;
+	if (recurse && old_nd.mnt->mnt_namespace)
+		mnt = copy_tree(old_nd.mnt, old_nd.dentry, mntpt_ns);
+	else
+		mnt = clone_mnt(old_nd.mnt, old_nd.dentry, mntpt_ns);
+
 	if (mnt) {
 		/* stop bind mounts from expiring */
 		spin_lock(&vfsmount_lock);
@@ -656,7 +702,15 @@ static int do_loopback(struct nameidata 
 			mntput(mnt);
 	}
 
-	up_write(&current->namespace->sem);
+error_out:
+	up_write(&mntpt_ns->sem);
+	if (recurse && (old_ns != mntpt_ns)) {
+		up_write(&old_ns->sem);
+		put_namespace(old_ns);
+	}
+	put_namespace(mntpt_ns);
+
+out:
 	path_release(&old_nd);
 	return err;
 }
@@ -1090,7 +1144,8 @@ int copy_namespace(int flags, struct tas
 
 	down_write(&tsk->namespace->sem);
 	/* First pass: copy the tree topology */
-	new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root);
+	new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, 
+				new_ns);
 	if (!new_ns->root) {
 		up_write(&tsk->namespace->sem);
 		kfree(new_ns);
@@ -1108,7 +1163,6 @@ int copy_namespace(int flags, struct tas
 	p = namespace->root;
 	q = new_ns->root;
 	while (p) {
-		q->mnt_namespace = new_ns;
 		if (fs) {
 			if (p == fs->rootmnt) {
 				rootmnt = p;

  reply	other threads:[~2005-05-23  7:24 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-05-20 22:11 [RFC][PATCH] rbind across namespaces Ram
2005-05-21  6:27 ` Miklos Szeredi
2005-05-21  7:26   ` Ram
2005-05-21  8:09     ` Miklos Szeredi
2005-05-21  8:45       ` Ram
2005-05-21  9:09         ` Miklos Szeredi
2005-05-21 10:07           ` Ram
2005-05-21 13:12             ` Miklos Szeredi
2005-05-22 20:25               ` Ram
2005-05-22 20:51                 ` Ram
2005-05-23  5:08                   ` Miklos Szeredi
2005-05-23  7:24                     ` Ram [this message]
2005-05-23  8:24                       ` Miklos Szeredi
2005-05-21  9:48         ` Miklos Szeredi
2005-05-21 13:46       ` Jamie Lokier
2005-05-22  8:08         ` Miklos Szeredi
2005-05-22 17:04           ` [RFC][PATCH] /proc/dead_mounts support (Was: [RFC][PATCH] rbind across ...) Miklos Szeredi
2005-05-22 21:10           ` [RFC][PATCH] rbind across namespaces Ram
2005-05-23  5:07             ` Miklos Szeredi
2005-05-24  0:39           ` Mike Waychison
2005-05-24  5:43             ` Miklos Szeredi
2005-05-24  7:13               ` Mike Waychison
2005-05-24  8:25                 ` Miklos Szeredi
2005-05-24 17:09                   ` Mike Waychison
2005-05-24 17:31                     ` Miklos Szeredi
2005-05-24 17:44                       ` Mike Waychison
2005-05-24 17:56                         ` Miklos Szeredi
2005-05-24 18:04                           ` Mike Waychison
2005-05-30 19:06                             ` Ram
2005-05-24  9:18                 ` Miklos Szeredi
2005-05-24 17:15                   ` Mike Waychison
2005-05-24 17:46                     ` Miklos Szeredi
2005-05-24 18:15                     ` Jamie Lokier
2005-05-24 18:33                       ` Mike Waychison
2005-05-24 21:51                         ` Jamie Lokier
2005-05-21 13:43     ` Jamie Lokier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1116833048.4397.137.camel@localhost \
    --to=linuxram@us.ibm.com \
    --cc=akpm@osdl.org \
    --cc=jamie@shareable.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=viro@parcelfarce.linux.theplanet.co.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).