linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: ebiederm@xmission.com (Eric W. Biederman)
To: Pavel Emelyanov <xemul@openvz.org>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>, Pavel Machek <pavel@ucw.cz>,
	kernel list <linux-kernel@vger.kernel.org>,
	netdev <netdev@vger.kernel.org>
Subject: [CFT][PATCH] proc_net: Remove userspace visible changes.
Date: Sat, 24 Nov 2007 16:34:00 -0700	[thread overview]
Message-ID: <m1prxznrpz.fsf_-_@ebiederm.dsl.xmission.com> (raw)
In-Reply-To: <4743026B.2020907@openvz.org> (Pavel Emelyanov's message of "Tue, 20 Nov 2007 18:51:07 +0300")


Ok.  I have kicked around a lot implementation ideas and took a good hard
look at my /proc/net implementation.  The patch below should close all
of the holes with /proc/net that I am aware of.

Bind mounts work and properly capture /proc/net/
stat of /proc/net and /proc/net/ return the same information.
cd /proc/net/ ; ls .. works
The dentry has the proper parent and no longer appears deleted.

As well as few more theoretical cases I have been able to imagine,
like open("/proc/net", O_NOFOLLOW | O_DIRECTORY) getdents...

Please take a look and kick this patch around.  I don't expect anyone
to find any issues but a few more eyeballs before I send this
along to Linus would be appreciated.  Thanks.


From: Eric W. Biederman <ebiederm@xmission.com>
Subject: [PATCH] proc_net: Remove userspace visible changes.

This patch fixes some bugs in corner cases of the /proc/net
implementation.

In proc_net_shadow_dentry.
- Set the parent dentry properly.
- Make the dentry appear hashed so .. works.

Remove the unreachable proc_net_lookup.

Implement proc_net_getattr to complete the
set of implemented inode operations.

Implement proc_net_open which changes the directory we
are openting to remove the need to implement any other
file operations.

Add a big fat comment on how /proc/net works to make it
easier for someone else to look at and understand this code.

This patch should remove the last of the accidental user visible artifacts
that arose from adding network namespace support to /proc/net.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
 fs/proc/proc_net.c |  116 +++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 93 insertions(+), 23 deletions(-)

diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 131f9c6..b0b4b3f 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -50,24 +50,69 @@ struct net *get_proc_net(const struct inode *inode)
 }
 EXPORT_SYMBOL_GPL(get_proc_net);
 
+/*
+ * The contents of the files under /proc/net depend on which network
+ * namespace you are in.  
+ *
+ * This implementation relies on the following properties.
+ *
+ * - Each network namespaces has it's own /proc/net dcache tree.
+ * - A directory with a follow_link method never calls lookup
+ * - It is possible in ->open to competely change which underlying
+ *   filesystem, path, and inode the struct file refers to.
+ * - A dcache entry with DCACHE_UNHASHED clear and pprev set
+ *   appares hashed (and thus valid) to the dcache.
+ *
+ * To give each network namespace it's own /proc/net directory
+ * in a manner transparent to user space (and not requiring /proc)
+ * be remounted we do the following things:
+ *
+ *   Keep a different dentry tree for each network namespace under
+ *   /proc/net.
+ *
+ *   Have the root of the /proc/net dentry tree be a ``unhashed''
+ *   dentry with it's root pointing at the /proc dentry.  Making
+ *   it appear in parallel with the normal /proc/net.
+ *
+ *   Redirect all opens of the normal /proc/net to the one appropriate
+ *   for the opening process in ->open.
+ *
+ *   Redirect all directory traversals onto the appropriate /proc/net
+ *   with a follow_link method.
+ *
+ *   Wrap all other applicable inode operations so they appear to
+ *   happen not on the normal /proc/net but on the network namespace
+ *   specific one.
+ *
+ * Currently we can use a bind mount inside a network namespace
+ * to /proc/net visible to processes outside that network namespace.
+ * Long term /proc/net should migrate to /proc/<pid>/net removing
+ * the need for the bind mount for monitoring processes.
+ */
+
 static struct proc_dir_entry *proc_net_shadow;
 
-static struct dentry *proc_net_shadow_dentry(struct dentry *parent,
-						struct proc_dir_entry *de)
+static struct dentry *proc_net_shadow_dentry(struct net *net,
+					     struct dentry *dentry)
 {
+	struct proc_dir_entry *de = net->proc_net;
 	struct dentry *shadow = NULL;
 	struct inode *inode;
 	if (!de)
 		goto out;
 	de_get(de);
-	inode = proc_get_inode(parent->d_inode->i_sb, de->low_ino, de);
+	inode = proc_get_inode(dentry->d_sb, de->low_ino, de);
 	if (!inode)
 		goto out_de_put;
-	shadow = d_alloc_name(parent, de->name);
+	shadow = d_alloc(dentry->d_parent, &dentry->d_name);
 	if (!shadow)
 		goto out_iput;
-	shadow->d_op = parent->d_op; /* proc_dentry_operations */
+	shadow->d_op = dentry->d_op; /* proc_dentry_operations */
 	d_instantiate(shadow, inode);
+
+	/* Make the dentry looked hashed */
+	shadow->d_hash.pprev = &shadow->d_hash.next;
+	shadow->d_flags &= ~DCACHE_UNHASHED;
 out:
 	return shadow;
 out_iput:
@@ -77,36 +122,36 @@ out_de_put:
 	goto out;
 }
 
-static void *proc_net_follow_link(struct dentry *parent, struct nameidata *nd)
+static void *proc_net_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct dentry *shadow;
-	shadow = proc_net_shadow_dentry(parent, net->proc_net);
+
+	shadow = proc_net_shadow_dentry(net, dentry);
 	if (!shadow)
-		return ERR_PTR(-ENOENT);
+		goto out_err;
 
 	dput(nd->dentry);
-	/* My dentry count is 1 and that should be enough as the
-	 * shadow dentry is thrown away immediately.
-	 */
 	nd->dentry = shadow;
+
 	return NULL;
+out_err:
+	return ERR_PTR(-ENOENT);
 }
 
-static struct dentry *proc_net_lookup(struct inode *dir, struct dentry *dentry,
-				      struct nameidata *nd)
+static int proc_net_getattr(struct vfsmount *mnt, struct dentry *dentry,
+			    struct kstat *stat)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct dentry *shadow;
+	int ret;
 
-	shadow = proc_net_shadow_dentry(nd->dentry, net->proc_net);
+	shadow = proc_net_shadow_dentry(net, dentry);
 	if (!shadow)
-		return ERR_PTR(-ENOENT);
-
-	dput(nd->dentry);
-	nd->dentry = shadow;
-
-	return shadow->d_inode->i_op->lookup(shadow->d_inode, dentry, nd);
+		return -ENOENT;
+	ret = shadow->d_inode->i_op->getattr(mnt, shadow, stat);
+	dput(shadow);
+	return ret;
 }
 
 static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -115,7 +160,7 @@ static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
 	struct dentry *shadow;
 	int ret;
 
-	shadow = proc_net_shadow_dentry(dentry->d_parent, net->proc_net);
+	shadow = proc_net_shadow_dentry(net, dentry);
 	if (!shadow)
 		return -ENOENT;
 	ret = shadow->d_inode->i_op->setattr(shadow, iattr);
@@ -123,13 +168,38 @@ static int proc_net_setattr(struct dentry *dentry, struct iattr *iattr)
 	return ret;
 }
 
+static int proc_net_open(struct inode *inode, struct file *filp)
+{
+	struct net *net = current->nsproxy->net_ns;
+	struct dentry *shadow;
+	int ret;
+
+	shadow = proc_net_shadow_dentry(net, filp->f_dentry);
+	if (!shadow)
+		return -ENOENT;
+
+	inode = shadow->d_inode;
+
+	fops_put(filp->f_op);
+	dput(filp->f_dentry);
+
+	filp->f_mapping = inode->i_mapping;
+	filp->f_op = fops_get(inode->i_fop);
+	filp->f_dentry = shadow;
+
+	ret = 0;
+	if (filp->f_op && filp->f_op->open)
+		ret = filp->f_op->open(inode, filp);
+	return ret;
+}
+
 static const struct file_operations proc_net_dir_operations = {
-	.read			= generic_read_dir,
+	.open			= proc_net_open,
 };
 
 static struct inode_operations proc_net_dir_inode_operations = {
 	.follow_link	= proc_net_follow_link,
-	.lookup		= proc_net_lookup,
+	.getattr	= proc_net_getattr,
 	.setattr	= proc_net_setattr,
 };
 
-- 
1.5.3.rc6.17.g1911


  parent reply	other threads:[~2007-11-24 23:35 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-19 19:10 2.6.24-rc3: find complains about /proc/net Pavel Machek
2007-11-19 22:04 ` Rafael J. Wysocki
2007-11-20 15:51   ` Pavel Emelyanov
2007-11-20 21:52     ` Eric W. Biederman
2007-11-20 21:59       ` Ingo Molnar
2007-11-20 22:17         ` Eric W. Biederman
2007-11-20 22:35           ` Ingo Molnar
2007-11-20 22:54             ` Roland McGrath
2007-11-20 23:01               ` Ingo Molnar
2007-11-20 23:06                 ` Guillaume Chazarain
2007-11-20 23:26                   ` Roland McGrath
2007-11-20 23:32                     ` Ulrich Drepper
2007-11-20 23:45                       ` Ingo Molnar
2007-11-20 23:51                         ` Roland McGrath
2007-11-21  0:47                           ` Eric W. Biederman
2007-11-21  1:01                           ` Rafael J. Wysocki
2007-11-21  0:41                       ` Eric W. Biederman
2007-11-20 23:43                   ` Ingo Molnar
2007-11-20 22:41         ` [PATCH] proc: Fix the threaded /proc/self Eric W. Biederman
2007-11-20 22:58           ` Guillaume Chazarain
2007-11-20 23:03           ` Ingo Molnar
2007-11-21  1:19     ` 2.6.24-rc3: find complains about /proc/net Eric W. Biederman
2007-11-21  6:36     ` Eric W. Biederman
2007-11-21  9:36       ` Pavel Emelyanov
2007-11-24 23:34     ` Eric W. Biederman [this message]
2007-11-26  8:43       ` [CFT][PATCH] proc_net: Remove userspace visible changes Eric W. Biederman
2007-11-26 22:17     ` [PATCH 2.6.24-rc3] Fix /proc/net breakage Eric W. Biederman
2007-11-27 11:20       ` Pavel Emelyanov
2007-11-27 12:36         ` Eric W. Biederman
2007-12-07  4:51       ` David Woodhouse
2007-12-07 10:23         ` Andrew Morton
2007-12-07 11:11           ` Denis V. Lunev
2007-12-27 17:40           ` Andreas Mohr
2007-12-27 18:41             ` Alexey Dobriyan
2007-12-27 22:17               ` Andreas Mohr
2007-12-28  6:22                 ` Alexey Dobriyan
2007-12-28  7:21                   ` Andreas Mohr
2007-12-30 16:14                     ` [usb regression] " Ingo Molnar
2007-12-30 20:34                       ` Alan Stern
2007-12-31  5:25                         ` Greg KH
2007-12-31 17:49                           ` Alan Stern
2007-12-31 19:26                             ` Greg KH
2008-01-02  6:00                               ` Greg KH
2008-01-02  6:13                                 ` Andreas Mohr
2008-01-02  7:14                                   ` Greg KH
2008-01-02 15:56                                 ` Alan Stern
2008-01-02 18:48                                   ` David Brownell
2008-01-02  6:04                         ` Andreas Mohr

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=m1prxznrpz.fsf_-_@ebiederm.dsl.xmission.com \
    --to=ebiederm@xmission.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pavel@ucw.cz \
    --cc=rjw@sisk.pl \
    --cc=xemul@openvz.org \
    /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).