drivers/base/devtmpfs.c | 8 +- drivers/staging/lustre/lustre/llite/file.c | 6 +- .../staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/lvfs/lvfs_linux.c | 4 +- fs/afs/internal.h | 2 +- fs/afs/security.c | 2 +- fs/bad_inode.c | 2 +- fs/btrfs/inode.c | 2 +- fs/btrfs/ioctl.c | 16 +-- fs/cachefiles/namei.c | 11 +- fs/ceph/inode.c | 2 +- fs/ceph/super.h | 2 +- fs/cifs/cifsfs.c | 2 +- fs/coda/coda_linux.h | 2 +- fs/coda/dir.c | 2 +- fs/coda/pioctl.c | 4 +- fs/ecryptfs/inode.c | 26 ++--- fs/exec.c | 2 +- fs/fuse/dir.c | 2 +- fs/gfs2/inode.c | 11 +- fs/hostfs/hostfs_kern.c | 2 +- fs/internal.h | 1 - fs/kernfs/inode.c | 2 +- fs/kernfs/kernfs-internal.h | 2 +- fs/namei.c | 126 ++++++++++++--------- fs/ncpfs/ioctl.c | 6 +- fs/nfs/dir.c | 2 +- fs/nfsd/nfs4recover.c | 6 +- fs/nfsd/nfsfh.c | 2 +- fs/nfsd/vfs.c | 32 ++---- fs/nilfs2/inode.c | 2 +- fs/nilfs2/nilfs.h | 2 +- fs/notify/fanotify/fanotify_user.c | 2 +- fs/notify/inotify/inotify_user.c | 2 +- fs/ocfs2/file.c | 2 +- fs/ocfs2/file.h | 2 +- fs/ocfs2/refcounttree.c | 15 ++- fs/open.c | 14 ++- fs/proc/base.c | 2 +- fs/proc/fd.c | 2 +- fs/proc/fd.h | 2 +- fs/proc/proc_sysctl.c | 2 +- fs/reiserfs/xattr.c | 2 +- fs/reiserfs/xattr.h | 2 +- fs/udf/file.c | 2 +- fs/utimes.c | 2 +- fs/xattr.c | 12 +- include/linux/fs.h | 20 ++-- include/linux/nfs_fs.h | 2 +- ipc/mqueue.c | 10 +- kernel/sys.c | 2 +- mm/memcontrol.c | 2 +- net/unix/af_unix.c | 4 +- virt/kvm/assigned-dev.c | 2 +- 54 files changed, 210 insertions(+), 192 deletions(-) diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 25798db14553..fb81de9a78a3 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -157,7 +157,7 @@ static int dev_mkdir(const char *name, umode_t mode) if (IS_ERR(dentry)) return PTR_ERR(dentry); - err = vfs_mkdir(path.dentry->d_inode, dentry, mode); + err = vfs_mkdir(path.dentry, dentry, mode); if (!err) /* mark as kernel-created inode */ dentry->d_inode->i_private = &thread; @@ -207,7 +207,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid, if (IS_ERR(dentry)) return PTR_ERR(dentry); - err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt); + err = vfs_mknod(path.dentry, dentry, mode, dev->devt); if (!err) { struct iattr newattrs; @@ -237,7 +237,7 @@ static int dev_rmdir(const char *name) return PTR_ERR(dentry); if (dentry->d_inode) { if (dentry->d_inode->i_private == &thread) - err = vfs_rmdir(parent.dentry->d_inode, dentry); + err = vfs_rmdir(parent.dentry, dentry); else err = -EPERM; } else { @@ -324,7 +324,7 @@ static int handle_remove(const char *nodename, struct device *dev) mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs, NULL); mutex_unlock(&dentry->d_inode->i_mutex); - err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); + err = vfs_unlink(parent.dentry, dentry, NULL); if (!err || err == -ENOENT) deleted = 1; } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c12821aedc2f..7a2e5f9b2e1d 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1951,8 +1951,8 @@ static int ll_swap_layouts(struct file *file1, struct file *file2, if (!S_ISREG(llss->inode2->i_mode)) GOTO(free, rc = -EINVAL); - if (inode_permission(llss->inode1, MAY_WRITE) || - inode_permission(llss->inode2, MAY_WRITE)) + if (inode_permission(file1->f_dentry, llss->inode1, MAY_WRITE) || + inode_permission(file2->f_dentry, llss->inode2, MAY_WRITE)) GOTO(free, rc = -EPERM); if (llss->inode2->i_sb != llss->inode1->i_sb) @@ -3079,7 +3079,7 @@ struct posix_acl * ll_get_acl(struct inode *inode, int type) } -int ll_inode_permission(struct inode *inode, int mask) +int ll_inode_permission(struct dentry *dentry, struct inode *inode, int mask) { int rc = 0; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 7ee5c02783f9..b767e484dfe9 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -799,7 +799,7 @@ int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat); struct ll_file_data *ll_file_data_get(void); struct posix_acl * ll_get_acl(struct inode *inode, int type); -int ll_inode_permission(struct inode *inode, int mask); +int ll_inode_permission(struct dentry *dentry, struct inode *inode, int mask); int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, int flags, struct lov_user_md *lum, diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index 428ffd8c37b7..c4aa260def19 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -222,8 +222,8 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt, if (IS_ERR(dchild_new)) GOTO(put_old, err = PTR_ERR(dchild_new)); - err = ll_vfs_rename(dir->d_inode, dchild_old, mnt, - dir->d_inode, dchild_new, mnt, NULL); + err = ll_vfs_rename(dir, dchild_old, mnt, + dir, dchild_new, mnt, NULL); dput(dchild_new); put_old: diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 6621f8008122..63a03b555fd3 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -626,7 +626,7 @@ extern void afs_clear_permits(struct afs_vnode *); extern void afs_cache_permit(struct afs_vnode *, struct key *, long); extern void afs_zap_permits(struct rcu_head *); extern struct key *afs_request_key(struct afs_cell *); -extern int afs_permission(struct inode *, int); +extern int afs_permission(struct dentry *, struct inode *, int); /* * server.c diff --git a/fs/afs/security.c b/fs/afs/security.c index 8d010422dc89..cc34a41bab04 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c @@ -285,7 +285,7 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key, * - AFS ACLs are attached to directories only, and a file is controlled by its * parent directory's ACL */ -int afs_permission(struct inode *inode, int mask) +int afs_permission(struct dentry *dentry, struct inode *inode, int mask) { struct afs_vnode *vnode = AFS_FS_I(inode); afs_access_t uninitialized_var(access); diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 7c93953030fb..cf6181b12add 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -230,7 +230,7 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer, return -EIO; } -static int bad_inode_permission(struct inode *inode, int mask) +static int bad_inode_permission(struct dentry *dentry, struct inode *inode, int mask) { return -EIO; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5c4ab9c18940..546a6872e841 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8817,7 +8817,7 @@ static int btrfs_set_page_dirty(struct page *page) return __set_page_dirty_nobuffers(page); } -static int btrfs_permission(struct inode *inode, int mask) +static int btrfs_permission(struct dentry *dentry, struct inode *inode, int mask) { struct btrfs_root *root = BTRFS_I(inode)->root; umode_t mode = inode->i_mode; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b0134892dc70..d07fdc9b8c9e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -716,9 +716,10 @@ static inline int btrfs_check_sticky(struct inode *dir, struct inode *inode) * nfs_async_unlink(). */ -static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir) +static int btrfs_may_delete(struct dentry *parent, struct dentry *victim, int isdir) { int error; + struct inode *dir = parent->d_inode; if (!victim->d_inode) return -ENOENT; @@ -726,7 +727,7 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir) BUG_ON(victim->d_parent->d_inode != dir); audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); - error = inode_permission(dir, MAY_WRITE | MAY_EXEC); + error = inode_permission(parent, dir, MAY_WRITE | MAY_EXEC); if (error) return error; if (IS_APPEND(dir)) @@ -750,13 +751,14 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir) } /* copy of may_create in fs/namei.c() */ -static inline int btrfs_may_create(struct inode *dir, struct dentry *child) +static inline int btrfs_may_create(struct dentry *parent, struct dentry *child) { + struct inode *dir = parent->d_inode; if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) return -ENOENT; - return inode_permission(dir, MAY_WRITE | MAY_EXEC); + return inode_permission(parent, dir, MAY_WRITE | MAY_EXEC); } /* @@ -787,7 +789,7 @@ static noinline int btrfs_mksubvol(struct path *parent, if (dentry->d_inode) goto out_dput; - error = btrfs_may_create(dir, dentry); + error = btrfs_may_create(parent->dentry, dentry); if (error) goto out_dput; @@ -2213,13 +2215,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, if (root == dest) goto out_dput; - err = inode_permission(inode, MAY_WRITE | MAY_EXEC); + err = inode_permission(dentry, inode, MAY_WRITE | MAY_EXEC); if (err) goto out_dput; } /* check if subvolume may be deleted by a user */ - err = btrfs_may_delete(dir, dentry, 1); + err = btrfs_may_delete(parent, dentry, 1); if (err) goto out_dput; diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index ca65f39dc8dc..c4b6712909e3 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -294,7 +294,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, if (ret < 0) { cachefiles_io_error(cache, "Unlink security error"); } else { - ret = vfs_unlink(dir->d_inode, rep, NULL); + ret = vfs_unlink(dir, rep, NULL); if (preemptive) cachefiles_mark_object_buried(cache, rep); @@ -395,8 +395,7 @@ try_again: if (ret < 0) { cachefiles_io_error(cache, "Rename security error %d", ret); } else { - ret = vfs_rename(dir->d_inode, rep, - cache->graveyard->d_inode, grave, NULL); + ret = vfs_rename(dir, rep, cache->graveyard, grave, NULL); if (ret != 0 && ret != -ENOMEM) cachefiles_io_error(cache, "Rename failed with error %d", ret); @@ -537,7 +536,7 @@ lookup_again: if (ret < 0) goto create_error; start = jiffies; - ret = vfs_mkdir(dir->d_inode, next, 0); + ret = vfs_mkdir(dir, next, 0); cachefiles_hist(cachefiles_mkdir_histogram, start); if (ret < 0) goto create_error; @@ -566,7 +565,7 @@ lookup_again: if (ret < 0) goto create_error; start = jiffies; - ret = vfs_create(dir->d_inode, next, S_IFREG, true); + ret = vfs_create(dir, next, S_IFREG, true); cachefiles_hist(cachefiles_create_histogram, start); if (ret < 0) goto create_error; @@ -755,7 +754,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, ret = security_path_mkdir(&path, subdir, 0700); if (ret < 0) goto mkdir_error; - ret = vfs_mkdir(dir->d_inode, subdir, 0700); + ret = vfs_mkdir(dir, subdir, 0700); if (ret < 0) goto mkdir_error; diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 32d519d8a2e2..04db1774cb2d 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1875,7 +1875,7 @@ int ceph_do_getattr(struct inode *inode, int mask) * Check inode permissions. We verify we have a valid value for * the AUTH cap, then call the generic handler. */ -int ceph_permission(struct inode *inode, int mask) +int ceph_permission(struct dentry *dentry, struct inode *inode, int mask) { int err; diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 19793b56d0a7..6215dc38b676 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -716,7 +716,7 @@ extern void ceph_queue_invalidate(struct inode *inode); extern void ceph_queue_writeback(struct inode *inode); extern int ceph_do_getattr(struct inode *inode, int mask); -extern int ceph_permission(struct inode *inode, int mask); +extern int ceph_permission(struct dentry *, struct inode *inode, int mask); extern int ceph_setattr(struct dentry *dentry, struct iattr *attr); extern int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 849f6132b327..ca304878ef7b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -211,7 +211,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) return 0; } -static int cifs_permission(struct inode *inode, int mask) +static int cifs_permission(struct dentry *dentry, struct inode *inode, int mask) { struct cifs_sb_info *cifs_sb; diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h index e7550cb9fb74..be666ad53717 100644 --- a/fs/coda/coda_linux.h +++ b/fs/coda/coda_linux.h @@ -39,7 +39,7 @@ extern const struct file_operations coda_ioctl_operations; /* operations shared over more than one file */ int coda_open(struct inode *i, struct file *f); int coda_release(struct inode *i, struct file *f); -int coda_permission(struct inode *inode, int mask); +int coda_permission(struct dentry *dentry, struct inode *inode, int mask); int coda_revalidate_inode(struct inode *); int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); int coda_setattr(struct dentry *, struct iattr *); diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 5efbb5ee0adc..c3ce50ad725e 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -128,7 +128,7 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsig } -int coda_permission(struct inode *inode, int mask) +int coda_permission(struct dentry *dentry, struct inode *inode, int mask) { int error; diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 3f5de96bbb58..2b760b97fe9c 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -24,7 +24,7 @@ #include "coda_linux.h" /* pioctl ops */ -static int coda_ioctl_permission(struct inode *inode, int mask); +static int coda_ioctl_permission(struct dentry *dentry, struct inode *inode, int mask); static long coda_pioctl(struct file *filp, unsigned int cmd, unsigned long user_data); @@ -41,7 +41,7 @@ const struct file_operations coda_ioctl_operations = { }; /* the coda pioctl inode ops */ -static int coda_ioctl_permission(struct inode *inode, int mask) +static int coda_ioctl_permission(struct dentry *dentry, struct inode *inode, int mask) { return (mask & MAY_EXEC) ? -EACCES : 0; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index b167ca48b8ee..f2dc516c626a 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -153,7 +153,7 @@ static int ecryptfs_do_unlink(struct inode *dir, struct dentry *dentry, dget(lower_dentry); lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL); + rc = vfs_unlink(lower_dir_dentry, lower_dentry, NULL); if (rc) { printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); goto out_unlock; @@ -198,7 +198,7 @@ ecryptfs_do_create(struct inode *directory_inode, inode = ERR_CAST(lower_dir_dentry); goto out; } - rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true); + rc = vfs_create(lower_dir_dentry, lower_dentry, mode, true); if (rc) { printk(KERN_ERR "%s: Failure to create dentry in lower fs; " "rc = [%d]\n", __func__, rc); @@ -208,7 +208,7 @@ ecryptfs_do_create(struct inode *directory_inode, inode = __ecryptfs_get_inode(lower_dentry->d_inode, directory_inode->i_sb); if (IS_ERR(inode)) { - vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, NULL); + vfs_unlink(lower_dir_dentry, lower_dentry, NULL); goto out_lock; } fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode); @@ -474,8 +474,7 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, dget(lower_old_dentry); dget(lower_new_dentry); lower_dir_dentry = lock_parent(lower_new_dentry); - rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, - lower_new_dentry, NULL); + rc = vfs_link(lower_old_dentry, lower_dir_dentry, lower_new_dentry, NULL); if (rc || !lower_new_dentry->d_inode) goto out_lock; rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb); @@ -520,8 +519,7 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry, strlen(symname)); if (rc) goto out_lock; - rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, - encoded_symname); + rc = vfs_symlink(lower_dir_dentry, lower_dentry, encoded_symname); kfree(encoded_symname); if (rc || !lower_dentry->d_inode) goto out_lock; @@ -546,7 +544,7 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode); + rc = vfs_mkdir(lower_dir_dentry, lower_dentry, mode); if (rc || !lower_dentry->d_inode) goto out; rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); @@ -572,7 +570,7 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) dget(dentry); lower_dir_dentry = lock_parent(lower_dentry); dget(lower_dentry); - rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); + rc = vfs_rmdir(lower_dir_dentry, lower_dentry); dput(lower_dentry); if (!rc && dentry->d_inode) clear_nlink(dentry->d_inode); @@ -594,7 +592,7 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev lower_dentry = ecryptfs_dentry_to_lower(dentry); lower_dir_dentry = lock_parent(lower_dentry); - rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev); + rc = vfs_mknod(lower_dir_dentry, lower_dentry, mode, dev); if (rc || !lower_dentry->d_inode) goto out; rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb); @@ -639,8 +637,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry, rc = -ENOTEMPTY; goto out_lock; } - rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry, - lower_new_dir_dentry->d_inode, lower_new_dentry, + rc = vfs_rename(lower_old_dir_dentry, lower_old_dentry, + lower_new_dir_dentry, lower_new_dentry, NULL); if (rc) goto out_lock; @@ -884,9 +882,9 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) } static int -ecryptfs_permission(struct inode *inode, int mask) +ecryptfs_permission(struct dentry *dentry, struct inode *inode, int mask) { - return inode_permission(ecryptfs_inode_to_lower(inode), mask); + return inode_permission(ecryptfs_dentry_to_lower(dentry), ecryptfs_inode_to_lower(inode), mask); } /** diff --git a/fs/exec.c b/fs/exec.c index e1529b4c79b1..3d86968c5ffb 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1100,7 +1100,7 @@ EXPORT_SYMBOL(flush_old_exec); void would_dump(struct linux_binprm *bprm, struct file *file) { - if (inode_permission(file_inode(file), MAY_READ) < 0) + if (inode_permission(file->f_path.dentry, file_inode(file), MAY_READ) < 0) bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; } EXPORT_SYMBOL(would_dump); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 1d1292c581c3..dbb7ae00e66b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1095,7 +1095,7 @@ static int fuse_perm_getattr(struct inode *inode, int mask) * access request is sent. Execute permission is still checked * locally based on file mode. */ -static int fuse_permission(struct inode *inode, int mask) +static int fuse_permission(struct dentry *dentry, struct inode *inode, int mask) { struct fuse_conn *fc = get_fuse_conn(inode); bool refreshed = false; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 5c524180c98e..79d162029cae 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1890,8 +1890,13 @@ out: return ret; } +static int gfs2_vfs_permission(struct dentry *dentry, struct inode *inode, int mask) +{ + return gfs2_permission(inode, mask); +} + const struct inode_operations gfs2_file_iops = { - .permission = gfs2_permission, + .permission = gfs2_vfs_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, .setxattr = gfs2_setxattr, @@ -1913,7 +1918,7 @@ const struct inode_operations gfs2_dir_iops = { .rmdir = gfs2_unlink, .mknod = gfs2_mknod, .rename = gfs2_rename, - .permission = gfs2_permission, + .permission = gfs2_vfs_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, .setxattr = gfs2_setxattr, @@ -1930,7 +1935,7 @@ const struct inode_operations gfs2_symlink_iops = { .readlink = generic_readlink, .follow_link = gfs2_follow_link, .put_link = kfree_put_link, - .permission = gfs2_permission, + .permission = gfs2_vfs_permission, .setattr = gfs2_setattr, .getattr = gfs2_getattr, .setxattr = gfs2_setxattr, diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index fe649d325b1f..ef1573189fd7 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -759,7 +759,7 @@ static int hostfs_rename(struct inode *from_ino, struct dentry *from, return err; } -static int hostfs_permission(struct inode *ino, int desired) +static int hostfs_permission(struct dentry *dentry, struct inode *ino, int desired) { char *name; int r = 0, w = 0, x = 0, err; diff --git a/fs/internal.h b/fs/internal.h index 465742407466..52108c8f3919 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -42,7 +42,6 @@ extern void __init chrdev_init(void); /* * namei.c */ -extern int __inode_permission(struct inode *, int); extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *); extern int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *, unsigned int, struct path *); diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index e55126f85bd2..9f084fc16fcf 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -360,7 +360,7 @@ void kernfs_evict_inode(struct inode *inode) kernfs_put(kn); } -int kernfs_iop_permission(struct inode *inode, int mask) +int kernfs_iop_permission(struct dentry *dentry, struct inode *inode, int mask) { struct kernfs_node *kn; diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index eb536b76374a..f41ba12978a9 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -78,7 +78,7 @@ extern struct kmem_cache *kernfs_node_cache; */ struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn); void kernfs_evict_inode(struct inode *inode); -int kernfs_iop_permission(struct inode *inode, int mask); +int kernfs_iop_permission(struct dentry *dentry, struct inode *inode, int mask); int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr); int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); diff --git a/fs/namei.c b/fs/namei.c index d580df2e6804..a885b9322637 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -335,11 +335,11 @@ int generic_permission(struct inode *inode, int mask) * flag in inode->i_opflags, that says "this has not special * permission function, use the fast case". */ -static inline int do_inode_permission(struct inode *inode, int mask) +static inline int do_inode_permission(struct dentry *dentry, struct inode *inode, int mask) { if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) { if (likely(inode->i_op->permission)) - return inode->i_op->permission(inode, mask); + return inode->i_op->permission(dentry, inode, mask); /* This gets set once for the inode lifetime */ spin_lock(&inode->i_lock); @@ -361,7 +361,7 @@ static inline int do_inode_permission(struct inode *inode, int mask) * This does not check for a read-only file system. You probably want * inode_permission(). */ -int __inode_permission(struct inode *inode, int mask) +static int __inode_permission(struct dentry *dentry, struct inode *inode, int mask) { int retval; @@ -373,7 +373,7 @@ int __inode_permission(struct inode *inode, int mask) return -EACCES; } - retval = do_inode_permission(inode, mask); + retval = do_inode_permission(dentry, inode, mask); if (retval) return retval; @@ -416,14 +416,14 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) * * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. */ -int inode_permission(struct inode *inode, int mask) +int inode_permission(struct dentry *dentry, struct inode *inode, int mask) { int retval; retval = sb_permission(inode->i_sb, inode, mask); if (retval) return retval; - return __inode_permission(inode, mask); + return __inode_permission(dentry, inode, mask); } /** @@ -729,7 +729,7 @@ static inline int may_follow_link(struct path *link, struct nameidata *nd) * * Otherwise returns true. */ -static bool safe_hardlink_source(struct inode *inode) +static bool safe_hardlink_source(struct dentry *dentry, struct inode *inode) { umode_t mode = inode->i_mode; @@ -746,7 +746,7 @@ static bool safe_hardlink_source(struct inode *inode) return false; /* Hardlinking to unreadable or unwritable sources is dangerous. */ - if (inode_permission(inode, MAY_READ | MAY_WRITE)) + if (inode_permission(dentry, inode, MAY_READ | MAY_WRITE)) return false; return true; @@ -778,7 +778,7 @@ static int may_linkat(struct path *link) /* Source inode owner (or CAP_FOWNER) can hardlink all they like, * otherwise, it must be a safe source. */ - if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(inode) || + if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(link->dentry, inode) || capable(CAP_FOWNER)) return 0; @@ -1442,13 +1442,13 @@ static int lookup_slow(struct nameidata *nd, struct path *path) static inline int may_lookup(struct nameidata *nd) { if (nd->flags & LOOKUP_RCU) { - int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK); + int err = inode_permission(nd->path.dentry, nd->inode, MAY_EXEC|MAY_NOT_BLOCK); if (err != -ECHILD) return err; if (unlazy_walk(nd, NULL)) return -ECHILD; } - return inode_permission(nd->inode, MAY_EXEC); + return inode_permission(nd->path.dentry, nd->inode, MAY_EXEC); } static inline int handle_dots(struct nameidata *nd, int type) @@ -1792,7 +1792,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, if (*name) { if (!d_is_directory(root)) return -ENOTDIR; - retval = inode_permission(inode, MAY_EXEC); + retval = inode_permission(root, inode, MAY_EXEC); if (retval) return retval; } @@ -2078,7 +2078,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) return ERR_PTR(err); } - err = inode_permission(base->d_inode, MAY_EXEC); + err = inode_permission(base, base->d_inode, MAY_EXEC); if (err) return ERR_PTR(err); @@ -2365,8 +2365,9 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) * 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, bool isdir) +static int may_delete(struct dentry *parent, struct dentry *victim, bool isdir) { + struct inode *dir = parent->d_inode; struct inode *inode = victim->d_inode; int error; @@ -2377,7 +2378,7 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) BUG_ON(victim->d_parent->d_inode != dir); audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); - error = inode_permission(dir, MAY_WRITE | MAY_EXEC); + error = inode_permission(parent, dir, MAY_WRITE | MAY_EXEC); if (error) return error; if (IS_APPEND(dir)) @@ -2408,14 +2409,15 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) * 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) +static inline int may_create(struct dentry *parent, struct dentry *child) { + struct inode *dir = parent->d_inode; audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) return -ENOENT; - return inode_permission(dir, MAY_WRITE | MAY_EXEC); + return inode_permission(parent, dir, MAY_WRITE | MAY_EXEC); } /* @@ -2460,10 +2462,11 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) } } -int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, +int vfs_create(struct dentry *parent, struct dentry *dentry, umode_t mode, bool want_excl) { - int error = may_create(dir, dentry); + struct inode *dir = parent->d_inode; + int error = may_create(parent, dentry); if (error) return error; @@ -2511,7 +2514,7 @@ static int may_open(struct path *path, int acc_mode, int flag) break; } - error = inode_permission(inode, acc_mode); + error = inode_permission(dentry, inode, acc_mode); if (error) return error; @@ -2567,7 +2570,7 @@ static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode) if (error) return error; - error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC); + error = inode_permission(dir->dentry, dir->dentry->d_inode, MAY_WRITE | MAY_EXEC); if (error) return error; @@ -2812,8 +2815,7 @@ static int lookup_open(struct nameidata *nd, struct path *path, error = security_path_mknod(&nd->path, dentry, mode, 0); if (error) goto out_dput; - error = vfs_create(dir->d_inode, dentry, mode, - nd->flags & LOOKUP_EXCL); + error = vfs_create(dir, dentry, mode, nd->flags & LOOKUP_EXCL); if (error) goto out_dput; } @@ -3077,10 +3079,10 @@ static int do_tmpfile(int dfd, struct filename *pathname, if (unlikely(error)) goto out; /* we want directory to be writable */ - error = inode_permission(nd->inode, MAY_WRITE | MAY_EXEC); + dentry = nd->path.dentry; + error = inode_permission(dentry, nd->inode, MAY_WRITE | MAY_EXEC); if (error) goto out2; - dentry = nd->path.dentry; dir = dentry->d_inode; if (!dir->i_op->tmpfile) { error = -EOPNOTSUPP; @@ -3323,9 +3325,10 @@ struct dentry *user_path_create(int dfd, const char __user *pathname, } EXPORT_SYMBOL(user_path_create); -int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) +int vfs_mknod(struct dentry *parent, struct dentry *dentry, umode_t mode, dev_t dev) { - int error = may_create(dir, dentry); + struct inode *dir; + int error = may_create(parent, dentry); if (error) return error; @@ -3333,6 +3336,7 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) return -EPERM; + dir = parent->d_inode; if (!dir->i_op->mknod) return -EPERM; @@ -3390,14 +3394,14 @@ retry: goto out; switch (mode & S_IFMT) { case 0: case S_IFREG: - error = vfs_create(path.dentry->d_inode,dentry,mode,true); + error = vfs_create(path.dentry,dentry,mode,true); break; case S_IFCHR: case S_IFBLK: - error = vfs_mknod(path.dentry->d_inode,dentry,mode, + error = vfs_mknod(path.dentry,dentry,mode, new_decode_dev(dev)); break; case S_IFIFO: case S_IFSOCK: - error = vfs_mknod(path.dentry->d_inode,dentry,mode,0); + error = vfs_mknod(path.dentry,dentry,mode,0); break; } out: @@ -3414,14 +3418,16 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d return sys_mknodat(AT_FDCWD, filename, mode, dev); } -int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +int vfs_mkdir(struct dentry *parent, struct dentry *dentry, umode_t mode) { - int error = may_create(dir, dentry); - unsigned max_links = dir->i_sb->s_max_links; + struct inode *dir; + unsigned max_links; + int error = may_create(parent, dentry); if (error) return error; + dir = parent->d_inode; if (!dir->i_op->mkdir) return -EPERM; @@ -3430,6 +3436,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (error) return error; + max_links = dir->i_sb->s_max_links; if (max_links && dir->i_nlink >= max_links) return -EMLINK; @@ -3455,7 +3462,7 @@ retry: mode &= ~current_umask(); error = security_path_mkdir(&path, dentry, mode); if (!error) - error = vfs_mkdir(path.dentry->d_inode, dentry, mode); + error = vfs_mkdir(path.dentry, dentry, mode); done_path_create(&path, dentry); if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; @@ -3493,13 +3500,15 @@ void dentry_unhash(struct dentry *dentry) spin_unlock(&dentry->d_lock); } -int vfs_rmdir(struct inode *dir, struct dentry *dentry) +int vfs_rmdir(struct dentry *parent, struct dentry *dentry) { - int error = may_delete(dir, dentry, 1); + struct inode *dir; + int error = may_delete(parent, dentry, 1); if (error) return error; + dir = parent->d_inode; if (!dir->i_op->rmdir) return -EPERM; @@ -3571,7 +3580,7 @@ retry: error = security_path_rmdir(&nd.path, dentry); if (error) goto exit3; - error = vfs_rmdir(nd.path.dentry->d_inode, dentry); + error = vfs_rmdir(nd.path.dentry, dentry); exit3: dput(dentry); exit2: @@ -3610,10 +3619,11 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) * be appropriate for callers that expect the underlying filesystem not * to be NFS exported. */ -int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode) +int vfs_unlink(struct dentry *parent, struct dentry *dentry, struct inode **delegated_inode) { + struct inode *dir = parent->d_inode; struct inode *target = dentry->d_inode; - int error = may_delete(dir, dentry, 0); + int error = may_delete(parent, dentry, 0); if (error) return error; @@ -3690,7 +3700,7 @@ retry_deleg: error = security_path_unlink(&nd.path, dentry); if (error) goto exit2; - error = vfs_unlink(nd.path.dentry->d_inode, dentry, &delegated_inode); + error = vfs_unlink(nd.path.dentry, dentry, &delegated_inode); exit2: dput(dentry); } @@ -3740,13 +3750,15 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname) return do_unlinkat(AT_FDCWD, pathname); } -int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) +int vfs_symlink(struct dentry *parent, struct dentry *dentry, const char *oldname) { - int error = may_create(dir, dentry); + struct inode *dir; + int error = may_create(parent, dentry); if (error) return error; + dir = parent->d_inode; if (!dir->i_op->symlink) return -EPERM; @@ -3780,7 +3792,7 @@ retry: error = security_path_symlink(&path, dentry, from->name); if (!error) - error = vfs_symlink(path.dentry->d_inode, dentry, from->name); + error = vfs_symlink(path.dentry, dentry, from->name); done_path_create(&path, dentry); if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; @@ -3815,8 +3827,9 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn * be appropriate for callers that expect the underlying filesystem not * to be NFS exported. */ -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode) +int vfs_link(struct dentry *old_dentry, struct dentry *new_parent, struct dentry *new_dentry, struct inode **delegated_inode) { + struct inode *dir = new_parent->d_inode; struct inode *inode = old_dentry->d_inode; unsigned max_links = dir->i_sb->s_max_links; int error; @@ -3824,7 +3837,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de if (!inode) return -ENOENT; - error = may_create(dir, new_dentry); + error = may_create(new_parent, new_dentry); if (error) return error; @@ -3921,7 +3934,7 @@ retry: error = security_path_link(old_path.dentry, &new_path, new_dentry); if (error) goto out_dput; - error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode); + error = vfs_link(old_path.dentry, new_path.dentry, new_dentry, &delegated_inode); out_dput: done_path_create(&new_path, new_dentry); if (delegated_inode) { @@ -3987,7 +4000,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, * we'll need to flip '..'. */ if (new_dir != old_dir) { - error = inode_permission(old_dentry->d_inode, MAY_WRITE); + error = inode_permission(old_dentry, old_dentry->d_inode, MAY_WRITE); if (error) return error; } @@ -4091,28 +4104,31 @@ out: * be appropriate for callers that expect the underlying filesystem not * to be NFS exported. */ -int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, +int vfs_rename(struct dentry *old_parent, struct dentry *old_dentry, + struct dentry *new_parent, struct dentry *new_dentry, struct inode **delegated_inode) { int error; + struct inode *old_dir, *new_dir; int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); const unsigned char *old_name; if (old_dentry->d_inode == new_dentry->d_inode) return 0; - error = may_delete(old_dir, old_dentry, is_dir); + error = may_delete(old_parent, old_dentry, is_dir); if (error) return error; if (!new_dentry->d_inode) - error = may_create(new_dir, new_dentry); + error = may_create(new_parent, new_dentry); else - error = may_delete(new_dir, new_dentry, is_dir); + error = may_delete(new_parent, new_dentry, is_dir); if (error) return error; + old_dir = old_parent->d_inode; + new_dir = new_parent->d_inode; if (!old_dir->i_op->rename) return -EPERM; @@ -4213,9 +4229,9 @@ retry_deleg: &newnd.path, new_dentry); if (error) goto exit5; - error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry, - &delegated_inode); + error = vfs_rename(old_dir, old_dentry, + new_dir, new_dentry, + &delegated_inode); exit5: dput(new_dentry); exit4: diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 60426ccb3b65..1294ebb5b4ce 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -872,7 +872,8 @@ long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (ret) goto out; need_drop_write = 1; - ret = inode_permission(inode, MAY_WRITE); + // Why not just check f_mode & FMODE_WRITE? + ret = inode_permission(filp->f_path.dentry, inode, MAY_WRITE); if (ret) goto outDropWrite; break; @@ -884,7 +885,8 @@ long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) case NCP_IOC_GETMOUNTUID64: case NCP_IOC_GETROOT: case NCP_IOC_SIGN_WANTED: - ret = inode_permission(inode, MAY_READ); + // Why not just check f_mode & FMODE_READ? + ret = inode_permission(filp->f_path.dentry, inode, MAY_READ); if (ret) goto out; break; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be38b573495a..d13216693d1a 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -2269,7 +2269,7 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) } EXPORT_SYMBOL_GPL(nfs_may_open); -int nfs_permission(struct inode *inode, int mask) +int nfs_permission(struct dentry *dentry, struct inode *inode, int mask) { struct rpc_cred *cred; int res = 0; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 9c271f42604a..666223b0d00a 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -209,7 +209,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) * as well be forgiving and just succeed silently. */ goto out_put; - status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); + status = vfs_mkdir(dir, dentry, S_IRWXU); out_put: dput(dentry); out_unlock: @@ -323,7 +323,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn) status = -ENOENT; if (!dentry->d_inode) goto out; - status = vfs_rmdir(dir->d_inode, dentry); + status = vfs_rmdir(dir, dentry); out: dput(dentry); out_unlock: @@ -383,7 +383,7 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) if (nfs4_has_reclaimed_state(child->d_name.name, nn)) return 0; - status = vfs_rmdir(parent->d_inode, child); + status = vfs_rmdir(parent, child); if (status) printk("failed to remove client recovery directory %pd\n", child); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 3c37b160dcad..979be190080f 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -38,7 +38,7 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry) /* make sure parents give x permission to user */ int err; parent = dget_parent(tdentry); - err = inode_permission(parent->d_inode, MAY_EXEC); + err = inode_permission(parent, parent->d_inode, MAY_EXEC); if (err < 0) { dput(parent); break; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 017d3cb5e99b..f045c435d49a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1220,18 +1220,18 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, host_err = 0; switch (type) { case S_IFREG: - host_err = vfs_create(dirp, dchild, iap->ia_mode, true); + host_err = vfs_create(dentry, dchild, iap->ia_mode, true); if (!host_err) nfsd_check_ignore_resizing(iap); break; case S_IFDIR: - host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); + host_err = vfs_mkdir(dentry, dchild, iap->ia_mode); break; case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); + host_err = vfs_mknod(dentry, dchild, iap->ia_mode, rdev); break; } if (host_err < 0) @@ -1388,7 +1388,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out; } - host_err = vfs_create(dirp, dchild, iap->ia_mode, true); + host_err = vfs_create(dentry, dchild, iap->ia_mode, true); if (host_err < 0) { fh_drop_write(fhp); goto out_nfserr; @@ -1528,11 +1528,11 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, else { strncpy(path_alloced, path, plen); path_alloced[plen] = 0; - host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced); + host_err = vfs_symlink(dentry, dnew, path_alloced); kfree(path_alloced); } } else - host_err = vfs_symlink(dentry->d_inode, dnew, path); + host_err = vfs_symlink(dentry, dnew, path); err = nfserrno(host_err); if (!err) err = nfserrno(commit_metadata(fhp)); @@ -1560,7 +1560,6 @@ 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; __be32 err; int host_err; @@ -1588,7 +1587,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, fh_lock_nested(ffhp, I_MUTEX_PARENT); ddir = ffhp->fh_dentry; - dirp = ddir->d_inode; dnew = lookup_one_len(name, ddir, len); host_err = PTR_ERR(dnew); @@ -1600,7 +1598,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, err = nfserr_noent; if (!dold->d_inode) goto out_dput; - host_err = vfs_link(dold, dirp, dnew, NULL); + host_err = vfs_link(dold, ddir, dnew, NULL); if (!host_err) { err = nfserrno(commit_metadata(ffhp)); if (!err) @@ -1633,7 +1631,6 @@ 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 inode *fdir, *tdir; __be32 err; int host_err; @@ -1645,10 +1642,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, goto out; fdentry = ffhp->fh_dentry; - fdir = fdentry->d_inode; - tdentry = tfhp->fh_dentry; - tdir = tdentry->d_inode; err = nfserr_perm; if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen)) @@ -1693,7 +1687,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, if (ffhp->fh_export->ex_path.dentry != tfhp->fh_export->ex_path.dentry) goto out_dput_new; - host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL); + host_err = vfs_rename(fdentry, odentry, tdentry, ndentry, NULL); if (!host_err) { host_err = commit_metadata(tfhp); if (!host_err) @@ -1729,7 +1723,6 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, char *fname, int flen) { struct dentry *dentry, *rdentry; - struct inode *dirp; __be32 err; int host_err; @@ -1746,7 +1739,6 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, fh_lock_nested(fhp, I_MUTEX_PARENT); dentry = fhp->fh_dentry; - dirp = dentry->d_inode; rdentry = lookup_one_len(fname, dentry, flen); host_err = PTR_ERR(rdentry); @@ -1763,9 +1755,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, type = rdentry->d_inode->i_mode & S_IFMT; if (type != S_IFDIR) - host_err = vfs_unlink(dirp, rdentry, NULL); + host_err = vfs_unlink(dentry, rdentry, NULL); else - host_err = vfs_rmdir(dirp, rdentry); + host_err = vfs_rmdir(dentry, rdentry); if (!host_err) host_err = commit_metadata(fhp); dput(rdentry); @@ -2036,13 +2028,13 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, return 0; /* This assumes NFSD_MAY_{READ,WRITE,EXEC} == MAY_{READ,WRITE,EXEC} */ - err = inode_permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC)); + err = inode_permission(dentry, inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC)); /* Allow read access to binaries even when mode 111 */ if (err == -EACCES && S_ISREG(inode->i_mode) && (acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE) || acc == (NFSD_MAY_READ | NFSD_MAY_READ_IF_EXEC))) - err = inode_permission(inode, MAY_EXEC); + err = inode_permission(dentry, inode, MAY_EXEC); return err? nfserrno(err) : 0; } diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 7e350c562e0e..5348b2f14395 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -850,7 +850,7 @@ out_err: return err; } -int nilfs_permission(struct inode *inode, int mask) +int nilfs_permission(struct dentry *dentry, struct inode *inode, int mask) { struct nilfs_root *root = NILFS_I(inode)->i_root; if ((mask & MAY_WRITE) && root && diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 9bc72dec3fa6..3d5abd228b8c 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -278,7 +278,7 @@ extern void nilfs_truncate(struct inode *); extern void nilfs_evict_inode(struct inode *); extern int nilfs_setattr(struct dentry *, struct iattr *); extern void nilfs_write_failed(struct address_space *mapping, loff_t to); -int nilfs_permission(struct inode *inode, int mask); +int nilfs_permission(struct dentry *dentry, struct inode *inode, int mask); int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh); extern int nilfs_inode_dirty(struct inode *); int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty); diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index b6175fa11bf8..5f151d788733 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -490,7 +490,7 @@ static int fanotify_find_path(int dfd, const char __user *filename, } /* you can only watch an inode if you have read permissions on it */ - ret = inode_permission(path->dentry->d_inode, MAY_READ); + ret = inode_permission(path->dentry, path->dentry->d_inode, MAY_READ); if (ret) path_put(path); out: diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 497395c8274b..4c022eb266c7 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -338,7 +338,7 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns if (error) return error; /* you can only watch an inode if you have read permissions on it */ - error = inode_permission(path->dentry->d_inode, MAY_READ); + error = inode_permission(path->dentry, path->dentry->d_inode, MAY_READ); if (error) path_put(path); return error; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d77d71ead8d1..562d9d73433d 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1269,7 +1269,7 @@ bail: return err; } -int ocfs2_permission(struct inode *inode, int mask) +int ocfs2_permission(struct dentry *dentry, struct inode *inode, int mask) { int ret; diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index 97bf761c9e7c..e2bdbcadd6f4 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h @@ -61,7 +61,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); -int ocfs2_permission(struct inode *inode, int mask); +int ocfs2_permission(struct dentry *dentry, struct inode *inode, int mask); int ocfs2_should_update_atime(struct inode *inode, struct vfsmount *vfsmnt); diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 6ba4bcbc4796..a5d429b65bef 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -4350,13 +4350,15 @@ out: */ /* copied from may_create in VFS. */ -static inline int ocfs2_may_create(struct inode *dir, struct dentry *child) +static inline int ocfs2_may_create(struct dentry *parent, struct dentry *child) { + struct inode *dir = parent->d_inode; + if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) return -ENOENT; - return inode_permission(dir, MAY_WRITE | MAY_EXEC); + return inode_permission(parent, dir, MAY_WRITE | MAY_EXEC); } /** @@ -4367,16 +4369,17 @@ static inline int ocfs2_may_create(struct inode *dir, struct dentry *child) * @new_dentry: target dentry * @preserve: if true, preserve all file attributes */ -static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir, +static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct dentry *new_parent, struct dentry *new_dentry, bool preserve) { + struct inode *dir = new_parent->d_inode; struct inode *inode = old_dentry->d_inode; int error; if (!inode) return -ENOENT; - error = ocfs2_may_create(dir, new_dentry); + error = ocfs2_may_create(new_parent, new_dentry); if (error) return error; @@ -4410,7 +4413,7 @@ static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir, * file. */ if (!preserve) { - error = inode_permission(inode, MAY_READ); + error = inode_permission(old_dentry, inode, MAY_READ); if (error) return error; } @@ -4458,7 +4461,7 @@ int ocfs2_reflink_ioctl(struct inode *inode, } error = ocfs2_vfs_reflink(old_path.dentry, - new_path.dentry->d_inode, + new_path.dentry, new_dentry, preserve); out_dput: done_path_create(&new_path, new_dentry); diff --git a/fs/open.c b/fs/open.c index 4b3e1edf2fe4..788be4fb87f3 100644 --- a/fs/open.c +++ b/fs/open.c @@ -65,10 +65,12 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, long vfs_truncate(struct path *path, loff_t length) { + struct dentry *dentry; struct inode *inode; long error; - inode = path->dentry->d_inode; + dentry = path->dentry; + inode = dentry->d_inode; /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ if (S_ISDIR(inode->i_mode)) @@ -80,7 +82,7 @@ long vfs_truncate(struct path *path, loff_t length) if (error) goto out; - error = inode_permission(inode, MAY_WRITE); + error = inode_permission(dentry, inode, MAY_WRITE); if (error) goto mnt_drop_write_and_out; @@ -344,7 +346,7 @@ retry: goto out_path_release; } - res = inode_permission(inode, mode | MAY_ACCESS); + res = inode_permission(path.dentry, inode, mode | MAY_ACCESS); /* SuS v2 requires we report a read only fs too */ if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) goto out_path_release; @@ -388,7 +390,7 @@ retry: if (error) goto out; - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); + error = inode_permission(path.dentry, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); if (error) goto dput_and_out; @@ -420,7 +422,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd) if (!S_ISDIR(inode->i_mode)) goto out_putf; - error = inode_permission(inode, MAY_EXEC | MAY_CHDIR); + error = inode_permission(f.file->f_path.dentry, inode, MAY_EXEC | MAY_CHDIR); if (!error) set_fs_pwd(current->fs, &f.file->f_path); out_putf: @@ -439,7 +441,7 @@ retry: if (error) goto out; - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); + error = inode_permission(path.dentry, path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); if (error) goto dput_and_out; diff --git a/fs/proc/base.c b/fs/proc/base.c index 51507065263b..eb4752863442 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -596,7 +596,7 @@ static bool has_pid_permissions(struct pid_namespace *pid, } -static int proc_pid_permission(struct inode *inode, int mask) +static int proc_pid_permission(struct dentry *dentry, struct inode *inode, int mask) { struct pid_namespace *pid = inode->i_sb->s_fs_info; struct task_struct *task; diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 985ea881b5bc..026594d5c820 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -281,7 +281,7 @@ static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry, * /proc/pid/fd needs a special permission handler so that a process can still * access /proc/self/fd after it has executed a setuid(). */ -int proc_fd_permission(struct inode *inode, int mask) +int proc_fd_permission(struct dentry *dentry, struct inode *inode, int mask) { int rv = generic_permission(inode, mask); if (rv == 0) diff --git a/fs/proc/fd.h b/fs/proc/fd.h index 7c047f256ae2..29a70c16fd67 100644 --- a/fs/proc/fd.h +++ b/fs/proc/fd.h @@ -9,7 +9,7 @@ extern const struct inode_operations proc_fd_inode_operations; extern const struct file_operations proc_fdinfo_operations; extern const struct inode_operations proc_fdinfo_inode_operations; -extern int proc_fd_permission(struct inode *inode, int mask); +extern int proc_fd_permission(struct dentry *dentry, struct inode *inode, int mask); static inline int proc_fd(struct inode *inode) { diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 71290463a1d3..afcf1e80ab97 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -680,7 +680,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx) return 0; } -static int proc_sys_permission(struct inode *inode, int mask) +static int proc_sys_permission(struct dentry *dentry, struct inode *inode, int mask) { /* * sysctl entries that are not writeable, diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 5cdfbd638b5c..fbfed32cb2d7 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -930,7 +930,7 @@ static int xattr_mount_check(struct super_block *s) return 0; } -int reiserfs_permission(struct inode *inode, int mask) +int reiserfs_permission(struct dentry *dentry, struct inode *inode, int mask) { /* * We don't do permission checks on the internal objects. diff --git a/fs/reiserfs/xattr.h b/fs/reiserfs/xattr.h index f59626c5d33b..8d29ed9a19d4 100644 --- a/fs/reiserfs/xattr.h +++ b/fs/reiserfs/xattr.h @@ -15,7 +15,7 @@ int reiserfs_xattr_init(struct super_block *sb, int mount_flags); int reiserfs_lookup_privroot(struct super_block *sb); int reiserfs_delete_xattrs(struct inode *inode); int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); -int reiserfs_permission(struct inode *inode, int mask); +int reiserfs_permission(struct dentry *dentry, struct inode *inode, int mask); #ifdef CONFIG_REISERFS_FS_XATTR #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir) diff --git a/fs/udf/file.c b/fs/udf/file.c index c02a27a19c6d..0da4aabe25d6 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -182,7 +182,7 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) long old_block, new_block; int result = -EINVAL; - if (inode_permission(inode, MAY_READ) != 0) { + if (inode_permission(filp->f_path.dentry, inode, MAY_READ) != 0) { udf_debug("no permission to access inode %lu\n", inode->i_ino); result = -EPERM; goto out; diff --git a/fs/utimes.c b/fs/utimes.c index aa138d64560a..b7f17db4f08c 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -97,7 +97,7 @@ static int utimes_common(struct path *path, struct timespec *times) goto mnt_drop_write_and_out; if (!inode_owner_or_capable(inode)) { - error = inode_permission(inode, MAY_WRITE); + error = inode_permission(path->dentry, inode, MAY_WRITE); if (error) goto mnt_drop_write_and_out; } diff --git a/fs/xattr.c b/fs/xattr.c index 3377dff18404..00575e033549 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -29,7 +29,7 @@ * because different namespaces have very different rules. */ static int -xattr_permission(struct inode *inode, const char *name, int mask) +xattr_permission(struct dentry *dentry, struct inode *inode, const char *name, int mask) { /* * We can never set or remove an extended attribute on a read-only @@ -70,7 +70,7 @@ xattr_permission(struct inode *inode, const char *name, int mask) return -EPERM; } - return inode_permission(inode, mask); + return inode_permission(dentry, inode, mask); } /** @@ -125,7 +125,7 @@ vfs_setxattr(struct dentry *dentry, const char *name, const void *value, struct inode *inode = dentry->d_inode; int error; - error = xattr_permission(inode, name, MAY_WRITE); + error = xattr_permission(dentry, inode, name, MAY_WRITE); if (error) return error; @@ -185,7 +185,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, char *value = *xattr_value; int error; - error = xattr_permission(inode, name, MAY_READ); + error = xattr_permission(dentry, inode, name, MAY_READ); if (error) return error; @@ -233,7 +233,7 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) struct inode *inode = dentry->d_inode; int error; - error = xattr_permission(inode, name, MAY_READ); + error = xattr_permission(dentry, inode, name, MAY_READ); if (error) return error; @@ -292,7 +292,7 @@ vfs_removexattr(struct dentry *dentry, const char *name) if (!inode->i_op->removexattr) return -EOPNOTSUPP; - error = xattr_permission(inode, name, MAY_WRITE); + error = xattr_permission(dentry, inode, name, MAY_WRITE); if (error) return error; diff --git a/include/linux/fs.h b/include/linux/fs.h index 09f553c59813..2350d8b10c18 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1449,14 +1449,14 @@ extern bool inode_owner_or_capable(const struct inode *inode); /* * VFS helper functions.. */ -extern int vfs_create(struct inode *, struct dentry *, umode_t, bool); -extern int vfs_mkdir(struct inode *, struct dentry *, umode_t); -extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); -extern int vfs_symlink(struct inode *, struct dentry *, const char *); -extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); -extern int vfs_rmdir(struct inode *, struct dentry *); -extern int vfs_unlink(struct inode *, struct dentry *, struct inode **); -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **); +extern int vfs_create(struct dentry *, struct dentry *, umode_t, bool); +extern int vfs_mkdir(struct dentry *, struct dentry *, umode_t); +extern int vfs_mknod(struct dentry *, struct dentry *, umode_t, dev_t); +extern int vfs_symlink(struct dentry *, struct dentry *, const char *); +extern int vfs_link(struct dentry *, struct dentry *, struct dentry *, struct inode **); +extern int vfs_rmdir(struct dentry *, struct dentry *); +extern int vfs_unlink(struct dentry *, struct dentry *, struct inode **); +extern int vfs_rename(struct dentry *, struct dentry *, struct dentry *, struct dentry *, struct inode **); /* * VFS dentry helper functions. @@ -1552,7 +1552,7 @@ struct file_operations { struct inode_operations { struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); void * (*follow_link) (struct dentry *, struct nameidata *); - int (*permission) (struct inode *, int); + int (*permission) (struct dentry *, struct inode *, int); struct posix_acl * (*get_acl)(struct inode *, int); int (*readlink) (struct dentry *, char __user *,int); @@ -2280,7 +2280,7 @@ extern void emergency_remount(void); extern sector_t bmap(struct inode *, sector_t); #endif extern int notify_change(struct dentry *, struct iattr *, struct inode **); -extern int inode_permission(struct inode *, int); +extern int inode_permission(struct dentry *, struct inode *, int); extern int generic_permission(struct inode *, int); static inline bool execute_ok(struct inode *inode) diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 0ae5807480f4..f0e056cbe19e 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -345,7 +345,7 @@ extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fa extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern void nfs_access_set_mask(struct nfs_access_entry *, u32); -extern int nfs_permission(struct inode *, int); +extern int nfs_permission(struct dentry *, struct inode *, int); extern int nfs_open(struct inode *, struct file *); extern int nfs_release(struct inode *, struct file *); extern int nfs_attribute_timeout(struct inode *inode); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index ccf1f9fd263a..a1c751b5858e 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -728,7 +728,7 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) /* * Invoked when creating a new queue via sys_mq_open */ -static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, +static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *parent, struct path *path, int oflag, umode_t mode, struct mq_attr *attr) { @@ -754,7 +754,7 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, } mode &= ~current_umask(); - ret = vfs_create(dir, path->dentry, mode, true); + ret = vfs_create(parent, path->dentry, mode, true); path->dentry->d_fsdata = NULL; if (ret) return ERR_PTR(ret); @@ -770,7 +770,7 @@ static struct file *do_open(struct path *path, int oflag) if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) return ERR_PTR(-EINVAL); acc = oflag2acc[oflag & O_ACCMODE]; - if (inode_permission(path->dentry->d_inode, acc)) + if (inode_permission(path->dentry, path->dentry->d_inode, acc)) return ERR_PTR(-EACCES); return dentry_open(path, oflag, current_cred()); } @@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, goto out; } audit_inode_parent_hidden(name, root); - filp = do_create(ipc_ns, root->d_inode, + filp = do_create(ipc_ns, root, &path, oflag, mode, u_attr ? &attr : NULL); } @@ -886,7 +886,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) err = -ENOENT; } else { ihold(inode); - err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL); + err = vfs_unlink(dentry->d_parent, dentry, NULL); } dput(dentry); diff --git a/kernel/sys.c b/kernel/sys.c index c0a58be780a4..7346f9240571 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1650,7 +1650,7 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) exe.file->f_path.mnt->mnt_flags & MNT_NOEXEC) goto exit; - err = inode_permission(inode, MAY_EXEC); + err = inode_permission(exe.file->f_path.dentry, inode, MAY_EXEC); if (err) goto exit; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 53385cd4e6f0..597648160d73 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -6147,7 +6147,7 @@ static int memcg_write_event_control(struct cgroup_subsys_state *css, /* the process need read permission on control file */ /* AV: shouldn't we check that it's been opened for read instead? */ - ret = inode_permission(file_inode(cfile.file), MAY_READ); + ret = inode_permission(cfile.file->f_path.dentry, file_inode(cfile.file), MAY_READ); if (ret < 0) goto out_put_cfile; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 29fc8bee9702..9509fbf1d3df 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -785,7 +785,7 @@ static struct sock *unix_find_other(struct net *net, if (err) goto fail; inode = path.dentry->d_inode; - err = inode_permission(inode, MAY_WRITE); + err = inode_permission(path.dentry, inode, MAY_WRITE); if (err) goto put_fail; @@ -845,7 +845,7 @@ static int unix_mknod(const char *sun_path, umode_t mode, struct path *res) */ err = security_path_mknod(&path, dentry, mode, 0); if (!err) { - err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0); + err = vfs_mknod(path.dentry, dentry, mode, 0); if (!err) { res->mnt = mntget(path.mnt); res->dentry = dget(dentry); diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c index 8db43701016f..c12024692c0d 100644 --- a/virt/kvm/assigned-dev.c +++ b/virt/kvm/assigned-dev.c @@ -639,7 +639,7 @@ static int probe_sysfs_permissions(struct pci_dev *dev) inode = path.dentry->d_inode; - r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS); + r = inode_permission(path.dentry, inode, MAY_READ | MAY_WRITE | MAY_ACCESS); path_put(&path); if (r) return r;