From 0d121e6dc31de8fd8731032c0e7db45c49c670db Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Tue, 12 May 2020 11:37:21 -0700 Subject: [PATCH] soc: qcom: mem-buf: Limit the number of input ACL entries The number of ACL entries is currently not sanitized, which can allow for unreasonably large ACL to be allocated for later processing. Allowing for this to happen doesn't make much sense, as there aren't any valid usecases that require a large ACL, so restrict the number of ACL entries to 16. Also, while we're here, fix up some of the error handling in a few places. Change-Id: I5d1371ed180608486bcde1e208a36782986313af Signed-off-by: Isaac J. Manjarres --- drivers/soc/qcom/mem-buf.c | 35 ++++++++++++++++++++++++----------- include/uapi/linux/mem-buf.h | 2 ++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/soc/qcom/mem-buf.c b/drivers/soc/qcom/mem-buf.c index ad34a20e2ccc..969fb10585fe 100644 --- a/drivers/soc/qcom/mem-buf.c +++ b/drivers/soc/qcom/mem-buf.c @@ -1128,6 +1128,9 @@ static int mem_buf_vmid_to_vmid(u32 mem_buf_vmid) hh_vmid_t vmid; enum hh_vm_names vm_name; + if (!is_valid_mem_buf_vmid(mem_buf_vmid)) + return -EINVAL; + if (mem_buf_vmid == MEM_BUF_VMID_PRIMARY_VM) vm_name = HH_PRIMARY_VM; else if (mem_buf_vmid == MEM_BUF_VMID_TRUSTED_VM) @@ -1145,6 +1148,9 @@ static int mem_buf_perms_to_perms(u32 mem_buf_perms) { int perms = 0; + if (!is_valid_mem_buf_perms(mem_buf_perms)) + return -EINVAL; + if (mem_buf_perms & MEM_BUF_PERM_FLAG_READ) perms |= PERM_READ; if (mem_buf_perms & MEM_BUF_PERM_FLAG_WRITE) @@ -1173,13 +1179,12 @@ static struct hh_acl_desc *mem_buf_acl_to_hh_acl(unsigned int nr_acl_entries, for (i = 0; i < nr_acl_entries; i++) { mem_buf_vmid = entries[i].vmid; mem_buf_perms = entries[i].perms; - if (!is_valid_mem_buf_vmid(mem_buf_vmid) || - !is_valid_mem_buf_perms(mem_buf_perms)) { + vmid = mem_buf_vmid_to_vmid(mem_buf_vmid); + perms = mem_buf_perms_to_perms(mem_buf_perms); + if (vmid < 0 || perms < 0) { ret = -EINVAL; goto err_inv_vmid_perms; } - vmid = mem_buf_vmid_to_vmid(mem_buf_vmid); - perms = mem_buf_perms_to_perms(mem_buf_perms); acl_desc->acl_entries[i].vmid = vmid; acl_desc->acl_entries[i].perms = perms; } @@ -1266,6 +1271,12 @@ static const struct file_operations mem_buf_fops = { .release = mem_buf_buffer_release, }; +static bool is_valid_mem_type(enum mem_buf_mem_type mem_type) +{ + return mem_type >= MEM_BUF_ION_MEM_TYPE && + mem_type < MEM_BUF_MAX_MEM_TYPE; +} + void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data) { int ret; @@ -1275,7 +1286,11 @@ void *mem_buf_alloc(struct mem_buf_allocation_data *alloc_data) if (!(mem_buf_capability & MEM_BUF_CAP_CONSUMER)) return ERR_PTR(-ENOTSUPP); - if (!alloc_data) + if (!alloc_data || !alloc_data->size || !alloc_data->nr_acl_entries || + !alloc_data->acl_list || + (alloc_data->nr_acl_entries > MEM_BUF_MAX_NR_ACL_ENTS) || + !is_valid_mem_type(alloc_data->src_mem_type) || + !is_valid_mem_type(alloc_data->dst_mem_type)) return ERR_PTR(-EINVAL); membuf = kzalloc(sizeof(*membuf), GFP_KERNEL); @@ -1363,6 +1378,9 @@ int mem_buf_get_fd(void *membuf_desc) int fd; struct mem_buf_desc *membuf = membuf_desc; + if (!membuf_desc) + return -EINVAL; + fd = get_unused_fd_flags(O_CLOEXEC); if (fd < 0) return fd; @@ -1486,16 +1504,11 @@ out: return ret; } -static bool is_valid_mem_type(enum mem_buf_mem_type mem_type) -{ - return mem_type >= MEM_BUF_ION_MEM_TYPE && - mem_type < MEM_BUF_MAX_MEM_TYPE; -} - static int validate_ioctl_arg(struct mem_buf_alloc_ioctl_arg *allocation) { if (!allocation->size || !allocation->nr_acl_entries || !allocation->acl_list || + (allocation->nr_acl_entries > MEM_BUF_MAX_NR_ACL_ENTS) || !is_valid_mem_type(allocation->src_mem_type) || !is_valid_mem_type(allocation->dst_mem_type) || allocation->reserved0 || allocation->reserved1 || diff --git a/include/uapi/linux/mem-buf.h b/include/uapi/linux/mem-buf.h index 1567e2144018..025e1acd3bc8 100644 --- a/include/uapi/linux/mem-buf.h +++ b/include/uapi/linux/mem-buf.h @@ -31,6 +31,8 @@ enum mem_buf_mem_type { (MEM_BUF_PERM_FLAG_READ | MEM_BUF_PERM_FLAG_WRITE |\ MEM_BUF_PERM_FLAG_EXEC) +#define MEM_BUF_MAX_NR_ACL_ENTS 16 + /** * struct acl_entry: Represents the access control permissions for a VMID. * @vmid: The mem-buf VMID specifier associated with the VMID that will access