From 486d7b2d1ef29c77bcc25153a1801ca746524e55 Mon Sep 17 00:00:00 2001 From: Mandar Mahesh Kamble Date: Wed, 11 Dec 2024 15:03:38 +0530 Subject: [PATCH 1/2] tty: msm: Update timer handling for interrupt-safe context Modified timer handling to address recent updates in del_timer_sync() behavior. The function is not permitted to be invoked from interrupt context unless the timer is marked with TIMER_IRQSAFE. To ensure compliance and avoid potential race conditions, the affected timer is now explicitly marked with TIMER_IRQSAFE. Change-Id: I5724f4172e6576ba2f0cce5e383d76dbdb0ce637 Signed-off-by: Mandar Mahesh Kamble --- drivers/tty/serial/msm_serial_hs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index cfee5b5799b6..47c50bb1eef3 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -2684,7 +2684,7 @@ static int msm_hs_startup(struct uart_port *uport) tx->dma_in_flight = false; MSM_HS_DBG("%s():desc usage flag 0x%lx\n", __func__, rx->queued_flag); timer_setup(&(tx->tx_timeout_timer), - tx_timeout_handler, 0); + tx_timeout_handler, TIMER_IRQSAFE); /* Enable reading the current CTS, no harm even if CTS is ignored */ msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK; From c2adf7dc3fbf9c4d71742f0b49ad577cccb08b03 Mon Sep 17 00:00:00 2001 From: Santosh Sakore Date: Mon, 18 May 2026 16:15:14 +0530 Subject: [PATCH 2/2] msm:adsprpc: Fix UAF of ctx->perf in async invoke perf counter In async invoke path, fastrpc_update_invoke_count is called at invoke_end with perf_counter pointing into ctx->perf. After fastrpc_invoke_send returns, the async response thread may call context_free(ctx), freeing ctx->perf before invoke_end. This causes a use-after-free write that corrupts the SLUB freelist and may trigger a kernel panic on next allocation. Fix by storing submission timestamp in ctx->invoke_start_time before send, removing unsafe call from invoke_end, and moving fastrpc_update_invoke_count to fastrpc_wait_on_async_queue. There, ctx is guaranteed valid before context_free. This also aligns async perf->invoke with sync, measuring full end-to-end latency instead of submission-only latency. Acked-by: Sharad Kumar Change-Id: I91f2a2479b508fde2fe7c26783ee56dc9391eb17 Signed-off-by: Santosh Sakore --- drivers/char/adsprpc.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 39bdf863b597..ee38e227a93a 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ /* Uncomment this block to log an error on every VERIFY failure */ @@ -444,6 +444,7 @@ struct smq_invoke_ctx { uint32_t sc_interrupted; struct fastrpc_file *fl_interrupted; uint32_t handle_interrupted; + struct timespec64 invoke_start_time; /* submission timestamp for async perf */ }; struct fastrpc_ctx_lst { @@ -3362,6 +3363,15 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, inv_args(ctx); PERF_END); + /* + * Store submission timestamp in ctx before sending to DSP. + * For async invokes, perf->invoke will be updated in the collector + * thread (fastrpc_wait_on_async_queue) where ctx is still valid, + * measuring full end-to-end latency consistent with the sync path. + */ + if (fl->profile && isasyncinvoke) + ctx->invoke_start_time = invoket; + PERF(fl->profile, GET_COUNTER(perf_counter, PERF_LINK), VERIFY(err, 0 == (err = fastrpc_invoke_send(ctx, kernel, invoke->handle))); @@ -3423,9 +3433,6 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, err = -ECONNRESET; invoke_end: - if (fl->profile && !interrupted && isasyncinvoke) - fastrpc_update_invoke_count(invoke->handle, perf_counter, - &invoket); return err; } @@ -3495,6 +3502,15 @@ bail: async_res->result = ierr; if (ctx) { if (fl->profile && ctx->perf && ctx->handle > FASTRPC_STATIC_HANDLE_MAX) { + /* + * Update invoke/count perf counters here where ctx->perf is + * guaranteed valid. This measures full end-to-end async latency + * (submit → DSP → collect), consistent with the sync path. + * invoke_start_time was stored in ctx before fastrpc_invoke_send + * in fastrpc_internal_invoke. + */ + fastrpc_update_invoke_count(ctx->handle, perf_counter, + &ctx->invoke_start_time); trace_fastrpc_perf_counters(ctx->handle, ctx->sc, ctx->perf->count, ctx->perf->flush, ctx->perf->map, ctx->perf->copy, ctx->perf->link, ctx->perf->getargs,