Commit a090d913 authored by Al Viro's avatar Al Viro Committed by Linus Torvalds

[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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6ad0013b
...@@ -48,6 +48,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -48,6 +48,7 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
flags &= ~EXT3_DIRSYNC_FL; flags &= ~EXT3_DIRSYNC_FL;
mutex_lock(&inode->i_mutex);
oldflags = ei->i_flags; oldflags = ei->i_flags;
/* The JOURNAL_DATA flag is modifiable only by root */ /* The JOURNAL_DATA flag is modifiable only by root */
...@@ -60,23 +61,29 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, ...@@ -60,23 +61,29 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
* This test looks nicer. Thanks to Pauline Middelink * This test looks nicer. Thanks to Pauline Middelink
*/ */
if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
if (!capable(CAP_LINUX_IMMUTABLE)) if (!capable(CAP_LINUX_IMMUTABLE)) {
mutex_unlock(&inode->i_mutex);
return -EPERM; return -EPERM;
} }
}
/* /*
* The JOURNAL_DATA flag can only be changed by * The JOURNAL_DATA flag can only be changed by
* the relevant capability. * the relevant capability.
*/ */
if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
if (!capable(CAP_SYS_RESOURCE)) if (!capable(CAP_SYS_RESOURCE)) {
mutex_unlock(&inode->i_mutex);
return -EPERM; return -EPERM;
} }
}
handle = ext3_journal_start(inode, 1); handle = ext3_journal_start(inode, 1);
if (IS_ERR(handle)) if (IS_ERR(handle)) {
mutex_unlock(&inode->i_mutex);
return PTR_ERR(handle); return PTR_ERR(handle);
}
if (IS_SYNC(inode)) if (IS_SYNC(inode))
handle->h_sync = 1; handle->h_sync = 1;
err = ext3_reserve_inode_write(handle, inode, &iloc); 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,11 +100,14 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
err = ext3_mark_iloc_dirty(handle, inode, &iloc); err = ext3_mark_iloc_dirty(handle, inode, &iloc);
flags_err: flags_err:
ext3_journal_stop(handle); ext3_journal_stop(handle);
if (err) if (err) {
mutex_unlock(&inode->i_mutex);
return err; return err;
}
if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
err = ext3_change_inode_journal_flag(inode, jflag); err = ext3_change_inode_journal_flag(inode, jflag);
mutex_unlock(&inode->i_mutex);
return err; return err;
} }
case EXT3_IOC_GETVERSION: case EXT3_IOC_GETVERSION:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment