ext{3,4}: Fix potential race when setversion ioctl updates inode
The EXT{3,4}_IOC_SETVERSION ioctl() updates i_ctime and i_generation without i_mutex. This can lead to a race with the other operations that update i_ctime. This is not a big issue but let's make the ioctl consistent with how we handle e.g. other timestamp updates and use i_mutex to protect inode changes. Signed-off-by: Djalal Harouni <tixxdz@opendz.org> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
@@ -134,10 +134,11 @@ flags_out:
|
|||||||
goto setversion_out;
|
goto setversion_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&inode->i_mutex);
|
||||||
handle = ext3_journal_start(inode, 1);
|
handle = ext3_journal_start(inode, 1);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
err = PTR_ERR(handle);
|
err = PTR_ERR(handle);
|
||||||
goto setversion_out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
err = ext3_reserve_inode_write(handle, inode, &iloc);
|
err = ext3_reserve_inode_write(handle, inode, &iloc);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
@@ -146,6 +147,9 @@ flags_out:
|
|||||||
err = ext3_mark_iloc_dirty(handle, inode, &iloc);
|
err = ext3_mark_iloc_dirty(handle, inode, &iloc);
|
||||||
}
|
}
|
||||||
ext3_journal_stop(handle);
|
ext3_journal_stop(handle);
|
||||||
|
|
||||||
|
unlock_out:
|
||||||
|
mutex_unlock(&inode->i_mutex);
|
||||||
setversion_out:
|
setversion_out:
|
||||||
mnt_drop_write(filp->f_path.mnt);
|
mnt_drop_write(filp->f_path.mnt);
|
||||||
return err;
|
return err;
|
||||||
|
@@ -158,10 +158,11 @@ flags_out:
|
|||||||
goto setversion_out;
|
goto setversion_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&inode->i_mutex);
|
||||||
handle = ext4_journal_start(inode, 1);
|
handle = ext4_journal_start(inode, 1);
|
||||||
if (IS_ERR(handle)) {
|
if (IS_ERR(handle)) {
|
||||||
err = PTR_ERR(handle);
|
err = PTR_ERR(handle);
|
||||||
goto setversion_out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
err = ext4_reserve_inode_write(handle, inode, &iloc);
|
err = ext4_reserve_inode_write(handle, inode, &iloc);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
@@ -170,6 +171,9 @@ flags_out:
|
|||||||
err = ext4_mark_iloc_dirty(handle, inode, &iloc);
|
err = ext4_mark_iloc_dirty(handle, inode, &iloc);
|
||||||
}
|
}
|
||||||
ext4_journal_stop(handle);
|
ext4_journal_stop(handle);
|
||||||
|
|
||||||
|
unlock_out:
|
||||||
|
mutex_unlock(&inode->i_mutex);
|
||||||
setversion_out:
|
setversion_out:
|
||||||
mnt_drop_write(filp->f_path.mnt);
|
mnt_drop_write(filp->f_path.mnt);
|
||||||
return err;
|
return err;
|
||||||
|
Reference in New Issue
Block a user