From d99b95617c1ec6d20c59d0780bd47f5babd0b213 Mon Sep 17 00:00:00 2001 From: Sergey Cheremencev Date: Thu, 15 Apr 2021 17:14:51 +0300 Subject: [PATCH] LU-13587 quota: protect qpi in proc Access to pool info only when pool is fully inited. This patch protects from following panic: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] qpi_state_seq_show+0x86/0xe0 [lquota] ... Call Trace: [] seq_read+0x130/0x440 [] proc_reg_read+0x40/0x80 [] vfs_read+0x9f/0x170 [] SyS_read+0x7f/0xf0 [] system_call_fastpath+0x22/0x27 Add test 79 to sanity-quota to check that race between access to /proc/.../dt-pool_name/info of non-existed pool with this pool creating doesn't cause a panic. Lustre-change: https://review.whamcloud.com/43987 Lustre-commit: a11168f46cf01c45a431a804da01cf67e18ecca9 HPE-bug-id: LUS-9938 Change-Id: I8eff846c6c3881a8431a98efb54e660ecb9155bf Signed-off-by: Sergey Cheremencev Reviewed-by: Andreas Dilger Reviewed-by: Patrick Farrell Reviewed-on: https://review.whamcloud.com/46658 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Hongchao Zhang --- lustre/quota/qmt_internal.h | 1 + lustre/quota/qmt_pool.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/lustre/quota/qmt_internal.h b/lustre/quota/qmt_internal.h index 919876c..286edb1 100644 --- a/lustre/quota/qmt_internal.h +++ b/lustre/quota/qmt_internal.h @@ -100,6 +100,7 @@ enum { enum { /* set while recalc_thread is working */ QPI_FLAG_RECALC_OFFSET, + QPI_FLAG_STATE_INITED, }; /* diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index 37034eb..e31787c 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -79,6 +79,8 @@ static int qpi_state_seq_show(struct seq_file *m, void *data) int type; LASSERT(pool != NULL); + if (unlikely(!test_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags))) + return -ENOENT; seq_printf(m, "pool:\n" " id: %u\n" @@ -106,6 +108,8 @@ static int qpi_soft_least_qunit_seq_show(struct seq_file *m, void *data) { struct qmt_pool_info *pool = m->private; LASSERT(pool != NULL); + if (unlikely(!test_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags))) + return -ENOENT; seq_printf(m, "%lu\n", pool->qpi_soft_least_qunit); return 0; @@ -121,6 +125,8 @@ qpi_soft_least_qunit_seq_write(struct file *file, const char __user *buffer, int rc; LASSERT(pool != NULL); + if (unlikely(!test_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags))) + return -ENOENT; /* Not tuneable for inode limit */ if (pool->qpi_rtype != LQUOTA_RES_DT) @@ -177,6 +183,7 @@ static int qmt_pool_alloc(const struct lu_env *env, struct qmt_device *qmt, init_rwsem(&pool->qpi_recalc_sem); pool->qpi_rtype = pool_type; + pool->qpi_flags = 0; /* initialize refcount to 1, hash table will then grab an additional * reference */ @@ -670,6 +677,7 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, qmt->qmt_svname, PFID(&qti->qti_fid), rc); #endif } + set_bit(QPI_FLAG_STATE_INITED, &pool->qpi_flags); if (name) break; } -- 1.8.3.1