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

cachefiles: add consistency check for copen/cread

mainline inclusion
from mainline-v6.10-rc4
commit a26dc49df37e996876f50a0210039b2d211fdd6f
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IA6I1T

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a26dc49df37e996876f50a0210039b2d211fdd6f



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

This prevents malicious processes from completing random copen/cread
requests and crashing the system. Added checks are listed below:

  * Generic, copen can only complete open requests, and cread can only
    complete read requests.
  * For copen, ondemand_id must not be 0, because this indicates that the
    request has not been read by the daemon.
  * For cread, the object corresponding to fd and req should be the same.

Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
Link: https://lore.kernel.org/r/20240522114308.2402121-7-libaokun@huaweicloud.com


Acked-by: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatarJingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarZizhi Wo <wozizhi@huawei.com>
parent fd3c07ac
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -82,12 +82,12 @@ static loff_t cachefiles_ondemand_fd_llseek(struct file *filp, loff_t pos,
}

static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl,
					 unsigned long arg)
					 unsigned long id)
{
	struct cachefiles_object *object = filp->private_data;
	struct cachefiles_cache *cache = object->volume->cache;
	struct cachefiles_req *req;
	unsigned long id;
	XA_STATE(xas, &cache->reqs, id);

	if (ioctl != CACHEFILES_IOC_READ_COMPLETE)
		return -EINVAL;
@@ -95,10 +95,15 @@ static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl,
	if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))
		return -EOPNOTSUPP;

	id = arg;
	req = xa_erase(&cache->reqs, id);
	if (!req)
	xa_lock(&cache->reqs);
	req = xas_load(&xas);
	if (!req || req->msg.opcode != CACHEFILES_OP_READ ||
	    req->object != object) {
		xa_unlock(&cache->reqs);
		return -EINVAL;
	}
	xas_store(&xas, NULL);
	xa_unlock(&cache->reqs);

	trace_cachefiles_ondemand_cread(object, id);
	complete(&req->done);
@@ -126,6 +131,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
	unsigned long id;
	long size;
	int ret;
	XA_STATE(xas, &cache->reqs, 0);

	if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))
		return -EOPNOTSUPP;
@@ -149,9 +155,16 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
	if (ret)
		return ret;

	req = xa_erase(&cache->reqs, id);
	if (!req)
	xa_lock(&cache->reqs);
	xas.xa_index = id;
	req = xas_load(&xas);
	if (!req || req->msg.opcode != CACHEFILES_OP_OPEN ||
	    !req->object->ondemand->ondemand_id) {
		xa_unlock(&cache->reqs);
		return -EINVAL;
	}
	xas_store(&xas, NULL);
	xa_unlock(&cache->reqs);

	/* fail OPEN request if copen format is invalid */
	ret = kstrtol(psize, 0, &size);