ext{3,4}: Fix potential race when setversion ioctl updates inode
authorDjalal Harouni <tixxdz@opendz.org>
Tue, 3 Jan 2012 01:31:52 +0000 (02:31 +0100)
committerJan Kara <jack@suse.cz>
Mon, 9 Jan 2012 12:52:10 +0000 (13:52 +0100)
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>
fs/ext3/ioctl.c
fs/ext4/ioctl.c

index ba1b54e23cae14fd08b630db914b8f639908406d..e7b2ed9d36cc7cbc885ca35039fbe80146a047a8 100644 (file)
@@ -134,10 +134,11 @@ flags_out:
                        goto setversion_out;
                }
 
+               mutex_lock(&inode->i_mutex);
                handle = ext3_journal_start(inode, 1);
                if (IS_ERR(handle)) {
                        err = PTR_ERR(handle);
-                       goto setversion_out;
+                       goto unlock_out;
                }
                err = ext3_reserve_inode_write(handle, inode, &iloc);
                if (err == 0) {
@@ -146,6 +147,9 @@ flags_out:
                        err = ext3_mark_iloc_dirty(handle, inode, &iloc);
                }
                ext3_journal_stop(handle);
+
+unlock_out:
+               mutex_unlock(&inode->i_mutex);
 setversion_out:
                mnt_drop_write(filp->f_path.mnt);
                return err;
index a56796814d6ab1a564af494e23b57871f2121692..46a8de6f2089e521288fcdd05de022c4a7374810 100644 (file)
@@ -158,10 +158,11 @@ flags_out:
                        goto setversion_out;
                }
 
+               mutex_lock(&inode->i_mutex);
                handle = ext4_journal_start(inode, 1);
                if (IS_ERR(handle)) {
                        err = PTR_ERR(handle);
-                       goto setversion_out;
+                       goto unlock_out;
                }
                err = ext4_reserve_inode_write(handle, inode, &iloc);
                if (err == 0) {
@@ -170,6 +171,9 @@ flags_out:
                        err = ext4_mark_iloc_dirty(handle, inode, &iloc);
                }
                ext4_journal_stop(handle);
+
+unlock_out:
+               mutex_unlock(&inode->i_mutex);
 setversion_out:
                mnt_drop_write(filp->f_path.mnt);
                return err;