ignore_hardlimit() exempts CAP_SYS_RESOURCE holders from enforcement of hard limits and of soft limits whose grace time expired. DQF_ROOT_SQUASH disables that exemption, but it has been confined to the old v1 quota format since the quota format abstraction was introduced, and commit ca6cb0918e87 ("quota: Verify flags passed to Q_SETINFO") later made Q_SETINFO reject it explicitly on other formats. That confinement predates generic project quota support. Project limits bound the size of a directory tree rather than restrict a user, and are commonly used for capacity isolation of container volumes and NFS exports. There the exemption defeats the purpose: knfsd raises CAP_SYS_RESOURCE for requests mapped to root on no_root_squash exports (CAP_NFSD_SET), so any remote root write silently exceeds project hard limits. XFS enforces project limits regardless of capabilities. Lift the format restriction so the flag can be set per quota type through Q_SETINFO on journaled quota as well. Existing setups keep their behaviour: the flag stays clear unless explicitly set, and setting it was previously rejected with -EINVAL on anything but QFMT_VFS_OLD - accepting it there is the user-visible ABI change this patch makes. Signed-off-by: Kitae Yoo --- fs/quota/dquot.c | 8 +------- include/uapi/linux/quota.h | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 9850de3955..e431e72dfe 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1309,8 +1309,7 @@ static int ignore_hardlimit(struct dquot *dquot) struct mem_dqinfo *info = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type]; return capable(CAP_SYS_RESOURCE) && - (info->dqi_format->qf_fmt_id != QFMT_VFS_OLD || - !(info->dqi_flags & DQF_ROOT_SQUASH)); + !(info->dqi_flags & DQF_ROOT_SQUASH); } static int dquot_add_inodes(struct dquot *dquot, qsize_t inodes, @@ -2900,11 +2899,6 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii) if (!sb_has_quota_active(sb, type)) return -ESRCH; mi = sb_dqopt(sb)->info + type; - if (ii->i_fieldmask & QC_FLAGS) { - if ((ii->i_flags & QCI_ROOT_SQUASH && - mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) - return -EINVAL; - } spin_lock(&dq_data_lock); if (ii->i_fieldmask & QC_SPC_TIMER) mi->dqi_bgrace = ii->i_spc_timelimit; diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h index 52090105b8..a34f43519a 100644 --- a/include/uapi/linux/quota.h +++ b/include/uapi/linux/quota.h @@ -149,7 +149,7 @@ enum { DQF_PRIVATE }; -/* Root squash enabled (for v1 quota format) */ +/* Enforce limits also for CAP_SYS_RESOURCE processes */ #define DQF_ROOT_SQUASH (1 << DQF_ROOT_SQUASH_B) /* Quota stored in a system file */ #define DQF_SYS_FILE (1 << DQF_SYS_FILE_B) -- 2.50.1 (Apple Git-155)