diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-03-16 08:16:27 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-03-16 21:03:29 -0400 |
commit | 46230aa6ea1671690e3e5efa2a961fc0745fe9b5 (patch) | |
tree | 9224af1ccdb48fac6d0b400b6a76e2d62f104972 /arch/mips | |
parent | bc4809e939b91c9642f1ddaea732e2d432ee6af6 (diff) |
[MIPS] RTLX: Handle copy_*_user return values.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/kspd.c | 18 | ||||
-rw-r--r-- | arch/mips/kernel/rtlx.c | 46 |
2 files changed, 35 insertions, 29 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 | ||
292 | static inline void copy_to(void *dst, void *src, size_t count, int user) | 292 | ssize_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 | |||
300 | static 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 | |||
308 | ssize_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 | |||
323 | out: | ||
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 | ||
344 | ssize_t rtlx_write(int index, void *buffer, size_t count, int user) | 334 | ssize_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 | |||
365 | out: | ||
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 | ||
432 | static ssize_t file_write(struct file *file, const char __user * buffer, | 428 | static 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 | ||
458 | static const struct file_operations rtlx_fops = { | 454 | static const struct file_operations rtlx_fops = { |