Skip to content

Commit

Permalink
[PATCH] sanitize ->permission() prototype
Browse files Browse the repository at this point in the history
* kill nameidata * argument; map the 3 bits in ->flags anybody cares
  about to new MAY_... ones and pass with the mask.
* kill redundant gfs2_iop_permission()
* sanitize ecryptfs_permission()
* fix remaining places where ->permission() instances might barf on new
  MAY_... found in mask.

The obvious next target in that direction is permission(9)

folded fix for nfs_permission() breakage from Miklos Szeredi <mszeredi@suse.cz>

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Jul 27, 2008
1 parent 1bd5191 commit e6305c4
Show file tree
Hide file tree
Showing 38 changed files with 74 additions and 87 deletions.
4 changes: 1 addition & 3 deletions fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,6 @@ extern bool afs_cm_incoming_call(struct afs_call *);
extern const struct inode_operations afs_dir_inode_operations;
extern const struct file_operations afs_dir_file_operations;

extern int afs_permission(struct inode *, int, struct nameidata *);

/*
* file.c
*/
Expand Down Expand Up @@ -605,7 +603,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, struct nameidata *);
extern int afs_permission(struct inode *, int);

/*
* server.c
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,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, struct nameidata *nd)
int afs_permission(struct inode *inode, int mask)
{
struct afs_vnode *vnode = AFS_FS_I(inode);
afs_access_t uninitialized_var(access);
Expand Down
3 changes: 1 addition & 2 deletions fs/bad_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,7 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
return -EIO;
}

static int bad_inode_permission(struct inode *inode, int mask,
struct nameidata *nd)
static int bad_inode_permission(struct inode *inode, int mask)
{
return -EIO;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
return 0;
}

static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
static int cifs_permission(struct inode *inode, int mask)
{
struct cifs_sb_info *cifs_sb;

Expand Down
4 changes: 3 additions & 1 deletion fs/coda/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,11 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
}


int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
int coda_permission(struct inode *inode, int mask)
{
int error = 0;

mask &= MAY_READ | MAY_WRITE | MAY_EXEC;

if (!mask)
return 0;
Expand Down
6 changes: 2 additions & 4 deletions fs/coda/pioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
#include <linux/coda_psdev.h>

/* pioctl ops */
static int coda_ioctl_permission(struct inode *inode, int mask,
struct nameidata *nd);
static int coda_ioctl_permission(struct inode *inode, int mask);
static int coda_pioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long user_data);

Expand All @@ -42,8 +41,7 @@ const struct file_operations coda_ioctl_operations = {
};

/* the coda pioctl inode ops */
static int coda_ioctl_permission(struct inode *inode, int mask,
struct nameidata *nd)
static int coda_ioctl_permission(struct inode *inode, int mask)
{
return 0;
}
Expand Down
17 changes: 2 additions & 15 deletions fs/ecryptfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,22 +830,9 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
}

static int
ecryptfs_permission(struct inode *inode, int mask, struct nameidata *nd)
ecryptfs_permission(struct inode *inode, int mask)
{
int rc;

if (nd) {
struct vfsmount *vfsmnt_save = nd->path.mnt;
struct dentry *dentry_save = nd->path.dentry;

nd->path.mnt = ecryptfs_dentry_to_lower_mnt(nd->path.dentry);
nd->path.dentry = ecryptfs_dentry_to_lower(nd->path.dentry);
rc = permission(ecryptfs_inode_to_lower(inode), mask, nd);
nd->path.mnt = vfsmnt_save;
nd->path.dentry = dentry_save;
} else
rc = permission(ecryptfs_inode_to_lower(inode), mask, NULL);
return rc;
return permission(ecryptfs_inode_to_lower(inode), mask, NULL);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion fs/ext2/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ ext2_check_acl(struct inode *inode, int mask)
}

int
ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
ext2_permission(struct inode *inode, int mask)
{
return generic_permission(inode, mask, ext2_check_acl);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/ext2/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static inline int ext2_acl_count(size_t size)
#define EXT2_ACL_NOT_CACHED ((void *)-1)

/* acl.c */
extern int ext2_permission (struct inode *, int, struct nameidata *);
extern int ext2_permission (struct inode *, int);
extern int ext2_acl_chmod (struct inode *);
extern int ext2_init_acl (struct inode *, struct inode *);

Expand Down
2 changes: 1 addition & 1 deletion fs/ext3/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ ext3_check_acl(struct inode *inode, int mask)
}

int
ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
ext3_permission(struct inode *inode, int mask)
{
return generic_permission(inode, mask, ext3_check_acl);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/ext3/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static inline int ext3_acl_count(size_t size)
#define EXT3_ACL_NOT_CACHED ((void *)-1)

/* acl.c */
extern int ext3_permission (struct inode *, int, struct nameidata *);
extern int ext3_permission (struct inode *, int);
extern int ext3_acl_chmod (struct inode *);
extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);

Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ ext4_check_acl(struct inode *inode, int mask)
}

int
ext4_permission(struct inode *inode, int mask, struct nameidata *nd)
ext4_permission(struct inode *inode, int mask)
{
return generic_permission(inode, mask, ext4_check_acl);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static inline int ext4_acl_count(size_t size)
#define EXT4_ACL_NOT_CACHED ((void *)-1)

/* acl.c */
extern int ext4_permission (struct inode *, int, struct nameidata *);
extern int ext4_permission (struct inode *, int);
extern int ext4_acl_chmod (struct inode *);
extern int ext4_init_acl (handle_t *, struct inode *, struct inode *);

Expand Down
6 changes: 3 additions & 3 deletions fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ static int fuse_access(struct inode *inode, int mask)
return PTR_ERR(req);

memset(&inarg, 0, sizeof(inarg));
inarg.mask = mask;
inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
req->in.h.opcode = FUSE_ACCESS;
req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
Expand Down Expand Up @@ -927,7 +927,7 @@ static int fuse_access(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, struct nameidata *nd)
static int fuse_permission(struct inode *inode, int mask)
{
struct fuse_conn *fc = get_fuse_conn(inode);
bool refreshed = false;
Expand Down Expand Up @@ -962,7 +962,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
exist. So if permissions are revoked this won't be
noticed immediately, only after the attribute
timeout has expired */
} else if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) {
} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
err = fuse_access(inode, mask);
} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
if (!(inode->i_mode & S_IXUGO)) {
Expand Down
12 changes: 3 additions & 9 deletions fs/gfs2/ops_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,12 +915,6 @@ int gfs2_permission(struct inode *inode, int mask)
return error;
}

static int gfs2_iop_permission(struct inode *inode, int mask,
struct nameidata *nd)
{
return gfs2_permission(inode, mask);
}

static int setattr_size(struct inode *inode, struct iattr *attr)
{
struct gfs2_inode *ip = GFS2_I(inode);
Expand Down Expand Up @@ -1150,7 +1144,7 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
}

const struct inode_operations gfs2_file_iops = {
.permission = gfs2_iop_permission,
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
.setxattr = gfs2_setxattr,
Expand All @@ -1169,7 +1163,7 @@ const struct inode_operations gfs2_dir_iops = {
.rmdir = gfs2_rmdir,
.mknod = gfs2_mknod,
.rename = gfs2_rename,
.permission = gfs2_iop_permission,
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
.setxattr = gfs2_setxattr,
Expand All @@ -1181,7 +1175,7 @@ const struct inode_operations gfs2_dir_iops = {
const struct inode_operations gfs2_symlink_iops = {
.readlink = gfs2_readlink,
.follow_link = gfs2_follow_link,
.permission = gfs2_iop_permission,
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
.setxattr = gfs2_setxattr,
Expand Down
3 changes: 1 addition & 2 deletions fs/hfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,7 @@ void hfs_clear_inode(struct inode *inode)
}
}

static int hfs_permission(struct inode *inode, int mask,
struct nameidata *nd)
static int hfs_permission(struct inode *inode, int mask)
{
if (S_ISREG(inode->i_mode) && mask & MAY_EXEC)
return 0;
Expand Down
2 changes: 1 addition & 1 deletion fs/hfsplus/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ static void hfsplus_set_perms(struct inode *inode, struct hfsplus_perm *perms)
perms->dev = cpu_to_be32(HFSPLUS_I(inode).dev);
}

static int hfsplus_permission(struct inode *inode, int mask, struct nameidata *nd)
static int hfsplus_permission(struct inode *inode, int mask)
{
/* MAY_EXEC is also used for lookup, if no x bit is set allow lookup,
* open_exec has the same test, so it's still not executable, if a x bit
Expand Down
2 changes: 1 addition & 1 deletion fs/hostfs/hostfs_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from,
return err;
}

int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
int hostfs_permission(struct inode *ino, int desired)
{
char *name;
int r = 0, w = 0, x = 0, err;
Expand Down
2 changes: 1 addition & 1 deletion fs/jffs2/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ static int jffs2_check_acl(struct inode *inode, int mask)
return -EAGAIN;
}

int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
int jffs2_permission(struct inode *inode, int mask)
{
return generic_permission(inode, mask, jffs2_check_acl);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/jffs2/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct jffs2_acl_header {

#define JFFS2_ACL_NOT_CACHED ((void *)-1)

extern int jffs2_permission(struct inode *, int, struct nameidata *);
extern int jffs2_permission(struct inode *, int);
extern int jffs2_acl_chmod(struct inode *);
extern int jffs2_init_acl_pre(struct inode *, struct inode *, int *);
extern int jffs2_init_acl_post(struct inode *);
Expand Down
2 changes: 1 addition & 1 deletion fs/jfs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static int jfs_check_acl(struct inode *inode, int mask)
return -EAGAIN;
}

int jfs_permission(struct inode *inode, int mask, struct nameidata *nd)
int jfs_permission(struct inode *inode, int mask)
{
return generic_permission(inode, mask, jfs_check_acl);
}
Expand Down
2 changes: 1 addition & 1 deletion fs/jfs/jfs_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

#ifdef CONFIG_JFS_POSIX_ACL

int jfs_permission(struct inode *, int, struct nameidata *);
int jfs_permission(struct inode *, int);
int jfs_init_acl(tid_t, struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *);

Expand Down
23 changes: 17 additions & 6 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ int generic_permission(struct inode *inode, int mask,
{
umode_t mode = inode->i_mode;

mask &= MAY_READ | MAY_WRITE | MAY_EXEC;

if (current->fsuid == inode->i_uid)
mode >>= 6;
else {
Expand All @@ -203,7 +205,7 @@ int generic_permission(struct inode *inode, int mask,
/*
* If the DACs are ok we don't need any capability check.
*/
if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
if ((mask & ~mode) == 0)
return 0;

check_capabilities:
Expand All @@ -228,7 +230,7 @@ int generic_permission(struct inode *inode, int mask,

int permission(struct inode *inode, int mask, struct nameidata *nd)
{
int retval, submask;
int retval;
struct vfsmount *mnt = NULL;

if (nd)
Expand Down Expand Up @@ -261,9 +263,17 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
}

/* Ordinary permission routines do not understand MAY_APPEND. */
submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission) {
retval = inode->i_op->permission(inode, submask, nd);
int extra = 0;
if (nd) {
if (nd->flags & LOOKUP_ACCESS)
extra |= MAY_ACCESS;
if (nd->flags & LOOKUP_CHDIR)
extra |= MAY_CHDIR;
if (nd->flags & LOOKUP_OPEN)
extra |= MAY_OPEN;
}
retval = inode->i_op->permission(inode, mask | extra);
if (!retval) {
/*
* Exec permission on a regular file is denied if none
Expand All @@ -277,7 +287,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
return -EACCES;
}
} else {
retval = generic_permission(inode, submask, NULL);
retval = generic_permission(inode, mask, NULL);
}
if (retval)
return retval;
Expand All @@ -286,7 +296,8 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
if (retval)
return retval;

return security_inode_permission(inode, mask, nd);
return security_inode_permission(inode,
mask & (MAY_READ|MAY_WRITE|MAY_EXEC), nd);
}

/**
Expand Down
11 changes: 5 additions & 6 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1884,7 +1884,7 @@ static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
return status;
nfs_access_add_cache(inode, &cache);
out:
if ((cache.mask & mask) == mask)
if ((mask & ~cache.mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
return 0;
return -EACCES;
}
Expand All @@ -1907,17 +1907,17 @@ int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags)
return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags));
}

int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
int nfs_permission(struct inode *inode, int mask)
{
struct rpc_cred *cred;
int res = 0;

nfs_inc_stats(inode, NFSIOS_VFSACCESS);

if (mask == 0)
if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0)
goto out;
/* Is this sys_access() ? */
if (nd != NULL && (nd->flags & LOOKUP_ACCESS))
if (mask & MAY_ACCESS)
goto force_lookup;

switch (inode->i_mode & S_IFMT) {
Expand All @@ -1926,8 +1926,7 @@ int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
case S_IFREG:
/* NFSv4 has atomic_open... */
if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
&& nd != NULL
&& (nd->flags & LOOKUP_OPEN))
&& (mask & MAY_OPEN))
goto out;
break;
case S_IFDIR:
Expand Down
Loading

0 comments on commit e6305c4

Please sign in to comment.