Commit bfe51376 authored by Baokun Li's avatar Baokun Li
Browse files

cachefiles: cyclic allocation of msg_id to avoid reuse

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: c8383054 ("cachefiles: notify the user daemon when looking up cookie")
Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
parent 96a26c59
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -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);