From nobody Thu Apr 9 13:31:45 2026 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0BBEF361646 for ; Sun, 8 Mar 2026 11:09:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772968184; cv=none; b=NQvUc0nSyLW+lwl5Kd8+4AGtfpnmP7du+AIXcIluuYPhSf4YtMDcunS1HhqJA0G5Iu7ZMdVtN6sh+LZnzgUGwYVkvC6vxQDzHc0NvDDF1cyGYqWhHByA00KvKnAmwsuAkJQrC1kyXrLaoHbZfk3nsz74wqaNzr280g0je+jz++0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772968184; c=relaxed/simple; bh=6AAcio1GJc6nbuHkpQ3SnZoLqNmIyKgEysZExP+QjKY=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=BOouMxp74Un5jpGVyKGPMViOOlO2xpXwPkHReVugSsF5KnDsnAFYF9NL+ZmRHVsSghakzb04D9WCwqR/fpVberdZmuaVIqNPZSDbpB68/HIlzg6o4iVcnMnjh5DH3I+DCiOQ2LYXc7KsjyPUALwuPI4T+0fDCR126lLi5ahWgEc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gaQIAEj8; arc=none smtp.client-ip=209.85.128.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gaQIAEj8" Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-485345e1013so3438935e9.1 for ; Sun, 08 Mar 2026 04:09:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772968180; x=1773572980; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=l+XUt0u5XJpVULNhibEfvn6UJrIOwH1+vFY88JXb0GQ=; b=gaQIAEj8qcRyfy0A1EJ7LWr7x9qCSBcV2nsMH4A75SQ8cUdvCD+bTt3YNRfO7SNm40 0hHs1G3IVjfy6m41VSrnvYeEpxeZxLYpTzaXIRsiHIysGPTXXzs575bf+12dW5s1oSam MsdADRWx3/ETkAzOMATciXJz3BSbHEBTNLGO5IG/0UQ0hiUyBBiDciuDhSwpcQigMQxg ZwjsJD0Yv2iKblfNEbJFFHB0rT2POfQnktzvMt/2G3L+5cD/jdPyBVgvPb0HlMxFvBqf vTEtxF39JRHuPz7Ph4L273iQa99Pyrw3ZY9S/fPXi9QkhXORfU6FtmQl4SkmPijwzK/V VZJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772968180; x=1773572980; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=l+XUt0u5XJpVULNhibEfvn6UJrIOwH1+vFY88JXb0GQ=; b=b0QHF/zDnf/9qDalYkc0dCPQ/te7lXSqztqeFNVRIf17I5zNDqekgwqwaVgnrv0+gX 1gcQWjanYxCtZ1AHfy7nozLUJ41q5QofbKObmF+wPIkfbJw1pm3MTN8/JN/D8wURoQuP T4s0BxyIE1YQl7Y4XGstrD6/g4284RA+3bb/ImnM1p9o0B8bs+LLCCNIWKeSv2u9dCUF Tb+TjU6cI7DWCunqT9HsxkznUrMQU07wZNCCG46SoGhdG6L+GsZDLZtQ83xUMb9DmtjH yBejek4mKKPMaWfo80Bdl3nGDBNmP0XzwHeOiIoYqmIiu1cvjZgZT/i8v3Bv6OOI1bHz UUXA== X-Forwarded-Encrypted: i=1; AJvYcCUiSGIqlicGAesDxLFFdzltylzXntrdYJmy156RMWIMourfzkH7/SDwXIkGOtotCVcpugnr9QaSxm04Bjk=@vger.kernel.org X-Gm-Message-State: AOJu0YxLfQWzl7gz5QLIqj63XV/722loOshFoIaVVCfY1lG4KlmPLpLB 8KmfZrETYtx8AKSNepe7Lz0eWhr7dVlDzG96qEkIpZ/E23QLgPMBmTU= X-Gm-Gg: ATEYQzy3zSsLQMuSD28gN7+0YAX/CwNqDh3oUQl0u8errhtn919RDCiTBXbICeeFh8D VOEwP+R/AYIbHfgblpxBiHnSrHmjRoqjObAQCGqSgMgseem6czOS0v/3PVHfkA+YnbEARykjRRV nrqCQk4UCiaoQHuVaBYlUAeH7C9O2SxdbYUU97gjy5MmemV871tL/S/nJYMjrj4cfdMGaNs0DDG L4Meo+CR3ijNLNDyH1jzAmoXlVYWaslscK4DKE51w8EhOWkzzoknzW2eAfWUYIrJhmzCuzzyHhl s+KZW2gK2V9QR7Kjwm4GaJkF3hRr+KOUQVJ6BQ+Ij+lzNYrN2q2UqVTW4/OiN0GM7889qkCgP/c auBhOQh/6QhhaNWKR8Xt17aQDz4p08NzSQjTqhrS2bu3GoGfIDDZbx+p8h2B7Erx4ZdU9X2ue8W ugKtefdawKWHoME0lK4VN7yOGb30XGysQVz968fjiujy4= X-Received: by 2002:a05:600c:8b6f:b0:46e:59bd:f7e2 with SMTP id 5b1f17b1804b1-4852674e8f7mr136098015e9.11.1772968180067; Sun, 08 Mar 2026 04:09:40 -0700 (PDT) Received: from localhost.localdomain ([2a01:e11:2401:e440:4d43:1ae9:c232:cc4d]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4851fb3668csm406058865e9.13.2026.03.08.04.09.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Mar 2026 04:09:38 -0700 (PDT) From: Matteo Cotifava To: lgirdwood@gmail.com, broonie@kernel.org Cc: perex@perex.cz, tiwai@suse.com, srini@kernel.org, cujomalainey@chromium.org, linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, Matteo Cotifava Subject: [PATCH] ASoC: soc-core: fix use-after-free in snd_soc_unbind_card() Date: Sun, 8 Mar 2026 12:09:31 +0100 Message-Id: <20260308110931.148919-1-cotifavamatteo@gmail.com> X-Mailer: git-send-email 2.39.5 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When a sound card is unbound (e.g. on module removal) while a PCM stream close is pending, a race between the close delayed work and soc_cleanup_card_resources() can cause a use-after-free: BUG: KASAN: use-after-free in snd_soc_dapm_stream_event+0x39c/0x430 Read of size 8 at addr ffff00000a29a918 by task kworker/u8:0/8 CPU: 2 PID: 8 Comm: kworker/u8:0 Not tainted 5.15.71 #1 Hardware name: NXP i.MX8MM Workqueue: events_power_efficient close_delayed_work Call trace: snd_soc_dapm_stream_event+0x39c/0x430 snd_soc_close_delayed_work+0x208/0x2ac close_delayed_work+0x3c/0x54 process_one_work+0x670/0xfd4 worker_thread+0x84c/0xe74 kthread+0x370/0x410 ret_from_fork+0x10/0x20 Allocated by task 8: snd_soc_dapm_new_control_unlocked+0x2c/0xbc4 snd_soc_dapm_new_dai_widgets+0x12c/0x35c soc_probe_component+0x418/0xbb0 snd_soc_bind_card+0xa38/0x2200 Freed by task 488: snd_soc_dapm_free_widget+0x384/0x520 snd_soc_dapm_free+0x11c/0x284 soc_remove_component+0xd4/0x1b0 soc_cleanup_card_resources+0x184/0x700 snd_soc_unregister_card+0x1dc/0x240 __device_release_driver+0x2b0/0x584 driver_detach+0x190/0x290 asoc_simple_card_exit+0x18/0x30 [snd_soc_simple_card] __arm64_sys_delete_module+0x2f0/0x4b0 The PCM close path schedules rtd->delayed_work with a timer delay (pmdown_time). snd_soc_unbind_card() calls snd_soc_flush_all_delayed_work(), but flush_delayed_work() does not execute if the delayed work timer has not fired yet and the work item has not been enqueued in the workqueue. Cleanup then frees DAPM widgets, after which the timer fires and the work runs against freed memory. Replace snd_soc_flush_all_delayed_work() with a new snd_soc_cancel_all_delayed_work() in the unbind path to guarantee that any pending or running delayed work is cancelled or awaited before card resources are released. Also fix soc_free_pcm_runtime() to use cancel_delayed_work_sync() unconditionally instead of the racy conditional flush. The original check of delayed_work_pending() followed by flush_delayed_work() has a time window where the work can become pending between the two calls. Fixes: e894efef9ac7 ("ASoC: core: add support to card rebind") Fixes: 9c9b65203492 ("ASoC: core: only flush inited work during free") Signed-off-by: Matteo Cotifava --- sound/soc/soc-core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d0fffef65daf..0f459679d459 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -462,8 +462,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_run= time *rtd) =20 list_del(&rtd->list); =20 - if (delayed_work_pending(&rtd->delayed_work)) - flush_delayed_work(&rtd->delayed_work); + cancel_delayed_work_sync(&rtd->delayed_work); snd_soc_pcm_component_free(rtd); =20 /* @@ -616,6 +615,14 @@ static void snd_soc_flush_all_delayed_work(struct snd_= soc_card *card) flush_delayed_work(&rtd->delayed_work); } =20 +static void snd_soc_cancel_all_delayed_work(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd; + + for_each_card_rtds(card, rtd) + cancel_delayed_work_sync(&rtd->delayed_work); +} + #ifdef CONFIG_PM_SLEEP static void soc_playback_digital_mute(struct snd_soc_card *card, int mute) { @@ -2149,7 +2156,7 @@ static void snd_soc_unbind_card(struct snd_soc_card *= card) { if (snd_soc_card_is_instantiated(card)) { card->instantiated =3D false; - snd_soc_flush_all_delayed_work(card); + snd_soc_cancel_all_delayed_work(card); =20 soc_cleanup_card_resources(card); } --=20 2.39.5