* [RFC][PATCH 0/7] Automount behaviour correction
@ 2011-09-23 16:24 David Howells
2011-09-23 16:24 ` [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW David Howells
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:24 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Here are a set of patches to correct the behaviour of automounting, hopefully
without introducing extra fragility. We might want to merge them together in
various ways, and the last one or two patches we may want to drop, depending on
what we actually want the behaviour to actually be.
They are:
(1) Revert Miklos's patch. Not strictly a necessary part of the series, but
it does fix the NFS4 regression immediately.
(2) Make chown and lchown jump to fchownat with appropriate flags. This is a
useful cleanup for the following patches.
(3) Replace LOOKUP_NO_AUTOMOUNT with LOOKUP_AUTOMOUNT and set it where
appropriate before calling pathwalk (usually when we'd be setting
LOOKUP_FOLLOW). This just switches the polarity of the flag.
(4) Move the automount/no-automount policy to the callers of pathwalk so that
things such as NFS4 don't get caught out by changes to the policy. The
policy is outlined in that patch header.
(5) Remove the logic from follow_automount() to try and guess from the
LOOKUP_* flags whether or not we should be automounting this time. It's
shown to be a bit fragile and the policy is better predetermined by this
point.
(6) Make stat and xattr unconditionally _not_ automount. This reinstates the
old autofs behaviour, but does then regress NFS, AFS and CIFS.
(7) Make stat and xattr vary their behaviour depending on whether the
automount point belongs to autofs or not. This should reinstate the NFS,
AFS and CIFS behaviour without regressing autofs.
Now if we want 6 and maybe 7, these can be rolled into 4. Patch 1 can be
discarded entirely if 5 is taken.
David
---
David Howells (7):
VFS: Vary the automounting rules for autofs
VFS: Make stat and xattr calls not automount
VFS: Ignore symlink following advice when pathwalking
VFS: Move the automount suppression decision out to the initial callers of
VFS: Change LOOKUP_NO_AUTOMOUNT to LOOKUP_AUTOMOUNT
VFS: Make chown() and lchown() call fchownat()
NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW
drivers/mtd/ubi/build.c | 2 +
drivers/mtd/ubi/kapi.c | 2 +
fs/autofs4/dev-ioctl.c | 2 +
fs/block_dev.c | 2 +
fs/configfs/symlink.c | 2 +
fs/ecryptfs/main.c | 2 +
fs/exec.c | 5 ++-
fs/fhandle.c | 11 +++----
fs/gfs2/ops_fstype.c | 2 +
fs/internal.h | 24 +++++++++++++++
fs/namei.c | 30 ++++++-------------
fs/namespace.c | 8 +++--
fs/nfs/super.c | 2 +
fs/nfsd/nfs4state.c | 2 +
fs/notify/fanotify/fanotify_user.c | 2 +
fs/notify/inotify/inotify_user.c | 2 +
fs/open.c | 57 +++++++++---------------------------
fs/quota/quota.c | 2 +
fs/stat.c | 20 ++++++-------
fs/statfs.c | 2 +
fs/utimes.c | 14 ++++-----
fs/xattr.c | 24 ++++++++++-----
include/linux/fcntl.h | 1 +
include/linux/namei.h | 10 ++++--
net/unix/af_unix.c | 2 +
security/tomoyo/load_policy.c | 2 +
security/tomoyo/mount.c | 3 +-
27 files changed, 116 insertions(+), 121 deletions(-)
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
@ 2011-09-23 16:24 ` David Howells
2011-09-23 16:35 ` Linus Torvalds
2011-09-23 16:53 ` David Howells
2011-09-23 16:25 ` [PATCH 2/7] VFS: Make chown() and lchown() call fchownat() David Howells
` (6 subsequent siblings)
7 siblings, 2 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:24 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Revert the following change:
commit 0ec26fd0698285b31248e34bf1abb022c00f23d6
Author: Miklos Szeredi <mszeredi@suse.cz>
Date: Mon Sep 5 18:06:26 2011 +0200
Subject: vfs: automount should ignore LOOKUP_FOLLOW
which makes stat(), getxattr(), etc. behave as lstat(), lgetxattr(), etc. with
respect to automounting: it prevents them from triggering terminal automounts.
The problem with this is that this breaks nfs_follow_remote_path() used by NFS4
to find the root object to mount for the mount() syscall.
This can be tested by the following procedure:
(1) Export a directory from an NFS4 server that has something mounted upon it
and that isn't "/" - say, for example, "/scratch". It must have a
different FSID from "/".
(2) Mount this on the client.
mount sirius:/scratch /mnt
(3) List the contents of the client's mountpoint:
ls /mnt
(4) Examine /proc/fs/nfsfs/volumes. You should see one entry (assuming
nothing else is NFS mounted) :
NV SERVER PORT DEV FSID FSC
v4 200108b001940000021125fffe84efad 801 0:34 1:0 no
which corresponds to the filesystem mounted on /scratch on the server.
If, however, you see two entries:
NV SERVER PORT DEV FSID FSC
v4 200108b001940000021125fffe84efad 801 0:33 0:0 no
v4 200108b001940000021125fffe84efad 801 0:34 1:0 no
then it went wrong.
When it goes wrong, what happens is that nfs_follow_remote_path() walks from
the rootfh to the remote directory (/scratch) using vfs_path_lookup(). It
passes LOOKUP_FOLLOW to vfs_path_lookup() to tell it to transit terminal
symlinks and terminal automounts. Unfortunately, with the problematic commit,
LOOKUP_FOLLOW now expressly does not follow terminal automounts, and so the
dummy automount directory fabricated in fsid 0:0 gets mounted instead of the
root of fsid 1:0.
Reported-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---
fs/namei.c | 33 ++++++++++++++++++---------------
1 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index f478836..c64b81d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -727,22 +727,25 @@ static int follow_automount(struct path *path, unsigned flags,
if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
return -EISDIR; /* we actually want to stop here */
- /* We don't want to mount if someone's just doing a stat -
- * unless they're stat'ing a directory and appended a '/' to
- * the name.
- *
- * We do, however, want to mount if someone wants to open or
- * create a file of any type under the mountpoint, wants to
- * traverse through the mountpoint or wants to open the
- * mounted directory. Also, autofs may mark negative dentries
- * as being automount points. These will need the attentions
- * of the daemon to instantiate them before they can be used.
+ /*
+ * We don't want to mount if someone's just doing a stat and they've
+ * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
+ * appended a '/' to the name.
*/
- if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
- LOOKUP_OPEN | LOOKUP_CREATE)) &&
- path->dentry->d_inode)
- return -EISDIR;
-
+ if (!(flags & LOOKUP_FOLLOW)) {
+ /* We do, however, want to mount if someone wants to open or
+ * create a file of any type under the mountpoint, wants to
+ * traverse through the mountpoint or wants to open the mounted
+ * directory.
+ * Also, autofs may mark negative dentries as being automount
+ * points. These will need the attentions of the daemon to
+ * instantiate them before they can be used.
+ */
+ if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
+ LOOKUP_OPEN | LOOKUP_CREATE)) &&
+ path->dentry->d_inode)
+ return -EISDIR;
+ }
current->total_link_count++;
if (current->total_link_count >= 40)
return -ELOOP;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/7] VFS: Make chown() and lchown() call fchownat()
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
2011-09-23 16:24 ` [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW David Howells
@ 2011-09-23 16:25 ` David Howells
2011-09-23 16:25 ` [PATCH 3/7] VFS: Change LOOKUP_NO_AUTOMOUNT to LOOKUP_AUTOMOUNT David Howells
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:25 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Make the chown() and lchown() syscalls jump to the fchownat() syscall with the
appropriate extra arguments.
Signed-off-by: David Howells <dhowells@redhat.com>
---
fs/open.c | 40 ++++++----------------------------------
1 files changed, 6 insertions(+), 34 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index f711921..6d6cd90 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -527,25 +527,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
return error;
}
-SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
-{
- struct path path;
- int error;
-
- error = user_path(filename, &path);
- if (error)
- goto out;
- error = mnt_want_write(path.mnt);
- if (error)
- goto out_release;
- error = chown_common(&path, user, group);
- mnt_drop_write(path.mnt);
-out_release:
- path_put(&path);
-out:
- return error;
-}
-
SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
gid_t, group, int, flag)
{
@@ -573,23 +554,14 @@ out:
return error;
}
-SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
+SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
{
- struct path path;
- int error;
+ return fchownat(AT_FDCWD, filename, user, group, 0);
+}
- error = user_lpath(filename, &path);
- if (error)
- goto out;
- error = mnt_want_write(path.mnt);
- if (error)
- goto out_release;
- error = chown_common(&path, user, group);
- mnt_drop_write(path.mnt);
-out_release:
- path_put(&path);
-out:
- return error;
+SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
+{
+ return fchownat(AT_FDCWD, filename, user, group, AT_SYMLINK_NOFOLLOW);
}
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/7] VFS: Change LOOKUP_NO_AUTOMOUNT to LOOKUP_AUTOMOUNT
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
2011-09-23 16:24 ` [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW David Howells
2011-09-23 16:25 ` [PATCH 2/7] VFS: Make chown() and lchown() call fchownat() David Howells
@ 2011-09-23 16:25 ` David Howells
2011-09-23 16:25 ` [PATCH 4/7] VFS: Move the automount suppression decision out to the initial callers of David Howells
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:25 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Change LOOKUP_NO_AUTOMOUNT (don't do terminal automount) to LOOKUP_AUTOMOUNT
(do terminal automount) to parallel LOOKUP_FOLLOW and set it everywhere
LOOKUP_FOLLOW is set.
Signed-off-by: David Howells <dhowells@redhat.com>
---
drivers/mtd/ubi/build.c | 2 +-
drivers/mtd/ubi/kapi.c | 2 +-
fs/autofs4/dev-ioctl.c | 2 +-
fs/block_dev.c | 2 +-
fs/configfs/symlink.c | 2 +-
fs/ecryptfs/main.c | 2 +-
fs/exec.c | 5 +++--
fs/fhandle.c | 2 +-
fs/gfs2/ops_fstype.c | 2 +-
fs/namei.c | 11 ++++++-----
fs/namespace.c | 8 ++++----
fs/nfs/super.c | 2 +-
fs/nfsd/nfs4state.c | 2 +-
fs/notify/fanotify/fanotify_user.c | 2 +-
fs/notify/inotify/inotify_user.c | 2 +-
fs/open.c | 12 ++++++------
fs/quota/quota.c | 2 +-
fs/stat.c | 4 ++--
fs/utimes.c | 2 +-
include/linux/namei.h | 9 +++++----
net/unix/af_unix.c | 2 +-
security/tomoyo/load_policy.c | 2 +-
security/tomoyo/mount.c | 3 ++-
23 files changed, 44 insertions(+), 40 deletions(-)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 6c3fb5a..28627f1 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1122,7 +1122,7 @@ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
struct path path;
/* Probably this is an MTD character device node path */
- err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path);
+ err = kern_path(mtd_dev, LOOKUP_FOLLOW_ALL, &path);
if (err)
return ERR_PTR(err);
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index d39716e..056fbdb 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -303,7 +303,7 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
if (!pathname || !*pathname)
return ERR_PTR(-EINVAL);
- error = kern_path(pathname, LOOKUP_FOLLOW, &path);
+ error = kern_path(pathname, LOOKUP_FOLLOW_ALL, &path);
if (error)
return ERR_PTR(error);
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 509fe1e..1b2120d 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -533,7 +533,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(name, LOOKUP_FOLLOW_ALL, &path);
else
err = find_autofs_mount(name, &path, test_by_type, &type);
if (err)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 95f786e..ff38dc5 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1629,7 +1629,7 @@ struct block_device *lookup_bdev(const char *pathname)
if (!pathname || !*pathname)
return ERR_PTR(-EINVAL);
- error = kern_path(pathname, LOOKUP_FOLLOW, &path);
+ error = kern_path(pathname, LOOKUP_FOLLOW_ALL, &path);
if (error)
return ERR_PTR(error);
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index 0f3eb41..c602b92 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -114,7 +114,7 @@ static int get_target(const char *symname, struct path *path,
{
int ret;
- ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path);
+ ret = kern_path(symname, LOOKUP_FOLLOW_ALL|LOOKUP_DIRECTORY, path);
if (!ret) {
if (path->dentry->d_sb == configfs_sb) {
*target = configfs_get_config_item(path->dentry);
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index b4a6bef..00e8ba7 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -519,7 +519,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
s->s_d_op = &ecryptfs_dops;
err = "Reading sb failed";
- rc = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
+ rc = kern_path(dev_name, LOOKUP_FOLLOW_ALL | LOOKUP_DIRECTORY, &path);
if (rc) {
ecryptfs_printk(KERN_WARNING, "kern_path() failed\n");
goto out1;
diff --git a/fs/exec.c b/fs/exec.c
index 25dcbe5..7d56198 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -124,7 +124,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
if (IS_ERR(tmp))
goto out;
- file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW);
+ file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW_ALL);
putname(tmp);
error = PTR_ERR(file);
if (IS_ERR(file))
@@ -769,7 +769,8 @@ struct file *open_exec(const char *name)
.intent = LOOKUP_OPEN
};
- file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
+ file = do_filp_open(AT_FDCWD, name, &open_exec_flags,
+ LOOKUP_FOLLOW_ALL);
if (IS_ERR(file))
goto out;
diff --git a/fs/fhandle.c b/fs/fhandle.c
index 6b08864..131e1ae 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -98,7 +98,7 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
return -EINVAL;
- lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
+ lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW_ALL : 0;
if (flag & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
err = user_path_at(dfd, name, lookup_flags, &path);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 079587e..c532776 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1350,7 +1350,7 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type,
struct path path;
int error;
- error = kern_path(dev_name, LOOKUP_FOLLOW, &path);
+ error = kern_path(dev_name, LOOKUP_FOLLOW_ALL, &path);
if (error) {
printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n",
dev_name, error);
diff --git a/fs/namei.c b/fs/namei.c
index c64b81d..30a364b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -724,7 +724,7 @@ static int follow_automount(struct path *path, unsigned flags,
/* We don't want to mount if someone supplied AT_NO_AUTOMOUNT
* and this is the terminal part of the path.
*/
- if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
+ if (!(flags & LOOKUP_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
return -EISDIR; /* we actually want to stop here */
/*
@@ -1573,7 +1573,7 @@ out_fail:
static inline int lookup_last(struct nameidata *nd, struct path *path)
{
if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
- nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+ nd->flags |= LOOKUP_FOLLOW_ALL | LOOKUP_DIRECTORY;
nd->flags &= ~LOOKUP_PARENT;
return walk_component(nd, path, &nd->last, nd->last_type,
@@ -2125,8 +2125,8 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (!(open_flag & O_CREAT)) {
int symlink_ok = 0;
if (nd->last.name[nd->last.len])
- nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
- if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
+ nd->flags |= LOOKUP_FOLLOW_ALL | LOOKUP_DIRECTORY;
+ if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW_ALL))
symlink_ok = 1;
/* we _can_ be in RCU mode here */
error = walk_component(nd, path, &nd->last, LAST_NORM,
@@ -2928,7 +2928,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
{
struct dentry *new_dentry;
struct path old_path, new_path;
- int how = 0;
+ int how;
int error;
if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
@@ -2946,6 +2946,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
if (flags & AT_SYMLINK_FOLLOW)
how |= LOOKUP_FOLLOW;
+ how |= LOOKUP_AUTOMOUNT;
error = user_path_at(olddfd, oldname, how, &old_path);
if (error)
diff --git a/fs/namespace.c b/fs/namespace.c
index 22bfe82..71c218a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1368,7 +1368,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
return -EINVAL;
if (!(flags & UMOUNT_NOFOLLOW))
- lookup_flags |= LOOKUP_FOLLOW;
+ lookup_flags |= LOOKUP_FOLLOW_ALL;
retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
if (retval)
@@ -1757,7 +1757,7 @@ static int do_loopback(struct path *path, char *old_name,
return err;
if (!old_name || !*old_name)
return -EINVAL;
- err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
+ err = kern_path(old_name, LOOKUP_FOLLOW_ALL, &old_path);
if (err)
return err;
@@ -1875,7 +1875,7 @@ static int do_move_mount(struct path *path, char *old_name)
return -EPERM;
if (!old_name || !*old_name)
return -EINVAL;
- err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
+ err = kern_path(old_name, LOOKUP_FOLLOW_ALL, &old_path);
if (err)
return err;
@@ -2305,7 +2305,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
((char *)data_page)[PAGE_SIZE - 1] = 0;
/* ... and get the mountpoint */
- retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
+ retval = kern_path(dir_name, LOOKUP_FOLLOW_ALL, &path);
if (retval)
return retval;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 9b7dd70..1143a77 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2798,7 +2798,7 @@ static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
goto out_put_mnt_ns;
ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
- export_path, LOOKUP_FOLLOW, &path);
+ export_path, LOOKUP_FOLLOW_ALL, &path);
nfs_referral_loop_unprotect();
put_mnt_ns(ns_private);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3787ec1..0d50e6e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4656,7 +4656,7 @@ nfs4_reset_recoverydir(char *recdir)
int status;
struct path path;
- status = kern_path(recdir, LOOKUP_FOLLOW, &path);
+ status = kern_path(recdir, LOOKUP_FOLLOW_ALL, &path);
if (status)
return status;
status = -ENOTDIR;
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 9fde1c0..e8a4467 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -491,7 +491,7 @@ static int fanotify_find_path(int dfd, const char __user *filename,
path_get(path);
fput_light(file, fput_needed);
} else {
- unsigned int lookup_flags = 0;
+ unsigned int lookup_flags = LOOKUP_AUTOMOUNT;
if (!(flags & FAN_MARK_DONT_FOLLOW))
lookup_flags |= LOOKUP_FOLLOW;
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 8445fbc..90f6010 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -759,7 +759,7 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
struct path path;
struct file *filp;
int ret, fput_needed;
- unsigned flags = 0;
+ unsigned flags = LOOKUP_AUTOMOUNT;
filp = fget_light(fd, &fput_needed);
if (unlikely(!filp))
diff --git a/fs/open.c b/fs/open.c
index 6d6cd90..414939e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -325,7 +325,7 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
old_cred = override_creds(override_cred);
- res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
+ res = user_path_at(dfd, filename, LOOKUP_FOLLOW_ALL, &path);
if (res)
goto out;
@@ -487,7 +487,7 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
struct path path;
int error;
- error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
+ error = user_path_at(dfd, filename, LOOKUP_FOLLOW_ALL, &path);
if (!error) {
error = chmod_common(&path, mode);
path_put(&path);
@@ -537,7 +537,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
goto out;
- lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+ lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW_ALL;
if (flag & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
error = user_path_at(dfd, filename, lookup_flags, &path);
@@ -556,12 +556,12 @@ out:
SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
{
- return fchownat(AT_FDCWD, filename, user, group, 0);
+ return sys_fchownat(AT_FDCWD, filename, user, group, 0);
}
SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
{
- return fchownat(AT_FDCWD, filename, user, group, AT_SYMLINK_NOFOLLOW);
+ return sys_fchownat(AT_FDCWD, filename, user, group, AT_SYMLINK_NOFOLLOW);
}
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
@@ -901,7 +901,7 @@ static inline int build_open_flags(int flags, int mode, struct open_flags *op)
if (flags & O_DIRECTORY)
lookup_flags |= LOOKUP_DIRECTORY;
if (!(flags & O_NOFOLLOW))
- lookup_flags |= LOOKUP_FOLLOW;
+ lookup_flags |= LOOKUP_FOLLOW_ALL;
return lookup_flags;
}
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index b34bdb2..156486a 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -355,7 +355,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
* resolution (think about autofs) and thus deadlocks could arise.
*/
if (cmds == Q_QUOTAON) {
- ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW, &path);
+ ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW_ALL, &path);
if (ret)
pathp = ERR_PTR(ret);
else
diff --git a/fs/stat.c b/fs/stat.c
index ba5316f..52ead31 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -80,9 +80,9 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
goto out;
if (!(flag & AT_SYMLINK_NOFOLLOW))
- lookup_flags |= LOOKUP_FOLLOW;
+ lookup_flags |= LOOKUP_FOLLOW_ALL;
if (flag & AT_NO_AUTOMOUNT)
- lookup_flags |= LOOKUP_NO_AUTOMOUNT;
+ lookup_flags &= ~LOOKUP_AUTOMOUNT;
if (flag & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
diff --git a/fs/utimes.c b/fs/utimes.c
index ba653f3..ea82831 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -157,7 +157,7 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times,
int lookup_flags = 0;
if (!(flags & AT_SYMLINK_NOFOLLOW))
- lookup_flags |= LOOKUP_FOLLOW;
+ lookup_flags |= LOOKUP_FOLLOW_ALL;
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 76fe2c6..86d6993 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -44,7 +44,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
* - ending slashes ok even for nonexistent files
* - internal "there are more path components" flag
* - dentry cache is untrusted; force a real lookup
- * - suppress terminal automount
+ * - follow terminal automount
*/
#define LOOKUP_FOLLOW 0x0001
#define LOOKUP_DIRECTORY 0x0002
@@ -52,7 +52,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_PARENT 0x0010
#define LOOKUP_REVAL 0x0020
#define LOOKUP_RCU 0x0040
-#define LOOKUP_NO_AUTOMOUNT 0x0080
+#define LOOKUP_AUTOMOUNT 0x0080
+#define LOOKUP_FOLLOW_ALL (LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT)
/*
* Intent data
*/
@@ -67,10 +68,10 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
extern int user_path_at(int, const char __user *, unsigned, struct path *);
-#define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
+#define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW_ALL, path)
#define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
#define user_path_dir(name, path) \
- user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path)
+ user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW_ALL | LOOKUP_DIRECTORY, path)
extern int kern_path(const char *, unsigned, struct path *);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index ec68e1c..0c091d5 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -756,7 +756,7 @@ static struct sock *unix_find_other(struct net *net,
if (sunname->sun_path[0]) {
struct inode *inode;
- err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
+ err = kern_path(sunname->sun_path, LOOKUP_FOLLOW_ALL, &path);
if (err)
goto fail;
inode = path.dentry->d_inode;
diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c
index 6797540..8de4d49 100644
--- a/security/tomoyo/load_policy.c
+++ b/security/tomoyo/load_policy.c
@@ -38,7 +38,7 @@ static bool tomoyo_policy_loader_exists(void)
struct path path;
if (!tomoyo_loader)
tomoyo_loader = CONFIG_SECURITY_TOMOYO_POLICY_LOADER;
- if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
+ if (kern_path(tomoyo_loader, LOOKUP_FOLLOW_ALL, &path)) {
printk(KERN_INFO "Not activating Mandatory Access Control "
"as %s does not exist.\n", tomoyo_loader);
return false;
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index bee09d0..786c47f 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -128,7 +128,8 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
}
if (need_dev) {
/* Get mount point or device file. */
- if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
+ if (!dev_name ||
+ kern_path(dev_name, LOOKUP_FOLLOW_ALL, &path)) {
error = -ENOENT;
goto out;
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/7] VFS: Move the automount suppression decision out to the initial callers of
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
` (2 preceding siblings ...)
2011-09-23 16:25 ` [PATCH 3/7] VFS: Change LOOKUP_NO_AUTOMOUNT to LOOKUP_AUTOMOUNT David Howells
@ 2011-09-23 16:25 ` David Howells
2011-09-23 16:25 ` [PATCH 5/7] VFS: Ignore symlink following advice when pathwalking David Howells
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:25 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
pathwalk, in particular get attribute-fetching system calls and define the
to-terminal-automount-or-not policy there by supplying LOOKUP_AUTOMOUNT or not
as appropriate.
Suppress automount on the following:
lchown
lgetxattr
llistxattr
lremovexattr
lsetxattr
lstat
openat/open with O_NOFOLLOW but not O_DIRECTORY
readlinkat, readlink
ocfs2_reflink_ioctl()
Require terminal automounting on the following:
chdir
chown
chroot
execve
faccessat, access
fanotify
fchmodat, chmod
getxattr
inotify
linkat, link
listxattr
mkdirat, mkdir
mknodat, mknod
mount
openat/open without O_NOFOLLOW or with O_DIRECTORY
quotactl
removexattr
renameat, rename
setxattr
socket(AF_UNIX)
stat
statfs
symlinkat, symlink
unlinkat, unlink, rmdir
uselib
utimes, futimesat
autofs_dev_ioctl_ismountpoint()
ecryptfs_mount()
get_target() in configfs/symlink.c
gfs2_mount_meta()
lookup_bdev()
nfs4_reset_recoverydir()
nfs_follow_remote_path()
open_mtd_by_chdev()
tomoyo_mount_acl()
tomoyo_policy_loader_exists()
ubi_open_volume_path()
Default the automount-follow setting to the same as the symlink-follow setting
(as controlled by AT_SYMLINK_NOFOLLOW, UMOUNT_NOFOLLOW or
FAN_MARK_DONT_FOLLOW):
fchownat
fstatat
name_to_handle_at
umount
utimensat
Provide an AT_AUTOMOUNT_FOLLOW option where possible to override the
behaviour, and try to make all four relevant AT_ flags available to all AT_
flag taking functions. Given the flags available, the behaviour is then
calculated using the following rules in order of descending priority:
(1) If the path ends in a '/', follow the automount.
(2) If AT_AUTOMOUNT_FOLLOW is set, follow the automount.
(3) If AT_NO_AUTOMOUNT is set, don't follow the automount.
(4) If AT_SYMLINK_FOLLOW is set, follow the automount.
(5) If AT_SYMLINK_NOFOLLOW is set, don't follow the automount.
(6) Follow the automount.
To change the behaviour to make stat, xattr functions always suppress
automounting too is then a matter of changing vfs_fstatat() and the
appropriate xattr syscalls.
Signed-off-by: David Howells <dhowells@redhat.com>
---
fs/fhandle.c | 11 +++++------
fs/internal.h | 17 +++++++++++++++++
fs/namei.c | 2 +-
fs/open.c | 13 +++++++------
fs/stat.c | 14 +++++---------
fs/statfs.c | 2 +-
fs/utimes.c | 14 +++++++-------
fs/xattr.c | 16 ++++++++--------
include/linux/fcntl.h | 1 +
9 files changed, 52 insertions(+), 38 deletions(-)
diff --git a/fs/fhandle.c b/fs/fhandle.c
index 131e1ae..d81c506 100644
--- a/fs/fhandle.c
+++ b/fs/fhandle.c
@@ -92,15 +92,14 @@ SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
int, flag)
{
struct path path;
- int lookup_flags;
- int err;
+ int err, lookup_flags;
- if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW |
+ AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW |
+ AT_EMPTY_PATH)) != 0)
return -EINVAL;
+ lookup_flags = at_to_lookup_flags(flag, 0);
- lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW_ALL : 0;
- if (flag & AT_EMPTY_PATH)
- lookup_flags |= LOOKUP_EMPTY;
err = user_path_at(dfd, name, lookup_flags, &path);
if (!err) {
err = do_sys_name_to_handle(&path, handle, mnt_id);
diff --git a/fs/internal.h b/fs/internal.h
index fe327c2..11664f5 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/namei.h>
#include <linux/lglock.h>
struct super_block;
@@ -16,6 +17,22 @@ struct file_system_type;
struct linux_binprm;
struct path;
+/**
+ * at_to_lookup_flags - Translate AT_ flags to LOOKUP_ flags
+ * @flags: The AT_ flags to translate.
+ * @lookup_flags: The default.
+ */
+static inline int at_to_lookup_flags(int flag, int lookup_flags)
+{
+ if (flag & AT_SYMLINK_NOFOLLOW) lookup_flags &= ~LOOKUP_FOLLOW_ALL;
+ if (flag & AT_SYMLINK_FOLLOW) lookup_flags |= LOOKUP_FOLLOW_ALL;
+ if (flag & AT_NO_AUTOMOUNT) lookup_flags &= ~LOOKUP_AUTOMOUNT;
+ if (flag & AT_AUTOMOUNT_FOLLOW) lookup_flags |= LOOKUP_AUTOMOUNT;
+ if (flag & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY;
+
+ return lookup_flags;
+}
+
/*
* block_dev.c
*/
diff --git a/fs/namei.c b/fs/namei.c
index 30a364b..c2a2cc3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2126,7 +2126,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
int symlink_ok = 0;
if (nd->last.name[nd->last.len])
nd->flags |= LOOKUP_FOLLOW_ALL | LOOKUP_DIRECTORY;
- if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW_ALL))
+ if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
symlink_ok = 1;
/* we _can_ be in RCU mode here */
error = walk_component(nd, path, &nd->last, LAST_NORM,
diff --git a/fs/open.c b/fs/open.c
index 414939e..b592c18 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -534,12 +534,12 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
int error = -EINVAL;
int lookup_flags;
- if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
+ if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW |
+ AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW |
+ AT_EMPTY_PATH)) != 0)
goto out;
+ lookup_flags = at_to_lookup_flags(flag, LOOKUP_FOLLOW_ALL);
- lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW_ALL;
- if (flag & AT_EMPTY_PATH)
- lookup_flags |= LOOKUP_EMPTY;
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
goto out;
@@ -561,7 +561,8 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
{
- return sys_fchownat(AT_FDCWD, filename, user, group, AT_SYMLINK_NOFOLLOW);
+ return sys_fchownat(AT_FDCWD, filename, user, group,
+ AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT);
}
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
@@ -899,7 +900,7 @@ static inline int build_open_flags(int flags, int mode, struct open_flags *op)
}
if (flags & O_DIRECTORY)
- lookup_flags |= LOOKUP_DIRECTORY;
+ lookup_flags |= LOOKUP_DIRECTORY | LOOKUP_AUTOMOUNT;
if (!(flags & O_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW_ALL;
return lookup_flags;
diff --git a/fs/stat.c b/fs/stat.c
index 52ead31..305aa10 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -17,6 +17,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include "internal.h"
void generic_fillattr(struct inode *inode, struct kstat *stat)
{
@@ -73,18 +74,13 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
{
struct path path;
int error = -EINVAL;
- int lookup_flags = 0;
+ int lookup_flags;
- if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
+ if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW |
+ AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW |
AT_EMPTY_PATH)) != 0)
goto out;
-
- if (!(flag & AT_SYMLINK_NOFOLLOW))
- lookup_flags |= LOOKUP_FOLLOW_ALL;
- if (flag & AT_NO_AUTOMOUNT)
- lookup_flags &= ~LOOKUP_AUTOMOUNT;
- if (flag & AT_EMPTY_PATH)
- lookup_flags |= LOOKUP_EMPTY;
+ lookup_flags = at_to_lookup_flags(flag, LOOKUP_FOLLOW_ALL);
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
diff --git a/fs/statfs.c b/fs/statfs.c
index 8244924..e82eae2 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -76,7 +76,7 @@ EXPORT_SYMBOL(vfs_statfs);
int user_statfs(const char __user *pathname, struct kstatfs *st)
{
struct path path;
- int error = user_path(pathname, &path);
+ int error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
if (!error) {
error = vfs_statfs(&path, st);
path_put(&path);
diff --git a/fs/utimes.c b/fs/utimes.c
index ea82831..72f10c5 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -10,6 +10,7 @@
#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include "internal.h"
#ifdef __ARCH_WANT_SYS_UTIME
@@ -116,7 +117,7 @@ out:
* @dfd: open file descriptor, -1 or AT_FDCWD
* @filename: path name or NULL
* @times: new times or NULL
- * @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment)
+ * @flags: zero or more AT_* flags
*
* If filename is NULL and dfd refers to an open file, then operate on
* the file. Otherwise look up filename, possibly using dfd as a
@@ -136,13 +137,15 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times,
goto out;
}
- if (flags & ~AT_SYMLINK_NOFOLLOW)
+ if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW |
+ AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW))
goto out;
if (filename == NULL && dfd != AT_FDCWD) {
struct file *file;
- if (flags & AT_SYMLINK_NOFOLLOW)
+ if (flags & (AT_SYMLINK_NOFOLLOW | AT_SYMLINK_FOLLOW |
+ AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW))
goto out;
file = fget(dfd);
@@ -154,10 +157,7 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times,
fput(file);
} else {
struct path path;
- int lookup_flags = 0;
-
- if (!(flags & AT_SYMLINK_NOFOLLOW))
- lookup_flags |= LOOKUP_FOLLOW_ALL;
+ int lookup_flags = at_to_lookup_flags(flags, LOOKUP_FOLLOW_ALL);
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
diff --git a/fs/xattr.c b/fs/xattr.c
index f060663..4921010 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -290,7 +290,7 @@ SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
struct path path;
int error;
- error = user_path(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
@@ -309,7 +309,7 @@ SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname,
struct path path;
int error;
- error = user_lpath(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, 0, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
@@ -386,7 +386,7 @@ SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
struct path path;
ssize_t error;
- error = user_path(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
if (error)
return error;
error = getxattr(path.dentry, name, value, size);
@@ -400,7 +400,7 @@ SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname,
struct path path;
ssize_t error;
- error = user_lpath(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, 0, &path);
if (error)
return error;
error = getxattr(path.dentry, name, value, size);
@@ -459,7 +459,7 @@ SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
struct path path;
ssize_t error;
- error = user_path(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
if (error)
return error;
error = listxattr(path.dentry, list, size);
@@ -473,7 +473,7 @@ SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list,
struct path path;
ssize_t error;
- error = user_lpath(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, 0, &path);
if (error)
return error;
error = listxattr(path.dentry, list, size);
@@ -519,7 +519,7 @@ SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
struct path path;
int error;
- error = user_path(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
@@ -537,7 +537,7 @@ SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname,
struct path path;
int error;
- error = user_lpath(pathname, &path);
+ error = user_path_at(AT_FDCWD, pathname, 0, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index f550f89..768fb66 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -47,6 +47,7 @@
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
+#define AT_AUTOMOUNT_FOLLOW 0x2000 /* Follow terminal automounts */
#ifdef __KERNEL__
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/7] VFS: Ignore symlink following advice when pathwalking
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
` (3 preceding siblings ...)
2011-09-23 16:25 ` [PATCH 4/7] VFS: Move the automount suppression decision out to the initial callers of David Howells
@ 2011-09-23 16:25 ` David Howells
2011-09-23 16:25 ` [PATCH 6/7] VFS: Make stat and xattr calls not automount David Howells
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:25 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Ignore symlink advice (LOOKUP_FOLLOW) when walking the terminal component of a
path. Base the decision entirely on LOOKUP_NO_AUTOMOUNT as this is now set
(or not) by the callers of path walk, most notably the relevant syscall
handlers.
Signed-off-by: David Howells <dhowells@redhat.com>
---
fs/namei.c | 19 -------------------
1 files changed, 0 insertions(+), 19 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index c2a2cc3..89e3dc3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -727,25 +727,6 @@ static int follow_automount(struct path *path, unsigned flags,
if (!(flags & LOOKUP_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
return -EISDIR; /* we actually want to stop here */
- /*
- * We don't want to mount if someone's just doing a stat and they've
- * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
- * appended a '/' to the name.
- */
- if (!(flags & LOOKUP_FOLLOW)) {
- /* We do, however, want to mount if someone wants to open or
- * create a file of any type under the mountpoint, wants to
- * traverse through the mountpoint or wants to open the mounted
- * directory.
- * Also, autofs may mark negative dentries as being automount
- * points. These will need the attentions of the daemon to
- * instantiate them before they can be used.
- */
- if (!(flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY |
- LOOKUP_OPEN | LOOKUP_CREATE)) &&
- path->dentry->d_inode)
- return -EISDIR;
- }
current->total_link_count++;
if (current->total_link_count >= 40)
return -ELOOP;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/7] VFS: Make stat and xattr calls not automount
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
` (4 preceding siblings ...)
2011-09-23 16:25 ` [PATCH 5/7] VFS: Ignore symlink following advice when pathwalking David Howells
@ 2011-09-23 16:25 ` David Howells
2011-09-23 16:26 ` [PATCH 7/7] VFS: Vary the automounting rules for autofs David Howells
2011-09-23 16:29 ` [RFC][PATCH 0/7] Automount behaviour correction Linus Torvalds
7 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:25 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Make stat() and get/set/list/removexattr calls not automount so that the
autofs behaviour remains the same. This causes NFS, AFS and CIFS automounting
behaviour to change, however.
To vary the behaviour follow_automount() needs to know when it is mounting for
autofs and when the aforementioned calls are the ones being processed.
Signed-off-by: David Howells <dhowells@redhat.com>
---
fs/stat.c | 7 ++++---
fs/xattr.c | 8 ++++----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/fs/stat.c b/fs/stat.c
index 305aa10..7fa96a1 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -80,7 +80,7 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW |
AT_EMPTY_PATH)) != 0)
goto out;
- lookup_flags = at_to_lookup_flags(flag, LOOKUP_FOLLOW_ALL);
+ lookup_flags = at_to_lookup_flags(flag, LOOKUP_FOLLOW);
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
@@ -95,13 +95,14 @@ EXPORT_SYMBOL(vfs_fstatat);
int vfs_stat(const char __user *name, struct kstat *stat)
{
- return vfs_fstatat(AT_FDCWD, name, stat, 0);
+ return vfs_fstatat(AT_FDCWD, name, stat, AT_NO_AUTOMOUNT);
}
EXPORT_SYMBOL(vfs_stat);
int vfs_lstat(const char __user *name, struct kstat *stat)
{
- return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW);
+ return vfs_fstatat(AT_FDCWD, name, stat,
+ AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT);
}
EXPORT_SYMBOL(vfs_lstat);
diff --git a/fs/xattr.c b/fs/xattr.c
index 4921010..bb9d5be 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -290,7 +290,7 @@ SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
struct path path;
int error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
@@ -386,7 +386,7 @@ SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
struct path path;
ssize_t error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
if (error)
return error;
error = getxattr(path.dentry, name, value, size);
@@ -459,7 +459,7 @@ SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
struct path path;
ssize_t error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
if (error)
return error;
error = listxattr(path.dentry, list, size);
@@ -519,7 +519,7 @@ SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
struct path path;
int error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW_ALL, &path);
+ error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/7] VFS: Vary the automounting rules for autofs
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
` (5 preceding siblings ...)
2011-09-23 16:25 ` [PATCH 6/7] VFS: Make stat and xattr calls not automount David Howells
@ 2011-09-23 16:26 ` David Howells
2011-09-23 16:29 ` [RFC][PATCH 0/7] Automount behaviour correction Linus Torvalds
7 siblings, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:26 UTC (permalink / raw)
To: miklos, raven, viro, torvalds
Cc: dhowells, jlayton, gregkh, linux-nfs, leonardo.lists
Allow the behaviour of in-kernel automounting to vary according to whether
we're mounting on autofs or not.
The differences of behaviour concern the fstatat, stat, getxattr, setxattr,
listxattr and removexattr system calls. Prior to the d_automount changes
being applied, these caused automounting for NFS, AFS and CIFS automount
points, but not for autofs mountpounts.
After the d_automount changes they caused automounting unconditionally because
LOOKUP_FOLLOW was set.
With the application of a later patch from Miklos Szeredi to revert the
behaviour of autofs to the original, these no longer cause a mountpoint to
automount.
Reinstate the pre-d_automount behaviour.
Signed-off-by: David Howells <dhowells@redhat.com>
---
fs/internal.h | 17 ++++++++++++-----
fs/namei.c | 7 +++++--
fs/stat.c | 3 ++-
fs/xattr.c | 16 ++++++++++++----
include/linux/namei.h | 1 +
5 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/fs/internal.h b/fs/internal.h
index 11664f5..b54c5e6 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -24,11 +24,18 @@ struct path;
*/
static inline int at_to_lookup_flags(int flag, int lookup_flags)
{
- if (flag & AT_SYMLINK_NOFOLLOW) lookup_flags &= ~LOOKUP_FOLLOW_ALL;
- if (flag & AT_SYMLINK_FOLLOW) lookup_flags |= LOOKUP_FOLLOW_ALL;
- if (flag & AT_NO_AUTOMOUNT) lookup_flags &= ~LOOKUP_AUTOMOUNT;
- if (flag & AT_AUTOMOUNT_FOLLOW) lookup_flags |= LOOKUP_AUTOMOUNT;
- if (flag & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY;
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ lookup_flags &= ~(LOOKUP_FOLLOW_ALL | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS);
+ if (flag & AT_SYMLINK_FOLLOW)
+ lookup_flags |= LOOKUP_FOLLOW_ALL;
+ if (flag & AT_NO_AUTOMOUNT)
+ lookup_flags &= ~(LOOKUP_AUTOMOUNT | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS);
+ if (flag & AT_AUTOMOUNT_FOLLOW) {
+ lookup_flags |= LOOKUP_AUTOMOUNT;
+ lookup_flags &= ~LOOKUP_AUTOMOUNT_UNLESS_AUTOFS;
+ }
+ if (flag & AT_EMPTY_PATH)
+ lookup_flags |= LOOKUP_EMPTY;
return lookup_flags;
}
diff --git a/fs/namei.c b/fs/namei.c
index 89e3dc3..3b1da48 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -724,8 +724,11 @@ static int follow_automount(struct path *path, unsigned flags,
/* We don't want to mount if someone supplied AT_NO_AUTOMOUNT
* and this is the terminal part of the path.
*/
- if (!(flags & LOOKUP_AUTOMOUNT) && !(flags & LOOKUP_PARENT))
- return -EISDIR; /* we actually want to stop here */
+ if (!(flags & LOOKUP_AUTOMOUNT) && !(flags & LOOKUP_PARENT)) {
+ if (!(flags & LOOKUP_AUTOMOUNT_UNLESS_AUTOFS) ||
+ strcmp(path->dentry->d_sb->s_type->name, "autofs") == 0)
+ return -EISDIR; /* we actually want to stop here */
+ }
current->total_link_count++;
if (current->total_link_count >= 40)
diff --git a/fs/stat.c b/fs/stat.c
index 7fa96a1..f7e9abb 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -80,7 +80,8 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
AT_NO_AUTOMOUNT | AT_AUTOMOUNT_FOLLOW |
AT_EMPTY_PATH)) != 0)
goto out;
- lookup_flags = at_to_lookup_flags(flag, LOOKUP_FOLLOW);
+ lookup_flags = at_to_lookup_flags(
+ flag, LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS);
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
diff --git a/fs/xattr.c b/fs/xattr.c
index bb9d5be..7a85b9a 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -290,7 +290,9 @@ SYSCALL_DEFINE5(setxattr, const char __user *, pathname,
struct path path;
int error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
+ error = user_path_at(AT_FDCWD, pathname,
+ LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS,
+ &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
@@ -386,7 +388,9 @@ SYSCALL_DEFINE4(getxattr, const char __user *, pathname,
struct path path;
ssize_t error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
+ error = user_path_at(AT_FDCWD, pathname,
+ LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS,
+ &path);
if (error)
return error;
error = getxattr(path.dentry, name, value, size);
@@ -459,7 +463,9 @@ SYSCALL_DEFINE3(listxattr, const char __user *, pathname, char __user *, list,
struct path path;
ssize_t error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
+ error = user_path_at(AT_FDCWD, pathname,
+ LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS,
+ &path);
if (error)
return error;
error = listxattr(path.dentry, list, size);
@@ -519,7 +525,9 @@ SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
struct path path;
int error;
- error = user_path_at(AT_FDCWD, pathname, LOOKUP_FOLLOW, &path);
+ error = user_path_at(AT_FDCWD, pathname,
+ LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT_UNLESS_AUTOFS,
+ &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 86d6993..e1b03a0 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -65,6 +65,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_JUMPED 0x1000
#define LOOKUP_ROOT 0x2000
#define LOOKUP_EMPTY 0x4000
+#define LOOKUP_AUTOMOUNT_UNLESS_AUTOFS 0x8000
extern int user_path_at(int, const char __user *, unsigned, struct path *);
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC][PATCH 0/7] Automount behaviour correction
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
` (6 preceding siblings ...)
2011-09-23 16:26 ` [PATCH 7/7] VFS: Vary the automounting rules for autofs David Howells
@ 2011-09-23 16:29 ` Linus Torvalds
7 siblings, 0 replies; 11+ messages in thread
From: Linus Torvalds @ 2011-09-23 16:29 UTC (permalink / raw)
To: David Howells
Cc: miklos, raven, viro, jlayton, gregkh, linux-nfs, leonardo.lists
On Fri, Sep 23, 2011 at 9:24 AM, David Howells <dhowells@redhat.com> wrote:
>
> They are:
Christ, this is like the worst of all worlds. We make more code to
make more random decisions that now depend not just on random system
calls but on what filesystem those system calls act on too.
Ugh. Seriously nasty.
I did like the lchown/fchownat unification, but that was independent.
Linus
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW
2011-09-23 16:24 ` [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW David Howells
@ 2011-09-23 16:35 ` Linus Torvalds
2011-09-23 16:53 ` David Howells
1 sibling, 0 replies; 11+ messages in thread
From: Linus Torvalds @ 2011-09-23 16:35 UTC (permalink / raw)
To: David Howells
Cc: miklos, raven, viro, jlayton, gregkh, linux-nfs, leonardo.lists
On Fri, Sep 23, 2011 at 9:24 AM, David Howells <dhowells@redhat.com> wrote:
>
> The problem with this is that this breaks nfs_follow_remote_path() used by NFS4
> to find the root object to mount for the mount() syscall.
The above message is basically dishonest.
That's not AT ALL the problem.
That problem could have been fixed with a one-liner patch that already exists.
This whole patch-series looks like just excuses for doing stupid things.
Afaik, LOOKUP_OPEN and LOOKUP_DIRECTORY already force the auto-mount.
You can use either or both to force it.
Why are people so deep in denial about this?
Linus
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW
2011-09-23 16:24 ` [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW David Howells
2011-09-23 16:35 ` Linus Torvalds
@ 2011-09-23 16:53 ` David Howells
1 sibling, 0 replies; 11+ messages in thread
From: David Howells @ 2011-09-23 16:53 UTC (permalink / raw)
To: Linus Torvalds
Cc: dhowells, miklos, raven, viro, jlayton, gregkh, linux-nfs,
leonardo.lists
Linus Torvalds <torvalds@linux-foundation.org> wrote:
> > The problem with this is that this breaks nfs_follow_remote_path() used by
> > NFS4 to find the root object to mount for the mount() syscall.
>
> The above message is basically dishonest.
>
> That's not AT ALL the problem.
Dishonest? In what way am I lying about it? After I wrote that line I went
on to explain how to reproduce it and what was happening.
That was the problem addressed by that patch. I was including it as a means
to fix the NFS regression and as I pointed out in the cover note, it can be
actually be dropped if one of the further patches is introduced.
> That problem could have been fixed with a one-liner patch that already exists.
Which is fragile.
> This whole patch-series looks like just excuses for doing stupid things.
I believe you to be wrong.
Anyway, if I'm going to be accused of dishonesty, I see no further reason to
continuing in this discussion.
Have a good weekend.
David
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2011-09-23 16:53 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-23 16:24 [RFC][PATCH 0/7] Automount behaviour correction David Howells
2011-09-23 16:24 ` [PATCH 1/7] NFS4: Revert commit to make the automount code ignore LOOKUP_FOLLOW David Howells
2011-09-23 16:35 ` Linus Torvalds
2011-09-23 16:53 ` David Howells
2011-09-23 16:25 ` [PATCH 2/7] VFS: Make chown() and lchown() call fchownat() David Howells
2011-09-23 16:25 ` [PATCH 3/7] VFS: Change LOOKUP_NO_AUTOMOUNT to LOOKUP_AUTOMOUNT David Howells
2011-09-23 16:25 ` [PATCH 4/7] VFS: Move the automount suppression decision out to the initial callers of David Howells
2011-09-23 16:25 ` [PATCH 5/7] VFS: Ignore symlink following advice when pathwalking David Howells
2011-09-23 16:25 ` [PATCH 6/7] VFS: Make stat and xattr calls not automount David Howells
2011-09-23 16:26 ` [PATCH 7/7] VFS: Vary the automounting rules for autofs David Howells
2011-09-23 16:29 ` [RFC][PATCH 0/7] Automount behaviour correction Linus Torvalds
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.