From nobody Tue Apr 7 04:33:41 2026 Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) (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 6C561238166 for ; Mon, 16 Mar 2026 07:04:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773644681; cv=none; b=KbU1uf3DTAL9BpTaFTxq0AUXcMRTiTUcNWB9pZFhDyLBZZiN58+ye7++zg9mwhwollgPzSABUWH90PIhkaFKSXcg9P7fRpFFuXef7lpZauLRahnhfdv+ca/iG8M3BsWhh3wv8zYqmtJvESFRfxS5E5wINhZoIpVLXvehIckWVMo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773644681; c=relaxed/simple; bh=ez82zxCDf9P9+PNzHGei2Hhnm1dPlCEked1dI8VnhJ4=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=p0KiYIC7Jt6syCzrez0xeV8p3RNDuI1xOp0vW4iMbrK3ch3M8VDxZgVZ1d513E8FO2GiwUm+WZ+vQYXlJNscEjKbLASnMe1WS6xdNx+p8i0iA2ycBnMBgpq8l3tdiTVYUjF6i1V2jpTY1volBHHPiXtbA5RaPfihM9roXi0mKbE= 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=UUkgYD52; arc=none smtp.client-ip=209.85.216.47 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="UUkgYD52" Received: by mail-pj1-f47.google.com with SMTP id 98e67ed59e1d1-35b88a4f123so736859a91.1 for ; Mon, 16 Mar 2026 00:04:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773644680; x=1774249480; 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=UUkgYD52+y8JATLvhduQb13MXCB7p5pJeChY2uO8XOy1DtLdWy75l/O+aturRFQ0Xk ZZkciDtSDpGlnqBjCGF6DSdxPeTBH+fxPi/70lWprzxNQojSp64jyJ+FKqXZwHEDzBJC Ej+VzAyBvid8LvsuPMl52L6PbvoSnPfy50+8oi/jISCieYXhxW+SbsNtCakXxO2T9qG0 0NI+/AZZDqe2uS3ZTfXrW5ybQdYWuG6US7BeQEZZiALAvrXQZG1FZ1RNtWSHTneubzDV 2fl4pjRWP/7kAo7GWp/DD3qO4BvUcwIqLU+9kqDY2yXezsXKal9GqTGFquQePWXPlJH9 7vQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773644680; x=1774249480; 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=NpLpMfY2x50nFUFB8mQDPjGkcQjauiUAuEiuFr9GWIZwoo3Ih7ZBu1c5u3M1ebl7nT tugm0OqZDJqeOKOpyiMpCg+7nPJH6B22Cq5nqN4LrwgeYTyzeddJ4q52q0Bm1xvM0ww7 Y22W2NdVmWgxztXRzJ8rm9DhUAwN5tXSZowUnEQ5P2o0+qwwqgPQNaGBzLdx1vizMzGo kkZVmQ+RUMh6NxNk7YgOHcKV2QX6/puKdAS9UMGWOXyG8niBjJM/GjdOc4jy/t9B0dDI rMbFy3aVt+Z03eOxIgSuoKJfBQAT+ybIw2OGVXVyKPTgY7m/jRI6ZZq2MrKRlczk8pYo xOaA== X-Forwarded-Encrypted: i=1; AJvYcCXU7comFKQEALfMv6Jm6YNnU4u6327HKWwo+d1TdUtkpaaVey0otqvxeBTqMxB08vtS8ChW6FLsla04I7I=@vger.kernel.org X-Gm-Message-State: AOJu0YwIxfEouCxff0jpLevB1pmnO6aeuCepSkeYyl9P32krAdLePfwz T+I/KNI+/hWVHitNFfhGREl8Qf7GjNwZ/rWjzbWvPo5aZKN9h9j7xlo1 X-Gm-Gg: ATEYQzwXCkChUdBHbAck/Sw/wtkNsOUnnxUVbDSjz4Aaj7Ikw3vxygYG6WCrBv3ZpZb xVP8EhS47rH1tO4qfFJn0VX4r7vq/S/Q4Qezsg2uZcWpiM97Vkuh5SLiiH+l9wb0HRbhRnQC2f9 PSaZQGFt29RaNv7/V72tkEKBR6Hbla7wAJzFTAECQdEUIcr8tWgFmUaYS0PQBHGGuJ6TugLrvGw r9rYmYd32lE19fxQyyDtj2++JHUqDpXwfnJ4pxOSyUbbXK7fNlKDC9fXk9b1SJI019inyRgBHiE oUfaKocVdMgwVN9VaVCv4Y/pyrLE1z0TDNQSkYP275YHxwgliy8uHha7gdwY/JjdCZGzZc/o4PN 7JTPJZFItvVEUddU8TxRPou5lDFkaCVUnm/4lwcWlG2B/YKEowsviIhsRBXYtineEqu7Tn4kfgH gfpP8mRJ9aWvzCSQuwyQLPC5vTrnZADCtWjHzKIoQ= X-Received: by 2002:a17:90b:580c:b0:359:8df1:8553 with SMTP id 98e67ed59e1d1-35a21fd7ac6mr9423638a91.9.1773644679682; Mon, 16 Mar 2026 00:04:39 -0700 (PDT) Received: from lavm-prs74opxn5.. ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35b95822ca2sm1419864a91.4.2026.03.16.00.04.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Mar 2026 00:04:39 -0700 (PDT) From: Cen Zhang To: perex@perex.cz, chleroy@kernel.org Cc: tiwai@suse.com, 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 14:48:18 +0800 Message-Id: <20260316064818.2865473-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