Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Djalal Harouni and committed by
Jan Kara
34b07840 353b67d8

+16 -6
+16 -6
fs/ext2/ioctl.c
··· 77 77 flags = flags & EXT2_FL_USER_MODIFIABLE; 78 78 flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE; 79 79 ei->i_flags = flags; 80 - mutex_unlock(&inode->i_mutex); 81 80 82 81 ext2_set_inode_flags(inode); 83 82 inode->i_ctime = CURRENT_TIME_SEC; 83 + mutex_unlock(&inode->i_mutex); 84 + 84 85 mark_inode_dirty(inode); 85 86 setflags_out: 86 87 mnt_drop_write_file(filp); ··· 89 88 } 90 89 case EXT2_IOC_GETVERSION: 91 90 return put_user(inode->i_generation, (int __user *) arg); 92 - case EXT2_IOC_SETVERSION: 91 + case EXT2_IOC_SETVERSION: { 92 + __u32 generation; 93 + 93 94 if (!inode_owner_or_capable(inode)) 94 95 return -EPERM; 95 96 ret = mnt_want_write_file(filp); 96 97 if (ret) 97 98 return ret; 98 - if (get_user(inode->i_generation, (int __user *) arg)) { 99 + if (get_user(generation, (int __user *) arg)) { 99 100 ret = -EFAULT; 100 - } else { 101 - inode->i_ctime = CURRENT_TIME_SEC; 102 - mark_inode_dirty(inode); 101 + goto setversion_out; 103 102 } 103 + 104 + mutex_lock(&inode->i_mutex); 105 + inode->i_ctime = CURRENT_TIME_SEC; 106 + inode->i_generation = generation; 107 + mutex_unlock(&inode->i_mutex); 108 + 109 + mark_inode_dirty(inode); 110 + setversion_out: 104 111 mnt_drop_write_file(filp); 105 112 return ret; 113 + } 106 114 case EXT2_IOC_GETRSVSZ: 107 115 if (test_opt(inode->i_sb, RESERVATION) 108 116 && S_ISREG(inode->i_mode)