aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorArnd Bergmann <arnd.bergmann@de.ibm.com>2007-03-09 18:05:35 -0500
committerArnd Bergmann <arnd@klappe.arndb.de>2007-03-09 18:07:48 -0500
commitaa0ed2bdb663608d5e409faecff3e1e81a3d413a (patch)
tree88382df6dec804ae319316753c661c8212cd0832 /arch/powerpc
parentf194bda4ce7e71cc95535f494a4a5515cd91ed85 (diff)
[POWERPC] spufs: fix possible memory corruption is spufs_mem_write
Due to a buggy unsigned comparison, it was possible to write beyond the end of the local store file in spufs under some circumstances. This rewrites the buggy function to look more like simple_copy_from_buffer. Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Cc: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index b00653d69c01..505266a568d4 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -63,8 +63,8 @@ static ssize_t
63spufs_mem_read(struct file *file, char __user *buffer, 63spufs_mem_read(struct file *file, char __user *buffer,
64 size_t size, loff_t *pos) 64 size_t size, loff_t *pos)
65{ 65{
66 int ret;
67 struct spu_context *ctx = file->private_data; 66 struct spu_context *ctx = file->private_data;
67 ssize_t ret;
68 68
69 spu_acquire(ctx); 69 spu_acquire(ctx);
70 ret = __spufs_mem_read(ctx, buffer, size, pos); 70 ret = __spufs_mem_read(ctx, buffer, size, pos);
@@ -74,25 +74,29 @@ spufs_mem_read(struct file *file, char __user *buffer,
74 74
75static ssize_t 75static ssize_t
76spufs_mem_write(struct file *file, const char __user *buffer, 76spufs_mem_write(struct file *file, const char __user *buffer,
77 size_t size, loff_t *pos) 77 size_t size, loff_t *ppos)
78{ 78{
79 struct spu_context *ctx = file->private_data; 79 struct spu_context *ctx = file->private_data;
80 char *local_store; 80 char *local_store;
81 loff_t pos = *ppos;
81 int ret; 82 int ret;
82 83
83 size = min_t(ssize_t, LS_SIZE - *pos, size); 84 if (pos < 0)
84 if (size <= 0) 85 return -EINVAL;
86 if (pos > LS_SIZE)
85 return -EFBIG; 87 return -EFBIG;
86 *pos += size; 88 if (size > LS_SIZE - pos)
89 size = LS_SIZE - pos;
87 90
88 spu_acquire(ctx); 91 spu_acquire(ctx);
89
90 local_store = ctx->ops->get_ls(ctx); 92 local_store = ctx->ops->get_ls(ctx);
91 ret = copy_from_user(local_store + *pos - size, 93 ret = copy_from_user(local_store + pos, buffer, size);
92 buffer, size) ? -EFAULT : size;
93
94 spu_release(ctx); 94 spu_release(ctx);
95 return ret; 95
96 if (ret)
97 return -EFAULT;
98 *ppos = pos + size;
99 return size;
96} 100}
97 101
98static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma, 102static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,