ext2: protect inode changes in the SETVERSION and SETFLAGS ioctls

Unlock mutex after i_flags and i_ctime updates in the EXT2_IOC_SETFLAGS
ioctl.

Use i_mutex in the EXT2_IOC_SETVERSION ioctl to protect i_ctime and
i_generation updates and make the ioctl consistent since i_mutex is
also used in other places to protect timestamps and inode changes.

Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: Jan Kara <jack@suse.cz>
Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
Djalal Harouni 2012-01-09 15:58:37 +01:00 committed by Jan Kara
parent 353b67d8ce
commit 34b0784056
1 changed files with 16 additions and 6 deletions

View File

@ -77,10 +77,11 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
flags = flags & EXT2_FL_USER_MODIFIABLE;
flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
ei->i_flags = flags;
mutex_unlock(&inode->i_mutex);
ext2_set_inode_flags(inode);
inode->i_ctime = CURRENT_TIME_SEC;
mutex_unlock(&inode->i_mutex);
mark_inode_dirty(inode);
setflags_out:
mnt_drop_write_file(filp);
@ -88,20 +89,29 @@ setflags_out:
}
case EXT2_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *) arg);
case EXT2_IOC_SETVERSION:
case EXT2_IOC_SETVERSION: {
__u32 generation;
if (!inode_owner_or_capable(inode))
return -EPERM;
ret = mnt_want_write_file(filp);
if (ret)
return ret;
if (get_user(inode->i_generation, (int __user *) arg)) {
if (get_user(generation, (int __user *) arg)) {
ret = -EFAULT;
} else {
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
goto setversion_out;
}
mutex_lock(&inode->i_mutex);
inode->i_ctime = CURRENT_TIME_SEC;
inode->i_generation = generation;
mutex_unlock(&inode->i_mutex);
mark_inode_dirty(inode);
setversion_out:
mnt_drop_write_file(filp);
return ret;
}
case EXT2_IOC_GETRSVSZ:
if (test_opt(inode->i_sb, RESERVATION)
&& S_ISREG(inode->i_mode)