Commit a574f324 authored by Trond Myklebust's avatar Trond Myklebust

[PATCH] Pass 'nameidata' to ->permission()

   - Make the VFS pass the struct nameidata as an optional parameter
     to the permission() inode operation.

   - Patch may_create()/may_open() so it passes the struct nameidata from
     vfs_create()/open_namei() as an argument to permission().

   - Add an intent flag for the sys_access() function.
parent 675b5da0
...@@ -3767,7 +3767,7 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3767,7 +3767,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
* Needed so that programs such as fdrawcmd still can work on write * Needed so that programs such as fdrawcmd still can work on write
* protected disks */ * protected disks */
if ((filp->f_mode & 2) || if ((filp->f_mode & 2) ||
(inode->i_sb && (permission(inode,2) == 0))) (inode->i_sb && (permission(inode,2, NULL) == 0)))
filp->private_data = (void*) 8; filp->private_data = (void*) 8;
if (UFDCS->rawcmd == 1) if (UFDCS->rawcmd == 1)
......
...@@ -178,7 +178,7 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) ...@@ -178,7 +178,7 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
return 0; /* always return success? what if volume is no longer available? */ return 0; /* always return success? what if volume is no longer available? */
} }
static int cifs_permission(struct inode * inode, int mask) static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
{ {
/* the server does permission checks, we do not need to do it here */ /* the server does permission checks, we do not need to do it here */
return 0; return 0;
......
...@@ -147,7 +147,7 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc ...@@ -147,7 +147,7 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
} }
int coda_permission(struct inode *inode, int mask) int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
int error = 0; int error = 0;
......
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
#include <linux/coda_psdev.h> #include <linux/coda_psdev.h>
/* pioctl ops */ /* pioctl ops */
static int coda_ioctl_permission(struct inode *inode, int mask); static int coda_ioctl_permission(struct inode *inode, int mask,
struct nameidata *nd);
static int coda_pioctl(struct inode * inode, struct file * filp, static int coda_pioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long user_data); unsigned int cmd, unsigned long user_data);
...@@ -41,7 +42,8 @@ struct file_operations coda_ioctl_operations = { ...@@ -41,7 +42,8 @@ struct file_operations coda_ioctl_operations = {
}; };
/* the coda pioctl inode ops */ /* the coda pioctl inode ops */
static int coda_ioctl_permission(struct inode *inode, int mask) static int coda_ioctl_permission(struct inode *inode, int mask,
struct nameidata *nd)
{ {
return 0; return 0;
} }
......
...@@ -126,7 +126,7 @@ asmlinkage long sys_uselib(const char __user * library) ...@@ -126,7 +126,7 @@ asmlinkage long sys_uselib(const char __user * library)
if (!S_ISREG(nd.dentry->d_inode->i_mode)) if (!S_ISREG(nd.dentry->d_inode->i_mode))
goto exit; goto exit;
error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC); error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd);
if (error) if (error)
goto exit; goto exit;
...@@ -462,7 +462,7 @@ struct file *open_exec(const char *name) ...@@ -462,7 +462,7 @@ struct file *open_exec(const char *name)
file = ERR_PTR(-EACCES); file = ERR_PTR(-EACCES);
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
S_ISREG(inode->i_mode)) { S_ISREG(inode->i_mode)) {
int err = permission(inode, MAY_EXEC); int err = permission(inode, MAY_EXEC, &nd);
if (!err && !(inode->i_mode & 0111)) if (!err && !(inode->i_mode & 0111))
err = -EACCES; err = -EACCES;
file = ERR_PTR(err); file = ERR_PTR(err);
...@@ -794,7 +794,7 @@ int flush_old_exec(struct linux_binprm * bprm) ...@@ -794,7 +794,7 @@ int flush_old_exec(struct linux_binprm * bprm)
flush_thread(); flush_thread();
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
permission(bprm->file->f_dentry->d_inode,MAY_READ)) permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL))
current->mm->dumpable = 0; current->mm->dumpable = 0;
/* An exec changes our domain. We are no longer part of the thread /* An exec changes our domain. We are no longer part of the thread
......
...@@ -309,7 +309,7 @@ __ext2_permission(struct inode *inode, int mask, int lock) ...@@ -309,7 +309,7 @@ __ext2_permission(struct inode *inode, int mask, int lock)
* BKL held [before 2.5.x] * BKL held [before 2.5.x]
*/ */
int int
ext2_permission(struct inode *inode, int mask) ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
return __ext2_permission(inode, mask, 1); return __ext2_permission(inode, mask, 1);
} }
......
...@@ -59,7 +59,7 @@ static inline int ext2_acl_count(size_t size) ...@@ -59,7 +59,7 @@ static inline int ext2_acl_count(size_t size)
#define EXT2_ACL_NOT_CACHED ((void *)-1) #define EXT2_ACL_NOT_CACHED ((void *)-1)
/* acl.c */ /* acl.c */
extern int ext2_permission (struct inode *, int); extern int ext2_permission (struct inode *, int, struct nameidata *);
extern int ext2_permission_locked (struct inode *, int); extern int ext2_permission_locked (struct inode *, int);
extern int ext2_acl_chmod (struct inode *); extern int ext2_acl_chmod (struct inode *);
extern int ext2_init_acl (struct inode *, struct inode *); extern int ext2_init_acl (struct inode *, struct inode *);
......
...@@ -47,7 +47,7 @@ ext2_xattr_user_get(struct inode *inode, const char *name, ...@@ -47,7 +47,7 @@ ext2_xattr_user_get(struct inode *inode, const char *name,
#ifdef CONFIG_EXT2_FS_POSIX_ACL #ifdef CONFIG_EXT2_FS_POSIX_ACL
error = ext2_permission_locked(inode, MAY_READ); error = ext2_permission_locked(inode, MAY_READ);
#else #else
error = permission(inode, MAY_READ); error = permission(inode, MAY_READ, NULL);
#endif #endif
if (error) if (error)
return error; return error;
...@@ -71,7 +71,7 @@ ext2_xattr_user_set(struct inode *inode, const char *name, ...@@ -71,7 +71,7 @@ ext2_xattr_user_set(struct inode *inode, const char *name,
#ifdef CONFIG_EXT2_FS_POSIX_ACL #ifdef CONFIG_EXT2_FS_POSIX_ACL
error = ext2_permission_locked(inode, MAY_WRITE); error = ext2_permission_locked(inode, MAY_WRITE);
#else #else
error = permission(inode, MAY_WRITE); error = permission(inode, MAY_WRITE, NULL);
#endif #endif
if (error) if (error)
return error; return error;
......
...@@ -312,7 +312,7 @@ __ext3_permission(struct inode *inode, int mask, int lock) ...@@ -312,7 +312,7 @@ __ext3_permission(struct inode *inode, int mask, int lock)
* inode->i_sem: up * inode->i_sem: up
*/ */
int int
ext3_permission(struct inode *inode, int mask) ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
return __ext3_permission(inode, mask, 1); return __ext3_permission(inode, mask, 1);
} }
......
...@@ -59,7 +59,7 @@ static inline int ext3_acl_count(size_t size) ...@@ -59,7 +59,7 @@ static inline int ext3_acl_count(size_t size)
#define EXT3_ACL_NOT_CACHED ((void *)-1) #define EXT3_ACL_NOT_CACHED ((void *)-1)
/* acl.c */ /* acl.c */
extern int ext3_permission (struct inode *, int); extern int ext3_permission (struct inode *, int, struct nameidata *);
extern int ext3_permission_locked (struct inode *, int); extern int ext3_permission_locked (struct inode *, int);
extern int ext3_acl_chmod (struct inode *); extern int ext3_acl_chmod (struct inode *);
extern int ext3_init_acl (handle_t *, struct inode *, struct inode *); extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
......
...@@ -49,7 +49,7 @@ ext3_xattr_user_get(struct inode *inode, const char *name, ...@@ -49,7 +49,7 @@ ext3_xattr_user_get(struct inode *inode, const char *name,
#ifdef CONFIG_EXT3_FS_POSIX_ACL #ifdef CONFIG_EXT3_FS_POSIX_ACL
error = ext3_permission_locked(inode, MAY_READ); error = ext3_permission_locked(inode, MAY_READ);
#else #else
error = permission(inode, MAY_READ); error = permission(inode, MAY_READ, NULL);
#endif #endif
if (error) if (error)
return error; return error;
...@@ -73,7 +73,7 @@ ext3_xattr_user_set(struct inode *inode, const char *name, ...@@ -73,7 +73,7 @@ ext3_xattr_user_set(struct inode *inode, const char *name,
#ifdef CONFIG_EXT3_FS_POSIX_ACL #ifdef CONFIG_EXT3_FS_POSIX_ACL
error = ext3_permission_locked(inode, MAY_WRITE); error = ext3_permission_locked(inode, MAY_WRITE);
#else #else
error = permission(inode, MAY_WRITE); error = permission(inode, MAY_WRITE, NULL);
#endif #endif
if (error) if (error)
return error; return error;
......
...@@ -374,7 +374,7 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -374,7 +374,7 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry)
d_drop(dentry); d_drop(dentry);
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
if (atomic_read(&dentry->d_count) > 1 || if (atomic_read(&dentry->d_count) > 1 ||
permission(inode, MAY_WRITE) || permission(inode, MAY_WRITE, NULL) ||
get_write_access(inode)) { get_write_access(inode)) {
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
d_rehash(dentry); d_rehash(dentry);
......
...@@ -81,7 +81,7 @@ static inline void presto_unlock(struct inode *dir) ...@@ -81,7 +81,7 @@ static inline void presto_unlock(struct inode *dir)
/* /*
* these are initialized in super.c * these are initialized in super.c
*/ */
extern int presto_permission(struct inode *inode, int mask); extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
static int izo_authorized_uid = 0; static int izo_authorized_uid = 0;
int izo_dentry_is_ilookup(struct dentry *dentry, ino_t *id, int izo_dentry_is_ilookup(struct dentry *dentry, ino_t *id,
...@@ -830,7 +830,7 @@ int presto_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -830,7 +830,7 @@ int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
* appropriate permission function. Thus we do not worry here about ACLs * appropriate permission function. Thus we do not worry here about ACLs
* or EAs. -SHP * or EAs. -SHP
*/ */
int presto_permission(struct inode *inode, int mask) int presto_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
unsigned short mode = inode->i_mode; unsigned short mode = inode->i_mode;
struct presto_cache *cache; struct presto_cache *cache;
...@@ -852,11 +852,11 @@ int presto_permission(struct inode *inode, int mask) ...@@ -852,11 +852,11 @@ int presto_permission(struct inode *inode, int mask)
if ( S_ISREG(mode) && fiops && fiops->permission ) { if ( S_ISREG(mode) && fiops && fiops->permission ) {
EXIT; EXIT;
return fiops->permission(inode, mask); return fiops->permission(inode, mask, nd);
} }
if ( S_ISDIR(mode) && diops && diops->permission ) { if ( S_ISDIR(mode) && diops && diops->permission ) {
EXIT; EXIT;
return diops->permission(inode, mask); return diops->permission(inode, mask, nd);
} }
} }
...@@ -867,7 +867,7 @@ int presto_permission(struct inode *inode, int mask) ...@@ -867,7 +867,7 @@ int presto_permission(struct inode *inode, int mask)
* the VFS permission function. * the VFS permission function.
*/ */
inode->i_op->permission = NULL; inode->i_op->permission = NULL;
rc = permission(inode, mask); rc = permission(inode, mask, nd);
inode->i_op->permission = &presto_permission; inode->i_op->permission = &presto_permission;
EXIT; EXIT;
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
/* /*
* these are initialized in super.c * these are initialized in super.c
*/ */
extern int presto_permission(struct inode *inode, int mask); extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
static int presto_open_upcall(int minor, struct dentry *de) static int presto_open_upcall(int minor, struct dentry *de)
......
...@@ -134,7 +134,7 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir) ...@@ -134,7 +134,7 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
int error; int error;
if (!victim->d_inode || victim->d_parent->d_inode != dir) if (!victim->d_inode || victim->d_parent->d_inode != dir)
return -ENOENT; return -ENOENT;
error = permission(dir,MAY_WRITE | MAY_EXEC); error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error) if (error)
return error; return error;
if (IS_APPEND(dir)) if (IS_APPEND(dir))
...@@ -158,7 +158,7 @@ static inline int may_create(struct inode *dir, struct dentry *child) { ...@@ -158,7 +158,7 @@ static inline int may_create(struct inode *dir, struct dentry *child) {
return -EEXIST; return -EEXIST;
if (IS_DEADDIR(dir)) if (IS_DEADDIR(dir))
return -ENOENT; return -ENOENT;
return permission(dir,MAY_WRITE | MAY_EXEC); return permission(dir,MAY_WRITE | MAY_EXEC, NULL);
} }
#ifdef PRESTO_DEBUG #ifdef PRESTO_DEBUG
...@@ -1840,7 +1840,7 @@ int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent, ...@@ -1840,7 +1840,7 @@ int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
* we'll need to flip '..'. * we'll need to flip '..'.
*/ */
if (new_dir != old_dir) { if (new_dir != old_dir) {
error = permission(old_dentry->d_inode, MAY_WRITE); error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
} }
if (error) if (error)
return error; return error;
......
...@@ -208,7 +208,7 @@ static int __jfs_permission(struct inode * inode, int mask, int have_sem) ...@@ -208,7 +208,7 @@ static int __jfs_permission(struct inode * inode, int mask, int have_sem)
return -EACCES; return -EACCES;
} }
int jfs_permission(struct inode * inode, int mask) int jfs_permission(struct inode * inode, int mask, struct nameidata *nd)
{ {
return __jfs_permission(inode, mask, 0); return __jfs_permission(inode, mask, 0);
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
struct posix_acl *jfs_get_acl(struct inode *, int); struct posix_acl *jfs_get_acl(struct inode *, int);
int jfs_set_acl(struct inode *, int, struct posix_acl *); int jfs_set_acl(struct inode *, int, struct posix_acl *);
int jfs_permission_have_sem(struct inode *, int); int jfs_permission_have_sem(struct inode *, int);
int jfs_permission(struct inode *, int); int jfs_permission(struct inode *, int, struct nameidata *);
int jfs_init_acl(struct inode *, struct inode *); int jfs_init_acl(struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *); int jfs_setattr(struct dentry *, struct iattr *);
......
...@@ -731,7 +731,7 @@ static int can_set_xattr(struct inode *inode, const char *name, ...@@ -731,7 +731,7 @@ static int can_set_xattr(struct inode *inode, const char *name,
#ifdef CONFIG_JFS_POSIX_ACL #ifdef CONFIG_JFS_POSIX_ACL
return jfs_permission_have_sem(inode, MAY_WRITE); return jfs_permission_have_sem(inode, MAY_WRITE);
#else #else
return permission(inode, MAY_WRITE); return permission(inode, MAY_WRITE, NULL);
#endif #endif
} }
...@@ -893,7 +893,7 @@ static int can_get_xattr(struct inode *inode, const char *name) ...@@ -893,7 +893,7 @@ static int can_get_xattr(struct inode *inode, const char *name)
else else
return jfs_permission_have_sem(inode, MAY_READ); return jfs_permission_have_sem(inode, MAY_READ);
#else #else
return permission(inode, MAY_READ); return permission(inode, MAY_READ, NULL);
#endif #endif
} }
......
...@@ -203,7 +203,7 @@ int vfs_permission(struct inode * inode, int mask) ...@@ -203,7 +203,7 @@ int vfs_permission(struct inode * inode, int mask)
return -EACCES; return -EACCES;
} }
int permission(struct inode * inode,int mask) int permission(struct inode * inode,int mask, struct nameidata *nd)
{ {
int retval; int retval;
int submask; int submask;
...@@ -212,7 +212,7 @@ int permission(struct inode * inode,int mask) ...@@ -212,7 +212,7 @@ int permission(struct inode * inode,int mask)
submask = mask & ~MAY_APPEND; submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission) if (inode->i_op && inode->i_op->permission)
retval = inode->i_op->permission(inode, submask); retval = inode->i_op->permission(inode, submask, nd);
else else
retval = vfs_permission(inode, submask); retval = vfs_permission(inode, submask);
if (retval) if (retval)
...@@ -588,7 +588,7 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -588,7 +588,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
err = exec_permission_lite(inode); err = exec_permission_lite(inode);
if (err == -EAGAIN) { if (err == -EAGAIN) {
err = permission(inode, MAY_EXEC); err = permission(inode, MAY_EXEC, nd);
} }
if (err) if (err)
break; break;
...@@ -876,7 +876,7 @@ static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, st ...@@ -876,7 +876,7 @@ static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, st
int err; int err;
inode = base->d_inode; inode = base->d_inode;
err = permission(inode, MAY_EXEC); err = permission(inode, MAY_EXEC, nd);
dentry = ERR_PTR(err); dentry = ERR_PTR(err);
if (err) if (err)
goto out; goto out;
...@@ -996,12 +996,12 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) ...@@ -996,12 +996,12 @@ 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 * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink(). * nfs_async_unlink().
*/ */
static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir) static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
{ {
int error; int error;
if (!victim->d_inode || victim->d_parent->d_inode != dir) if (!victim->d_inode || victim->d_parent->d_inode != dir)
return -ENOENT; return -ENOENT;
error = permission(dir,MAY_WRITE | MAY_EXEC); error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error) if (error)
return error; return error;
if (IS_APPEND(dir)) if (IS_APPEND(dir))
...@@ -1031,12 +1031,14 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir) ...@@ -1031,12 +1031,14 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
* 3. We should have write and exec permissions on dir * 3. We should have write and exec permissions on dir
* 4. We can't do it if dir is immutable (done in permission()) * 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 inode *dir, struct dentry *child,
struct nameidata *nd)
{
if (child->d_inode) if (child->d_inode)
return -EEXIST; return -EEXIST;
if (IS_DEADDIR(dir)) if (IS_DEADDIR(dir))
return -ENOENT; return -ENOENT;
return permission(dir,MAY_WRITE | MAY_EXEC); return permission(dir,MAY_WRITE | MAY_EXEC, nd);
} }
/* /*
...@@ -1108,7 +1110,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) ...@@ -1108,7 +1110,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
int vfs_create(struct inode *dir, struct dentry *dentry, int mode, int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd) struct nameidata *nd)
{ {
int error = may_create(dir, dentry); int error = may_create(dir, dentry, nd);
if (error) if (error)
return error; return error;
...@@ -1144,7 +1146,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) ...@@ -1144,7 +1146,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
return -EISDIR; return -EISDIR;
error = permission(inode, acc_mode); error = permission(inode, acc_mode, nd);
if (error) if (error)
return error; return error;
...@@ -1398,7 +1400,7 @@ static struct dentry *lookup_create(struct nameidata *nd, int is_dir) ...@@ -1398,7 +1400,7 @@ static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{ {
int error = may_create(dir, dentry); int error = may_create(dir, dentry, NULL);
if (error) if (error)
return error; return error;
...@@ -1469,7 +1471,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, dev_t dev) ...@@ -1469,7 +1471,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, dev_t dev)
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{ {
int error = may_create(dir, dentry); int error = may_create(dir, dentry, NULL);
if (error) if (error)
return error; return error;
...@@ -1715,7 +1717,7 @@ asmlinkage long sys_unlink(const char __user * pathname) ...@@ -1715,7 +1717,7 @@ asmlinkage long sys_unlink(const char __user * pathname)
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{ {
int error = may_create(dir, dentry); int error = may_create(dir, dentry, NULL);
if (error) if (error)
return error; return error;
...@@ -1777,7 +1779,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de ...@@ -1777,7 +1779,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
if (!inode) if (!inode)
return -ENOENT; return -ENOENT;
error = may_create(dir, new_dentry); error = may_create(dir, new_dentry, NULL);
if (error) if (error)
return error; return error;
...@@ -1898,7 +1900,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1898,7 +1900,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
* we'll need to flip '..'. * we'll need to flip '..'.
*/ */
if (new_dir != old_dir) { if (new_dir != old_dir) {
error = permission(old_dentry->d_inode, MAY_WRITE); error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
if (error) if (error)
return error; return error;
} }
...@@ -1976,7 +1978,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1976,7 +1978,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return error; return error;
if (!new_dentry->d_inode) if (!new_dentry->d_inode)
error = may_create(new_dir, new_dentry); error = may_create(new_dir, new_dentry, NULL);
else else
error = may_delete(new_dir, new_dentry, is_dir); error = may_delete(new_dir, new_dentry, is_dir);
if (error) if (error)
......
...@@ -403,7 +403,7 @@ static int mount_is_safe(struct nameidata *nd) ...@@ -403,7 +403,7 @@ static int mount_is_safe(struct nameidata *nd)
if (current->uid != nd->dentry->d_inode->i_uid) if (current->uid != nd->dentry->d_inode->i_uid)
return -EPERM; return -EPERM;
} }
if (permission(nd->dentry->d_inode, MAY_WRITE)) if (permission(nd->dentry->d_inode, MAY_WRITE, nd))
return -EPERM; return -EPERM;
return 0; return 0;
#endif #endif
......
...@@ -40,7 +40,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -40,7 +40,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
switch (cmd) { switch (cmd) {
case NCP_IOC_NCPREQUEST: case NCP_IOC_NCPREQUEST:
if ((permission(inode, MAY_WRITE) != 0) if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) { && (current->uid != server->m.mounted_uid)) {
return -EACCES; return -EACCES;
} }
...@@ -99,7 +99,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -99,7 +99,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{ {
struct ncp_fs_info info; struct ncp_fs_info info;
if ((permission(inode, MAY_WRITE) != 0) if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) { && (current->uid != server->m.mounted_uid)) {
return -EACCES; return -EACCES;
} }
...@@ -127,7 +127,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -127,7 +127,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{ {
struct ncp_fs_info_v2 info2; struct ncp_fs_info_v2 info2;
if ((permission(inode, MAY_WRITE) != 0) if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) { && (current->uid != server->m.mounted_uid)) {
return -EACCES; return -EACCES;
} }
...@@ -155,7 +155,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -155,7 +155,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{ {
unsigned long tmp = server->m.mounted_uid; unsigned long tmp = server->m.mounted_uid;
if ( (permission(inode, MAY_READ) != 0) if ( (permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) && (current->uid != server->m.mounted_uid))
{ {
return -EACCES; return -EACCES;
...@@ -169,7 +169,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -169,7 +169,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{ {
struct ncp_setroot_ioctl sr; struct ncp_setroot_ioctl sr;
if ( (permission(inode, MAY_READ) != 0) if ( (permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) && (current->uid != server->m.mounted_uid))
{ {
return -EACCES; return -EACCES;
...@@ -249,7 +249,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -249,7 +249,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_PACKET_SIGNING #ifdef CONFIG_NCPFS_PACKET_SIGNING
case NCP_IOC_SIGN_INIT: case NCP_IOC_SIGN_INIT:
if ((permission(inode, MAY_WRITE) != 0) if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) && (current->uid != server->m.mounted_uid))
{ {
return -EACCES; return -EACCES;
...@@ -272,7 +272,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -272,7 +272,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0; return 0;
case NCP_IOC_SIGN_WANTED: case NCP_IOC_SIGN_WANTED:
if ( (permission(inode, MAY_READ) != 0) if ( (permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) && (current->uid != server->m.mounted_uid))
{ {
return -EACCES; return -EACCES;
...@@ -285,7 +285,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -285,7 +285,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{ {
int newstate; int newstate;
if ( (permission(inode, MAY_WRITE) != 0) if ( (permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) && (current->uid != server->m.mounted_uid))
{ {
return -EACCES; return -EACCES;
...@@ -306,7 +306,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -306,7 +306,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_IOCTL_LOCKING #ifdef CONFIG_NCPFS_IOCTL_LOCKING
case NCP_IOC_LOCKUNLOCK: case NCP_IOC_LOCKUNLOCK:
if ( (permission(inode, MAY_WRITE) != 0) if ( (permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) && (current->uid != server->m.mounted_uid))
{ {
return -EACCES; return -EACCES;
...@@ -608,7 +608,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -608,7 +608,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
} }
#endif /* CONFIG_NCPFS_NLS */ #endif /* CONFIG_NCPFS_NLS */
case NCP_IOC_SETDENTRYTTL: case NCP_IOC_SETDENTRYTTL:
if ((permission(inode, MAY_WRITE) != 0) && if ((permission(inode, MAY_WRITE, NULL) != 0) &&
(current->uid != server->m.mounted_uid)) (current->uid != server->m.mounted_uid))
return -EACCES; return -EACCES;
{ {
...@@ -637,7 +637,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, ...@@ -637,7 +637,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
/* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2, /* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
so we have this out of switch */ so we have this out of switch */
if (cmd == NCP_IOC_GETMOUNTUID) { if (cmd == NCP_IOC_GETMOUNTUID) {
if ((permission(inode, MAY_READ) != 0) if ((permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) { && (current->uid != server->m.mounted_uid)) {
return -EACCES; return -EACCES;
} }
......
...@@ -1240,7 +1240,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1240,7 +1240,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
} }
int int
nfs_permission(struct inode *inode, int mask) nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
struct nfs_access_cache *cache = &NFS_I(inode)->cache_access; struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
struct rpc_cred *cred; struct rpc_cred *cred;
......
...@@ -56,7 +56,7 @@ int nfsd_acceptable(void *expv, struct dentry *dentry) ...@@ -56,7 +56,7 @@ int nfsd_acceptable(void *expv, struct dentry *dentry)
/* make sure parents give x permission to user */ /* make sure parents give x permission to user */
int err; int err;
parent = dget_parent(tdentry); parent = dget_parent(tdentry);
err = permission(parent->d_inode, S_IXOTH); err = permission(parent->d_inode, S_IXOTH, NULL);
if (err < 0) { if (err < 0) {
dput(parent); dput(parent);
break; break;
......
...@@ -1584,12 +1584,12 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc) ...@@ -1584,12 +1584,12 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
inode->i_uid == current->fsuid) inode->i_uid == current->fsuid)
return 0; return 0;
err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC)); err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
/* Allow read access to binaries even when mode 111 */ /* Allow read access to binaries even when mode 111 */
if (err == -EACCES && S_ISREG(inode->i_mode) && if (err == -EACCES && S_ISREG(inode->i_mode) &&
acc == (MAY_READ | MAY_OWNER_OVERRIDE)) acc == (MAY_READ | MAY_OWNER_OVERRIDE))
err = permission(inode, MAY_EXEC); err = permission(inode, MAY_EXEC, NULL);
return err? nfserrno(err) : 0; return err? nfserrno(err) : 0;
} }
......
...@@ -219,7 +219,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) ...@@ -219,7 +219,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
goto dput_and_out; goto dput_and_out;
error = permission(inode,MAY_WRITE); error = permission(inode,MAY_WRITE,&nd);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
...@@ -365,7 +365,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) ...@@ -365,7 +365,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
} else { } else {
if (current->fsuid != inode->i_uid && if (current->fsuid != inode->i_uid &&
(error = permission(inode,MAY_WRITE)) != 0) (error = permission(inode,MAY_WRITE,&nd)) != 0)
goto dput_and_out; goto dput_and_out;
} }
down(&inode->i_sem); down(&inode->i_sem);
...@@ -410,7 +410,7 @@ long do_utimes(char __user * filename, struct timeval * times) ...@@ -410,7 +410,7 @@ long do_utimes(char __user * filename, struct timeval * times)
newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
} else { } else {
if (current->fsuid != inode->i_uid && if (current->fsuid != inode->i_uid &&
(error = permission(inode,MAY_WRITE)) != 0) (error = permission(inode,MAY_WRITE,&nd)) != 0)
goto dput_and_out; goto dput_and_out;
} }
down(&inode->i_sem); down(&inode->i_sem);
...@@ -467,9 +467,9 @@ asmlinkage long sys_access(const char __user * filename, int mode) ...@@ -467,9 +467,9 @@ asmlinkage long sys_access(const char __user * filename, int mode)
else else
current->cap_effective = current->cap_permitted; current->cap_effective = current->cap_permitted;
res = user_path_walk(filename, &nd); res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
if (!res) { if (!res) {
res = permission(nd.dentry->d_inode, mode); res = permission(nd.dentry->d_inode, mode, &nd);
/* SuS v2 requires we report a read only fs too */ /* SuS v2 requires we report a read only fs too */
if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
&& !special_file(nd.dentry->d_inode->i_mode)) && !special_file(nd.dentry->d_inode->i_mode))
...@@ -493,7 +493,7 @@ asmlinkage long sys_chdir(const char __user * filename) ...@@ -493,7 +493,7 @@ asmlinkage long sys_chdir(const char __user * filename)
if (error) if (error)
goto out; goto out;
error = permission(nd.dentry->d_inode,MAY_EXEC); error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
...@@ -526,7 +526,7 @@ asmlinkage long sys_fchdir(unsigned int fd) ...@@ -526,7 +526,7 @@ asmlinkage long sys_fchdir(unsigned int fd)
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
goto out_putf; goto out_putf;
error = permission(inode, MAY_EXEC); error = permission(inode, MAY_EXEC, NULL);
if (!error) if (!error)
set_fs_pwd(current->fs, mnt, dentry); set_fs_pwd(current->fs, mnt, dentry);
out_putf: out_putf:
...@@ -544,7 +544,7 @@ asmlinkage long sys_chroot(const char __user * filename) ...@@ -544,7 +544,7 @@ asmlinkage long sys_chroot(const char __user * filename)
if (error) if (error)
goto out; goto out;
error = permission(nd.dentry->d_inode,MAY_EXEC); error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
......
...@@ -334,7 +334,7 @@ static int proc_check_root(struct inode *inode) ...@@ -334,7 +334,7 @@ static int proc_check_root(struct inode *inode)
goto exit; goto exit;
} }
static int proc_permission(struct inode *inode, int mask) static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
if (vfs_permission(inode, mask) != 0) if (vfs_permission(inode, mask) != 0)
return -EACCES; return -EACCES;
......
...@@ -367,7 +367,7 @@ smb_file_release(struct inode *inode, struct file * file) ...@@ -367,7 +367,7 @@ smb_file_release(struct inode *inode, struct file * file)
* privileges, so we need our own check for this. * privileges, so we need our own check for this.
*/ */
static int static int
smb_file_permission(struct inode *inode, int mask) smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
{ {
int mode = inode->i_mode; int mode = inode->i_mode;
int error = 0; int error = 0;
......
...@@ -188,7 +188,7 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -188,7 +188,7 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
{ {
int result = -EINVAL; int result = -EINVAL;
if ( permission(inode, MAY_READ) != 0 ) if ( permission(inode, MAY_READ, NULL) != 0 )
{ {
udf_debug("no permission to access inode %lu\n", udf_debug("no permission to access inode %lu\n",
inode->i_ino); inode->i_ino);
......
...@@ -431,7 +431,8 @@ linvfs_follow_link( ...@@ -431,7 +431,8 @@ linvfs_follow_link(
STATIC int STATIC int
linvfs_permission( linvfs_permission(
struct inode *inode, struct inode *inode,
int mode) int mode,
struct nameidata *nd)
{ {
vnode_t *vp = LINVFS_GET_VP(inode); vnode_t *vp = LINVFS_GET_VP(inode);
int error; int error;
......
...@@ -38,7 +38,7 @@ extern struct file_operations coda_ioctl_operations; ...@@ -38,7 +38,7 @@ extern struct file_operations coda_ioctl_operations;
int coda_open(struct inode *i, struct file *f); int coda_open(struct inode *i, struct file *f);
int coda_flush(struct file *f); int coda_flush(struct file *f);
int coda_release(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 inode *inode, int mask, struct nameidata *nd);
int coda_revalidate_inode(struct dentry *); int coda_revalidate_inode(struct dentry *);
int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *); int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int coda_setattr(struct dentry *, struct iattr *); int coda_setattr(struct dentry *, struct iattr *);
......
...@@ -743,7 +743,7 @@ struct inode_operations { ...@@ -743,7 +743,7 @@ struct inode_operations {
int (*readlink) (struct dentry *, char __user *,int); int (*readlink) (struct dentry *, char __user *,int);
int (*follow_link) (struct dentry *, struct nameidata *); int (*follow_link) (struct dentry *, struct nameidata *);
void (*truncate) (struct inode *); void (*truncate) (struct inode *);
int (*permission) (struct inode *, int); int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *); int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
...@@ -1121,7 +1121,7 @@ extern int do_remount_sb(struct super_block *sb, int flags, ...@@ -1121,7 +1121,7 @@ extern int do_remount_sb(struct super_block *sb, int flags,
extern sector_t bmap(struct inode *, sector_t); extern sector_t bmap(struct inode *, sector_t);
extern int setattr_mask(unsigned int); extern int setattr_mask(unsigned int);
extern int notify_change(struct dentry *, struct iattr *); extern int notify_change(struct dentry *, struct iattr *);
extern int permission(struct inode *, int); extern int permission(struct inode *, int, struct nameidata *);
extern int vfs_permission(struct inode *, int); extern int vfs_permission(struct inode *, int);
extern int get_write_access(struct inode *); extern int get_write_access(struct inode *);
extern int deny_write_access(struct file *); extern int deny_write_access(struct file *);
......
...@@ -46,6 +46,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; ...@@ -46,6 +46,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
*/ */
#define LOOKUP_OPEN (0x0100) #define LOOKUP_OPEN (0x0100)
#define LOOKUP_CREATE (0x0200) #define LOOKUP_CREATE (0x0200)
#define LOOKUP_ACCESS (0x0400)
extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *)); extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
#define user_path_walk(name,nd) \ #define user_path_walk(name,nd) \
......
...@@ -240,7 +240,7 @@ extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *, ...@@ -240,7 +240,7 @@ extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
struct nfs_fattr *); struct nfs_fattr *);
extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *); extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int nfs_permission(struct inode *, int); extern int nfs_permission(struct inode *, int, struct nameidata *);
extern int nfs_open(struct inode *, struct file *); extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *); extern int nfs_release(struct inode *, struct file *);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
......
...@@ -130,7 +130,7 @@ extern ctl_table random_table[]; ...@@ -130,7 +130,7 @@ extern ctl_table random_table[];
static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *); static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *); static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
static int proc_sys_permission(struct inode *, int); static int proc_sys_permission(struct inode *, int, struct nameidata *);
struct file_operations proc_sys_file_operations = { struct file_operations proc_sys_file_operations = {
.read = proc_readsys, .read = proc_readsys,
...@@ -1177,7 +1177,7 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf, ...@@ -1177,7 +1177,7 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf,
return do_rw_proc(1, file, (char __user *) buf, count, ppos); return do_rw_proc(1, file, (char __user *) buf, count, ppos);
} }
static int proc_sys_permission(struct inode *inode, int op) static int proc_sys_permission(struct inode *inode, int op, struct nameidata *nd)
{ {
return test_perm(inode->i_mode, op); return test_perm(inode->i_mode, op);
} }
......
...@@ -594,7 +594,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, ...@@ -594,7 +594,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
if (err) if (err)
goto fail; goto fail;
err = permission(nd.dentry->d_inode,MAY_WRITE); err = permission(nd.dentry->d_inode,MAY_WRITE, &nd);
if (err) if (err)
goto put_fail; goto put_fail;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment