diff options
author | Dave Hansen <haveblue@us.ibm.com> | 2008-02-15 17:37:46 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-19 00:29:24 -0400 |
commit | 42a74f206b914db13ee1f5ae932dcd91a77c8579 (patch) | |
tree | 24e3dbe55edaacc750067ab9e01778255a6bff08 /fs/reiserfs | |
parent | 20ddee2c75339cc095f6191c3115f81da8955e96 (diff) |
[PATCH] r/o bind mounts: elevate write count for ioctls()
Some ioctl()s can cause writes to the filesystem. Take these, and make them
use mnt_want/drop_write() instead.
[AV: updated]
Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/reiserfs')
-rw-r--r-- | fs/reiserfs/ioctl.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index e0f0f098a52..74363a7aacb 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #include <linux/capability.h> | 5 | #include <linux/capability.h> |
6 | #include <linux/fs.h> | 6 | #include <linux/fs.h> |
7 | #include <linux/mount.h> | ||
7 | #include <linux/reiserfs_fs.h> | 8 | #include <linux/reiserfs_fs.h> |
8 | #include <linux/time.h> | 9 | #include <linux/time.h> |
9 | #include <asm/uaccess.h> | 10 | #include <asm/uaccess.h> |
@@ -25,6 +26,7 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
25 | unsigned long arg) | 26 | unsigned long arg) |
26 | { | 27 | { |
27 | unsigned int flags; | 28 | unsigned int flags; |
29 | int err = 0; | ||
28 | 30 | ||
29 | switch (cmd) { | 31 | switch (cmd) { |
30 | case REISERFS_IOC_UNPACK: | 32 | case REISERFS_IOC_UNPACK: |
@@ -48,50 +50,67 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
48 | if (!reiserfs_attrs(inode->i_sb)) | 50 | if (!reiserfs_attrs(inode->i_sb)) |
49 | return -ENOTTY; | 51 | return -ENOTTY; |
50 | 52 | ||
51 | if (IS_RDONLY(inode)) | 53 | err = mnt_want_write(filp->f_path.mnt); |
52 | return -EROFS; | 54 | if (err) |
55 | return err; | ||
53 | 56 | ||
54 | if (!is_owner_or_cap(inode)) | 57 | if (!is_owner_or_cap(inode)) { |
55 | return -EPERM; | 58 | err = -EPERM; |
56 | 59 | goto setflags_out; | |
57 | if (get_user(flags, (int __user *)arg)) | 60 | } |
58 | return -EFAULT; | 61 | if (get_user(flags, (int __user *)arg)) { |
59 | 62 | err = -EFAULT; | |
60 | /* Is it quota file? Do not allow user to mess with it. */ | 63 | goto setflags_out; |
61 | if (IS_NOQUOTA(inode)) | 64 | } |
62 | return -EPERM; | 65 | /* |
66 | * Is it quota file? Do not allow user to mess with it | ||
67 | */ | ||
68 | if (IS_NOQUOTA(inode)) { | ||
69 | err = -EPERM; | ||
70 | goto setflags_out; | ||
71 | } | ||
63 | if (((flags ^ REISERFS_I(inode)-> | 72 | if (((flags ^ REISERFS_I(inode)-> |
64 | i_attrs) & (REISERFS_IMMUTABLE_FL | | 73 | i_attrs) & (REISERFS_IMMUTABLE_FL | |
65 | REISERFS_APPEND_FL)) | 74 | REISERFS_APPEND_FL)) |
66 | && !capable(CAP_LINUX_IMMUTABLE)) | 75 | && !capable(CAP_LINUX_IMMUTABLE)) { |
67 | return -EPERM; | 76 | err = -EPERM; |
68 | 77 | goto setflags_out; | |
78 | } | ||
69 | if ((flags & REISERFS_NOTAIL_FL) && | 79 | if ((flags & REISERFS_NOTAIL_FL) && |
70 | S_ISREG(inode->i_mode)) { | 80 | S_ISREG(inode->i_mode)) { |
71 | int result; | 81 | int result; |
72 | 82 | ||
73 | result = reiserfs_unpack(inode, filp); | 83 | result = reiserfs_unpack(inode, filp); |
74 | if (result) | 84 | if (result) { |
75 | return result; | 85 | err = result; |
86 | goto setflags_out; | ||
87 | } | ||
76 | } | 88 | } |
77 | sd_attrs_to_i_attrs(flags, inode); | 89 | sd_attrs_to_i_attrs(flags, inode); |
78 | REISERFS_I(inode)->i_attrs = flags; | 90 | REISERFS_I(inode)->i_attrs = flags; |
79 | inode->i_ctime = CURRENT_TIME_SEC; | 91 | inode->i_ctime = CURRENT_TIME_SEC; |
80 | mark_inode_dirty(inode); | 92 | mark_inode_dirty(inode); |
81 | return 0; | 93 | setflags_out: |
94 | mnt_drop_write(filp->f_path.mnt); | ||
95 | return err; | ||
82 | } | 96 | } |
83 | case REISERFS_IOC_GETVERSION: | 97 | case REISERFS_IOC_GETVERSION: |
84 | return put_user(inode->i_generation, (int __user *)arg); | 98 | return put_user(inode->i_generation, (int __user *)arg); |
85 | case REISERFS_IOC_SETVERSION: | 99 | case REISERFS_IOC_SETVERSION: |
86 | if (!is_owner_or_cap(inode)) | 100 | if (!is_owner_or_cap(inode)) |
87 | return -EPERM; | 101 | return -EPERM; |
88 | if (IS_RDONLY(inode)) | 102 | err = mnt_want_write(filp->f_path.mnt); |
89 | return -EROFS; | 103 | if (err) |
90 | if (get_user(inode->i_generation, (int __user *)arg)) | 104 | return err; |
91 | return -EFAULT; | 105 | if (get_user(inode->i_generation, (int __user *)arg)) { |
106 | err = -EFAULT; | ||
107 | goto setversion_out; | ||
108 | } | ||
92 | inode->i_ctime = CURRENT_TIME_SEC; | 109 | inode->i_ctime = CURRENT_TIME_SEC; |
93 | mark_inode_dirty(inode); | 110 | mark_inode_dirty(inode); |
94 | return 0; | 111 | setversion_out: |
112 | mnt_drop_write(filp->f_path.mnt); | ||
113 | return err; | ||
95 | default: | 114 | default: |
96 | return -ENOTTY; | 115 | return -ENOTTY; |
97 | } | 116 | } |