chown/chmod,etc...  don't call permission in the same way that the normal
"open for write" calls do.  They still write to the filesystem, so bump the
write count during these operations.

This conflicts with the current (~2.6.23-rc7) audit git tree in -mm. 
wiggle'ing the patch merges it.

Signed-off-by: Dave Hansen <[EMAIL PROTECTED]>
Acked-by: Christoph Hellwig <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 linux-2.6.git-dave/fs/open.c |   39 ++++++++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 9 deletions(-)

diff -puN fs/open.c~r-o-bind-mounts-elevate-writer-count-for-chown-and-friends 
fs/open.c
--- 
linux-2.6.git/fs/open.c~r-o-bind-mounts-elevate-writer-count-for-chown-and-friends
  2007-11-01 14:46:17.000000000 -0700
+++ linux-2.6.git-dave/fs/open.c        2007-11-01 14:46:17.000000000 -0700
@@ -571,12 +571,12 @@ asmlinkage long sys_fchmod(unsigned int 
 
        audit_inode(NULL, dentry);
 
-       err = -EROFS;
-       if (IS_RDONLY(inode))
+       err = mnt_want_write(file->f_vfsmnt);
+       if (err)
                goto out_putf;
        err = -EPERM;
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto out_putf;
+               goto out_drop_write;
        mutex_lock(&inode->i_mutex);
        if (mode == (mode_t) -1)
                mode = inode->i_mode;
@@ -585,6 +585,8 @@ asmlinkage long sys_fchmod(unsigned int 
        err = notify_change(dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
 
+out_drop_write:
+       mnt_drop_write(file->f_vfsmnt);
 out_putf:
        fput(file);
 out:
@@ -604,13 +606,13 @@ asmlinkage long sys_fchmodat(int dfd, co
                goto out;
        inode = nd.dentry->d_inode;
 
-       error = -EROFS;
-       if (IS_RDONLY(inode))
+       error = mnt_want_write(nd.mnt);
+       if (error)
                goto dput_and_out;
 
        error = -EPERM;
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-               goto dput_and_out;
+               goto out_drop_write;
 
        mutex_lock(&inode->i_mutex);
        if (mode == (mode_t) -1)
@@ -620,6 +622,8 @@ asmlinkage long sys_fchmodat(int dfd, co
        error = notify_change(nd.dentry, &newattrs);
        mutex_unlock(&inode->i_mutex);
 
+out_drop_write:
+       mnt_drop_write(nd.mnt);
 dput_and_out:
        path_release(&nd);
 out:
@@ -642,9 +646,6 @@ static int chown_common(struct dentry * 
                printk(KERN_ERR "chown_common: NULL inode\n");
                goto out;
        }
-       error = -EROFS;
-       if (IS_RDONLY(inode))
-               goto out;
        error = -EPERM;
        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                goto out;
@@ -675,7 +676,12 @@ asmlinkage long sys_chown(const char __u
        error = user_path_walk(filename, &nd);
        if (error)
                goto out;
+       error = mnt_want_write(nd.mnt);
+       if (error)
+               goto out_release;
        error = chown_common(nd.dentry, user, group);
+       mnt_drop_write(nd.mnt);
+out_release:
        path_release(&nd);
 out:
        return error;
@@ -695,7 +701,12 @@ asmlinkage long sys_fchownat(int dfd, co
        error = __user_walk_fd(dfd, filename, follow, &nd);
        if (error)
                goto out;
+       error = mnt_want_write(nd.mnt);
+       if (error)
+               goto out_release;
        error = chown_common(nd.dentry, user, group);
+       mnt_drop_write(nd.mnt);
+out_release:
        path_release(&nd);
 out:
        return error;
@@ -709,7 +720,12 @@ asmlinkage long sys_lchown(const char __
        error = user_path_walk_link(filename, &nd);
        if (error)
                goto out;
+       error = mnt_want_write(nd.mnt);
+       if (error)
+               goto out_release;
        error = chown_common(nd.dentry, user, group);
+       mnt_drop_write(nd.mnt);
+out_release:
        path_release(&nd);
 out:
        return error;
@@ -726,9 +742,14 @@ asmlinkage long sys_fchown(unsigned int 
        if (!file)
                goto out;
 
+       error = mnt_want_write(file->f_vfsmnt);
+       if (error)
+               goto out_fput;
        dentry = file->f_path.dentry;
        audit_inode(NULL, dentry);
        error = chown_common(dentry, user, group);
+       mnt_drop_write(file->f_vfsmnt);
+out_fput:
        fput(file);
 out:
        return error;
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to