aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-03-16 08:16:27 -0400
committerRalf Baechle <ralf@linux-mips.org>2007-03-16 21:03:29 -0400
commit46230aa6ea1671690e3e5efa2a961fc0745fe9b5 (patch)
tree9224af1ccdb48fac6d0b400b6a76e2d62f104972
parentbc4809e939b91c9642f1ddaea732e2d432ee6af6 (diff)
[MIPS] RTLX: Handle copy_*_user return values.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/kspd.c18
-rw-r--r--arch/mips/kernel/rtlx.c46
-rw-r--r--include/asm-mips/rtlx.h4
3 files changed, 37 insertions, 31 deletions
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
index 241ee7a2906e..29eadd404fa5 100644
--- a/arch/mips/kernel/kspd.c
+++ b/arch/mips/kernel/kspd.c
@@ -191,6 +191,8 @@ void sp_work_handle_request(void)
191 struct mtsp_syscall_generic generic; 191 struct mtsp_syscall_generic generic;
192 struct mtsp_syscall_ret ret; 192 struct mtsp_syscall_ret ret;
193 struct kspd_notifications *n; 193 struct kspd_notifications *n;
194 unsigned long written;
195 mm_segment_t old_fs;
194 struct timeval tv; 196 struct timeval tv;
195 struct timezone tz; 197 struct timezone tz;
196 int cmd; 198 int cmd;
@@ -201,7 +203,11 @@ void sp_work_handle_request(void)
201 203
202 ret.retval = -1; 204 ret.retval = -1;
203 205
204 if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) { 206 old_fs = get_fs();
207 set_fs(KERNEL_DS);
208
209 if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall))) {
210 set_fs(old_fs);
205 printk(KERN_ERR "Expected request but nothing to read\n"); 211 printk(KERN_ERR "Expected request but nothing to read\n");
206 return; 212 return;
207 } 213 }
@@ -209,7 +215,8 @@ void sp_work_handle_request(void)
209 size = sc.size; 215 size = sc.size;
210 216
211 if (size) { 217 if (size) {
212 if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) { 218 if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size)) {
219 set_fs(old_fs);
213 printk(KERN_ERR "Expected request but nothing to read\n"); 220 printk(KERN_ERR "Expected request but nothing to read\n");
214 return; 221 return;
215 } 222 }
@@ -282,8 +289,11 @@ void sp_work_handle_request(void)
282 if (vpe_getuid(SP_VPE)) 289 if (vpe_getuid(SP_VPE))
283 sp_setfsuidgid( 0, 0); 290 sp_setfsuidgid( 0, 0);
284 291
285 if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0)) 292 old_fs = get_fs();
286 < sizeof(struct mtsp_syscall_ret)) 293 set_fs(KERNEL_DS);
294 written = rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(ret));
295 set_fs(old_fs);
296 if (written < sizeof(ret))
287 printk("KSPD: sp_work_handle_request failed to send to SP\n"); 297 printk("KSPD: sp_work_handle_request failed to send to SP\n");
288} 298}
289 299
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 745649e15adc..e6e3047151a6 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -289,26 +289,11 @@ unsigned int rtlx_write_poll(int index)
289 return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); 289 return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
290} 290}
291 291
292static inline void copy_to(void *dst, void *src, size_t count, int user) 292ssize_t rtlx_read(int index, void __user *buff, size_t count, int user)
293{
294 if (user)
295 copy_to_user(dst, src, count);
296 else
297 memcpy(dst, src, count);
298}
299
300static inline void copy_from(void *dst, void *src, size_t count, int user)
301{
302 if (user)
303 copy_from_user(dst, src, count);
304 else
305 memcpy(dst, src, count);
306}
307
308ssize_t rtlx_read(int index, void *buff, size_t count, int user)
309{ 293{
310 size_t lx_write, fl = 0L; 294 size_t lx_write, fl = 0L;
311 struct rtlx_channel *lx; 295 struct rtlx_channel *lx;
296 unsigned long failed;
312 297
313 if (rtlx == NULL) 298 if (rtlx == NULL)
314 return -ENOSYS; 299 return -ENOSYS;
@@ -327,11 +312,16 @@ ssize_t rtlx_read(int index, void *buff, size_t count, int user)
327 /* then how much from the read pointer onwards */ 312 /* then how much from the read pointer onwards */
328 fl = min(count, (size_t)lx->buffer_size - lx->lx_read); 313 fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
329 314
330 copy_to(buff, lx->lx_buffer + lx->lx_read, fl, user); 315 failed = copy_to_user(buff, lx->lx_buffer + lx->lx_read, fl);
316 if (failed)
317 goto out;
331 318
332 /* and if there is anything left at the beginning of the buffer */ 319 /* and if there is anything left at the beginning of the buffer */
333 if (count - fl) 320 if (count - fl)
334 copy_to(buff + fl, lx->lx_buffer, count - fl, user); 321 failed = copy_to_user(buff + fl, lx->lx_buffer, count - fl);
322
323out:
324 count -= failed;
335 325
336 smp_wmb(); 326 smp_wmb();
337 lx->lx_read = (lx->lx_read + count) % lx->buffer_size; 327 lx->lx_read = (lx->lx_read + count) % lx->buffer_size;
@@ -341,7 +331,7 @@ ssize_t rtlx_read(int index, void *buff, size_t count, int user)
341 return count; 331 return count;
342} 332}
343 333
344ssize_t rtlx_write(int index, void *buffer, size_t count, int user) 334ssize_t rtlx_write(int index, const void __user *buffer, size_t count, int user)
345{ 335{
346 struct rtlx_channel *rt; 336 struct rtlx_channel *rt;
347 size_t rt_read; 337 size_t rt_read;
@@ -363,11 +353,17 @@ ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
363 /* first bit from write pointer to the end of the buffer, or count */ 353 /* first bit from write pointer to the end of the buffer, or count */
364 fl = min(count, (size_t) rt->buffer_size - rt->rt_write); 354 fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
365 355
366 copy_from(rt->rt_buffer + rt->rt_write, buffer, fl, user); 356 failed = copy_from_user(rt->rt_buffer + rt->rt_write, buffer, fl);
357 if (failed)
358 goto out;
367 359
368 /* if there's any left copy to the beginning of the buffer */ 360 /* if there's any left copy to the beginning of the buffer */
369 if (count - fl) 361 if (count - fl) {
370 copy_from(rt->rt_buffer, buffer + fl, count - fl, user); 362 failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
363 }
364
365out:
366 count -= cailed;
371 367
372 smp_wmb(); 368 smp_wmb();
373 rt->rt_write = (rt->rt_write + count) % rt->buffer_size; 369 rt->rt_write = (rt->rt_write + count) % rt->buffer_size;
@@ -426,7 +422,7 @@ static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
426 return 0; // -EAGAIN makes cat whinge 422 return 0; // -EAGAIN makes cat whinge
427 } 423 }
428 424
429 return rtlx_read(minor, buffer, count, 1); 425 return rtlx_read(minor, buffer, count);
430} 426}
431 427
432static ssize_t file_write(struct file *file, const char __user * buffer, 428static ssize_t file_write(struct file *file, const char __user * buffer,
@@ -452,7 +448,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
452 return ret; 448 return ret;
453 } 449 }
454 450
455 return rtlx_write(minor, (void *)buffer, count, 1); 451 return rtlx_write(minor, buffer, count);
456} 452}
457 453
458static const struct file_operations rtlx_fops = { 454static const struct file_operations rtlx_fops = {
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h
index 59162f74a798..65778c890a62 100644
--- a/include/asm-mips/rtlx.h
+++ b/include/asm-mips/rtlx.h
@@ -23,8 +23,8 @@
23 23
24extern int rtlx_open(int index, int can_sleep); 24extern int rtlx_open(int index, int can_sleep);
25extern int rtlx_release(int index); 25extern int rtlx_release(int index);
26extern ssize_t rtlx_read(int index, void *buff, size_t count, int user); 26extern ssize_t rtlx_read(int index, void __user *buff, size_t count);
27extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user); 27extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count);
28extern unsigned int rtlx_read_poll(int index, int can_sleep); 28extern unsigned int rtlx_read_poll(int index, int can_sleep);
29extern unsigned int rtlx_write_poll(int index); 29extern unsigned int rtlx_write_poll(int index);
30 30