Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34b07840 authored by Djalal Harouni's avatar Djalal Harouni Committed by Jan Kara
Browse files

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: default avatarDjalal Harouni <tixxdz@opendz.org>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 353b67d8
Loading
Loading
Loading
Loading
+16 −6
Original line number Original line Diff line number Diff line
@@ -77,10 +77,11 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		flags = flags & EXT2_FL_USER_MODIFIABLE;
		flags = flags & EXT2_FL_USER_MODIFIABLE;
		flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
		flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
		ei->i_flags = flags;
		ei->i_flags = flags;
		mutex_unlock(&inode->i_mutex);


		ext2_set_inode_flags(inode);
		ext2_set_inode_flags(inode);
		inode->i_ctime = CURRENT_TIME_SEC;
		inode->i_ctime = CURRENT_TIME_SEC;
		mutex_unlock(&inode->i_mutex);

		mark_inode_dirty(inode);
		mark_inode_dirty(inode);
setflags_out:
setflags_out:
		mnt_drop_write_file(filp);
		mnt_drop_write_file(filp);
@@ -88,20 +89,29 @@ setflags_out:
	}
	}
	case EXT2_IOC_GETVERSION:
	case EXT2_IOC_GETVERSION:
		return put_user(inode->i_generation, (int __user *) arg);
		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))
		if (!inode_owner_or_capable(inode))
			return -EPERM;
			return -EPERM;
		ret = mnt_want_write_file(filp);
		ret = mnt_want_write_file(filp);
		if (ret)
		if (ret)
			return ret;
			return ret;
		if (get_user(inode->i_generation, (int __user *) arg)) {
		if (get_user(generation, (int __user *) arg)) {
			ret = -EFAULT;
			ret = -EFAULT;
		} else {
			goto setversion_out;
		}

		mutex_lock(&inode->i_mutex);
		inode->i_ctime = CURRENT_TIME_SEC;
		inode->i_ctime = CURRENT_TIME_SEC;
		inode->i_generation = generation;
		mutex_unlock(&inode->i_mutex);

		mark_inode_dirty(inode);
		mark_inode_dirty(inode);
		}
setversion_out:
		mnt_drop_write_file(filp);
		mnt_drop_write_file(filp);
		return ret;
		return ret;
	}
	case EXT2_IOC_GETRSVSZ:
	case EXT2_IOC_GETRSVSZ:
		if (test_opt(inode->i_sb, RESERVATION)
		if (test_opt(inode->i_sb, RESERVATION)
			&& S_ISREG(inode->i_mode)
			&& S_ISREG(inode->i_mode)