dsp-kernel: Fix memory leak in compact ioctl invoke

Currently, compact fastrpc ioctl functions allocate memory dynamically
and return without freeing this memory. Do memory free before return.

Change-Id: I4591ccc951e7e43362a4c2d9e0265c89ab8582f8
Signed-off-by: rnallago <quic_rnallago@quicinc.com>
This commit is contained in:
Ramesh Nallagopu
2024-06-18 11:24:25 +05:30
committed by rnallago
parent 2fc88a6251
commit e83cbc32d8

View File

@@ -328,7 +328,7 @@ static int compat_fastrpc_ioctl_invoke(struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct compat_fastrpc_ioctl_invoke_async __user *inv32; struct compat_fastrpc_ioctl_invoke_async __user *inv32;
struct fastrpc_ioctl_invoke_async *inv; struct fastrpc_ioctl_invoke_async *inv = NULL;
compat_uint_t sc = 0; compat_uint_t sc = 0;
int err = 0, len = 0; int err = 0, len = 0;
struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data; struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
@@ -342,12 +342,16 @@ static int compat_fastrpc_ioctl_invoke(struct file *filp,
sizeof(*inv) + len * sizeof(union remote_arg), GFP_KERNEL))); sizeof(*inv) + len * sizeof(union remote_arg), GFP_KERNEL)));
if (err) if (err)
return -EFAULT; return -EFAULT;
VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32, VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
inv, cmd, sc)); inv, cmd, sc));
if (err) if (err) {
kfree(inv);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
fl->mode, COMPAT_MSG, inv))); fl->mode, COMPAT_MSG, inv)));
kfree(inv);
return err; return err;
} }
@@ -474,17 +478,20 @@ static int compat_fastrpc_ioctl_invoke2(struct file *filp,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct compat_fastrpc_ioctl_invoke2 __user *inv32; struct compat_fastrpc_ioctl_invoke2 __user *inv32;
struct fastrpc_ioctl_invoke2 *inv; struct fastrpc_ioctl_invoke2 *inv = NULL;
int err = 0; int err = 0;
struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data; struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
inv32 = compat_ptr(arg); inv32 = compat_ptr(arg);
VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke2(inv32, VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke2(inv32,
&inv, cmd)); &inv, cmd));
if (err) if (err) {
kfree(inv);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv, true))); VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv, true)));
kfree(inv);
return err; return err;
} }
@@ -740,7 +747,7 @@ static int compat_fastrpc_control(struct fastrpc_file *fl,
{ {
int err = 0; int err = 0;
struct compat_fastrpc_ioctl_control __user *ctrl32; struct compat_fastrpc_ioctl_control __user *ctrl32;
struct fastrpc_ioctl_control *ctrl; struct fastrpc_ioctl_control *ctrl = NULL;
compat_uptr_t p; compat_uptr_t p;
ctrl32 = compat_ptr(arg); ctrl32 = compat_ptr(arg);
@@ -751,17 +758,19 @@ static int compat_fastrpc_control(struct fastrpc_file *fl,
VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32, VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
ctrl)); ctrl));
if (err) if (err)
return err; goto bail;
VERIFY(err, 0 == (err = fastrpc_internal_control(fl, ctrl))); VERIFY(err, 0 == (err = fastrpc_internal_control(fl, ctrl)));
if (err) if (err)
return err; goto bail;
err = get_user(p, &ctrl32->req); err = get_user(p, &ctrl32->req);
if (err) if (err)
return err; goto bail;
if (p == FASTRPC_CONTROL_KALLOC) { if (p == FASTRPC_CONTROL_KALLOC) {
memcpy(&p, &ctrl->kalloc.kalloc_support, sizeof(ctrl->kalloc.kalloc_support)); memcpy(&p, &ctrl->kalloc.kalloc_support, sizeof(ctrl->kalloc.kalloc_support));
err |= put_user(p, &ctrl32->kalloc.kalloc_support); err |= put_user(p, &ctrl32->kalloc.kalloc_support);
} }
bail:
kfree(ctrl);
return err; return err;
} }
@@ -784,20 +793,21 @@ static int compat_fastrpc_get_dsp_info(struct fastrpc_file *fl,
} }
err = get_user(u, &info32->domain); err = get_user(u, &info32->domain);
if (err) if (err)
return err; goto bail;
memcpy(&info->domain, &u, sizeof(info->domain)); memcpy(&info->domain, &u, sizeof(info->domain));
err = get_user(u, &info32->attribute_ID); err = get_user(u, &info32->attribute_ID);
if (err) if (err)
return err; goto bail;
memcpy(&info->attribute_ID, &u, sizeof(info->attribute_ID)); memcpy(&info->attribute_ID, &u, sizeof(info->attribute_ID));
err = fastrpc_get_info_from_kernel(info, fl); err = fastrpc_get_info_from_kernel(info, fl);
if (err) if (err)
return err; goto bail;
err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info); err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
bail:
kfree(info);
return err; return err;
} }
@@ -810,7 +820,7 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
case COMPAT_FASTRPC_IOCTL_MEM_MAP: case COMPAT_FASTRPC_IOCTL_MEM_MAP:
{ {
struct compat_fastrpc_ioctl_mem_map __user *map32; struct compat_fastrpc_ioctl_mem_map __user *map32;
struct fastrpc_ioctl_mem_map *map; struct fastrpc_ioctl_mem_map *map = NULL;
map32 = compat_ptr(arg); map32 = compat_ptr(arg);
VERIFY(err, NULL != (map = kmalloc( VERIFY(err, NULL != (map = kmalloc(
@@ -819,20 +829,25 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
return -EFAULT; return -EFAULT;
err = compat_get_fastrpc_ioctl_mem_map(map32, map); err = compat_get_fastrpc_ioctl_mem_map(map32, map);
if (err) if (err) {
kfree(map);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl, VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl,
map))); map)));
if (err) if (err) {
kfree(map);
return err; return err;
}
VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map)); VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map));
kfree(map);
return err; return err;
} }
case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
{ {
struct compat_fastrpc_ioctl_mem_unmap __user *unmap32; struct compat_fastrpc_ioctl_mem_unmap __user *unmap32;
struct fastrpc_ioctl_mem_unmap *unmap; struct fastrpc_ioctl_mem_unmap *unmap = NULL;
unmap32 = compat_ptr(arg); unmap32 = compat_ptr(arg);
unmap = kmalloc(sizeof(*unmap), GFP_KERNEL); unmap = kmalloc(sizeof(*unmap), GFP_KERNEL);
@@ -840,17 +855,20 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
return -EFAULT; return -EFAULT;
err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap); err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap);
if (err) if (err) {
kfree(unmap);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl, VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl,
unmap))); unmap)));
kfree(unmap);
return err; return err;
} }
case COMPAT_FASTRPC_IOCTL_MMAP: case COMPAT_FASTRPC_IOCTL_MMAP:
{ {
struct compat_fastrpc_ioctl_mmap __user *map32; struct compat_fastrpc_ioctl_mmap __user *map32;
struct fastrpc_ioctl_mmap *map; struct fastrpc_ioctl_mmap *map = NULL;
map32 = compat_ptr(arg); map32 = compat_ptr(arg);
VERIFY(err, NULL != (map = kmalloc( VERIFY(err, NULL != (map = kmalloc(
@@ -858,18 +876,21 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
if (err) if (err)
return -EFAULT; return -EFAULT;
VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map)); VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
if (err) if (err) {
kfree(map);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map))); VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map)); VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
kfree(map);
return err; return err;
} }
case COMPAT_FASTRPC_IOCTL_MMAP_64: case COMPAT_FASTRPC_IOCTL_MMAP_64:
{ {
struct compat_fastrpc_ioctl_mmap_64 __user *map32; struct compat_fastrpc_ioctl_mmap_64 __user *map32;
struct fastrpc_ioctl_mmap *map; struct fastrpc_ioctl_mmap *map = NULL;
map32 = compat_ptr(arg); map32 = compat_ptr(arg);
VERIFY(err, NULL != (map = kmalloc( VERIFY(err, NULL != (map = kmalloc(
@@ -877,16 +898,19 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
if (err) if (err)
return -EFAULT; return -EFAULT;
VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map)); VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map));
if (err) if (err) {
kfree(map);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map))); VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map)); VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map));
kfree(map);
return err; return err;
} }
case COMPAT_FASTRPC_IOCTL_MUNMAP: case COMPAT_FASTRPC_IOCTL_MUNMAP:
{ {
struct compat_fastrpc_ioctl_munmap __user *unmap32; struct compat_fastrpc_ioctl_munmap __user *unmap32;
struct fastrpc_ioctl_munmap *unmap; struct fastrpc_ioctl_munmap *unmap = NULL;
unmap32 = compat_ptr(arg); unmap32 = compat_ptr(arg);
VERIFY(err, NULL != (unmap = kmalloc( VERIFY(err, NULL != (unmap = kmalloc(
@@ -895,10 +919,13 @@ static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
return -EFAULT; return -EFAULT;
VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32, VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
unmap)); unmap));
if (err) if (err) {
kfree(unmap);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
unmap))); unmap)));
kfree(unmap);
return err; return err;
} }
default: default:
@@ -991,7 +1018,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
case COMPAT_FASTRPC_IOCTL_MUNMAP_64: case COMPAT_FASTRPC_IOCTL_MUNMAP_64:
{ {
struct compat_fastrpc_ioctl_munmap_64 __user *unmap32; struct compat_fastrpc_ioctl_munmap_64 __user *unmap32;
struct fastrpc_ioctl_munmap *unmap; struct fastrpc_ioctl_munmap *unmap = NULL;
unmap32 = compat_ptr(arg); unmap32 = compat_ptr(arg);
VERIFY(err, NULL != (unmap = kmalloc( VERIFY(err, NULL != (unmap = kmalloc(
@@ -1001,11 +1028,15 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
return -EFAULT; return -EFAULT;
VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32, VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32,
unmap)); unmap));
if (err) if (err) {
kfree(unmap);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
unmap))); unmap)));
kfree(unmap);
return err; return err;
} }
case COMPAT_FASTRPC_IOCTL_INIT: case COMPAT_FASTRPC_IOCTL_INIT:
@@ -1013,7 +1044,7 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
case COMPAT_FASTRPC_IOCTL_INIT_ATTRS: case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
{ {
struct compat_fastrpc_ioctl_init_attrs __user *init32; struct compat_fastrpc_ioctl_init_attrs __user *init32;
struct fastrpc_ioctl_init_attrs *init; struct fastrpc_ioctl_init_attrs *init = NULL;
init32 = compat_ptr(arg); init32 = compat_ptr(arg);
VERIFY(err, NULL != (init = kmalloc( VERIFY(err, NULL != (init = kmalloc(
@@ -1022,17 +1053,20 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
return -EFAULT; return -EFAULT;
VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32, VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
init, cmd)); init, cmd));
if (err) if (err) {
kfree(init);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_init_process(fl, init))); VERIFY(err, 0 == (err = fastrpc_init_process(fl, init)));
kfree(init);
return err; return err;
} }
case FASTRPC_IOCTL_GETINFO: case FASTRPC_IOCTL_GETINFO:
{ {
compat_uptr_t __user *info32; compat_uptr_t __user *info32;
uint32_t *info; uint32_t *info = NULL;
compat_uint_t u; compat_uint_t u;
info32 = compat_ptr(arg); info32 = compat_ptr(arg);
@@ -1042,11 +1076,14 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
return -EFAULT; return -EFAULT;
err = get_user(u, info32); err = get_user(u, info32);
memcpy(info, &u, sizeof(u)); memcpy(info, &u, sizeof(u));
if (err) if (err) {
kfree(info);
return err; return err;
}
VERIFY(err, 0 == (err = fastrpc_get_info(fl, info))); VERIFY(err, 0 == (err = fastrpc_get_info(fl, info)));
memcpy(&u, info, sizeof(*info)); memcpy(&u, info, sizeof(*info));
err |= put_user(u, info32); err |= put_user(u, info32);
kfree(info);
return err; return err;
} }
case FASTRPC_IOCTL_SETMODE: case FASTRPC_IOCTL_SETMODE: