Commit dbcacfa4 authored by Zizhi Wo's avatar Zizhi Wo Committed by Baokun Li
Browse files

cachefiles: Set object to close if ondemand_id < 0 in copen

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT



--------------------------------

Commit 27756c07db81 ("cachefiles: add consistency check for copen/cread")
added some validation to prevent malicious commands. But there is another
case: if copen is maliciously called in the user mode, it may delete the
request corresponding to the random id. And the request may have not been
read yet.

Note that when the object is set to reopen, the open request will be done
with the still reopen state in above case. As a result, the request
corresponding to this object is always skipped in select_req function, so
the read request is never completed and blocks other process.

Fix this issue by simply set object to close if its id < 0 in copen. In
addition, the "ret != 0" condition is no need in get_fd function as it
always meet, remove it.

Signed-off-by: default avatarZizhi Wo <wozizhi@huawei.com>
Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
parent 43759903
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -189,6 +189,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
	radix_tree_delete(&cache->reqs, id);
	xa_unlock(&cache->reqs);

	info = req->object->private;
	/* fail OPEN request if copen format is invalid */
	ret = kstrtol(psize, 0, &size);
	if (ret) {
@@ -208,7 +209,6 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
		goto out;
	}

	info = req->object->private;
	spin_lock(&info->lock);
	/* The anonymous fd was closed before copen. */
	if (info->ondemand_id == CACHEFILES_ONDEMAND_ID_CLOSED) {
@@ -228,6 +228,11 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
	wake_up_all(&cache->daemon_pollwq);

out:
	spin_lock(&info->lock);
	/* Need to set object close to avoid reopen status continuing */
	if (info->ondemand_id == CACHEFILES_ONDEMAND_ID_CLOSED)
		cachefiles_ondemand_set_object_close(req->object);
	spin_unlock(&info->lock);
	complete(&req->done);
	return ret;
}
@@ -323,7 +328,7 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req,
err:
	spin_lock(&req->object->private->lock);
	/* Avoid marking an opened object as closed. */
	if (ret && object->private->ondemand_id <= 0)
	if (object->private->ondemand_id <= 0)
		cachefiles_ondemand_set_object_close(req->object);
	spin_unlock(&req->object->private->lock);