Message ID | 1536710238-16858-1-git-send-email-wshilong1991@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | [v3,1/3] ext4: fix setattr project check upon fssetxattr ioctl | expand |
On Wed, Sep 12, 2018 at 08:57:16AM +0900, Wang Shilong wrote: > diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c > index a7074115d6f6..f81102bd3203 100644 > --- a/fs/ext4/ioctl.c > +++ b/fs/ext4/ioctl.c > @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) > if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) > return 0; > > - err = mnt_want_write_file(filp); > - if (err) > - return err; > - A huge part of this patch is dropping the calls to mnt_want_write_file() and mnt_drop_write_file(). What's the justification for doing this? The use of mnt_want_write_file() looks necessary to me... - Ted
> 在 2018年9月16日,上午11:55,Theodore Y. Ts'o <tytso@mit.edu> 写道: > > On Wed, Sep 12, 2018 at 08:57:16AM +0900, Wang Shilong wrote: >> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c >> index a7074115d6f6..f81102bd3203 100644 >> --- a/fs/ext4/ioctl.c >> +++ b/fs/ext4/ioctl.c >> @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) >> if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) >> return 0; >> >> - err = mnt_want_write_file(filp); >> - if (err) >> - return err; >> - > > A huge part of this patch is dropping the calls to > mnt_want_write_file() and mnt_drop_write_file(). What's the > justification for doing this? The use of mnt_want_write_file() looks > necessary to me… Hi Ted, mnt_want_write_file() and inode_lock is held before this function called now. Since both ioctl_set_flags and ext4_set_project() need call them. > > - Ted
On Sun, Sep 16, 2018 at 04:02:52AM +0000, Wang Shilong wrote: > > > > 在 2018年9月16日,上午11:55,Theodore Y. Ts'o <tytso@mit.edu> 写道: > > > > On Wed, Sep 12, 2018 at 08:57:16AM +0900, Wang Shilong wrote: > >> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c > >> index a7074115d6f6..f81102bd3203 100644 > >> --- a/fs/ext4/ioctl.c > >> +++ b/fs/ext4/ioctl.c > >> @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) > >> if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) > >> return 0; > >> > >> - err = mnt_want_write_file(filp); > >> - if (err) > >> - return err; > >> - > > > > A huge part of this patch is dropping the calls to > > mnt_want_write_file() and mnt_drop_write_file(). What's the > > justification for doing this? The use of mnt_want_write_file() looks > > necessary to me… > > Hi Ted, > > mnt_want_write_file() and inode_lock is held before this function called now. > Since both ioctl_set_flags and ext4_set_project() need call them. I don't see any place in this patch where mnt_want_write_file() is being called. What am I missing? And if there is a dependent patch to this first patch in the patch series, please include it in this patch series.... or least point it out after the --- list. Thanks, - Ted
> 在 2018年9月16日,下午8:20,Theodore Y. Ts'o <tytso@mit.edu> 写道: > > On Sun, Sep 16, 2018 at 04:02:52AM +0000, Wang Shilong wrote: >> >> >>> 在 2018年9月16日,上午11:55,Theodore Y. Ts'o <tytso@mit.edu> 写道: >>> >>> On Wed, Sep 12, 2018 at 08:57:16AM +0900, Wang Shilong wrote: >>>> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c >>>> index a7074115d6f6..f81102bd3203 100644 >>>> --- a/fs/ext4/ioctl.c >>>> +++ b/fs/ext4/ioctl.c >>>> @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) >>>> if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) >>>> return 0; >>>> >>>> - err = mnt_want_write_file(filp); >>>> - if (err) >>>> - return err; >>>> - >>> >>> A huge part of this patch is dropping the calls to >>> mnt_want_write_file() and mnt_drop_write_file(). What's the >>> justification for doing this? The use of mnt_want_write_file() looks >>> necessary to me… >> >> Hi Ted, >> >> mnt_want_write_file() and inode_lock is held before this function called now. >> Since both ioctl_set_flags and ext4_set_project() need call them. > > I don't see any place in this patch where mnt_want_write_file() is > being called. What am I missing? And if there is a dependent patch > to this first patch in the patch series, please include it in this > patch series.... or least point it out after the --- list. Sorry, I might not explain it clearly, here is current codes after applying patch: 039 err = mnt_want_write_file(filp); ———————>called here, this is originally there for ext4_ioctl_setflags() 1040 if (err) 1041 return err; 1042 1043 inode_lock(inode); 1044 err = ext4_ioctl_setattr_check_projid(inode, &fa); 1045 if (err) 1046 goto out; 1047 flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | 1048 (flags & EXT4_FL_XFLAG_VISIBLE); 1049 err = ext4_ioctl_setflags(inode, flags); 1050 if (err) 1051 goto out; 1052 err = ext4_ioctl_setproject(filp, fa.fsx_projid); 1053 out: 1054 inode_unlock(inode); 1055 mnt_drop_write_file(filp); ————————>dropped here. 1056 return err; 1057 } Thanks, Shilong > > Thanks, > > - Ted
> 在 2018年9月16日,下午8:25,Wang Shilong <wshilong@ddn.com> 写道: > > > >> 在 2018年9月16日,下午8:20,Theodore Y. Ts'o <tytso@mit.edu> 写道: >> >> On Sun, Sep 16, 2018 at 04:02:52AM +0000, Wang Shilong wrote: >>> >>> >>>> 在 2018年9月16日,上午11:55,Theodore Y. Ts'o <tytso@mit.edu> 写道: >>>> >>>> On Wed, Sep 12, 2018 at 08:57:16AM +0900, Wang Shilong wrote: >>>>> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c >>>>> index a7074115d6f6..f81102bd3203 100644 >>>>> --- a/fs/ext4/ioctl.c >>>>> +++ b/fs/ext4/ioctl.c >>>>> @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) >>>>> if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) >>>>> return 0; >>>>> >>>>> - err = mnt_want_write_file(filp); >>>>> - if (err) >>>>> - return err; >>>>> - >>>> >>>> A huge part of this patch is dropping the calls to >>>> mnt_want_write_file() and mnt_drop_write_file(). What's the >>>> justification for doing this? The use of mnt_want_write_file() looks >>>> necessary to me… >>> >>> Hi Ted, >>> >>> mnt_want_write_file() and inode_lock is held before this function called now. >>> Since both ioctl_set_flags and ext4_set_project() need call them. >> >> I don't see any place in this patch where mnt_want_write_file() is >> being called. What am I missing? And if there is a dependent patch >> to this first patch in the patch series, please include it in this >> patch series.... or least point it out after the --- list. > > Sorry, I might not explain it clearly, here is current codes after applying patch: > > 039 err = mnt_want_write_file(filp); ———————>called here, this is originally there for ext4_ioctl_setflags() > 1040 if (err) > 1041 return err; > 1042 > 1043 inode_lock(inode); > 1044 err = ext4_ioctl_setattr_check_projid(inode, &fa); > 1045 if (err) > 1046 goto out; > 1047 flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | > 1048 (flags & EXT4_FL_XFLAG_VISIBLE); > 1049 err = ext4_ioctl_setflags(inode, flags); > 1050 if (err) > 1051 goto out; > 1052 err = ext4_ioctl_setproject(filp, fa.fsx_projid); > 1053 out: > 1054 inode_unlock(inode); > 1055 mnt_drop_write_file(filp); ————————>dropped here. > 1056 return err; > 1057 } > > Thanks, > Shilong Just a general ping for this, make sure you did not miss reply. Since I saw you sent new pull request. Is there anything more I could do? > >> >> Thanks, >> >> - Ted >
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index a7074115d6f6..f81102bd3203 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) return 0; - err = mnt_want_write_file(filp); - if (err) - return err; - err = -EPERM; - inode_lock(inode); /* Is it quota file? Do not allow user to mess with it */ if (ext4_is_quota_file(inode)) - goto out_unlock; + return err; err = ext4_get_inode_loc(inode, &iloc); if (err) - goto out_unlock; + return err; raw_inode = ext4_raw_inode(&iloc); if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) { @@ -359,7 +354,7 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) EXT4_SB(sb)->s_want_extra_isize, &iloc); if (err) - goto out_unlock; + return err; } else { brelse(iloc.bh); } @@ -369,10 +364,8 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) handle = ext4_journal_start(inode, EXT4_HT_QUOTA, EXT4_QUOTA_INIT_BLOCKS(sb) + EXT4_QUOTA_DEL_BLOCKS(sb) + 3); - if (IS_ERR(handle)) { - err = PTR_ERR(handle); - goto out_unlock; - } + if (IS_ERR(handle)) + return PTR_ERR(handle); err = ext4_reserve_inode_write(handle, inode, &iloc); if (err) @@ -400,9 +393,6 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) err = rc; out_stop: ext4_journal_stop(handle); -out_unlock: - inode_unlock(inode); - mnt_drop_write_file(filp); return err; } #else @@ -626,6 +616,30 @@ static long ext4_ioctl_group_add(struct file *file, return err; } +static int ext4_ioctl_check_project(struct inode *inode, struct fsxattr *fa) +{ + /* + * Project Quota ID state is only allowed to change from within the init + * namespace. Enforce that restriction only if we are trying to change + * the quota ID state. Everything else is allowed in user namespaces. + */ + if (current_user_ns() == &init_user_ns) + return 0; + + if (__kprojid_val(EXT4_I(inode)->i_projid) != fa->fsx_projid) + return -EINVAL; + + if (ext4_test_inode_flag(inode, EXT4_INODE_PROJINHERIT)) { + if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT)) + return -EINVAL; + } else { + if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) + return -EINVAL; + } + + return 0; +} + long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -1025,19 +1039,19 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return err; inode_lock(inode); + err = ext4_ioctl_check_project(inode, &fa); + if (err) + goto out; flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | (flags & EXT4_FL_XFLAG_VISIBLE); err = ext4_ioctl_setflags(inode, flags); - inode_unlock(inode); - mnt_drop_write_file(filp); if (err) - return err; - + goto out; err = ext4_ioctl_setproject(filp, fa.fsx_projid); - if (err) - return err; - - return 0; +out: + inode_unlock(inode); + mnt_drop_write_file(filp); + return err; } case EXT4_IOC_SHUTDOWN: return ext4_shutdown(sb, arg);