apparmor/kernel-patches/for-mainline/vfs_unlink-args.diff

159 lines
4.7 KiB
Diff

From: Andreas Gruenbacher <agruen@suse.de>
Subject: Pass nameidata2 to vfs_unlink()
Instead of passing independent dentry and vfsmount parameters, use a
nameidata2.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
---
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
@@ -2128,8 +2128,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)
@@ -2144,7 +2145,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);
}
@@ -2192,7 +2193,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
@@ -994,7 +994,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);