cachefiles: add consistency check for copen/cread
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: Baokun Li <libaokun1@huawei.com> Link: https://lore.kernel.org/r/20240522114308.2402121-7-libaokun@huaweicloud.com Acked-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
3e6d704f02
commit
a26dc49df3
@ -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,
|
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_object *object = filp->private_data;
|
||||||
struct cachefiles_cache *cache = object->volume->cache;
|
struct cachefiles_cache *cache = object->volume->cache;
|
||||||
struct cachefiles_req *req;
|
struct cachefiles_req *req;
|
||||||
unsigned long id;
|
XA_STATE(xas, &cache->reqs, id);
|
||||||
|
|
||||||
if (ioctl != CACHEFILES_IOC_READ_COMPLETE)
|
if (ioctl != CACHEFILES_IOC_READ_COMPLETE)
|
||||||
return -EINVAL;
|
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))
|
if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
id = arg;
|
xa_lock(&cache->reqs);
|
||||||
req = xa_erase(&cache->reqs, id);
|
req = xas_load(&xas);
|
||||||
if (!req)
|
if (!req || req->msg.opcode != CACHEFILES_OP_READ ||
|
||||||
|
req->object != object) {
|
||||||
|
xa_unlock(&cache->reqs);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
xas_store(&xas, NULL);
|
||||||
|
xa_unlock(&cache->reqs);
|
||||||
|
|
||||||
trace_cachefiles_ondemand_cread(object, id);
|
trace_cachefiles_ondemand_cread(object, id);
|
||||||
complete(&req->done);
|
complete(&req->done);
|
||||||
@ -126,6 +131,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
|
|||||||
unsigned long id;
|
unsigned long id;
|
||||||
long size;
|
long size;
|
||||||
int ret;
|
int ret;
|
||||||
|
XA_STATE(xas, &cache->reqs, 0);
|
||||||
|
|
||||||
if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))
|
if (!test_bit(CACHEFILES_ONDEMAND_MODE, &cache->flags))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -149,9 +155,16 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
req = xa_erase(&cache->reqs, id);
|
xa_lock(&cache->reqs);
|
||||||
if (!req)
|
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;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
xas_store(&xas, NULL);
|
||||||
|
xa_unlock(&cache->reqs);
|
||||||
|
|
||||||
/* fail OPEN request if copen format is invalid */
|
/* fail OPEN request if copen format is invalid */
|
||||||
ret = kstrtol(psize, 0, &size);
|
ret = kstrtol(psize, 0, &size);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user