diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2006-04-26 02:32:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-26 10:52:21 -0400 |
commit | a090d9132c1e53e3517111123680c15afb25c0a4 (patch) | |
tree | 7654cbd50a49d1140c71112ce79387bfbc6c0c86 /fs | |
parent | 6ad0013b316367671ef316cff91ab2d912e309c9 (diff) |
[PATCH] protect ext3 ioctl modifying append_only, immutable, etc. with i_mutex
All modifications of ->i_flags in inodes that might be visible to
somebody else must be under ->i_mutex. That patch fixes ext3 ioctl()
setting S_APPEND and friends.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext3/ioctl.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index aaf1da17b6d4..8c22aa9a7fbb 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c | |||
@@ -48,6 +48,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
48 | if (!S_ISDIR(inode->i_mode)) | 48 | if (!S_ISDIR(inode->i_mode)) |
49 | flags &= ~EXT3_DIRSYNC_FL; | 49 | flags &= ~EXT3_DIRSYNC_FL; |
50 | 50 | ||
51 | mutex_lock(&inode->i_mutex); | ||
51 | oldflags = ei->i_flags; | 52 | oldflags = ei->i_flags; |
52 | 53 | ||
53 | /* The JOURNAL_DATA flag is modifiable only by root */ | 54 | /* The JOURNAL_DATA flag is modifiable only by root */ |
@@ -60,8 +61,10 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
60 | * This test looks nicer. Thanks to Pauline Middelink | 61 | * This test looks nicer. Thanks to Pauline Middelink |
61 | */ | 62 | */ |
62 | if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { | 63 | if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { |
63 | if (!capable(CAP_LINUX_IMMUTABLE)) | 64 | if (!capable(CAP_LINUX_IMMUTABLE)) { |
65 | mutex_unlock(&inode->i_mutex); | ||
64 | return -EPERM; | 66 | return -EPERM; |
67 | } | ||
65 | } | 68 | } |
66 | 69 | ||
67 | /* | 70 | /* |
@@ -69,14 +72,18 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
69 | * the relevant capability. | 72 | * the relevant capability. |
70 | */ | 73 | */ |
71 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { | 74 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { |
72 | if (!capable(CAP_SYS_RESOURCE)) | 75 | if (!capable(CAP_SYS_RESOURCE)) { |
76 | mutex_unlock(&inode->i_mutex); | ||
73 | return -EPERM; | 77 | return -EPERM; |
78 | } | ||
74 | } | 79 | } |
75 | 80 | ||
76 | 81 | ||
77 | handle = ext3_journal_start(inode, 1); | 82 | handle = ext3_journal_start(inode, 1); |
78 | if (IS_ERR(handle)) | 83 | if (IS_ERR(handle)) { |
84 | mutex_unlock(&inode->i_mutex); | ||
79 | return PTR_ERR(handle); | 85 | return PTR_ERR(handle); |
86 | } | ||
80 | if (IS_SYNC(inode)) | 87 | if (IS_SYNC(inode)) |
81 | handle->h_sync = 1; | 88 | handle->h_sync = 1; |
82 | err = ext3_reserve_inode_write(handle, inode, &iloc); | 89 | err = ext3_reserve_inode_write(handle, inode, &iloc); |
@@ -93,11 +100,14 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, | |||
93 | err = ext3_mark_iloc_dirty(handle, inode, &iloc); | 100 | err = ext3_mark_iloc_dirty(handle, inode, &iloc); |
94 | flags_err: | 101 | flags_err: |
95 | ext3_journal_stop(handle); | 102 | ext3_journal_stop(handle); |
96 | if (err) | 103 | if (err) { |
104 | mutex_unlock(&inode->i_mutex); | ||
97 | return err; | 105 | return err; |
106 | } | ||
98 | 107 | ||
99 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) | 108 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) |
100 | err = ext3_change_inode_journal_flag(inode, jflag); | 109 | err = ext3_change_inode_journal_flag(inode, jflag); |
110 | mutex_unlock(&inode->i_mutex); | ||
101 | return err; | 111 | return err; |
102 | } | 112 | } |
103 | case EXT3_IOC_GETVERSION: | 113 | case EXT3_IOC_GETVERSION: |