2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 06:16:03 +00:00

A batch of patches for passing non-NULL nameidata(2) to permission().

This commit is contained in:
Andreas Gruenbacher
2007-04-22 23:56:11 +00:00
parent e5913f70b4
commit 5a2265661e
14 changed files with 1760 additions and 294 deletions

View File

@@ -0,0 +1,78 @@
---
fs/namei.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1422,14 +1422,13 @@ static int may_delete(struct inode *dir,
* 3. We should have write and exec permissions on dir
* 4. We can't do it if dir is immutable (done in permission())
*/
-static inline int may_create(struct inode *dir, struct dentry *child,
- struct nameidata2 *nd)
+static inline int may_create(struct nameidata2 *nd, struct dentry *child)
{
if (child->d_inode)
return -EEXIST;
- if (IS_DEADDIR(dir))
+ if (IS_DEADDIR(nd->dentry->d_inode))
return -ENOENT;
- return permission(dir,MAY_WRITE | MAY_EXEC, nd);
+ return permission(nd->dentry->d_inode, MAY_WRITE | MAY_EXEC, nd);
}
/*
@@ -1495,7 +1494,7 @@ void unlock_rename(struct dentry *p1, st
int vfs_create(struct nameidata2 *nd, struct dentry *dentry, int mode)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -1841,7 +1840,7 @@ EXPORT_SYMBOL_GPL(lookup_create);
int vfs_mknod(struct nameidata2 *nd, struct dentry *dentry, int mode, dev_t dev)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -1921,7 +1920,7 @@ asmlinkage long sys_mknod(const char __u
int vfs_mkdir(struct nameidata2 *nd, struct dentry *dentry, int mode)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -2190,7 +2189,7 @@ int vfs_symlink(struct nameidata2 *nd, s
const char *oldname, int mode)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_create(dir, dentry, nd);
+ int error = may_create(nd, dentry);
if (error)
return error;
@@ -2262,7 +2261,7 @@ int vfs_link(struct nameidata2 *old_nd,
if (!inode)
return -ENOENT;
- error = may_create(dir, new_dentry, new_parent);
+ error = may_create(new_parent, new_dentry);
if (error)
return error;
@@ -2480,7 +2479,7 @@ int vfs_rename(struct nameidata2 *old_nd
return error;
if (!new_dentry->d_inode)
- error = may_create(new_dir, new_dentry, new_nd);
+ error = may_create(new_nd, new_dentry);
else
error = may_delete(new_dir, new_dentry, is_dir);
if (error)

View File

@@ -0,0 +1,61 @@
---
fs/namei.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1382,8 +1382,9 @@ static inline int check_sticky(struct in
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
-static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
+static int may_delete(struct nameidata2 *nd, struct dentry *victim, int isdir)
{
+ struct inode *dir = nd->dentry->d_inode;
int error;
if (!victim->d_inode)
@@ -1392,7 +1393,7 @@ static int may_delete(struct inode *dir,
BUG_ON(victim->d_parent->d_inode != dir);
audit_inode_child(victim->d_name.name, victim->d_inode, dir);
- error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
+ error = permission(dir, MAY_WRITE | MAY_EXEC, nd);
if (error)
return error;
if (IS_APPEND(dir))
@@ -2008,7 +2009,7 @@ void dentry_unhash(struct dentry *dentry
int vfs_rmdir(struct nameidata2 *nd, struct dentry *dentry)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_delete(dir, dentry, 1);
+ int error = may_delete(nd, dentry, 1);
if (error)
return error;
@@ -2090,7 +2091,7 @@ asmlinkage long sys_rmdir(const char __u
int vfs_unlink(struct nameidata2 *nd, struct dentry *dentry)
{
struct inode *dir = nd->dentry->d_inode;
- int error = may_delete(dir, dentry, 0);
+ int error = may_delete(nd, dentry, 0);
if (error)
return error;
@@ -2476,14 +2477,14 @@ int vfs_rename(struct nameidata2 *old_nd
if (old_dentry->d_inode == new_dentry->d_inode)
return 0;
- error = may_delete(old_dir, old_dentry, is_dir);
+ error = may_delete(old_nd, old_dentry, is_dir);
if (error)
return error;
if (!new_dentry->d_inode)
error = may_create(new_nd, new_dentry);
else
- error = may_delete(new_dir, new_dentry, is_dir);
+ error = may_delete(new_nd, new_dentry, is_dir);
if (error)
return error;

View File

@@ -1,142 +0,0 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Don't pass NULL nameidata to vfs_create()
The kernel nfs daemon and the mqueue fs pass a NULL nameidata to
vfs_create(), so the vfs cannot check the options of nd->mnt. Fix those
callers by creating a dummy nameidata.
(There are still tons of callers left that pass a NULL nameidata to
permission().)
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/namei.c | 7 ++++---
fs/nfsd/vfs.c | 23 +++++++++++++++++++----
ipc/mqueue.c | 6 +++++-
3 files changed, 28 insertions(+), 8 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1428,7 +1428,7 @@ static inline int may_create(struct inod
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
- return permission(dir,MAY_WRITE | MAY_EXEC, nd);
+ return permission(dir, MAY_WRITE | MAY_EXEC, nd);
}
/*
@@ -1503,7 +1503,7 @@ int vfs_create(struct inode *dir, struct
return -EACCES; /* shouldn't it be ENOSYS? */
mode &= S_IALLUGO;
mode |= S_IFREG;
- error = security_inode_create(dir, dentry, nd ? nd->mnt : NULL, mode);
+ error = security_inode_create(dir, dentry, nd->mnt, mode);
if (error)
return error;
DQUOT_INIT(dir);
@@ -1887,7 +1887,8 @@ asmlinkage long sys_mknodat(int dfd, con
if (!IS_ERR(dentry)) {
switch (mode & S_IFMT) {
case 0: case S_IFREG:
- error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
+ error = vfs_create(nd.dentry->d_inode, dentry, mode,
+ &nd);
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt,
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1108,6 +1108,18 @@ nfsd_commit(struct svc_rqst *rqstp, stru
}
#endif /* CONFIG_NFSD_V3 */
+static inline int
+nfsd_do_create(struct inode *dir, struct dentry *child, struct vfsmount *mnt,
+ int mode)
+{
+ struct nameidata nd = {
+ .dentry = child, /* FIXME: should be the parent */,
+ .mnt = mnt,
+ };
+
+ return vfs_create(dir, child, mode, &nd);
+}
+
/*
* Create a file (regular, directory, device, fifo); UNIX sockets
* not yet implemented.
@@ -1192,7 +1204,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
err = 0;
switch (type) {
case S_IFREG:
- host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+ host_err = nfsd_do_create(dirp, dchild, exp->ex_mnt,
+ iap->ia_mode);
break;
case S_IFDIR:
host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
@@ -1253,6 +1266,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
int *truncp, int *created)
{
struct dentry *dentry, *dchild = NULL;
+ struct svc_export *exp;
struct inode *dirp;
__be32 err;
int host_err;
@@ -1271,6 +1285,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
goto out;
dentry = fhp->fh_dentry;
+ exp = fhp->fh_export;
dirp = dentry->d_inode;
/* Get all the sanity checks out of the way before
@@ -1288,7 +1303,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
if (IS_ERR(dchild))
goto out_nfserr;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
+ err = fh_compose(resfhp, exp, dchild, fhp);
if (err)
goto out;
@@ -1334,13 +1349,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
goto out;
}
- host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+ host_err = nfsd_do_create(dirp, dchild, exp->ex_mnt, iap->ia_mode);
if (host_err < 0)
goto out_nfserr;
if (created)
*created = 1;
- if (EX_ISSYNC(fhp->fh_export)) {
+ if (EX_ISSYNC(exp)) {
err = nfserrno(nfsd_sync_dir(dentry));
/* setattr will sync the child (or not) */
}
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -604,6 +604,10 @@ static int mq_attr_ok(struct mq_attr *at
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
int oflag, mode_t mode, struct mq_attr __user *u_attr)
{
+ struct nameidata nd = {
+ .dentry = dentry, /* FIXME: should be the parent */,
+ /* Not a regular create, so set .mnt to NULL. */
+ };
struct mq_attr attr;
int ret;
@@ -619,7 +623,7 @@ static struct file *do_create(struct den
}
mode &= ~current->fs->umask;
- ret = vfs_create(dir->d_inode, dentry, mode, NULL);
+ ret = vfs_create(dir->d_inode, dentry, mode, &nd);
dentry->d_fsdata = NULL;
if (ret)
goto out;

View File

@@ -28,6 +28,10 @@ vfs-listxattr.diff
security-listxattr.diff
vfs-removexattr.diff
security-removexattr.diff
file_permission-1.diff
file_permission-2.diff
file_permission-3.diff
xattr_permission.diff
unambiguous-__d_path.diff
mount-consistent-__d_path.diff
d_namespace_path.diff
@@ -48,7 +52,17 @@ apparmor-module_interface.diff
apparmor-module_interface-2.diff
apparmor-misc.diff
apparmor-intree.diff
nameidata-never-NULL.diff
# split-up-nameidata.diff
# vfs_create-nameidata.diff
# vfs_create-args.diff
# vfs_mknod-args.diff
# vfs_mkdir-args.diff
# vfs_symlink-args.diff
# vfs_link-args.diff
# vfs_rename-args.diff
# may_create-args.diff
# vfs_rmdir-args.diff
# vfs_unlink-args.diff
# may_delete-args.diff
sysctl-pathname.diff
apparmor-sysctl-pathname.diff

View File

@@ -16,116 +16,115 @@ places where a full nameidat is not needed.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
fs/9p/vfs_inode.c | 4 ++--
fs/adfs/dir.c | 2 +-
fs/affs/affs.h | 4 ++--
fs/affs/namei.c | 4 ++--
fs/afs/dir.c | 8 ++++----
fs/afs/mntpt.c | 4 ++--
fs/autofs/root.c | 6 +++---
fs/autofs4/root.c | 8 ++++----
fs/bad_inode.c | 6 +++---
fs/befs/linuxvfs.c | 4 ++--
fs/bfs/dir.c | 4 ++--
fs/cifs/cifsfs.c | 2 +-
fs/cifs/cifsfs.h | 4 ++--
fs/cifs/dir.c | 6 +++---
fs/coda/dir.c | 14 +++++++-------
fs/coda/pioctl.c | 4 ++--
fs/configfs/dir.c | 2 +-
fs/cramfs/inode.c | 2 +-
fs/ecryptfs/dentry.c | 2 +-
fs/ecryptfs/inode.c | 10 +++++-----
fs/efs/namei.c | 2 +-
fs/exec.c | 8 ++++----
fs/ext2/acl.c | 2 +-
fs/ext2/acl.h | 2 +-
fs/ext2/namei.c | 4 ++--
fs/ext3/acl.c | 2 +-
fs/ext3/acl.h | 2 +-
fs/ext3/namei.c | 4 ++--
fs/ext4/acl.c | 2 +-
fs/ext4/acl.h | 2 +-
fs/ext4/namei.c | 4 ++--
fs/freevxfs/vxfs_lookup.c | 4 ++--
fs/fuse/dir.c | 10 +++++-----
fs/gfs2/inode.c | 2 +-
fs/gfs2/inode.h | 2 +-
fs/gfs2/ops_dentry.c | 2 +-
fs/gfs2/ops_inode.c | 6 +++---
fs/hfs/dir.c | 4 ++--
fs/hfs/inode.c | 4 ++--
fs/hfs/sysdep.c | 2 +-
fs/hfsplus/dir.c | 4 ++--
fs/hfsplus/inode.c | 4 ++--
fs/hpfs/dir.c | 2 +-
fs/hpfs/hpfs_fn.h | 2 +-
fs/hpfs/namei.c | 2 +-
fs/hugetlbfs/inode.c | 2 +-
fs/inotify_user.c | 2 +-
fs/isofs/isofs.h | 2 +-
fs/isofs/namei.c | 2 +-
fs/jffs2/acl.c | 2 +-
fs/jffs2/acl.h | 2 +-
fs/jffs2/dir.c | 8 ++++----
fs/jfs/acl.c | 2 +-
fs/jfs/jfs_acl.h | 2 +-
fs/jfs/namei.c | 4 ++--
fs/libfs.c | 2 +-
fs/minix/namei.c | 4 ++--
fs/msdos/namei.c | 4 ++--
fs/namei.c | 37 +++++++++++++++++++------------------
fs/ncpfs/dir.c | 14 +++++++-------
fs/nfs/dir.c | 30 +++++++++++++++---------------
fs/nfs/nfs3proc.c | 2 +-
fs/nfs/nfs4_fs.h | 4 ++--
fs/nfs/nfs4proc.c | 8 ++++----
fs/nfs/proc.c | 2 +-
fs/nfsd/vfs.c | 2 +-
fs/ntfs/namei.c | 2 +-
fs/ocfs2/dcache.c | 2 +-
fs/ocfs2/dlm/dlmfs.c | 2 +-
fs/ocfs2/file.c | 2 +-
fs/ocfs2/file.h | 2 +-
fs/ocfs2/namei.c | 4 ++--
fs/open.c | 13 +++++++------
fs/proc/base.c | 18 +++++++++---------
fs/proc/generic.c | 2 +-
fs/proc/proc_sysctl.c | 6 +++---
fs/proc/root.c | 2 +-
fs/qnx4/namei.c | 2 +-
fs/ramfs/inode.c | 2 +-
fs/reiserfs/namei.c | 4 ++--
fs/reiserfs/xattr.c | 2 +-
fs/romfs/inode.c | 2 +-
fs/smbfs/dir.c | 12 ++++++------
fs/smbfs/file.c | 2 +-
fs/sysfs/dir.c | 2 +-
fs/sysv/namei.c | 4 ++--
fs/udf/namei.c | 4 ++--
fs/ufs/namei.c | 4 ++--
fs/utimes.c | 4 ++--
fs/vfat/namei.c | 6 +++---
fs/xfs/linux-2.6/xfs_iops.c | 6 +++---
include/linux/coda_linux.h | 2 +-
include/linux/dcache.h | 3 ++-
include/linux/efs_fs.h | 2 +-
include/linux/fs.h | 15 ++++++++-------
include/linux/namei.h | 37 +++++++++++++++++++++++++++----------
include/linux/nfs_fs.h | 2 +-
include/linux/nfs_xdr.h | 2 +-
include/linux/proc_fs.h | 4 ++--
include/linux/qnx4_fs.h | 2 +-
include/linux/reiserfs_xattr.h | 2 +-
include/linux/security.h | 6 +++---
include/linux/shmem_fs.h | 2 +-
ipc/mqueue.c | 4 ++--
mm/shmem.c | 2 +-
mm/shmem_acl.c | 2 +-
security/apparmor/lsm.c | 2 +-
security/dummy.c | 2 +-
security/selinux/hooks.c | 2 +-
109 files changed, 273 insertions(+), 252 deletions(-)
fs/9p/vfs_inode.c | 4 +--
fs/adfs/dir.c | 2 -
fs/affs/affs.h | 4 +--
fs/affs/namei.c | 4 +--
fs/afs/dir.c | 8 +++----
fs/afs/mntpt.c | 4 +--
fs/autofs/root.c | 6 ++---
fs/autofs4/root.c | 8 +++----
fs/bad_inode.c | 6 ++---
fs/befs/linuxvfs.c | 4 +--
fs/bfs/dir.c | 4 +--
fs/cifs/cifsfs.c | 2 -
fs/cifs/cifsfs.h | 4 +--
fs/cifs/dir.c | 6 ++---
fs/coda/dir.c | 14 ++++++-------
fs/coda/pioctl.c | 4 +--
fs/configfs/dir.c | 2 -
fs/cramfs/inode.c | 2 -
fs/ecryptfs/dentry.c | 2 -
fs/ecryptfs/inode.c | 10 ++++-----
fs/efs/namei.c | 2 -
fs/exec.c | 8 +++----
fs/ext2/acl.c | 2 -
fs/ext2/acl.h | 2 -
fs/ext2/namei.c | 4 +--
fs/ext3/acl.c | 2 -
fs/ext3/acl.h | 2 -
fs/ext3/namei.c | 4 +--
fs/ext4/acl.c | 2 -
fs/ext4/acl.h | 2 -
fs/ext4/namei.c | 4 +--
fs/freevxfs/vxfs_lookup.c | 4 +--
fs/fuse/dir.c | 10 ++++-----
fs/gfs2/inode.c | 2 -
fs/gfs2/inode.h | 2 -
fs/gfs2/ops_dentry.c | 2 -
fs/gfs2/ops_inode.c | 6 ++---
fs/hfs/dir.c | 4 +--
fs/hfs/inode.c | 4 +--
fs/hfs/sysdep.c | 2 -
fs/hfsplus/dir.c | 4 +--
fs/hfsplus/inode.c | 4 +--
fs/hpfs/dir.c | 2 -
fs/hpfs/hpfs_fn.h | 2 -
fs/hpfs/namei.c | 2 -
fs/hugetlbfs/inode.c | 2 -
fs/inotify_user.c | 2 -
fs/isofs/isofs.h | 2 -
fs/isofs/namei.c | 2 -
fs/jffs2/acl.c | 2 -
fs/jffs2/acl.h | 2 -
fs/jffs2/dir.c | 8 +++----
fs/jfs/acl.c | 2 -
fs/jfs/jfs_acl.h | 2 -
fs/jfs/namei.c | 4 +--
fs/libfs.c | 2 -
fs/minix/namei.c | 4 +--
fs/msdos/namei.c | 4 +--
fs/namei.c | 42 +++++++++++++++++++++--------------------
fs/ncpfs/dir.c | 14 ++++++-------
fs/nfs/dir.c | 30 ++++++++++++++---------------
fs/nfs/nfs3proc.c | 2 -
fs/nfs/nfs4_fs.h | 4 +--
fs/nfs/nfs4proc.c | 8 +++----
fs/nfs/proc.c | 2 -
fs/ntfs/namei.c | 2 -
fs/ocfs2/dcache.c | 2 -
fs/ocfs2/dlm/dlmfs.c | 2 -
fs/ocfs2/file.c | 2 -
fs/ocfs2/file.h | 2 -
fs/ocfs2/namei.c | 4 +--
fs/open.c | 15 +++++++-------
fs/proc/base.c | 18 ++++++++---------
fs/proc/generic.c | 2 -
fs/proc/proc_sysctl.c | 6 ++---
fs/proc/root.c | 2 -
fs/qnx4/namei.c | 2 -
fs/ramfs/inode.c | 2 -
fs/reiserfs/namei.c | 4 +--
fs/reiserfs/xattr.c | 2 -
fs/romfs/inode.c | 2 -
fs/smbfs/dir.c | 12 +++++------
fs/smbfs/file.c | 2 -
fs/sysfs/dir.c | 2 -
fs/sysv/namei.c | 4 +--
fs/udf/namei.c | 4 +--
fs/ufs/namei.c | 4 +--
fs/utimes.c | 4 +--
fs/vfat/namei.c | 6 ++---
fs/xfs/linux-2.6/xfs_iops.c | 6 ++---
include/linux/coda_linux.h | 2 -
include/linux/dcache.h | 3 +-
include/linux/efs_fs.h | 2 -
include/linux/fs.h | 15 +++++++-------
include/linux/namei.h | 37 ++++++++++++++++++++++++++----------
include/linux/nfs_fs.h | 2 -
include/linux/nfs_xdr.h | 2 -
include/linux/proc_fs.h | 4 +--
include/linux/qnx4_fs.h | 2 -
include/linux/reiserfs_xattr.h | 2 -
include/linux/security.h | 6 ++---
include/linux/shmem_fs.h | 2 -
ipc/mqueue.c | 2 -
mm/shmem.c | 2 -
mm/shmem_acl.c | 2 -
security/apparmor/lsm.c | 2 -
security/dummy.c | 2 -
security/selinux/hooks.c | 2 -
108 files changed, 275 insertions(+), 253 deletions(-)
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1230,7 +1229,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
return permission(nd->dentry->d_inode, mask, nd);
}
@@ -366,7 +366,7 @@ void path_release_on_umount(struct namei
@@ -293,7 +293,7 @@ int vfs_permission(struct nameidata *nd,
*/
int file_permission(struct file *file, int mask)
{
- struct nameidata nd = {
+ struct nameidata2 nd = {
.dentry = file->f_path.dentry,
.mnt = file->f_path.mnt,
};
@@ -367,7 +367,7 @@ void path_release_on_umount(struct namei
* release_open_intent - free up open intent resources
* @nd: pointer to nameidata
*/
@@ -1239,7 +1247,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
if (nd->intent.open.file->f_path.dentry == NULL)
put_filp(nd->intent.open.file);
@@ -377,7 +377,7 @@ void release_open_intent(struct nameidat
@@ -378,7 +378,7 @@ void release_open_intent(struct nameidat
static inline struct dentry *
do_revalidate(struct dentry *dentry, struct nameidata *nd)
{
@@ -1248,7 +1256,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
if (unlikely(status <= 0)) {
/*
* The dentry failed validation.
@@ -455,7 +455,7 @@ static int exec_permission_lite(struct i
@@ -456,7 +456,7 @@ static int exec_permission_lite(struct i
return -EACCES;
ok:
@@ -1257,7 +1265,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
}
/*
@@ -491,7 +491,7 @@ static struct dentry * real_lookup(struc
@@ -492,7 +492,7 @@ static struct dentry * real_lookup(struc
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
@@ -1266,7 +1274,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
if (result)
dput(dentry);
else
@@ -832,7 +832,7 @@ static fastcall int __link_path_walk(con
@@ -833,7 +833,7 @@ static fastcall int __link_path_walk(con
nd->flags |= LOOKUP_CONTINUE;
err = exec_permission_lite(inode, nd);
if (err == -EAGAIN)
@@ -1275,7 +1283,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
if (err)
break;
@@ -978,7 +978,8 @@ return_reval:
@@ -979,7 +979,8 @@ return_reval:
(nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
err = -ESTALE;
/* Note: we do not d_invalidate() */
@@ -1285,6 +1293,15 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
break;
}
return_base:
@@ -1144,7 +1145,7 @@ static int fastcall do_path_lookup(int d
if (!S_ISDIR(nd->dentry->d_inode->i_mode))
goto fput_fail;
- retval = vfs_permission(nd, MAY_EXEC);
+ retval = vfs_permission(ND2(nd), MAY_EXEC);
if (retval)
goto fput_fail;
@@ -1194,7 +1195,7 @@ static int __path_lookup_intent_open(int
path_release(nd);
}
@@ -1366,11 +1383,12 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
return error;
}
nd->flags &= ~LOOKUP_PARENT;
@@ -1888,7 +1889,7 @@ asmlinkage long sys_mknodat(int dfd, con
@@ -1887,7 +1888,8 @@ asmlinkage long sys_mknodat(int dfd, con
if (!IS_ERR(dentry)) {
switch (mode & S_IFMT) {
case 0: case S_IFREG:
error = vfs_create(nd.dentry->d_inode, dentry, mode,
- &nd);
- error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
+ error = vfs_create(nd.dentry->d_inode, dentry, mode,
+ ND2(&nd));
break;
case S_IFCHR: case S_IFBLK:
@@ -1636,17 +1654,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct nfs_fh fhandle;
struct nfs_fattr fattr;
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1112,7 +1112,7 @@ static inline int
nfsd_do_create(struct inode *dir, struct dentry *child, struct vfsmount *mnt,
int mode)
{
- struct nameidata nd = {
+ struct nameidata2 nd = {
.dentry = child,
.mnt = mnt,
};
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -99,7 +99,7 @@
@@ -1751,7 +1758,16 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
if (error)
goto dput_and_out;
@@ -475,7 +475,7 @@ asmlinkage long sys_chroot(const char __
@@ -438,7 +438,7 @@ out:
asmlinkage long sys_fchdir(unsigned int fd)
{
- struct nameidata nd = {};
+ struct nameidata2 nd = {};
struct file *file;
int error;
@@ -472,7 +472,7 @@ asmlinkage long sys_chroot(const char __
if (error)
goto out;
@@ -1760,7 +1776,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
if (error)
goto dput_and_out;
@@ -796,8 +796,9 @@ EXPORT_SYMBOL(filp_open);
@@ -793,8 +793,9 @@ EXPORT_SYMBOL(filp_open);
* If the open callback is set to NULL, then the standard f_op->open()
* filesystem callback is substituted.
*/
@@ -1774,7 +1790,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
goto out;
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1071,7 +1071,7 @@ static int pid_getattr(struct vfsmount *
@@ -1072,7 +1072,7 @@ static int pid_getattr(struct vfsmount *
* made this apply to all per process world readable and executable
* directories.
*/
@@ -1783,7 +1799,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
@@ -1219,7 +1219,7 @@ static int proc_fd_link(struct inode *in
@@ -1220,7 +1220,7 @@ static int proc_fd_link(struct inode *in
return -ENOENT;
}
@@ -1792,7 +1808,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
@@ -1314,7 +1314,7 @@ out_iput:
@@ -1315,7 +1315,7 @@ out_iput:
goto out;
}
@@ -1801,7 +1817,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct task_struct *task = get_proc_task(dir);
unsigned fd = name_to_int(dentry);
@@ -1630,7 +1630,7 @@ static const struct file_operations proc
@@ -1631,7 +1631,7 @@ static const struct file_operations proc
};
static struct dentry *proc_attr_dir_lookup(struct inode *dir,
@@ -1810,7 +1826,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
return proc_pident_lookup(dir, dentry,
attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
@@ -1684,7 +1684,7 @@ static struct pid_entry proc_base_stuff[
@@ -1685,7 +1685,7 @@ static struct pid_entry proc_base_stuff[
* directory. In this case, however, we can do it - no aliasing problems
* due to the way we treat inodes.
*/
@@ -1819,7 +1835,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct inode *inode = dentry->d_inode;
struct task_struct *task = get_proc_task(inode);
@@ -1879,7 +1879,7 @@ static const struct file_operations proc
@@ -1880,7 +1880,7 @@ static const struct file_operations proc
.readdir = proc_tgid_base_readdir,
};
@@ -1828,7 +1844,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
return proc_pident_lookup(dir, dentry,
tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
}
@@ -1987,7 +1987,7 @@ out:
@@ -1988,7 +1988,7 @@ out:
return error;
}
@@ -1837,7 +1853,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct dentry *result = ERR_PTR(-ENOENT);
struct task_struct *task;
@@ -2152,7 +2152,7 @@ static int proc_tid_base_readdir(struct
@@ -2153,7 +2153,7 @@ static int proc_tid_base_readdir(struct
tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
}
@@ -1846,7 +1862,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
return proc_pident_lookup(dir, dentry,
tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
}
@@ -2196,7 +2196,7 @@ out:
@@ -2197,7 +2197,7 @@ out:
return error;
}
@@ -2315,7 +2331,7 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
- struct open_intent open;
- } intent;
+struct nameidata2 {
+ struct { __NAMEIDATA2 };
+ __NAMEIDATA2
};
+#undef __NAMEIDATA2
@@ -2456,15 +2472,6 @@ Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
{
struct inode *inode;
struct mq_attr *attr = dentry->d_fsdata;
@@ -604,7 +604,7 @@ static int mq_attr_ok(struct mq_attr *at
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
int oflag, mode_t mode, struct mq_attr __user *u_attr)
{
- struct nameidata nd = {
+ struct nameidata2 nd = {
.dentry = dentry,
/* Not a regular create, so .mnt is NULL. */
};
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1796,7 +1796,7 @@ static int shmem_mkdir(struct inode *dir

View File

@@ -0,0 +1,142 @@
---
fs/ecryptfs/inode.c | 10 +++++-----
fs/namei.c | 9 ++++-----
fs/nfsd/vfs.c | 4 ++--
include/linux/fs.h | 2 +-
ipc/mqueue.c | 11 +++++------
5 files changed, 17 insertions(+), 19 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -67,7 +67,7 @@ static void unlock_dir(struct dentry *di
* Returns zero on success; non-zero on error condition
*/
static int
-ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
+ecryptfs_create_underlying_file(struct dentry *lower_dir_dentry,
struct dentry *dentry, int mode,
struct nameidata2 *nd)
{
@@ -79,9 +79,9 @@ ecryptfs_create_underlying_file(struct i
dentry_save = nd->dentry;
vfsmount_save = nd->mnt;
- nd->dentry = lower_dentry;
+ nd->dentry = lower_dir_dentry;
nd->mnt = lower_mnt;
- rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd);
+ rc = vfs_create(nd, lower_dentry, mode);
nd->dentry = dentry_save;
nd->mnt = vfsmount_save;
return rc;
@@ -117,8 +117,8 @@ ecryptfs_do_create(struct inode *directo
rc = PTR_ERR(lower_dir_dentry);
goto out;
}
- rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
- ecryptfs_dentry, mode, nd);
+ rc = ecryptfs_create_underlying_file(lower_dir_dentry, ecryptfs_dentry,
+ mode, nd);
if (unlikely(rc)) {
ecryptfs_printk(KERN_ERR,
"Failure to create underlying file\n");
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1492,9 +1492,9 @@ void unlock_rename(struct dentry *p1, st
}
}
-int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata2 *nd)
+int vfs_create(struct nameidata2 *nd, struct dentry *dentry, int mode)
{
+ struct inode *dir = nd->dentry->d_inode;
int error = may_create(dir, dentry, nd);
if (error)
@@ -1602,7 +1602,7 @@ static int open_namei_create(struct name
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
- error = vfs_create(dir->d_inode, path->dentry, mode, ND2(nd));
+ error = vfs_create(ND2(nd), path->dentry, mode);
mutex_unlock(&dir->d_inode->i_mutex);
dput(nd->dentry);
nd->dentry = path->dentry;
@@ -1888,8 +1888,7 @@ asmlinkage long sys_mknodat(int dfd, con
if (!IS_ERR(dentry)) {
switch (mode & S_IFMT) {
case 0: case S_IFREG:
- error = vfs_create(nd.dentry->d_inode, dentry, mode,
- ND2(&nd));
+ error = vfs_create(ND2(&nd), dentry, mode);
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt,
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1194,7 +1194,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
err = 0;
switch (type) {
case S_IFREG:
- host_err = vfs_create(nd.dentry->d_inode, dchild, iap->ia_mode, &nd);
+ host_err = vfs_create(&nd, dchild, iap->ia_mode);
break;
case S_IFDIR:
host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
@@ -1340,7 +1340,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
goto out;
}
- host_err = vfs_create(nd.dentry->d_inode, dchild, iap->ia_mode, &nd);
+ host_err = vfs_create(&nd, dchild, iap->ia_mode);
if (host_err < 0)
goto out_nfserr;
if (created)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -983,7 +983,7 @@ extern void unlock_super(struct super_bl
* VFS helper functions..
*/
extern int vfs_permission(struct nameidata2 *, int);
-extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata2 *);
+extern int vfs_create(struct nameidata2 *, struct dentry *, int);
extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -601,11 +601,11 @@ static int mq_attr_ok(struct mq_attr *at
/*
* Invoked when creating a new queue via sys_mq_open
*/
-static struct file *do_create(struct dentry *dir, struct dentry *dentry,
- int oflag, mode_t mode, struct mq_attr __user *u_attr)
+static struct file *do_create(struct dentry *dentry, int oflag, mode_t mode,
+ struct mq_attr __user *u_attr)
{
struct nameidata2 nd = {
- .dentry = dir,
+ .dentry = mqueue_mnt->mnt_root,
/* Not a mounted filesystem, so set .mnt to NULL. */
};
struct mq_attr attr;
@@ -623,7 +623,7 @@ static struct file *do_create(struct den
}
mode &= ~current->fs->umask;
- ret = vfs_create(dir->d_inode, dentry, mode, &nd);
+ ret = vfs_create(&nd, dentry, mode);
dentry->d_fsdata = NULL;
if (ret)
goto out;
@@ -691,8 +691,7 @@ asmlinkage long sys_mq_open(const char _
goto out;
filp = do_open(dentry, oflag);
} else {
- filp = do_create(mqueue_mnt->mnt_root, dentry,
- oflag, mode, u_attr);
+ filp = do_create(dentry, oflag, mode, u_attr);
}
} else {
error = -ENOENT;

View File

@@ -0,0 +1,168 @@
---
fs/namei.c | 2 +-
fs/nfsd/vfs.c | 40 +++++++++++++++++++++++-----------------
ipc/mqueue.c | 6 +++++-
3 files changed, 29 insertions(+), 19 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1504,7 +1504,7 @@ int vfs_create(struct inode *dir, struct
return -EACCES; /* shouldn't it be ENOSYS? */
mode &= S_IALLUGO;
mode |= S_IFREG;
- error = security_inode_create(dir, dentry, nd ? nd->mnt : NULL, mode);
+ error = security_inode_create(dir, dentry, nd->mnt, mode);
if (error)
return error;
DQUOT_INIT(dir);
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1121,7 +1121,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
char *fname, int flen, struct iattr *iap,
int type, dev_t rdev, struct svc_fh *resfhp)
{
- struct dentry *dentry, *dchild = NULL;
+ struct nameidata2 nd = {};
+ struct dentry *dchild = NULL;
struct svc_export *exp;
struct inode *dirp;
__be32 err;
@@ -1138,9 +1139,10 @@ nfsd_create(struct svc_rqst *rqstp, stru
if (err)
goto out;
- dentry = fhp->fh_dentry;
+ nd.dentry = fhp->fh_dentry;
exp = fhp->fh_export;
- dirp = dentry->d_inode;
+ nd.mnt = exp->ex_mnt;
+ dirp = nd.dentry->d_inode;
err = nfserr_notdir;
if(!dirp->i_op || !dirp->i_op->lookup)
@@ -1152,7 +1154,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
if (!resfhp->fh_dentry) {
/* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
fh_lock_nested(fhp, I_MUTEX_PARENT);
- dchild = lookup_one_len(fname, dentry, flen);
+ dchild = lookup_one_len(fname, nd.dentry, flen);
host_err = PTR_ERR(dchild);
if (IS_ERR(dchild))
goto out_nfserr;
@@ -1166,8 +1168,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
/* not actually possible */
printk(KERN_ERR
"nfsd_create: parent %s/%s not locked!\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ nd.dentry->d_parent->d_name.name,
+ nd.dentry->d_name.name);
err = nfserr_io;
goto out;
}
@@ -1178,7 +1180,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
err = nfserr_exist;
if (dchild->d_inode) {
dprintk("nfsd_create: dentry %s/%s not negative!\n",
- dentry->d_name.name, dchild->d_name.name);
+ nd.dentry->d_name.name, dchild->d_name.name);
goto out;
}
@@ -1192,7 +1194,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
err = 0;
switch (type) {
case S_IFREG:
- host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+ host_err = vfs_create(nd.dentry->d_inode, dchild, iap->ia_mode, &nd);
break;
case S_IFDIR:
host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
@@ -1212,7 +1214,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
goto out_nfserr;
if (EX_ISSYNC(exp)) {
- err = nfserrno(nfsd_sync_dir(dentry));
+ err = nfserrno(nfsd_sync_dir(nd.dentry));
write_inode_now(dchild->d_inode, 1);
}
@@ -1252,7 +1254,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
struct svc_fh *resfhp, int createmode, u32 *verifier,
int *truncp, int *created)
{
- struct dentry *dentry, *dchild = NULL;
+ struct nameidata2 nd = {};
+ struct dentry *dchild = NULL;
+ struct svc_export *exp;
struct inode *dirp;
__be32 err;
int host_err;
@@ -1270,8 +1274,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
if (err)
goto out;
- dentry = fhp->fh_dentry;
- dirp = dentry->d_inode;
+ nd.dentry = fhp->fh_dentry;
+ exp = fhp->fh_export;
+ nd.mnt = exp->ex_mnt;
+ dirp = nd.dentry->d_inode;
/* Get all the sanity checks out of the way before
* we lock the parent. */
@@ -1283,12 +1289,12 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
/*
* Compose the response file handle.
*/
- dchild = lookup_one_len(fname, dentry, flen);
+ dchild = lookup_one_len(fname, nd.dentry, flen);
host_err = PTR_ERR(dchild);
if (IS_ERR(dchild))
goto out_nfserr;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
+ err = fh_compose(resfhp, exp, dchild, fhp);
if (err)
goto out;
@@ -1334,14 +1340,14 @@ nfsd_create_v3(struct svc_rqst *rqstp, s
goto out;
}
- host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+ host_err = vfs_create(nd.dentry->d_inode, dchild, iap->ia_mode, &nd);
if (host_err < 0)
goto out_nfserr;
if (created)
*created = 1;
- if (EX_ISSYNC(fhp->fh_export)) {
- err = nfserrno(nfsd_sync_dir(dentry));
+ if (EX_ISSYNC(exp)) {
+ err = nfserrno(nfsd_sync_dir(nd.dentry));
/* setattr will sync the child (or not) */
}
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -604,6 +604,10 @@ static int mq_attr_ok(struct mq_attr *at
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
int oflag, mode_t mode, struct mq_attr __user *u_attr)
{
+ struct nameidata2 nd = {
+ .dentry = dir,
+ /* Not a mounted filesystem, so set .mnt to NULL. */
+ };
struct mq_attr attr;
int ret;
@@ -619,7 +623,7 @@ static struct file *do_create(struct den
}
mode &= ~current->fs->umask;
- ret = vfs_create(dir->d_inode, dentry, mode, NULL);
+ ret = vfs_create(dir->d_inode, dentry, mode, &nd);
dentry->d_fsdata = NULL;
if (ret)
goto out;

View File

@@ -0,0 +1,158 @@
---
fs/ecryptfs/inode.c | 26 +++++++++++---------------
fs/namei.c | 14 ++++++++------
fs/nfsd/vfs.c | 22 ++++++++++++----------
include/linux/fs.h | 2 +-
4 files changed, 32 insertions(+), 32 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -410,25 +410,21 @@ out:
static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
- struct dentry *lower_old_dentry;
- struct vfsmount *lower_old_mnt;
+ struct nameidata2 old_nd = {};
+ struct nameidata2 new_parent = {};
struct dentry *lower_new_dentry;
- struct vfsmount *lower_new_mnt;
- struct dentry *lower_dir_dentry;
u64 file_size_save;
int rc;
file_size_save = i_size_read(old_dentry->d_inode);
- lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
- lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
+ old_nd.dentry = ecryptfs_dentry_to_lower(old_dentry);
+ old_nd.mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
- lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
- dget(lower_old_dentry);
+ new_parent.mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
+ dget(old_nd.dentry);
dget(lower_new_dentry);
- lower_dir_dentry = lock_parent(lower_new_dentry);
- rc = vfs_link(lower_old_dentry, lower_old_mnt,
- lower_dir_dentry->d_inode, lower_new_dentry,
- lower_new_mnt);
+ new_parent.dentry = lock_parent(lower_new_dentry);
+ rc = vfs_link(&old_nd, lower_new_dentry, &new_parent);
if (rc || !lower_new_dentry->d_inode)
goto out_lock;
rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
@@ -440,10 +436,10 @@ static int ecryptfs_link(struct dentry *
ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink;
i_size_write(new_dentry->d_inode, file_size_save);
out_lock:
- unlock_dir(lower_dir_dentry);
+ unlock_dir(new_parent.dentry);
dput(lower_new_dentry);
- dput(lower_old_dentry);
- d_drop(lower_old_dentry);
+ dput(old_nd.dentry);
+ d_drop(old_nd.dentry);
d_drop(new_dentry);
d_drop(old_dentry);
return rc;
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2251,15 +2251,18 @@ asmlinkage long sys_symlink(const char _
return sys_symlinkat(oldname, AT_FDCWD, newname);
}
-int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt)
+int vfs_link(struct nameidata2 *old_nd, struct dentry *new_dentry,
+ struct nameidata2 *new_parent)
{
+ struct dentry *old_dentry = old_nd->dentry;
struct inode *inode = old_dentry->d_inode;
+ struct inode *dir = new_parent->dentry->d_inode;
int error;
if (!inode)
return -ENOENT;
- error = may_create(dir, new_dentry, NULL);
+ error = may_create(dir, new_dentry, new_parent);
if (error)
return error;
@@ -2276,8 +2279,8 @@ int vfs_link(struct dentry *old_dentry,
if (S_ISDIR(old_dentry->d_inode->i_mode))
return -EPERM;
- error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
- new_mnt);
+ error = security_inode_link(old_dentry, old_nd->mnt, dir, new_dentry,
+ new_parent->mnt);
if (error)
return error;
@@ -2330,8 +2333,7 @@ asmlinkage long sys_linkat(int olddfd, c
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto out_unlock;
- error = vfs_link(old_nd.dentry, old_nd.mnt, nd.dentry->d_inode,
- new_dentry, nd.mnt);
+ error = vfs_link(ND2(&old_nd), new_dentry, ND2(&nd));
dput(new_dentry);
out_unlock:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1517,8 +1517,10 @@ __be32
nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
char *name, int len, struct svc_fh *tfhp)
{
- struct dentry *ddir, *dnew, *dold;
- struct inode *dirp, *dest;
+ struct nameidata2 old_nd = {};
+ struct nameidata2 new_parent = {};
+ struct dentry *dnew;
+ struct inode *dest;
__be32 err;
int host_err;
@@ -1537,22 +1539,22 @@ nfsd_link(struct svc_rqst *rqstp, struct
goto out;
fh_lock_nested(ffhp, I_MUTEX_PARENT);
- ddir = ffhp->fh_dentry;
- dirp = ddir->d_inode;
+ new_parent.dentry = ffhp->fh_dentry;
+ new_parent.mnt = ffhp->fh_export->ex_mnt;
- dnew = lookup_one_len(name, ddir, len);
+ dnew = lookup_one_len(name, new_parent.dentry, len);
host_err = PTR_ERR(dnew);
if (IS_ERR(dnew))
goto out_nfserr;
- dold = tfhp->fh_dentry;
- dest = dold->d_inode;
+ old_nd.dentry = tfhp->fh_dentry;
+ old_nd.mnt = tfhp->fh_export->ex_mnt;
+ dest = old_nd.dentry->d_inode;
- host_err = vfs_link(dold, tfhp->fh_export->ex_mnt, dirp,
- dnew, ffhp->fh_export->ex_mnt);
+ host_err = vfs_link(&old_nd, dnew, &new_parent);
if (!host_err) {
if (EX_ISSYNC(ffhp->fh_export)) {
- err = nfserrno(nfsd_sync_dir(ddir));
+ err = nfserrno(nfsd_sync_dir(new_parent.dentry));
write_inode_now(dest, 1);
}
err = 0;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -987,7 +987,7 @@ extern int vfs_create(struct nameidata2
extern int vfs_mkdir(struct nameidata2 *, struct dentry *, int);
extern int vfs_mknod(struct nameidata2 *, struct dentry *, int, dev_t);
extern int vfs_symlink(struct nameidata2 *, struct dentry *, const char *, int);
-extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
+extern int vfs_link(struct nameidata2 *, struct dentry *, struct nameidata2 *);
extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);

View File

@@ -0,0 +1,113 @@
---
fs/ecryptfs/inode.c | 18 ++++++++----------
fs/namei.c | 10 +++++-----
fs/nfsd/nfs4recover.c | 3 +--
fs/nfsd/vfs.c | 2 +-
include/linux/fs.h | 2 +-
5 files changed, 16 insertions(+), 19 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -515,26 +515,24 @@ out_lock:
static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
+ struct nameidata2 nd = {};
int rc;
struct dentry *lower_dentry;
- struct vfsmount *lower_mnt;
- struct dentry *lower_dir_dentry;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
- lower_dir_dentry = lock_parent(lower_dentry);
- rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
- mode);
+ nd.mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+ nd.dentry = lock_parent(lower_dentry);
+ rc = vfs_mkdir(&nd, lower_dentry, mode);
if (rc || !lower_dentry->d_inode)
goto out;
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
if (rc)
goto out;
- fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
- fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
- dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ fsstack_copy_attr_times(dir, nd.dentry->d_inode);
+ fsstack_copy_inode_size(dir, nd.dentry->d_inode);
+ dir->i_nlink = nd.dentry->d_inode->i_nlink;
out:
- unlock_dir(lower_dir_dentry);
+ unlock_dir(nd.dentry);
if (!dentry->d_inode)
d_drop(dentry);
return rc;
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1918,10 +1918,10 @@ asmlinkage long sys_mknod(const char __u
return sys_mknodat(AT_FDCWD, filename, mode, dev);
}
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
- int mode)
+int vfs_mkdir(struct nameidata2 *nd, struct dentry *dentry, int mode)
{
- int error = may_create(dir, dentry, NULL);
+ struct inode *dir = nd->dentry->d_inode;
+ int error = may_create(dir, dentry, nd);
if (error)
return error;
@@ -1930,7 +1930,7 @@ int vfs_mkdir(struct inode *dir, struct
return -EPERM;
mode &= (S_IRWXUGO|S_ISVTX);
- error = security_inode_mkdir(dir, dentry, mnt, mode);
+ error = security_inode_mkdir(dir, dentry, nd->mnt, mode);
if (error)
return error;
@@ -1963,7 +1963,7 @@ asmlinkage long sys_mkdirat(int dfd, con
if (!IS_POSIXACL(nd.dentry->d_inode))
mode &= ~current->fs->umask;
- error = vfs_mkdir(nd.dentry->d_inode, dentry, nd.mnt, mode);
+ error = vfs_mkdir(ND2(&nd), dentry, mode);
dput(dentry);
out_unlock:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -156,8 +156,7 @@ nfsd4_create_clid_dir(struct nfs4_client
dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
goto out_put;
}
- status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, rec_dir.mnt,
- S_IRWXU);
+ status = vfs_mkdir(ND2(&rec_dir), dentry, S_IRWXU);
out_put:
dput(dentry);
out_unlock:
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1197,7 +1197,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
host_err = vfs_create(&nd, dchild, iap->ia_mode);
break;
case S_IFDIR:
- host_err = vfs_mkdir(dirp, dchild, exp->ex_mnt, iap->ia_mode);
+ host_err = vfs_mkdir(&nd, dchild, iap->ia_mode);
break;
case S_IFCHR:
case S_IFBLK:
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -984,7 +984,7 @@ extern void unlock_super(struct super_bl
*/
extern int vfs_permission(struct nameidata2 *, int);
extern int vfs_create(struct nameidata2 *, struct dentry *, int);
-extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
+extern int vfs_mkdir(struct nameidata2 *, struct dentry *, int);
extern int vfs_mknod(struct nameidata2 *, struct dentry *, int, dev_t);
extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);

View File

@@ -0,0 +1,127 @@
---
fs/ecryptfs/inode.c | 16 +++++++---------
fs/namei.c | 15 +++++++--------
fs/nfsd/vfs.c | 3 +--
include/linux/fs.h | 2 +-
net/unix/af_unix.c | 4 ++--
5 files changed, 18 insertions(+), 22 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -568,25 +568,23 @@ static int ecryptfs_rmdir(struct inode *
static int
ecryptfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
+ struct nameidata2 nd = {};
int rc;
struct dentry *lower_dentry;
- struct vfsmount *lower_mnt;
- struct dentry *lower_dir_dentry;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
- lower_dir_dentry = lock_parent(lower_dentry);
- rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
- dev);
+ nd.mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+ nd.dentry = lock_parent(lower_dentry);
+ rc = vfs_mknod(&nd, lower_dentry, mode, dev);
if (rc || !lower_dentry->d_inode)
goto out;
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
if (rc)
goto out;
- fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
- fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(dir, nd.dentry->d_inode);
+ fsstack_copy_inode_size(dir, nd.dentry->d_inode);
out:
- unlock_dir(lower_dir_dentry);
+ unlock_dir(nd.dentry);
if (!dentry->d_inode)
d_drop(dentry);
return rc;
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1838,10 +1838,10 @@ fail:
}
EXPORT_SYMBOL_GPL(lookup_create);
-int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
- int mode, dev_t dev)
+int vfs_mknod(struct nameidata2 *nd, struct dentry *dentry, int mode, dev_t dev)
{
- int error = may_create(dir, dentry, NULL);
+ struct inode *dir = nd->dentry->d_inode;
+ int error = may_create(dir, dentry, nd);
if (error)
return error;
@@ -1852,7 +1852,7 @@ int vfs_mknod(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->mknod)
return -EPERM;
- error = security_inode_mknod(dir, dentry, mnt, mode, dev);
+ error = security_inode_mknod(dir, dentry, nd->mnt, mode, dev);
if (error)
return error;
@@ -1891,12 +1891,11 @@ asmlinkage long sys_mknodat(int dfd, con
error = vfs_create(ND2(&nd), dentry, mode);
break;
case S_IFCHR: case S_IFBLK:
- error = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt,
- mode, new_decode_dev(dev));
+ error = vfs_mknod(ND2(&nd), dentry, mode,
+ new_decode_dev(dev));
break;
case S_IFIFO: case S_IFSOCK:
- error = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt,
- mode, 0);
+ error = vfs_mknod(ND2(&nd), dentry, mode, 0);
break;
case S_IFDIR:
error = -EPERM;
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1203,8 +1203,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
case S_IFBLK:
case S_IFIFO:
case S_IFSOCK:
- host_err = vfs_mknod(dirp, dchild, exp->ex_mnt, iap->ia_mode,
- rdev);
+ host_err = vfs_mknod(&nd, dchild, iap->ia_mode, rdev);
break;
default:
printk("nfsd: bad file type %o in nfsd_create\n", type);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -985,7 +985,7 @@ extern void unlock_super(struct super_bl
extern int vfs_permission(struct nameidata2 *, int);
extern int vfs_create(struct nameidata2 *, struct dentry *, int);
extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
-extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
+extern int vfs_mknod(struct nameidata2 *, struct dentry *, int, dev_t);
extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -703,7 +703,7 @@ static struct sock *unix_find_other(stru
err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
if (err)
goto fail;
- err = vfs_permission(&nd, MAY_WRITE);
+ err = vfs_permission(ND2(&nd), MAY_WRITE);
if (err)
goto put_fail;
@@ -808,7 +808,7 @@ static int unix_bind(struct socket *sock
*/
mode = S_IFSOCK |
(SOCK_INODE(sock)->i_mode & ~current->fs->umask);
- err = vfs_mknod(nd.dentry->d_inode, dentry, nd.mnt, mode, 0);
+ err = vfs_mknod(ND2(&nd), dentry, mode, 0);
if (err)
goto out_mknod_dput;
mutex_unlock(&nd.dentry->d_inode->i_mutex);

View File

@@ -0,0 +1,253 @@
---
fs/ecryptfs/inode.c | 26 +++++++++++---------------
fs/namei.c | 45 ++++++++++++++++++++++++---------------------
fs/nfsd/vfs.c | 31 +++++++++++++++++--------------
include/linux/fs.h | 2 +-
4 files changed, 53 insertions(+), 51 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -586,33 +586,29 @@ static int
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
+ struct nameidata2 old_nd = {};
+ struct nameidata2 new_nd = {};
int rc;
struct dentry *lower_old_dentry;
- struct vfsmount *lower_old_mnt;
struct dentry *lower_new_dentry;
- struct vfsmount *lower_new_mnt;
- struct dentry *lower_old_dir_dentry;
- struct dentry *lower_new_dir_dentry;
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
- lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
- lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
dget(lower_old_dentry);
dget(lower_new_dentry);
- lower_old_dir_dentry = dget_parent(lower_old_dentry);
- lower_new_dir_dentry = dget_parent(lower_new_dentry);
- lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
- rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
- lower_old_mnt, lower_new_dir_dentry->d_inode,
- lower_new_dentry, lower_new_mnt);
+ old_nd.dentry = dget_parent(lower_old_dentry);
+ old_nd.mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
+ new_nd.dentry = dget_parent(lower_new_dentry);
+ new_nd.mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
+ lock_rename(old_nd.dentry, new_nd.dentry);
+ rc = vfs_rename(&old_nd, lower_old_dentry, &new_nd, lower_new_dentry);
if (rc)
goto out_lock;
- fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
+ fsstack_copy_attr_all(new_dir, new_nd.dentry->d_inode, NULL);
if (new_dir != old_dir)
- fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
+ fsstack_copy_attr_all(old_dir, old_nd.dentry->d_inode, NULL);
out_lock:
- unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
+ unlock_rename(old_nd.dentry, new_nd.dentry);
dput(lower_new_dentry->d_parent);
dput(lower_old_dentry->d_parent);
dput(lower_new_dentry);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2384,10 +2384,11 @@ asmlinkage long sys_link(const char __us
* ->i_mutex on parents, which works but leads to some truely excessive
* locking].
*/
-static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
- struct vfsmount *old_mnt, struct inode *new_dir,
- struct dentry *new_dentry, struct vfsmount *new_mnt)
+static int vfs_rename_dir(struct nameidata2 *old_nd, struct dentry *old_dentry,
+ struct nameidata2 *new_nd, struct dentry *new_dentry)
{
+ struct inode *old_dir = old_nd->dentry->d_inode;
+ struct inode *new_dir = new_nd->dentry->d_inode;
int error = 0;
struct inode *target;
@@ -2396,13 +2397,13 @@ static int vfs_rename_dir(struct inode *
* we'll need to flip '..'.
*/
if (new_dir != old_dir) {
- error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
+ error = permission(old_dentry->d_inode, MAY_WRITE, old_nd);
if (error)
return error;
}
- error = security_inode_rename(old_dir, old_dentry, old_mnt,
- new_dir, new_dentry, new_mnt);
+ error = security_inode_rename(old_dir, old_dentry, old_nd->mnt,
+ new_dir, new_dentry, new_nd->mnt);
if (error)
return error;
@@ -2429,15 +2430,18 @@ static int vfs_rename_dir(struct inode *
return error;
}
-static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
- struct vfsmount *old_mnt, struct inode *new_dir,
- struct dentry *new_dentry, struct vfsmount *new_mnt)
+static int vfs_rename_other(struct nameidata2 *old_nd,
+ struct dentry *old_dentry,
+ struct nameidata2 *new_nd,
+ struct dentry *new_dentry)
{
+ struct inode *old_dir = old_nd->dentry->d_inode;
+ struct inode *new_dir = new_nd->dentry->d_inode;
struct inode *target;
int error;
- error = security_inode_rename(old_dir, old_dentry, old_mnt,
- new_dir, new_dentry, new_mnt);
+ error = security_inode_rename(old_dir, old_dentry, old_nd->mnt,
+ new_dir, new_dentry, new_nd->mnt);
if (error)
return error;
@@ -2459,10 +2463,11 @@ static int vfs_rename_other(struct inode
return error;
}
-int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct vfsmount *old_mnt, struct inode *new_dir,
- struct dentry *new_dentry, struct vfsmount *new_mnt)
+int vfs_rename(struct nameidata2 *old_nd, struct dentry *old_dentry,
+ struct nameidata2 *new_nd, struct dentry *new_dentry)
{
+ struct inode *old_dir = old_nd->dentry->d_inode;
+ struct inode *new_dir = new_nd->dentry->d_inode;
int error;
int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
const char *old_name;
@@ -2475,7 +2480,7 @@ int vfs_rename(struct inode *old_dir, st
return error;
if (!new_dentry->d_inode)
- error = may_create(new_dir, new_dentry, NULL);
+ error = may_create(new_dir, new_dentry, new_nd);
else
error = may_delete(new_dir, new_dentry, is_dir);
if (error)
@@ -2490,11 +2495,10 @@ int vfs_rename(struct inode *old_dir, st
old_name = fsnotify_oldname_init(old_dentry->d_name.name);
if (is_dir)
- error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
- new_dir, new_dentry, new_mnt);
+ error = vfs_rename_dir(old_nd, old_dentry, new_nd, new_dentry);
else
- error = vfs_rename_other(old_dir, old_dentry, old_mnt,
- new_dir, new_dentry, new_mnt);
+ error = vfs_rename_other(old_nd, old_dentry, new_nd,
+ new_dentry);
if (!error) {
const char *new_name = old_dentry->d_name.name;
fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
@@ -2566,8 +2570,7 @@ static int do_rename(int olddfd, const c
if (new_dentry == trap)
goto exit5;
- error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.mnt,
- new_dir->d_inode, new_dentry, newnd.mnt);
+ error = vfs_rename(ND2(&oldnd), old_dentry, ND2(&newnd), new_dentry);
exit5:
dput(new_dentry);
exit4:
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1584,7 +1584,9 @@ __be32
nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
struct svc_fh *tfhp, char *tname, int tlen)
{
- struct dentry *fdentry, *tdentry, *odentry, *ndentry, *trap;
+ struct nameidata2 old_nd = {};
+ struct nameidata2 new_nd = {};
+ struct dentry *odentry, *ndentry, *trap;
struct inode *fdir, *tdir;
__be32 err;
int host_err;
@@ -1596,11 +1598,13 @@ nfsd_rename(struct svc_rqst *rqstp, stru
if (err)
goto out;
- fdentry = ffhp->fh_dentry;
- fdir = fdentry->d_inode;
-
- tdentry = tfhp->fh_dentry;
- tdir = tdentry->d_inode;
+ old_nd.dentry = ffhp->fh_dentry;
+ old_nd.mnt = ffhp->fh_export->ex_mnt;
+ fdir = old_nd.dentry->d_inode;
+
+ new_nd.dentry = tfhp->fh_dentry;
+ new_nd.mnt = tfhp->fh_export->ex_mnt;
+ tdir = new_nd.dentry->d_inode;
err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
if (ffhp->fh_export != tfhp->fh_export)
@@ -1612,12 +1616,12 @@ nfsd_rename(struct svc_rqst *rqstp, stru
/* cannot use fh_lock as we need deadlock protective ordering
* so do it by hand */
- trap = lock_rename(tdentry, fdentry);
+ trap = lock_rename(new_nd.dentry, old_nd.dentry);
ffhp->fh_locked = tfhp->fh_locked = 1;
fill_pre_wcc(ffhp);
fill_pre_wcc(tfhp);
- odentry = lookup_one_len(fname, fdentry, flen);
+ odentry = lookup_one_len(fname, old_nd.dentry, flen);
host_err = PTR_ERR(odentry);
if (IS_ERR(odentry))
goto out_nfserr;
@@ -1629,7 +1633,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
if (odentry == trap)
goto out_dput_old;
- ndentry = lookup_one_len(tname, tdentry, tlen);
+ ndentry = lookup_one_len(tname, new_nd.dentry, tlen);
host_err = PTR_ERR(ndentry);
if (IS_ERR(ndentry))
goto out_dput_old;
@@ -1644,12 +1648,11 @@ nfsd_rename(struct svc_rqst *rqstp, stru
host_err = -EPERM;
} else
#endif
- host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_mnt,
- tdir, ndentry, tfhp->fh_export->ex_mnt);
+ host_err = vfs_rename(&old_nd, odentry, &new_nd, ndentry);
if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
- host_err = nfsd_sync_dir(tdentry);
+ host_err = nfsd_sync_dir(new_nd.dentry);
if (!host_err)
- host_err = nfsd_sync_dir(fdentry);
+ host_err = nfsd_sync_dir(old_nd.dentry);
}
out_dput_new:
@@ -1665,7 +1668,7 @@ nfsd_rename(struct svc_rqst *rqstp, stru
*/
fill_post_wcc(ffhp);
fill_post_wcc(tfhp);
- unlock_rename(tdentry, fdentry);
+ unlock_rename(new_nd.dentry, old_nd.dentry);
ffhp->fh_locked = tfhp->fh_locked = 0;
out:
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -990,7 +990,7 @@ extern int vfs_symlink(struct nameidata2
extern int vfs_link(struct nameidata2 *, struct dentry *, struct nameidata2 *);
extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
-extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
+extern int vfs_rename(struct nameidata2 *, struct dentry *, struct nameidata2 *, struct dentry *);
/*
* VFS dentry helper functions.

View File

@@ -0,0 +1,181 @@
---
fs/ecryptfs/inode.c | 15 +++++++--------
fs/namei.c | 7 ++++---
fs/nfsd/nfs4recover.c | 6 +++++-
fs/nfsd/vfs.c | 14 ++++++++------
fs/reiserfs/xattr.c | 11 +++++++----
include/linux/fs.h | 2 +-
6 files changed, 32 insertions(+), 23 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -534,23 +534,22 @@ out:
static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
{
+ struct nameidata2 nd = {};
struct dentry *lower_dentry;
- struct vfsmount *lower_mnt;
- struct dentry *lower_dir_dentry;
int rc;
lower_dentry = ecryptfs_dentry_to_lower(dentry);
- lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
dget(dentry);
- lower_dir_dentry = lock_parent(lower_dentry);
+ nd.dentry = lock_parent(lower_dentry);
+ nd.mnt = ecryptfs_dentry_to_lower_mnt(dentry);
dget(lower_dentry);
- rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt);
+ rc = vfs_rmdir(&nd, lower_dentry);
dput(lower_dentry);
if (!rc)
d_delete(lower_dentry);
- fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
- dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
- unlock_dir(lower_dir_dentry);
+ fsstack_copy_attr_times(dir, nd.dentry->d_inode);
+ dir->i_nlink = nd.dentry->d_inode->i_nlink;
+ unlock_dir(nd.dentry);
if (!rc)
d_drop(dentry);
dput(dentry);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2005,8 +2005,9 @@ void dentry_unhash(struct dentry *dentry
spin_unlock(&dcache_lock);
}
-int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt)
+int vfs_rmdir(struct nameidata2 *nd, struct dentry *dentry)
{
+ struct inode *dir = nd->dentry->d_inode;
int error = may_delete(dir, dentry, 1);
if (error)
@@ -2015,7 +2016,7 @@ int vfs_rmdir(struct inode *dir, struct
if (!dir->i_op || !dir->i_op->rmdir)
return -EPERM;
- error = security_inode_rmdir(dir, dentry, mnt);
+ error = security_inode_rmdir(dir, dentry, nd->mnt);
if (error)
return error;
@@ -2070,7 +2071,7 @@ static long do_rmdir(int dfd, const char
error = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto exit2;
- error = vfs_rmdir(nd.dentry->d_inode, dentry, nd.mnt);
+ error = vfs_rmdir(ND2(&nd), dentry);
dput(dentry);
exit2:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -268,6 +268,10 @@ nfsd4_remove_clid_file(struct dentry *di
static int
nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
{
+ struct nameidata2 nd = {
+ .dentry = dir,
+ .mnt = rec_dir.mnt,
+ };
int status;
/* For now this directory should already be empty, but we empty it of
@@ -275,7 +279,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
* a kernel from the future.... */
nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
- status = vfs_rmdir(dir->d_inode, dentry, rec_dir.mnt);
+ status = vfs_rmdir(&nd, dentry);
mutex_unlock(&dir->d_inode->i_mutex);
return status;
}
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1683,7 +1683,8 @@ __be32
nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
char *fname, int flen)
{
- struct dentry *dentry, *rdentry;
+ struct nameidata2 nd = {};
+ struct dentry *rdentry;
struct svc_export *exp;
struct inode *dirp;
__be32 err;
@@ -1697,11 +1698,12 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
goto out;
fh_lock_nested(fhp, I_MUTEX_PARENT);
- dentry = fhp->fh_dentry;
- dirp = dentry->d_inode;
+ nd.dentry = fhp->fh_dentry;
exp = fhp->fh_export;
+ nd.mnt = exp->ex_mnt;
+ dirp = nd.dentry->d_inode;
- rdentry = lookup_one_len(fname, dentry, flen);
+ rdentry = lookup_one_len(fname, nd.dentry, flen);
host_err = PTR_ERR(rdentry);
if (IS_ERR(rdentry))
goto out_nfserr;
@@ -1724,7 +1726,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
#endif
host_err = vfs_unlink(dirp, rdentry, exp->ex_mnt);
} else { /* It's RMDIR */
- host_err = vfs_rmdir(dirp, rdentry, exp->ex_mnt);
+ host_err = vfs_rmdir(&nd, rdentry);
}
dput(rdentry);
@@ -1732,7 +1734,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
if (host_err)
goto out_nfserr;
if (EX_ISSYNC(exp))
- host_err = nfsd_sync_dir(dentry);
+ host_err = nfsd_sync_dir(nd.dentry);
out_nfserr:
err = nfserrno(host_err);
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -785,7 +785,7 @@ reiserfs_delete_xattrs_filler(void *buf,
int reiserfs_delete_xattrs(struct inode *inode)
{
struct file *fp;
- struct dentry *dir, *root;
+ struct dentry *dir;
int err = 0;
/* Skip out, an xattr has no xattrs associated with it */
@@ -821,11 +821,14 @@ int reiserfs_delete_xattrs(struct inode
/* Leftovers besides . and .. -- that's not good. */
if (dir->d_inode->i_nlink <= 2) {
- root = get_xa_root(inode->i_sb);
+ struct nameidata2 nd = {
+ .dentry = get_xa_root(inode->i_sb),
+ /* .mnt = NULL, */
+ };
reiserfs_write_lock_xattrs(inode->i_sb);
- err = vfs_rmdir(root->d_inode, dir, NULL);
+ err = vfs_rmdir(&nd, dir);
reiserfs_write_unlock_xattrs(inode->i_sb);
- dput(root);
+ dput(nd.dentry);
} else {
reiserfs_warning(inode->i_sb,
"Couldn't remove all entries in directory");
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -988,7 +988,7 @@ extern int vfs_mkdir(struct nameidata2 *
extern int vfs_mknod(struct nameidata2 *, struct dentry *, int, dev_t);
extern int vfs_symlink(struct nameidata2 *, struct dentry *, const char *, int);
extern int vfs_link(struct nameidata2 *, struct dentry *, struct nameidata2 *);
-extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
+extern int vfs_rmdir(struct nameidata2 *, struct dentry *);
extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_rename(struct nameidata2 *, struct dentry *, struct nameidata2 *, struct dentry *);

View File

@@ -0,0 +1,155 @@
---
fs/ecryptfs/inode.c | 16 +++++++---------
fs/namei.c | 10 +++++-----
fs/nfsd/vfs.c | 18 +++++++++---------
include/linux/fs.h | 2 +-
4 files changed, 22 insertions(+), 24 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -474,10 +474,9 @@ out_unlock:
static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname)
{
+ struct nameidata2 nd = {};
int rc;
struct dentry *lower_dentry;
- struct vfsmount *lower_mnt;
- struct dentry *lower_dir_dentry;
umode_t mode;
char *encoded_symname;
unsigned int encoded_symlen;
@@ -485,8 +484,8 @@ static int ecryptfs_symlink(struct inode
lower_dentry = ecryptfs_dentry_to_lower(dentry);
dget(lower_dentry);
- lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
- lower_dir_dentry = lock_parent(lower_dentry);
+ nd.mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+ nd.dentry = lock_parent(lower_dentry);
mode = S_IALLUGO;
encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
strlen(symname),
@@ -495,18 +494,17 @@ static int ecryptfs_symlink(struct inode
rc = encoded_symlen;
goto out_lock;
}
- rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
- encoded_symname, mode);
+ rc = vfs_symlink(&nd, lower_dentry, encoded_symname, mode);
kfree(encoded_symname);
if (rc || !lower_dentry->d_inode)
goto out_lock;
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
if (rc)
goto out_lock;
- fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
- fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+ fsstack_copy_attr_times(dir, nd.dentry->d_inode);
+ fsstack_copy_inode_size(dir, nd.dentry->d_inode);
out_lock:
- unlock_dir(lower_dir_dentry);
+ unlock_dir(nd.dentry);
dput(lower_dentry);
if (!dentry->d_inode)
d_drop(dentry);
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2186,10 +2186,11 @@ asmlinkage long sys_unlink(const char __
return do_unlinkat(AT_FDCWD, pathname);
}
-int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
+int vfs_symlink(struct nameidata2 *nd, struct dentry *dentry,
const char *oldname, int mode)
{
- int error = may_create(dir, dentry, NULL);
+ struct inode *dir = nd->dentry->d_inode;
+ int error = may_create(dir, dentry, nd);
if (error)
return error;
@@ -2197,7 +2198,7 @@ int vfs_symlink(struct inode *dir, struc
if (!dir->i_op || !dir->i_op->symlink)
return -EPERM;
- error = security_inode_symlink(dir, dentry, mnt, oldname);
+ error = security_inode_symlink(dir, dentry, nd->mnt, oldname);
if (error)
return error;
@@ -2233,8 +2234,7 @@ asmlinkage long sys_symlinkat(const char
if (IS_ERR(dentry))
goto out_unlock;
- error = vfs_symlink(nd.dentry->d_inode, dentry, nd.mnt, from,
- S_IALLUGO);
+ error = vfs_symlink(ND2(&nd), dentry, from, S_IALLUGO);
dput(dentry);
out_unlock:
mutex_unlock(&nd.dentry->d_inode->i_mutex);
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1447,7 +1447,8 @@ nfsd_symlink(struct svc_rqst *rqstp, str
struct svc_fh *resfhp,
struct iattr *iap)
{
- struct dentry *dentry, *dnew;
+ struct nameidata2 nd = {};
+ struct dentry *dnew;
struct svc_export *exp;
__be32 err, cerr;
int host_err;
@@ -1464,8 +1465,10 @@ nfsd_symlink(struct svc_rqst *rqstp, str
if (err)
goto out;
fh_lock(fhp);
- dentry = fhp->fh_dentry;
- dnew = lookup_one_len(fname, dentry, flen);
+ nd.dentry = fhp->fh_dentry;
+ exp = fhp->fh_export;
+ nd.mnt = exp->ex_mnt;
+ dnew = lookup_one_len(fname, nd.dentry, flen);
host_err = PTR_ERR(dnew);
if (IS_ERR(dnew))
goto out_nfserr;
@@ -1475,7 +1478,6 @@ nfsd_symlink(struct svc_rqst *rqstp, str
if (iap && (iap->ia_valid & ATTR_MODE))
mode = iap->ia_mode & S_IALLUGO;
- exp = fhp->fh_export;
if (unlikely(path[plen] != 0)) {
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
if (path_alloced == NULL)
@@ -1483,17 +1485,15 @@ nfsd_symlink(struct svc_rqst *rqstp, str
else {
strncpy(path_alloced, path, plen);
path_alloced[plen] = 0;
- host_err = vfs_symlink(dentry->d_inode, dnew,
- exp->ex_mnt, path_alloced, mode);
+ host_err = vfs_symlink(&nd, dnew, path_alloced, mode);
kfree(path_alloced);
}
} else
- host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_mnt, path,
- mode);
+ host_err = vfs_symlink(&nd, dnew, path, mode);
if (!host_err) {
if (EX_ISSYNC(exp))
- host_err = nfsd_sync_dir(dentry);
+ host_err = nfsd_sync_dir(nd.dentry);
}
err = nfserrno(host_err);
fh_unlock(fhp);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -986,7 +986,7 @@ extern int vfs_permission(struct nameida
extern int vfs_create(struct nameidata2 *, struct dentry *, int);
extern int vfs_mkdir(struct nameidata2 *, struct dentry *, int);
extern int vfs_mknod(struct nameidata2 *, struct dentry *, int, dev_t);
-extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int);
+extern int vfs_symlink(struct nameidata2 *, struct dentry *, const char *, int);
extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);

View File

@@ -0,0 +1,151 @@
---
fs/ecryptfs/inode.c | 18 ++++++------------
fs/namei.c | 7 ++++---
fs/nfsd/nfs4recover.c | 6 +++++-
fs/nfsd/vfs.c | 2 +-
include/linux/fs.h | 2 +-
ipc/mqueue.c | 6 +++++-
6 files changed, 22 insertions(+), 19 deletions(-)
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -42,12 +42,6 @@ static struct dentry *lock_parent(struct
return dir;
}
-static void unlock_parent(struct dentry *dentry)
-{
- mutex_unlock(&(dentry->d_parent->d_inode->i_mutex));
- dput(dentry->d_parent);
-}
-
static void unlock_dir(struct dentry *dir)
{
mutex_unlock(&dir->d_inode->i_mutex);
@@ -447,23 +441,23 @@ out_lock:
static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
{
+ struct nameidata2 nd = {};
int rc = 0;
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
- struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
- struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
- lock_parent(lower_dentry);
- rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt);
+ nd.dentry = lock_parent(lower_dentry);
+ nd.mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+ rc = vfs_unlink(&nd, lower_dentry);
if (rc) {
printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
goto out_unlock;
}
- fsstack_copy_attr_times(dir, lower_dir_inode);
+ fsstack_copy_attr_times(dir, nd.dentry->d_inode);
dentry->d_inode->i_nlink =
ecryptfs_inode_to_lower(dentry->d_inode)->i_nlink;
dentry->d_inode->i_ctime = dir->i_ctime;
out_unlock:
- unlock_parent(lower_dentry);
+ unlock_dir(nd.dentry);
return rc;
}
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2087,8 +2087,9 @@ asmlinkage long sys_rmdir(const char __u
return do_rmdir(AT_FDCWD, pathname);
}
-int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt)
+int vfs_unlink(struct nameidata2 *nd, struct dentry *dentry)
{
+ struct inode *dir = nd->dentry->d_inode;
int error = may_delete(dir, dentry, 0);
if (error)
@@ -2103,7 +2104,7 @@ int vfs_unlink(struct inode *dir, struct
if (d_mountpoint(dentry))
error = -EBUSY;
else {
- error = security_inode_unlink(dir, dentry, mnt);
+ error = security_inode_unlink(dir, dentry, nd->mnt);
if (!error)
error = dir->i_op->unlink(dir, dentry);
}
@@ -2151,7 +2152,7 @@ static long do_unlinkat(int dfd, const c
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);
- error = vfs_unlink(nd.dentry->d_inode, dentry, nd.mnt);
+ error = vfs_unlink(ND2(&nd), dentry);
exit2:
dput(dentry);
}
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -253,6 +253,10 @@ out:
static int
nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
{
+ struct nameidata2 nd = {
+ .dentry = dir,
+ .mnt = rec_dir.mnt,
+ };
int status;
if (!S_ISREG(dir->d_inode->i_mode)) {
@@ -260,7 +264,7 @@ nfsd4_remove_clid_file(struct dentry *di
return -EINVAL;
}
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
- status = vfs_unlink(dir->d_inode, dentry, rec_dir.mnt);
+ status = vfs_unlink(&nd, dentry);
mutex_unlock(&dir->d_inode->i_mutex);
return status;
}
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1724,7 +1724,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
host_err = -EPERM;
} else
#endif
- host_err = vfs_unlink(dirp, rdentry, exp->ex_mnt);
+ host_err = vfs_unlink(&nd, rdentry);
} else { /* It's RMDIR */
host_err = vfs_rmdir(&nd, rdentry);
}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -989,7 +989,7 @@ extern int vfs_mknod(struct nameidata2 *
extern int vfs_symlink(struct nameidata2 *, struct dentry *, const char *, int);
extern int vfs_link(struct nameidata2 *, struct dentry *, struct nameidata2 *);
extern int vfs_rmdir(struct nameidata2 *, struct dentry *);
-extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
+extern int vfs_unlink(struct nameidata2 *, struct dentry *);
extern int vfs_rename(struct nameidata2 *, struct dentry *, struct nameidata2 *, struct dentry *);
/*
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -725,6 +725,10 @@ out_putname:
asmlinkage long sys_mq_unlink(const char __user *u_name)
{
+ struct nameidata2 nd = {
+ .dentry = mqueue_mnt->mnt_root,
+ /* Not a mounted filesystem, so set .mnt to NULL. */
+ };
int err;
char *name;
struct dentry *dentry;
@@ -751,7 +755,7 @@ asmlinkage long sys_mq_unlink(const char
if (inode)
atomic_inc(&inode->i_count);
- err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt);
+ err = vfs_unlink(&nd, dentry);
out_err:
dput(dentry);