[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>
This commit is contained in:
parent
6ad0013b31
commit
a090d9132c
|
@ -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,8 +61,10 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -69,14 +72,18 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
|
||||||
* 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,
|
||||||
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:
|
||||||
|
|
Loading…
Reference in New Issue