aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2008-07-01 09:01:29 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-07-26 20:53:28 -0400
commitbeb29e058c35ab69e96e455a12ccf7505f6de425 (patch)
tree0da9869b7e0422c34423a02216db1a758a55a95a
parentb1da47e29e467f1ec36dc78d009bfb109fd533c7 (diff)
[patch 4/4] vfs: immutable inode checking cleanup
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>
-rw-r--r--fs/attr.c5
-rw-r--r--fs/open.c24
-rw-r--r--fs/utimes.c4
3 files changed, 7 insertions, 26 deletions
diff --git a/fs/attr.c b/fs/attr.c
index 765fc75fab3b..26c71ba1eed4 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -108,6 +108,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
108 struct timespec now; 108 struct timespec now;
109 unsigned int ia_valid = attr->ia_valid; 109 unsigned int ia_valid = attr->ia_valid;
110 110
111 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
112 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
113 return -EPERM;
114 }
115
111 now = current_fs_time(inode->i_sb); 116 now = current_fs_time(inode->i_sb);
112 117
113 attr->ia_ctime = now; 118 attr->ia_ctime = now;
diff --git a/fs/open.c b/fs/open.c
index 3317e1909b2c..3b3c43674be3 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -588,9 +588,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
588 err = mnt_want_write(file->f_path.mnt); 588 err = mnt_want_write(file->f_path.mnt);
589 if (err) 589 if (err)
590 goto out_putf; 590 goto out_putf;
591 err = -EPERM;
592 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
593 goto out_drop_write;
594 mutex_lock(&inode->i_mutex); 591 mutex_lock(&inode->i_mutex);
595 if (mode == (mode_t) -1) 592 if (mode == (mode_t) -1)
596 mode = inode->i_mode; 593 mode = inode->i_mode;
@@ -598,8 +595,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
598 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 595 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
599 err = notify_change(dentry, &newattrs); 596 err = notify_change(dentry, &newattrs);
600 mutex_unlock(&inode->i_mutex); 597 mutex_unlock(&inode->i_mutex);
601
602out_drop_write:
603 mnt_drop_write(file->f_path.mnt); 598 mnt_drop_write(file->f_path.mnt);
604out_putf: 599out_putf:
605 fput(file); 600 fput(file);
@@ -623,11 +618,6 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
623 error = mnt_want_write(nd.path.mnt); 618 error = mnt_want_write(nd.path.mnt);
624 if (error) 619 if (error)
625 goto dput_and_out; 620 goto dput_and_out;
626
627 error = -EPERM;
628 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
629 goto out_drop_write;
630
631 mutex_lock(&inode->i_mutex); 621 mutex_lock(&inode->i_mutex);
632 if (mode == (mode_t) -1) 622 if (mode == (mode_t) -1)
633 mode = inode->i_mode; 623 mode = inode->i_mode;
@@ -635,8 +625,6 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
635 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 625 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
636 error = notify_change(nd.path.dentry, &newattrs); 626 error = notify_change(nd.path.dentry, &newattrs);
637 mutex_unlock(&inode->i_mutex); 627 mutex_unlock(&inode->i_mutex);
638
639out_drop_write:
640 mnt_drop_write(nd.path.mnt); 628 mnt_drop_write(nd.path.mnt);
641dput_and_out: 629dput_and_out:
642 path_put(&nd.path); 630 path_put(&nd.path);
@@ -651,18 +639,10 @@ asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
651 639
652static int chown_common(struct dentry * dentry, uid_t user, gid_t group) 640static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
653{ 641{
654 struct inode * inode; 642 struct inode *inode = dentry->d_inode;
655 int error; 643 int error;
656 struct iattr newattrs; 644 struct iattr newattrs;
657 645
658 error = -ENOENT;
659 if (!(inode = dentry->d_inode)) {
660 printk(KERN_ERR "chown_common: NULL inode\n");
661 goto out;
662 }
663 error = -EPERM;
664 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
665 goto out;
666 newattrs.ia_valid = ATTR_CTIME; 646 newattrs.ia_valid = ATTR_CTIME;
667 if (user != (uid_t) -1) { 647 if (user != (uid_t) -1) {
668 newattrs.ia_valid |= ATTR_UID; 648 newattrs.ia_valid |= ATTR_UID;
@@ -678,7 +658,7 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
678 mutex_lock(&inode->i_mutex); 658 mutex_lock(&inode->i_mutex);
679 error = notify_change(dentry, &newattrs); 659 error = notify_change(dentry, &newattrs);
680 mutex_unlock(&inode->i_mutex); 660 mutex_unlock(&inode->i_mutex);
681out: 661
682 return error; 662 return error;
683} 663}
684 664
diff --git a/fs/utimes.c b/fs/utimes.c
index 8e09dbdfd7f5..dad679d3a158 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -64,10 +64,6 @@ static int utimes_common(struct path *path, struct timespec *times)
64 64
65 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 65 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
66 if (times) { 66 if (times) {
67 error = -EPERM;
68 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
69 goto mnt_drop_write_and_out;
70
71 if (times[0].tv_nsec == UTIME_OMIT) 67 if (times[0].tv_nsec == UTIME_OMIT)
72 newattrs.ia_valid &= ~ATTR_ATIME; 68 newattrs.ia_valid &= ~ATTR_ATIME;
73 else if (times[0].tv_nsec != UTIME_NOW) { 69 else if (times[0].tv_nsec != UTIME_NOW) {