Commit a090d9132c1e53e3517111123680c15afb25c0a4
Committed by
Linus Torvalds
1 parent
6ad0013b31
Exists in
master
and in
20 other branches
[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>
Showing 1 changed file with 14 additions and 4 deletions Side-by-side Diff
fs/ext3/ioctl.c
... | ... | @@ -48,6 +48,7 @@ |
48 | 48 | if (!S_ISDIR(inode->i_mode)) |
49 | 49 | flags &= ~EXT3_DIRSYNC_FL; |
50 | 50 | |
51 | + mutex_lock(&inode->i_mutex); | |
51 | 52 | oldflags = ei->i_flags; |
52 | 53 | |
53 | 54 | /* The JOURNAL_DATA flag is modifiable only by root */ |
54 | 55 | |
... | ... | @@ -60,8 +61,10 @@ |
60 | 61 | * This test looks nicer. Thanks to Pauline Middelink |
61 | 62 | */ |
62 | 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 | 66 | return -EPERM; |
67 | + } | |
65 | 68 | } |
66 | 69 | |
67 | 70 | /* |
68 | 71 | |
69 | 72 | |
70 | 73 | |
... | ... | @@ -69,14 +72,18 @@ |
69 | 72 | * the relevant capability. |
70 | 73 | */ |
71 | 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 | 77 | return -EPERM; |
78 | + } | |
74 | 79 | } |
75 | 80 | |
76 | 81 | |
77 | 82 | handle = ext3_journal_start(inode, 1); |
78 | - if (IS_ERR(handle)) | |
83 | + if (IS_ERR(handle)) { | |
84 | + mutex_unlock(&inode->i_mutex); | |
79 | 85 | return PTR_ERR(handle); |
86 | + } | |
80 | 87 | if (IS_SYNC(inode)) |
81 | 88 | handle->h_sync = 1; |
82 | 89 | err = ext3_reserve_inode_write(handle, inode, &iloc); |
83 | 90 | |
84 | 91 | |
... | ... | @@ -93,11 +100,14 @@ |
93 | 100 | err = ext3_mark_iloc_dirty(handle, inode, &iloc); |
94 | 101 | flags_err: |
95 | 102 | ext3_journal_stop(handle); |
96 | - if (err) | |
103 | + if (err) { | |
104 | + mutex_unlock(&inode->i_mutex); | |
97 | 105 | return err; |
106 | + } | |
98 | 107 | |
99 | 108 | if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) |
100 | 109 | err = ext3_change_inode_journal_flag(inode, jflag); |
110 | + mutex_unlock(&inode->i_mutex); | |
101 | 111 | return err; |
102 | 112 | } |
103 | 113 | case EXT3_IOC_GETVERSION: |