From: Erez Zadok Date: Fri, 2 Nov 2007 00:33:12 +0000 (-0400) Subject: Unionfs: cleanup permission checking code X-Git-Url: https://git.fsl.cs.sunysb.edu/?a=commitdiff_plain;h=32fe4f47736622c45c5596fda1ef86e9aec61a90;p=unionfs-3.14.y.git Unionfs: cleanup permission checking code Use vfs helpers and avoid redundant checks performed by the VFS already. Signed-off-by: Erez Zadok --- diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c index 7654bcb79517..50e57756e9cb 100644 --- a/fs/unionfs/commonfops.c +++ b/fs/unionfs/commonfops.c @@ -669,10 +669,6 @@ static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) lower_file = unionfs_lower_file(file); - err = security_file_ioctl(lower_file, cmd, arg); - if (err) - goto out; - err = -ENOTTY; if (!lower_file || !lower_file->f_op) goto out; diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c index f4facf42a9c3..169365c2bfbe 100644 --- a/fs/unionfs/inode.c +++ b/fs/unionfs/inode.c @@ -913,59 +913,6 @@ static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd, unionfs_read_unlock(dentry->d_sb); } -/* - * Basically copied from the kernel vfs permission(), but we've changed - * the following: - * (1) the IS_RDONLY check is skipped, and - * (2) We return 0 (success) if the non-leftmost branch is mounted - * readonly, to allow copyup to work. - * (3) we do call security_inode_permission, and therefore security inside - * SELinux, etc. are performed. - * - * @inode: the lower inode we're checking permission on - */ -static int inode_permission(struct super_block *sb, struct inode *inode, - int mask, struct nameidata *nd, int bindex) -{ - int retval, submask; - - if (mask & MAY_WRITE) { - umode_t mode = inode->i_mode; - /* The first branch is allowed to be really readonly. */ - if (bindex == 0 && - IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; - /* - * Nobody gets write access to an immutable file. - */ - if (IS_IMMUTABLE(inode)) - return -EACCES; - /* - * For all other branches than the first one, we ignore - * EROFS or if the branch is mounted as readonly, to let - * copyup take place. - */ - if (bindex > 0 && - is_robranch_super(sb, bindex) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return 0; - } - - /* 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); - else - retval = generic_permission(inode, submask, NULL); - - if (retval && retval != -EROFS) /* ignore EROFS */ - return retval; - - retval = security_inode_permission(inode, mask, nd); - return ((retval == -EROFS) ? 0 : retval); /* ignore EROFS */ -} - /* * Don't grab the superblock read-lock in unionfs_permission, which prevents * a deadlock with the branch-management "add branch" code (which grabbed @@ -1011,11 +958,20 @@ static int unionfs_permission(struct inode *inode, int mask, continue; /* - * We use our own special version of permission, such that - * only the first branch returns -EROFS. + * We check basic permissions, but we ignore any conditions + * such as readonly file systems or branches marked as + * readonly, because those conditions should lead to a + * copyup taking place later on. */ - err = inode_permission(inode->i_sb, lower_inode, mask, nd, - bindex); + err = permission(lower_inode, mask, nd); + if (err && bindex > 0) { + umode_t mode = lower_inode->i_mode; + if (is_robranch_super(inode->i_sb, bindex) && + (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) + err = 0; + if (IS_COPYUP_ERR(err)) + err = 0; + } /* * The permissions are an intersection of the overall directory