From nobody Tue Apr 7 04:33:41 2026 Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (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 8B7323191D0 for ; Mon, 16 Mar 2026 03:22:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773631336; cv=none; b=ZU4Zv+peC8sZIsSsplG4G7271W2DP5izCLxP2bH+3u9qR+iwoYhWLuHjewaj0CuaUHegClVTIYKPfVY9/XMZVd6lhbn+D3d8RO2JcVpXLlK93BfBm+C6Zl3N278IJBoWVOtzifm1A2vLNUGXscCkvMxjksc8guijesnZARnivKU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773631336; c=relaxed/simple; bh=ez82zxCDf9P9+PNzHGei2Hhnm1dPlCEked1dI8VnhJ4=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=gpGnuerLluakZw7x65RT3+9h8A8+/rqd6qGno6r2IykM2zSPybUIosuK/UYYbviQW1IS9PJcXNtY2GrF5CXhDS3wHQ3yZkBc8l90j5WCG3KNyQT/4+etkMnYm/uukGyAMfszSfA2qpIlf20CXH0Gc8/AvfRNRhBebqgKRSIdd54= 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=E+v3+2Al; arc=none smtp.client-ip=209.85.215.176 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="E+v3+2Al" Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-b6ce6d1d3dcso1652496a12.3 for ; Sun, 15 Mar 2026 20:22:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773631335; x=1774236135; 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=nVCjl98hSGWubchG+CVHkUXvsWypJfNduECzgqravVA=; b=E+v3+2AlQqalRr860RJSm30HrQXFFDMroT9aEwpIzyWknMnVBzDkqyieDINeAGuBcw qWpc4aU70tbspexSKbXWSoP8ollF3VWXSZoeO/ILuITf+LGibi1oF7A86BwyZOT4FjEM s2xooPiaD2w3lBoC4+MYUBgMhdnlxytg9+UjkpQvTZs2AfjWsAHo4UbWhUa1ZFheZk1h 7526upNCp2ZqgGIJLDf7SMyozYg912haV7mQ1l5tlgUD70DmKucW/upoVe8/p2GYLEfT nM77V5jLST7R1+50Xbe9emqEBuMvRZFT7Vsypb4z88X56fRyi2ra3EwbUfWv+8jFGrrq 1V9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773631335; x=1774236135; 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=nVCjl98hSGWubchG+CVHkUXvsWypJfNduECzgqravVA=; b=Cb1Xj1DhX4MKWgh9zUIT5OdNeYl6134zHagxqSUMS0Gu6yvqxGOojmdm/I7Yw21y73 myGsCwjBnnwpuBm4IWFkCirYPziGc+n5WxkiPa0l+dF9UU0msYW6i7RApqTWhWBxmbY3 ZncNpmKhOaXDHCwuOphIn7ad6MZrvIDkhyf0eWMB4iVx2mJBISmRMN4OAN8J3b6L7tH2 2XGJh7L11ewLyHfY5UUc5dLXTN/u8aqtK1/JFtwGUPoCeUqnO2CBRXqX90s2I6kCB8TX 6wHKjddxmsVdzp4egBffFFSIs5tbBt3wyLfJl0nLOWkQmU7raXIahs4bNE1BiyZSA5zq X28Q== X-Forwarded-Encrypted: i=1; AJvYcCUvqfB7uSd8qLFzCjKNV96mUeunmOpKOx6fZZdncME39RmcLH1wS31iGohy6wawIGSTWxmrma4dQjvD/CA=@vger.kernel.org X-Gm-Message-State: AOJu0Yx46VltL84NUFme9AnFlpgV+i/Bn3qVP62xDbmsZN9JoMOb3S8X fMYX+rLQPtEjprNMBwrTe2dGs+4uaKZh5ytR1HUDOr2X4shFG6Fwy62z X-Gm-Gg: ATEYQzx7Uy0mi4vGQWMMO8+CcZSMaVgtwvJ+pwtxPu7g2zXg33mVeCI7uPV0w5aoqsV mx71mfQg1ONa/v2d4EgMUf6KNj5MT4CWHhVKK60gPJGIaYusZQPtB5pBvX56R+qVUViN/NQgYBV g1kQRysiNkIhP+BwCPMOpUhEETfCRV4xnL3tFLoi54iEvTDK+YV+uE3nCGM2n7ExvyRgvtxkAes kobyugpjPOGMPwrcHUpLrcr2/6wCvG0jr10G0kwlts9rEriRlNe5pXmim1j88CbmpB3AKr95VRU 5AiCaelcVdBsIXG+QI967HzH2DX1y0pO7qBceGUiHhcP6UQWPOEhP8Whc21xszHcF5qWwEvrYTd hpTyo+CLiy6YSzwo19epBCVWbkoMz9Aye1JNLINBHG2jBbk7qtGwdyg+bh7qwHW7DKMzzbu/LDA PCq1DW8bKrrlHRX3ezAgedBgTlYwei X-Received: by 2002:a05:6a21:7113:b0:398:a306:d645 with SMTP id adf61e73a8af0-398ecaf75abmr10382710637.25.1773631334813; Sun, 15 Mar 2026 20:22:14 -0700 (PDT) Received: from lavm-prs74opxn5.. ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c73ebb6336bsm8319076a12.21.2026.03.15.20.22.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 15 Mar 2026 20:22:14 -0700 (PDT) From: Cen Zhang To: perex@perex.cz, tiwai@suse.com, chleroy@kernel.org Cc: linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, baijiaju1990@gmail.com, r33s3n6@gmail.com, gality369@gmail.com, zhenghaoran154@gmail.com, hanguidong02@gmail.com, ziyuzhang201@gmail.com, Cen Zhang Subject: [PATCH] ALSA: pcm: oss: annotate data-races around runtime->state Date: Mon, 16 Mar 2026 11:05:50 +0800 Message-Id: <20260316030550.2848349-1-zzzccc427@gmail.com> X-Mailer: git-send-email 2.34.1 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" __snd_pcm_set_state() writes runtime->state under the PCM stream lock: runtime->state =3D state; However, the OSS I/O functions snd_pcm_oss_write3(), snd_pcm_oss_read3(), snd_pcm_oss_writev3() and snd_pcm_oss_readv3() read runtime->state without holding the stream lock, only holding oss.params_lock (a different mutex that does not synchronize with the stream lock): if (runtime->state =3D=3D SNDRV_PCM_STATE_XRUN || ...) Since __snd_pcm_set_state() is called from IRQ context (e.g., snd_pcm_period_elapsed -> snd_pcm_update_state -> __snd_pcm_xrun -> snd_pcm_stop -> snd_pcm_post_stop) while the OSS read/write paths run in process context, these are concurrent accesses that constitute a data race. The code handles stale reads gracefully through its retry loop (re-checking after __snd_pcm_lib_xfer returns -EPIPE), so the race is not harmful under simple interleaving. However, plain C accesses are formally undefined under LKMM, and without READ_ONCE the compiler is free to fuse or cache the loads across loop iterations. Add WRITE_ONCE() in __snd_pcm_set_state() for the write side and READ_ONCE() on all lockless reads of runtime->state in the four OSS I/O functions. Signed-off-by: Cen Zhang --- include/sound/pcm.h | 2 +- sound/core/oss/pcm_oss.c | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index a7860c047503..a91061ace828 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -725,7 +725,7 @@ static inline int snd_pcm_running(struct snd_pcm_substr= eam *substream) static inline void __snd_pcm_set_state(struct snd_pcm_runtime *runtime, snd_pcm_state_t state) { - runtime->state =3D state; + WRITE_ONCE(runtime->state, state); runtime->status->state =3D state; /* copy for mmap */ } =20 diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index d4fd4dfc7fc3..b9277f54fa27 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1229,12 +1229,12 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm= _substream *substream, const struct snd_pcm_runtime *runtime =3D substream->runtime; int ret; while (1) { - if (runtime->state =3D=3D SNDRV_PCM_STATE_XRUN || - runtime->state =3D=3D SNDRV_PCM_STATE_SUSPENDED) { + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN || + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: write: recovering from %s\n", - runtime->state =3D=3D SNDRV_PCM_STATE_XRUN ? + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret =3D snd_pcm_oss_prepare(substream); @@ -1249,7 +1249,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_s= ubstream *substream, const break; /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->state =3D=3D SNDRV_PCM_STATE_PREPARED) + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1261,18 +1261,18 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_= substream *substream, char *p snd_pcm_sframes_t delay; int ret; while (1) { - if (runtime->state =3D=3D SNDRV_PCM_STATE_XRUN || - runtime->state =3D=3D SNDRV_PCM_STATE_SUSPENDED) { + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN || + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: read: recovering from %s\n", - runtime->state =3D=3D SNDRV_PCM_STATE_XRUN ? + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret =3D snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->state =3D=3D SNDRV_PCM_STATE_SETUP) { + } else if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_SETUP) { ret =3D snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1285,7 +1285,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_su= bstream *substream, char *p frames, in_kernel); mutex_lock(&runtime->oss.params_lock); if (ret =3D=3D -EPIPE) { - if (runtime->state =3D=3D SNDRV_PCM_STATE_DRAINING) { + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_DRAINING) { ret =3D snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if (ret < 0) break; @@ -1304,12 +1304,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pc= m_substream *substream, void struct snd_pcm_runtime *runtime =3D substream->runtime; int ret; while (1) { - if (runtime->state =3D=3D SNDRV_PCM_STATE_XRUN || - runtime->state =3D=3D SNDRV_PCM_STATE_SUSPENDED) { + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN || + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: writev: recovering from %s\n", - runtime->state =3D=3D SNDRV_PCM_STATE_XRUN ? + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret =3D snd_pcm_oss_prepare(substream); @@ -1322,7 +1322,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_= substream *substream, void =20 /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->state =3D=3D SNDRV_PCM_STATE_PREPARED) + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1333,18 +1333,18 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm= _substream *substream, void * struct snd_pcm_runtime *runtime =3D substream->runtime; int ret; while (1) { - if (runtime->state =3D=3D SNDRV_PCM_STATE_XRUN || - runtime->state =3D=3D SNDRV_PCM_STATE_SUSPENDED) { + if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN || + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: readv: recovering from %s\n", - runtime->state =3D=3D SNDRV_PCM_STATE_XRUN ? + READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret =3D snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->state =3D=3D SNDRV_PCM_STATE_SETUP) { + } else if (READ_ONCE(runtime->state) =3D=3D SNDRV_PCM_STATE_SETUP) { ret =3D snd_pcm_oss_prepare(substream); if (ret < 0) break; --=20 2.34.1