* [PATCH v2 0/5] powerpc/spufs: assorted fixes
@ 2026-08-04 8:50 Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 1/5] powerpc/spufs: fix spu_context leak in coredump Junrui Luo via B4 Relay
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Junrui Luo via B4 Relay @ 2026-08-04 8:50 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Arnd Bergmann, Paul Mackerras,
Al Viro
Cc: linuxppc-dev, linux-kernel, Yuhao Jiang, stable, Junrui Luo
Five independent fixes for spufs. There is no dependency between them,
so they can be applied or dropped individually.
1/5 spufs_coredump_extra_notes_write() never drops the reference taken
by coredump_next_context(), so every SPE context written into a
core dump leaks a spu_context. The matching ..._size() path gets
this right.
2/5 do_spu_run() copies out an uninitialized 'status' on the paths
where spufs_run_spu() returns before assigning it, leaking four
bytes of kernel stack to userspace.
3/5 spufs_setattr() calls setattr_copy() without setattr_prepare().
notify_change() leaves that check to the filesystem, so mode and
ownership of a context's files can be changed without the usual
authorization.
4/5 spufs_create_gang() calls unuse_gang() with the parent directory's
i_rwsem held for write, and the resulting simple_recursive_removal()
takes it again as I_MUTEX_CHILD. The task deadlocks against itself
and leaves the spufs directory write-locked.
5/5 The mailbox read/write handlers hold ctx->state_mutex across
put_user()/get_user(), so a userfaultfd region or FUSE-backed user
buffer can stall the context lock for an arbitrary time.
Patches 1-4 are tagged for stable. 5/5 is deliberately not: it changes the
atomicity of multi-element mailbox transfers rather than just adding a
check, so it seems better to let it soak in mainline first.
Build-tested only. I have no Cell or PS3 hardware, so none of this has
been exercised at runtime.
---
Changes in v2:
- Add an Assisted-by: trailer to each patch identifying the tooling, as
requested by Arnd.
- Drop 3/6 from v1 (bound NPC against local store size).
- Link to v1: https://lore.kernel.org/r/20260802-fixes-v1-0-7368423440f4@outlook.com
---
Junrui Luo (5):
powerpc/spufs: fix spu_context leak in coredump
powerpc/spufs: don't leak kernel stack via spu_run
powerpc/spufs: check permissions in spufs_setattr()
powerpc/spufs: fix deadlock on gang creation failure
powerpc/spufs: don't hold state_mutex during user access
arch/powerpc/platforms/cell/spufs/coredump.c | 6 +++-
arch/powerpc/platforms/cell/spufs/file.c | 52 ++++++++++++++++------------
arch/powerpc/platforms/cell/spufs/inode.c | 21 +++++++----
arch/powerpc/platforms/cell/spufs/syscalls.c | 2 +-
4 files changed, 50 insertions(+), 31 deletions(-)
---
base-commit: 02dc699f83d04069fdabc996fc22d47cda47a4a9
change-id: 20260802-fixes-f33361c1b2ae
Best regards,
--
Junrui Luo <moonafterrain@outlook.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/5] powerpc/spufs: fix spu_context leak in coredump
2026-08-04 8:50 [PATCH v2 0/5] powerpc/spufs: assorted fixes Junrui Luo via B4 Relay
@ 2026-08-04 8:50 ` Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 2/5] powerpc/spufs: don't leak kernel stack via spu_run Junrui Luo via B4 Relay
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Junrui Luo via B4 Relay @ 2026-08-04 8:50 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Arnd Bergmann, Paul Mackerras,
Al Viro
Cc: linuxppc-dev, linux-kernel, Yuhao Jiang, stable, Junrui Luo
From: Junrui Luo <moonafterrain@outlook.com>
coredump_next_context() returns a spu_context with a reference taken by
get_spu_context(), which the caller must drop.
spufs_coredump_extra_notes_size() does so on all of its exits, but
spufs_coredump_extra_notes_write() never calls put_spu_context(), so
every context dumped through elf_coredump_extra_notes_write() leaks a
reference, including on the success path.
Fix by dropping the reference on each of the three exits of the loop,
mirroring ..._size().
Fixes: 38b407be172d ("powerpc/spufs: Rework fcheck() usage")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Assisted-by: Claude:claude-opus-5
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 301ee7d8b7df..f5964c9ebb3e 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -162,13 +162,16 @@ int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
rc = spu_acquire_saved(ctx);
- if (rc)
+ if (rc) {
+ put_spu_context(ctx);
return rc;
+ }
for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
rc = spufs_arch_write_note(ctx, j, cprm, fd);
if (rc) {
spu_release_saved(ctx);
+ put_spu_context(ctx);
return rc;
}
}
@@ -177,6 +180,7 @@ int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
/* start searching the next fd next time */
fd++;
+ put_spu_context(ctx);
}
return 0;
--
2.51.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/5] powerpc/spufs: don't leak kernel stack via spu_run
2026-08-04 8:50 [PATCH v2 0/5] powerpc/spufs: assorted fixes Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 1/5] powerpc/spufs: fix spu_context leak in coredump Junrui Luo via B4 Relay
@ 2026-08-04 8:50 ` Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 3/5] powerpc/spufs: check permissions in spufs_setattr() Junrui Luo via B4 Relay
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Junrui Luo via B4 Relay @ 2026-08-04 8:50 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Arnd Bergmann, Paul Mackerras,
Al Viro
Cc: linuxppc-dev, linux-kernel, Yuhao Jiang, stable, Junrui Luo
From: Junrui Luo <moonafterrain@outlook.com>
do_spu_run() hands the address of an uninitialized local to
spufs_run_spu() and then copies it out unconditionally:
u32 npc, status;
...
ret = spufs_run_spu(i->i_ctx, &npc, &status);
...
if (ustatus && put_user(status, ustatus))
ret = -EFAULT;
spufs_run_spu() writes through that pointer at exactly one place, the
"out:" label, and two of its exits never reach it: the interruptible
acquisition of ctx->run_mutex returns -ERESTARTSYS directly, and a
failed spu_acquire() jumps to "out_unlock", which sits just after the
assignment.
Initialize status to 0, which is what userspace would have observed had
the assignment been reached anyway: spufs_run_spu() resets
ctx->event_return to 0 on entry, and 0 is the "no events pending" value
for this word.
Fixes: 67207b9664a8 ("[PATCH] spufs: The SPU file system, base")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Assisted-by: Claude:claude-opus-5
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
arch/powerpc/platforms/cell/spufs/syscalls.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index ea4ba1b6ce6a..549fcfbbc140 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -37,7 +37,7 @@ static long do_spu_run(struct file *filp,
{
long ret;
struct spufs_inode_info *i;
- u32 npc, status;
+ u32 npc, status = 0;
ret = -EFAULT;
if (get_user(npc, unpc))
--
2.51.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/5] powerpc/spufs: check permissions in spufs_setattr()
2026-08-04 8:50 [PATCH v2 0/5] powerpc/spufs: assorted fixes Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 1/5] powerpc/spufs: fix spu_context leak in coredump Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 2/5] powerpc/spufs: don't leak kernel stack via spu_run Junrui Luo via B4 Relay
@ 2026-08-04 8:50 ` Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 4/5] powerpc/spufs: fix deadlock on gang creation failure Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 5/5] powerpc/spufs: don't hold state_mutex during user access Junrui Luo via B4 Relay
4 siblings, 0 replies; 6+ messages in thread
From: Junrui Luo via B4 Relay @ 2026-08-04 8:50 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Arnd Bergmann, Paul Mackerras,
Al Viro
Cc: linuxppc-dev, linux-kernel, Yuhao Jiang, stable, Junrui Luo
From: Junrui Luo <moonafterrain@outlook.com>
spufs_setattr() applies the caller's attributes with setattr_copy() but
never calls setattr_prepare(). notify_change() leaves that to the
filesystem: it runs only may_setattr(), while inode_owner_or_capable()
and the CAP_CHOWN test live inside setattr_prepare(). setattr_copy()
performs no checking of its own.
The handler is installed for every regular spufs file, so mode and
ownership of another user's context files can be changed without the
usual authorization.
Call setattr_prepare() before setattr_copy(). The existing ATTR_SIZE
test stays ahead of it so that resizing a spufs file keeps returning
-EINVAL. &nop_mnt_idmap matches the adjacent setattr_copy() call.
Fixes: 67207b9664a8 ("[PATCH] spufs: The SPU file system, base")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Assisted-by: Claude:claude-opus-5
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
arch/powerpc/platforms/cell/spufs/inode.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 2b54afb31529..c2b15c30f7c0 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -96,10 +96,14 @@ spufs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
+ int ret;
if ((attr->ia_valid & ATTR_SIZE) &&
(attr->ia_size != inode->i_size))
return -EINVAL;
+ ret = setattr_prepare(&nop_mnt_idmap, dentry, attr);
+ if (ret)
+ return ret;
setattr_copy(&nop_mnt_idmap, inode, attr);
mark_inode_dirty(inode);
return 0;
--
2.51.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 4/5] powerpc/spufs: fix deadlock on gang creation failure
2026-08-04 8:50 [PATCH v2 0/5] powerpc/spufs: assorted fixes Junrui Luo via B4 Relay
` (2 preceding siblings ...)
2026-08-04 8:50 ` [PATCH v2 3/5] powerpc/spufs: check permissions in spufs_setattr() Junrui Luo via B4 Relay
@ 2026-08-04 8:50 ` Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 5/5] powerpc/spufs: don't hold state_mutex during user access Junrui Luo via B4 Relay
4 siblings, 0 replies; 6+ messages in thread
From: Junrui Luo via B4 Relay @ 2026-08-04 8:50 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Arnd Bergmann, Paul Mackerras,
Al Viro
Cc: linuxppc-dev, linux-kernel, Yuhao Jiang, stable, Junrui Luo
From: Junrui Luo <moonafterrain@outlook.com>
do_spu_create() enters spufs with the parent directory's i_rwsem held
for write, taken as I_MUTEX_PARENT by start_creating_user_path() and
dropped only by end_creating_path(). When spufs_gang_open() fails inside
that window, spufs_create_gang() cleans up by calling unuse_gang().
The gang was just created, so gang->alive drops to 0 and unuse_gang()
proceeds to simple_recursive_removal(), which takes the parent inode's
i_rwsem as I_MUTEX_CHILD. This leads to the task blocking on an rwsem it
already holds, leaving the spufs directory write-locked. The other two
callers of unuse_gang() do not hold the parent lock: spufs_gang_close()
runs from ->release, and spufs_dir_close() drops the parent lock first.
Tell unuse_gang() which context it is called from, and use
locked_recursive_removal() when the parent is already held. This matches
spufs_rmdir(), which spufs_create_context() already uses for the same
cleanup under the same lock.
Fixes: c134deabf478 ("spufs: fix gang directory lifetimes")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Assisted-by: Claude:claude-opus-5
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
arch/powerpc/platforms/cell/spufs/inode.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index c2b15c30f7c0..998512409552 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -175,7 +175,8 @@ static int spufs_fill_dir(struct dentry *dir,
return 0;
}
-static void unuse_gang(struct dentry *dir)
+/* @parent_locked: caller holds dir->d_parent's i_rwsem as I_MUTEX_PARENT */
+static void unuse_gang(struct dentry *dir, bool parent_locked)
{
struct inode *inode = dir->d_inode;
struct spu_gang *gang = SPUFS_I(inode)->i_gang;
@@ -187,8 +188,12 @@ static void unuse_gang(struct dentry *dir)
dead = !--gang->alive;
inode_unlock(inode);
- if (dead)
- simple_recursive_removal(dir, NULL);
+ if (dead) {
+ if (parent_locked)
+ locked_recursive_removal(dir, NULL);
+ else
+ simple_recursive_removal(dir, NULL);
+ }
}
}
@@ -204,7 +209,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
spufs_rmdir(parent, dir);
inode_unlock(parent);
- unuse_gang(dir->d_parent);
+ unuse_gang(dir->d_parent, false);
return dcache_dir_close(inode, file);
}
@@ -483,7 +488,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
static int spufs_gang_close(struct inode *inode, struct file *file)
{
- unuse_gang(file->f_path.dentry);
+ unuse_gang(file->f_path.dentry, false);
return dcache_dir_close(inode, file);
}
@@ -520,7 +525,7 @@ static int spufs_create_gang(struct inode *inode,
if (!ret) {
ret = spufs_gang_open(&path);
if (ret < 0)
- unuse_gang(dentry);
+ unuse_gang(dentry, true);
}
return ret;
}
--
2.51.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 5/5] powerpc/spufs: don't hold state_mutex during user access
2026-08-04 8:50 [PATCH v2 0/5] powerpc/spufs: assorted fixes Junrui Luo via B4 Relay
` (3 preceding siblings ...)
2026-08-04 8:50 ` [PATCH v2 4/5] powerpc/spufs: fix deadlock on gang creation failure Junrui Luo via B4 Relay
@ 2026-08-04 8:50 ` Junrui Luo via B4 Relay
4 siblings, 0 replies; 6+ messages in thread
From: Junrui Luo via B4 Relay @ 2026-08-04 8:50 UTC (permalink / raw)
To: Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Arnd Bergmann, Paul Mackerras,
Al Viro
Cc: linuxppc-dev, linux-kernel, Yuhao Jiang, Junrui Luo
From: Junrui Luo <moonafterrain@outlook.com>
spufs_mbox_read(), spufs_ibox_read() and spufs_wbox_write() take the
context state_mutex with spu_acquire() and only drop it once their
transfer loop has finished, so every put_user()/get_user() in those
loops runs with the mutex held. The faulting address comes from
userspace, so the fault can be made to take arbitrarily long via
userfaultfd region or a FUSE-backed mapping.
Drop the mutex around the user accesses: acquire it per mailbox element,
just long enough for the ctx->ops mailbox operation, and release it
before touching the user buffer.
spufs_switch_log_read() has the same problem but its loop needs the lock
for more than just the copy.
Fixes: cdcc89bb1c6e ("[POWERPC] spufs: make mailbox functions handle multiple elements")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Assisted-by: Claude:claude-opus-5
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
arch/powerpc/platforms/cell/spufs/file.c | 52 ++++++++++++++++++--------------
1 file changed, 29 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index de7494748fec..c8c3b6e8affb 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -602,13 +602,17 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
if (len < 4)
return -EINVAL;
- count = spu_acquire(ctx);
- if (count)
- return count;
-
for (count = 0; (count + 4) <= len; count += 4, udata++) {
int ret;
+
+ ret = spu_acquire(ctx);
+ if (ret) {
+ if (!count)
+ count = ret;
+ break;
+ }
ret = ctx->ops->mbox_read(ctx, &mbox_data);
+ spu_release(ctx);
if (ret == 0)
break;
@@ -624,7 +628,6 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
break;
}
}
- spu_release(ctx);
if (!count)
count = -EAGAIN;
@@ -705,29 +708,34 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
count = spu_acquire(ctx);
if (count)
- goto out;
+ return count;
/* wait only for the first element */
- count = 0;
if (file->f_flags & O_NONBLOCK) {
if (!spu_ibox_read(ctx, &ibox_data)) {
- count = -EAGAIN;
- goto out_unlock;
+ spu_release(ctx);
+ return -EAGAIN;
}
} else {
count = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
if (count)
- goto out;
+ return count;
}
+ spu_release(ctx);
/* if we can't write at all, return -EFAULT */
count = put_user(ibox_data, udata);
if (count)
- goto out_unlock;
+ return count;
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
int ret;
+
+ ret = spu_acquire(ctx);
+ if (ret)
+ break;
ret = ctx->ops->ibox_read(ctx, &ibox_data);
+ spu_release(ctx);
if (ret == 0)
break;
/*
@@ -740,9 +748,6 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
break;
}
-out_unlock:
- spu_release(ctx);
-out:
return count;
}
@@ -839,40 +844,41 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
count = spu_acquire(ctx);
if (count)
- goto out;
+ return count;
/*
* make sure we can at least write one element, by waiting
* in case of !O_NONBLOCK
*/
- count = 0;
if (file->f_flags & O_NONBLOCK) {
if (!spu_wbox_write(ctx, wbox_data)) {
- count = -EAGAIN;
- goto out_unlock;
+ spu_release(ctx);
+ return -EAGAIN;
}
} else {
count = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
if (count)
- goto out;
+ return count;
}
-
+ spu_release(ctx);
/* write as much as possible */
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
int ret;
+
ret = get_user(wbox_data, udata);
if (ret)
break;
+ ret = spu_acquire(ctx);
+ if (ret)
+ break;
ret = spu_wbox_write(ctx, wbox_data);
+ spu_release(ctx);
if (ret == 0)
break;
}
-out_unlock:
- spu_release(ctx);
-out:
return count;
}
--
2.51.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-04 8:51 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 8:50 [PATCH v2 0/5] powerpc/spufs: assorted fixes Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 1/5] powerpc/spufs: fix spu_context leak in coredump Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 2/5] powerpc/spufs: don't leak kernel stack via spu_run Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 3/5] powerpc/spufs: check permissions in spufs_setattr() Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 4/5] powerpc/spufs: fix deadlock on gang creation failure Junrui Luo via B4 Relay
2026-08-04 8:50 ` [PATCH v2 5/5] powerpc/spufs: don't hold state_mutex during user access Junrui Luo via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox