linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] autofs4 - fix device ioctl mount lookup
@ 2013-09-04  0:54 Ian Kent
  2013-09-04  0:55 ` [PATCH 2/3] autofs: fix the return value of autofs4_fill_super Ian Kent
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Ian Kent @ 2013-09-04  0:54 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: linux-fsdevel, rui.xiang, autofs mailing list,
	Kernel Mailing List, Al Viro

When reconnecting to automounts at startup an autofs ioctl is used
to find the device and inode of existing mounts so they can be used
to open a file descriptor of possibly covered mounts.

At this time the the caller might not yet "own" the mount so it can
trigger calling ->d_automount(). This causes automount to hang when
trying to reconnect to direct or offset mount types.

Consequently kern_path() can't be used.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs4/dev-ioctl.c |   72 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 62 insertions(+), 10 deletions(-)

diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 743c7c2..1d24e42 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -183,13 +183,67 @@ static int autofs_dev_ioctl_protosubver(struct file *fp,
 	return 0;
 }
 
+/*
+ * Lookup the the topmost path of a (possible) mount stack.
+ *
+ * kern_path() can't be used here because the caller might not
+ * "own" the automount dentry yet and we would end up calling
+ * back to ourself.
+ */
+static int kern_path_top(const char *pathname,
+			 unsigned int flags, struct path *path)
+{
+	struct dentry *dentry;
+	struct qstr name;
+	const char *tmp;
+	unsigned int len;
+	int err;
+
+	len = strlen(pathname);
+	if (len <= 1)
+		return -EINVAL;
+
+	tmp = pathname + len - 1;
+	len = 0;
+	if (*tmp == '/')
+		tmp--;
+	do {
+		if (*tmp == '/')
+			break;
+		len++;
+	} while (--tmp >= pathname);
+	tmp++;
+
+	err = kern_path(pathname, flags | LOOKUP_PARENT, path);
+	if (err)
+		return err;
+
+	name.name = tmp;
+	name.len = len;
+	name.hash = full_name_hash(tmp, len);
+
+	dentry = d_lookup(path->dentry, &name);
+	if (!dentry) {
+		path_put(path);
+		return -ENOENT;
+	}
+	dput(path->dentry);
+	path->dentry = dentry;
+
+	while (follow_down_one(path))
+		;
+
+	return 0;
+}
+
+/* Find the topmost mount satisfying test() */
 static int find_autofs_mount(const char *pathname,
 			     struct path *res,
 			     int test(struct path *path, void *data),
 			     void *data)
 {
 	struct path path;
-	int err = kern_path(pathname, 0, &path);
+	int err = kern_path_top(pathname, 0, &path);
 	if (err)
 		return err;
 	err = -ENOENT;
@@ -197,10 +251,9 @@ static int find_autofs_mount(const char *pathname,
 		if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) {
 			if (test(&path, data)) {
 				path_get(&path);
-				if (!err) /* already found some */
-					path_put(res);
 				*res = path;
 				err = 0;
+				break;
 			}
 		}
 		if (!follow_up(&path))
@@ -486,12 +539,11 @@ static int autofs_dev_ioctl_askumount(struct file *fp,
  * mount if there is one or 0 if it isn't a mountpoint.
  *
  * If we aren't supplied with a file descriptor then we
- * lookup the nameidata of the path and check if it is the
- * root of a mount. If a type is given we are looking for
- * a particular autofs mount and if we don't find a match
- * we return fail. If the located nameidata path is the
- * root of a mount we return 1 along with the super magic
- * of the mount or 0 otherwise.
+ * lookup the path and check if it is the root of a mount.
+ * If a type is given we are looking for a particular autofs
+ * mount and if we don't find a match we return fail. If the
+ * located path is the root of a mount we return 1 along with
+ * the super magic of the mount or 0 otherwise.
  *
  * In both cases the the device number (as returned by
  * new_encode_dev()) is also returned.
@@ -519,7 +571,7 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp,
 
 	if (!fp || param->ioctlfd == -1) {
 		if (autofs_type_any(type))
-			err = kern_path(name, LOOKUP_FOLLOW, &path);
+			err = kern_path_top(name, LOOKUP_FOLLOW, &path);
 		else
 			err = find_autofs_mount(name, &path, test_by_type, &type);
 		if (err)

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2013-09-06 10:11 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-04  0:54 [PATCH 1/3] autofs4 - fix device ioctl mount lookup Ian Kent
2013-09-04  0:55 ` [PATCH 2/3] autofs: fix the return value of autofs4_fill_super Ian Kent
2013-09-04  0:55 ` [PATCH 3/3] autofs: use IS_ROOT to replace root dentry checks Ian Kent
2013-09-04  1:03 ` [PATCH 1/3] autofs4 - fix device ioctl mount lookup Al Viro
2013-09-04  2:00   ` Al Viro
2013-09-04  2:18     ` Linus Torvalds
2013-09-04  2:26       ` Al Viro
2013-09-04  2:42         ` Al Viro
2013-09-04  3:53           ` Ian Kent
2013-09-04  4:07             ` Ian Kent
2013-09-04 10:35               ` Jeff Layton
2013-09-06  8:38           ` Ian Kent
2013-09-06  8:54             ` Ian Kent
2013-09-06 10:11               ` Jeff Layton
2013-09-04  2:46       ` Ian Kent

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).