spufs_ps_fault() recovers the SPU context from the faulting file with

        struct spu_context *ctx = vmf->vma->vm_file->private_data;

This is correct for most spufs files, whose ->open stores the context in
file->private_data. The cntl file is the exception: spufs_cntl_open()
sets file->private_data = ctx but then calls simple_attr_open(), which
allocates a struct simple_attr and overwrites file->private_data with it
so that simple_attr_read()/write() work. cntl is also the only such file
that installs an mmap fault handler (spufs_cntl_mmap, on 4K-page
configs). When that mapping is faulted, spufs_ps_fault() reads back the
struct simple_attr as a struct spu_context and dereferences it
(ctx->state, ctx->spu->problem_phys), feeding a bogus value into
vmf_insert_pfn() -- a type confusion reachable by an unprivileged opener
of the 0666 cntl file.

Obtain the context from the inode instead, which always refers to the
real spu_context regardless of what ->private_data holds, matching how
coredump_next_context() and the affinity path already fetch it. This is
equivalent for every other spufs_ps_fault() caller and removes cntl's
dependence on a pointer that simple_attr_open() owns.

Fixes: e1dbff2bafa8 ("[POWERPC] spufs: add support for read/write on cntl")
Reported-by: Yuhao Jiang <[email protected]>
Assisted-by: Claude:claude-opus-5
Cc: [email protected]
Signed-off-by: Zhenhao Wan <[email protected]>
---
 arch/powerpc/platforms/cell/spufs/file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/cell/spufs/file.c 
b/arch/powerpc/platforms/cell/spufs/file.c
index de7494748fec..8c7515140efb 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -313,7 +313,7 @@ static vm_fault_t spufs_ps_fault(struct vm_fault *vmf,
                                    unsigned long ps_offs,
                                    unsigned long ps_size)
 {
-       struct spu_context *ctx = vmf->vma->vm_file->private_data;
+       struct spu_context *ctx = SPUFS_I(file_inode(vmf->vma->vm_file))->i_ctx;
        unsigned long area, offset = vmf->pgoff << PAGE_SHIFT;
        int err = 0;
        vm_fault_t ret = VM_FAULT_NOPAGE;

-- 
2.34.1


Reply via email to