From 3ffa5d680f0092ae51ffa84bd94a9983f9a8c99e Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Mon, 7 Jun 2021 23:40:22 +0800 Subject: [PATCH] LU-14740 llite: avoid project quota overflow MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Currently, project ID is stored as u32, max possible value for it is 4294967295. However, VFS reserve max value for special usage, see following function: static inline bool qid_has_mapping(struct user_namespace *ns, struct kqid qid) { return from_kqid(ns, qid) != (qid_t) -1; } So qid_has_mapping() could return 0 for id 4294967295. A further try on chown test: $ chown 4294967295:4294967295 c.sh chown: invalid user: ‘4294967295:4294967295’ $ chown 4294967294:4294967294 c.sh Fix to check max possible value for project ID in the client kernel side, and add a test case for this. Test-parameters: trivial testlist=sanity-quota Fixes: 7b5c1f1404c3 ("LU-13845 utils: Quota id 0xFFFFFFFF is invalid") Signed-off-by: Wang Shilong Change-Id: Ide8b9cc79d9b7f2a8b9860a0c0f683ec903b8f91 Reviewed-on: https://review.whamcloud.com/43939 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Hongchao Zhang Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/llite/file.c | 11 ++++++++++- lustre/tests/sanity-quota.sh | 17 +++++++++++++++++ lustre/utils/lfs.c | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 2e57c64..41af22a 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -3414,8 +3414,17 @@ int ll_ioctl_check_project(struct inode *inode, __u32 xflags, * 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) + if (current_user_ns() == &init_user_ns) { + /* + * Caller is allowed to change the project ID. if it is being + * changed, make sure that the new value is valid. + */ + if (ll_i2info(inode)->lli_projid != projid && + !projid_valid(make_kprojid(&init_user_ns, projid))) + return -EINVAL; + return 0; + } if (ll_i2info(inode)->lli_projid != projid) return -EINVAL; diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 9103aac..2fcf058 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -5044,6 +5044,23 @@ test_75() } run_test 75 "nodemap squashed root respects quota enforcement" +test_76() { + ! is_project_quota_supported && + skip "skip project quota unsupported" + + setup_quota_test || error "setup quota failed with $?" + quota_init + + local testfile="$DIR/$tdir/$tfile-0" + + touch $testfile + $LFS project -p 4294967295 $testfile && + error "set project ID should fail" + + cleanup_quota_test +} +run_test 76 "project ID 4294967295 should be not allowed" + quota_fini() { do_nodes $(comma_list $(nodes_list)) \ diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index fd9f0c7..c124188 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -4577,6 +4577,7 @@ static int str2quotaid(__u32 *id, const char *arg) projid_tmp = strtoul(arg, &endptr, 10); if (*endptr != '\0') return -EINVAL; + /* UINT32_MAX is not allowed - see projid_valid()/INVALID_PROJID */ if (projid_tmp >= UINT32_MAX) return -ERANGE; -- 1.8.3.1