Offering: HULK hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT
--------------------------------
Reusing the msg_id after a maliciously completed reopen request may cause a read request to remain unprocessed and result in a hung, as shown below:
t1 | t2 | t3 ------------------------------------------------- cachefiles_ondemand_select_req cachefiles_ondemand_object_is_close(A) cachefiles_ondemand_set_object_reopening(A) queue_work(fscache_object_wq, &info->work) ondemand_object_worker cachefiles_ondemand_init_object(A) cachefiles_ondemand_send_req(OPEN) // get msg_id 6 wait_for_completion(&req_A->done) cachefiles_ondemand_daemon_read // read msg_id 6 req_A cachefiles_ondemand_get_fd copy_to_user // Malicious completion msg_id 6 copen 6,-1 // reopen fails, want daemon to close fd, // then set object to close, retrigger reopen cachefiles_ondemand_init_object(B) cachefiles_ondemand_send_req(OPEN) // new open req_B reuse msg_id 6 // daemon successfully copen msg_id 6, so it won't close the fd. // object is always reopening, so read requests are not processed // resulting in a hung
Therefore allocate the msg_id cyclically to avoid reusing the msg_id for a very short duration of time causing the above problem.
Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/cachefiles/ondemand.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c index 528da20e1119..76c936fc9a68 100644 --- a/fs/cachefiles/ondemand.c +++ b/fs/cachefiles/ondemand.c @@ -535,9 +535,11 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, goto out; }
- while (radix_tree_insert(&cache->reqs, - id = atomic64_read(&global_index), req)) - atomic64_inc(&global_index); + do { + id = atomic64_inc_return(&global_index); + if (unlikely(id == UINT_MAX)) + atomic64_set(&global_index, 0); + } while (radix_tree_insert(&cache->reqs, id, req));
radix_tree_tag_set(&cache->reqs, id, CACHEFILES_REQ_NEW); xa_unlock(&cache->reqs);