[PATCH 0/5] powerpc/spufs: fix a leak, an OOB read and three context lifetime/locking bugs

From: Junrui Luo via B4 Relay

Date: Wed Aug 12 2026 - 01:49:22 EST


This series fixes five independent bugs in spufs.

The first two are simple and directly reachable by an unprivileged user:

- Patch 1 frees the struct spufs_fs_context allocated by
->init_fs_context(). Nothing ever released it, so every spufs
fs_context leaks it, and fsopen() reaches ->init_fs_context() before
sget_fc() rejects the mount for the lack of FS_USERNS_MOUNT.

- Patch 2 removes a double sizeof(u32) scaling in
spufs_wbox_info_read(). The value handed to
simple_read_from_buffer() as the length of available data reaches 64
for a 16-byte on-stack buffer, so a read past offset 16 copies up to
48 bytes of adjacent kernel stack to userspace. The mailbox
occupancy that gates this is set by writing the context's own wbox
file, and wbox_info is mode 0444.

The remaining three are concurrency bugs in the context scheduler and
the fault path - one object lifetime race, and two around
ctx->state_mutex:

- Patch 3 takes a reference on contexts returned by
grab_runnable_context(). The runqueue holds no reference of its own,
and once the context is unlinked the owner's spu_del_from_rq()
becomes a no-op, so it can close and free the context while the
scheduler still holds the pointer - a use-after-free window spanning
a full context save. The BUG_ON(!list_empty(&ctx->rq)) in
destroy_spu_context() cannot catch it, because list_del_init() has
already emptied ctx->rq.

- Patch 4 retests ctx->state after spu_deactivate() in
spu_acquire_saved(). __spu_deactivate() drops state_mutex
internally, so the earlier test is stale on return; a second reader
can consume the single SPU_SCHED_WAS_ACTIVE bit and rebind the
context, leaving the first acquirer reading a save image the SPU is
still writing and then hitting the BUG_ON() in spu_release_saved()
with state_mutex held.

- Patch 5 releases state_mutex before re-taking mmap_lock in
spufs_ps_fault(). Every other spufs fault path takes the two locks
in the opposite order, and three threads sharing an mm can close the
cycle; because spusched_tick() takes the same state_mutex, one
wedged context also stalls SPU scheduling for the whole node.

Signed-off-by: Junrui Luo <moonafterrain@xxxxxxxxxxx>
---
Junrui Luo (5):
powerpc/spufs: fix memory leak of spufs_fs_context in spufs_free_fc()
powerpc/spufs: fix out-of-bounds read in spufs_wbox_info_read()
powerpc/spufs: take a reference on contexts pulled off the runqueue
powerpc/spufs: fix context state race in spu_acquire_saved()
powerpc/spufs: fix mmap_lock/state_mutex lock inversion

arch/powerpc/platforms/cell/spufs/context.c | 4 ++--
arch/powerpc/platforms/cell/spufs/file.c | 6 ++++--
arch/powerpc/platforms/cell/spufs/inode.c | 1 +
arch/powerpc/platforms/cell/spufs/sched.c | 9 ++++++++-
4 files changed, 15 insertions(+), 5 deletions(-)
---
base-commit: 075b74841bd0065a3bda3440873c747938e69b68
change-id: 20260812-spufs-fixes-ca7e13863189

Best regards,
--
Junrui Luo <moonafterrain@xxxxxxxxxxx>