[patch 4/4] vfs: immutable inode checking cleanup
Miklos Szeredi [Tue, 1 Jul 2008 13:01:29 +0000 (15:01 +0200)]
Move the immutable and append-only checks from chmod, chown and utimes
into notify_change().  Checks for immutable and append-only files are
always performed by the VFS and not by the filesystem (see
permission() and may_...() in namei.c), so these belong in
notify_change(), and not in inode_change_ok().

This should be completely equivalent.

CC: Ulrich Drepper <drepper@redhat.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

fs/attr.c
fs/open.c
fs/utimes.c

index 765fc75..26c71ba 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -108,6 +108,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
        struct timespec now;
        unsigned int ia_valid = attr->ia_valid;
 
+       if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
+               if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+                       return -EPERM;
+       }
+
        now = current_fs_time(inode->i_sb);
 
        attr->ia_ctime = now;
index 3317e19..3b3c436 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -588,9 +588,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        err = mnt_want_write(file->f_path.mnt);
        if (err)
                goto out_putf;
-       err = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out_drop_write;
        mutex_lock(&inode->i_mutex);
        if (mode == (mode_t) -1)
                mode = inode->i_mode;
@@ -598,8 +595,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
        err = notify_change(dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
-
-out_drop_write:
        mnt_drop_write(file->f_path.mnt);
 out_putf:
        fput(file);
@@ -623,11 +618,6 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
        error = mnt_want_write(nd.path.mnt);
        if (error)
                goto dput_and_out;
-
-       error = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out_drop_write;
-
        mutex_lock(&inode->i_mutex);
        if (mode == (mode_t) -1)
                mode = inode->i_mode;
@@ -635,8 +625,6 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
        error = notify_change(nd.path.dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
-
-out_drop_write:
        mnt_drop_write(nd.path.mnt);
 dput_and_out:
        path_put(&nd.path);
@@ -651,18 +639,10 @@ asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
 
 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
 {
-       struct inode * inode;
+       struct inode *inode = dentry->d_inode;
        int error;
        struct iattr newattrs;
 
-       error = -ENOENT;
-       if (!(inode = dentry->d_inode)) {
-               printk(KERN_ERR "chown_common: NULL inode\n");
-               goto out;
-       }
-       error = -EPERM;
-       if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out;
        newattrs.ia_valid =  ATTR_CTIME;
        if (user != (uid_t) -1) {
                newattrs.ia_valid |= ATTR_UID;
@@ -678,7 +658,7 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
        mutex_lock(&inode->i_mutex);
        error = notify_change(dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
-out:
+
        return error;
 }
 
index 8e09dbd..dad679d 100644 (file)
@@ -64,10 +64,6 @@ static int utimes_common(struct path *path, struct timespec *times)
 
        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
        if (times) {
-               error = -EPERM;
-                if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-                       goto mnt_drop_write_and_out;
-
                if (times[0].tv_nsec == UTIME_OMIT)
                        newattrs.ia_valid &= ~ATTR_ATIME;
                else if (times[0].tv_nsec != UTIME_NOW) {