1
0

Merge "dsp-kernel: Fix to avoid untrusted pointer dereference"

Este cometimento está contido em:
QCTECMDR Service
2024-07-09 03:52:57 -07:00
cometido por Gerrit - the friendly Code Review server
ascendente e07103109b c60ac212aa
cometimento 2fc88a6251
3 ficheiros modificados com 33 adições e 30 eliminações

Ver ficheiro

@@ -1841,11 +1841,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
struct fastrpc_ioctl_invoke *invoke = &invokefd->inv;
struct fastrpc_channel_ctx *chan = NULL;
unsigned long irq_flags = 0;
uint32_t is_kernel_memory = 0;
uint32_t kernel_msg = ((kernel == COMPAT_MSG) ? USER_MSG : kernel);
spin_lock(&fl->hlock);
if (fl->clst.num_active_ctxs > MAX_PENDING_CTX_PER_SESSION &&
!(kernel || invoke->handle < FASTRPC_STATIC_HANDLE_MAX)) {
!(kernel_msg || invoke->handle < FASTRPC_STATIC_HANDLE_MAX)) {
err = -EDQUOT;
spin_unlock(&fl->hlock);
goto bail;
@@ -1876,12 +1876,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
ctx->overs = (struct overlap *)(&ctx->attrs[bufs]);
ctx->overps = (struct overlap **)(&ctx->overs[bufs]);
/* If user message, do not use copy_from_user to copy buffers for
* compat driver,as memory is already copied to kernel memory
* for compat driver
*/
is_kernel_memory = ((kernel == USER_MSG) ? (fl->is_compat) : kernel);
K_COPY_FROM_USER(err, is_kernel_memory, (void *)ctx->lpra, invoke->pra,
K_COPY_FROM_USER(err, kernel, (void *)ctx->lpra, invoke->pra,
bufs * sizeof(*ctx->lpra));
if (err) {
ADSPRPC_ERR(
@@ -1964,7 +1959,15 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
spin_lock_irqsave(&chan->ctxlock, irq_flags);
me->jobid[cid]++;
for (ii = ((kernel || ctx->handle < FASTRPC_STATIC_HANDLE_MAX)
/*
* To prevent user invocations from exhausting all entries in context
* table, it is necessary to reserve a few context table entries for
* critical kernel and static RPC calls. The index will begin at 0 for
* static handles, while user handles start from
* NUM_KERNEL_AND_STATIC_ONLY_CONTEXTS.
*/
for (ii = ((kernel_msg || ctx->handle < FASTRPC_STATIC_HANDLE_MAX)
? 0 : NUM_KERNEL_AND_STATIC_ONLY_CONTEXTS);
ii < FASTRPC_CTX_MAX; ii++) {
if (!chan->ctxtable[ii]) {
@@ -3345,7 +3348,7 @@ static void fastrpc_update_invoke_count(uint32_t handle, uint64_t *perf_counter,
static int fastrpc_check_pd_status(struct fastrpc_file *fl, char *sloc_name);
int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
uint32_t kernel,
uint32_t msg_type,
struct fastrpc_ioctl_invoke_async *inv)
{
struct smq_invoke_ctx *ctx = NULL;
@@ -3354,6 +3357,7 @@ int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
struct timespec64 invoket = {0};
uint64_t *perf_counter = NULL;
bool isasyncinvoke = false, isworkdone = false;
uint32_t kernel = (msg_type == COMPAT_MSG) ? USER_MSG : msg_type;
cid = fl->cid;
VERIFY(err, VALID_FASTRPC_CID(cid) &&
@@ -3380,9 +3384,6 @@ int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
cid, invoke->handle);
goto bail;
}
}
if (!kernel) {
VERIFY(err, 0 == (err = context_restore_interrupted(fl,
inv, &ctx)));
if (err)
@@ -3400,7 +3401,7 @@ int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
}
trace_fastrpc_msg("context_alloc: begin");
VERIFY(err, 0 == (err = context_alloc(fl, kernel, inv, &ctx)));
VERIFY(err, 0 == (err = context_alloc(fl, msg_type, inv, &ctx)));
trace_fastrpc_msg("context_alloc: end");
if (err)
goto bail;
@@ -3822,7 +3823,7 @@ bail:
}
int fastrpc_internal_invoke2(struct fastrpc_file *fl,
struct fastrpc_ioctl_invoke2 *inv2)
struct fastrpc_ioctl_invoke2 *inv2, bool is_compat)
{
union {
struct fastrpc_ioctl_invoke_async inv;
@@ -3834,7 +3835,7 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
struct fastrpc_proc_sess_info sess_info;
} p;
struct fastrpc_dsp_capabilities *dsp_cap_ptr = NULL;
uint32_t size = 0;
uint32_t size = 0, kernel = 0;
int err = 0, domain = fl->cid;
if (inv2->req == FASTRPC_INVOKE2_ASYNC ||
@@ -3862,19 +3863,20 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
goto bail;
}
if (size > inv2->size) {
K_COPY_FROM_USER(err, fl->is_compat, &p.inv3, (void *)inv2->invparam,
K_COPY_FROM_USER(err, is_compat, &p.inv3, (void *)inv2->invparam,
sizeof(struct fastrpc_ioctl_invoke_async_no_perf));
if (err)
goto bail;
memcpy(&p.inv, &p.inv3, sizeof(struct fastrpc_ioctl_invoke_crc));
memcpy(&p.inv.job, &p.inv3.job, sizeof(p.inv.job));
} else {
K_COPY_FROM_USER(err, fl->is_compat, &p.inv, (void *)inv2->invparam, size);
K_COPY_FROM_USER(err, is_compat, &p.inv, (void *)inv2->invparam, size);
if (err)
goto bail;
}
kernel = (is_compat) ? COMPAT_MSG : USER_MSG;
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, fl->mode,
USER_MSG, &p.inv)));
kernel, &p.inv)));
if (err)
goto bail;
break;
@@ -3894,7 +3896,7 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
err = -EBADE;
goto bail;
}
K_COPY_FROM_USER(err, 0, &p.user_concurrency,
K_COPY_FROM_USER(err, is_compat, &p.user_concurrency,
(void *)inv2->invparam, size);
if (err)
goto bail;
@@ -3918,7 +3920,7 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
err = -EBADE;
goto bail;
}
K_COPY_FROM_USER(err, fl->is_compat, &p.buff_info,
K_COPY_FROM_USER(err, 0, &p.buff_info,
(void *)inv2->invparam, inv2->size);
if (err)
goto bail;
@@ -3933,7 +3935,7 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
err = -EBADE;
goto bail;
}
K_COPY_FROM_USER(err, fl->is_compat, &p.sess_info,
K_COPY_FROM_USER(err, is_compat, &p.sess_info,
(void *)inv2->invparam, inv2->size);
if (err)
goto bail;
@@ -6504,7 +6506,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->dsp_proc_init = 0;
fl->dsp_process_state = PROCESS_CREATE_DEFAULT;
fl->is_unsigned_pd = false;
fl->is_compat = false;
fl->exit_notif = false;
fl->exit_async = false;
fl->multi_session_support = false;
@@ -7504,7 +7505,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
err = -EFAULT;
goto bail;
}
VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, &p.inv2)));
VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, &p.inv2, false)));
if (err)
goto bail;
break;

Ver ficheiro

@@ -347,7 +347,7 @@ static int compat_fastrpc_ioctl_invoke(struct file *filp,
if (err)
return err;
VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
fl->mode, USER_MSG, inv)));
fl->mode, COMPAT_MSG, inv)));
return err;
}
@@ -484,7 +484,7 @@ static int compat_fastrpc_ioctl_invoke2(struct file *filp,
if (err)
return err;
VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv)));
VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv, true)));
return err;
}
@@ -975,7 +975,6 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
if (!filp->f_op || !filp->f_op->unlocked_ioctl)
return -ENOTTY;
fl->is_compat = true;
switch (cmd) {
case COMPAT_FASTRPC_IOCTL_INVOKE:
case COMPAT_FASTRPC_IOCTL_INVOKE_FD:

Ver ficheiro

@@ -469,9 +469,14 @@ enum fastrpc_buf_type {
/* Types of RPC calls to DSP */
enum fastrpc_msg_type {
/* 64 bit user application invoke message */
USER_MSG = 0,
/* kernel invoke message with zero pid */
KERNEL_MSG_WITH_ZERO_PID,
/* kernel invoke message with non zero pid to kill the PD in DSP */
KERNEL_MSG_WITH_NONZERO_PID,
/* 32 bit user application invoke message */
COMPAT_MSG,
};
/* Fastrpc remote pd type */
@@ -911,8 +916,6 @@ struct fastrpc_file {
/* Flag to indicate dynamic process creation status*/
enum fastrpc_process_create_state dsp_process_state;
bool is_unsigned_pd;
/* Flag to indicate 32 bit driver*/
bool is_compat;
/* Completion objects and state for dspsignals */
struct fastrpc_dspsignal *signal_groups[DSPSIGNAL_NUM_SIGNALS / DSPSIGNAL_GROUP_SIZE];
spinlock_t dspsignals_lock;
@@ -939,7 +942,7 @@ int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
struct fastrpc_ioctl_invoke_async *inv);
int fastrpc_internal_invoke2(struct fastrpc_file *fl,
struct fastrpc_ioctl_invoke2 *inv2);
struct fastrpc_ioctl_invoke2 *inv2, bool is_compat);
int fastrpc_internal_munmap(struct fastrpc_file *fl,
struct fastrpc_ioctl_munmap *ud);