diff options
Diffstat (limited to 'drivers/ieee1394/raw1394.c')
-rw-r--r-- | drivers/ieee1394/raw1394.c | 96 |
1 files changed, 91 insertions, 5 deletions
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index b05235639918..19f26c5c9479 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/atomic.h> | 43 | #include <asm/atomic.h> |
44 | #include <linux/devfs_fs_kernel.h> | 44 | #include <linux/devfs_fs_kernel.h> |
45 | #include <linux/compat.h> | ||
45 | 46 | ||
46 | #include "csr1212.h" | 47 | #include "csr1212.h" |
47 | #include "ieee1394.h" | 48 | #include "ieee1394.h" |
@@ -406,6 +407,65 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, | |||
406 | queue_complete_req(req); | 407 | queue_complete_req(req); |
407 | } | 408 | } |
408 | 409 | ||
410 | #ifdef CONFIG_COMPAT | ||
411 | struct compat_raw1394_req { | ||
412 | __u32 type; | ||
413 | __s32 error; | ||
414 | __u32 misc; | ||
415 | |||
416 | __u32 generation; | ||
417 | __u32 length; | ||
418 | |||
419 | __u64 address; | ||
420 | |||
421 | __u64 tag; | ||
422 | |||
423 | __u64 sendb; | ||
424 | __u64 recvb; | ||
425 | } __attribute__((packed)); | ||
426 | |||
427 | static const char __user *raw1394_compat_write(const char __user *buf) | ||
428 | { | ||
429 | struct compat_raw1394_req __user *cr = (typeof(cr)) buf; | ||
430 | struct raw1394_request __user *r; | ||
431 | r = compat_alloc_user_space(sizeof(struct raw1394_request)); | ||
432 | |||
433 | #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) | ||
434 | |||
435 | if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) || | ||
436 | C(address) || | ||
437 | C(tag) || | ||
438 | C(sendb) || | ||
439 | C(recvb)) | ||
440 | return ERR_PTR(-EFAULT); | ||
441 | return (const char __user *)r; | ||
442 | } | ||
443 | #undef C | ||
444 | |||
445 | #define P(x) __put_user(r->x, &cr->x) | ||
446 | |||
447 | static int | ||
448 | raw1394_compat_read(const char __user *buf, struct raw1394_request *r) | ||
449 | { | ||
450 | struct compat_raw1394_req __user *cr = (typeof(cr)) r; | ||
451 | if (!access_ok(VERIFY_WRITE,cr,sizeof(struct compat_raw1394_req)) || | ||
452 | P(type) || | ||
453 | P(error) || | ||
454 | P(misc) || | ||
455 | P(generation) || | ||
456 | P(length) || | ||
457 | P(address) || | ||
458 | P(tag) || | ||
459 | P(sendb) || | ||
460 | P(recvb)) | ||
461 | return -EFAULT; | ||
462 | return sizeof(struct compat_raw1394_req); | ||
463 | } | ||
464 | #undef P | ||
465 | |||
466 | #endif | ||
467 | |||
468 | |||
409 | static ssize_t raw1394_read(struct file *file, char __user * buffer, | 469 | static ssize_t raw1394_read(struct file *file, char __user * buffer, |
410 | size_t count, loff_t * offset_is_ignored) | 470 | size_t count, loff_t * offset_is_ignored) |
411 | { | 471 | { |
@@ -415,6 +475,11 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, | |||
415 | struct pending_request *req; | 475 | struct pending_request *req; |
416 | ssize_t ret; | 476 | ssize_t ret; |
417 | 477 | ||
478 | #ifdef CONFIG_COMPAT | ||
479 | if (count == sizeof(struct compat_raw1394_req)) { | ||
480 | /* ok */ | ||
481 | } else | ||
482 | #endif | ||
418 | if (count != sizeof(struct raw1394_request)) { | 483 | if (count != sizeof(struct raw1394_request)) { |
419 | return -EINVAL; | 484 | return -EINVAL; |
420 | } | 485 | } |
@@ -446,12 +511,22 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, | |||
446 | req->req.error = RAW1394_ERROR_MEMFAULT; | 511 | req->req.error = RAW1394_ERROR_MEMFAULT; |
447 | } | 512 | } |
448 | } | 513 | } |
449 | if (copy_to_user(buffer, &req->req, sizeof(req->req))) { | ||
450 | ret = -EFAULT; | ||
451 | goto out; | ||
452 | } | ||
453 | 514 | ||
454 | ret = (ssize_t) sizeof(struct raw1394_request); | 515 | #ifdef CONFIG_COMPAT |
516 | if (count == sizeof(struct compat_raw1394_req) && | ||
517 | sizeof(struct compat_raw1394_req) != | ||
518 | sizeof(struct raw1394_request)) { | ||
519 | ret = raw1394_compat_read(buffer, &req->req); | ||
520 | |||
521 | } else | ||
522 | #endif | ||
523 | { | ||
524 | if (copy_to_user(buffer, &req->req, sizeof(req->req))) { | ||
525 | ret = -EFAULT; | ||
526 | goto out; | ||
527 | } | ||
528 | ret = (ssize_t) sizeof(struct raw1394_request); | ||
529 | } | ||
455 | out: | 530 | out: |
456 | free_pending_request(req); | 531 | free_pending_request(req); |
457 | return ret; | 532 | return ret; |
@@ -2274,6 +2349,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) | |||
2274 | return handle_async_request(fi, req, node); | 2349 | return handle_async_request(fi, req, node); |
2275 | } | 2350 | } |
2276 | 2351 | ||
2352 | |||
2277 | static ssize_t raw1394_write(struct file *file, const char __user * buffer, | 2353 | static ssize_t raw1394_write(struct file *file, const char __user * buffer, |
2278 | size_t count, loff_t * offset_is_ignored) | 2354 | size_t count, loff_t * offset_is_ignored) |
2279 | { | 2355 | { |
@@ -2281,6 +2357,15 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, | |||
2281 | struct pending_request *req; | 2357 | struct pending_request *req; |
2282 | ssize_t retval = 0; | 2358 | ssize_t retval = 0; |
2283 | 2359 | ||
2360 | #ifdef CONFIG_COMPAT | ||
2361 | if (count == sizeof(struct compat_raw1394_req) && | ||
2362 | sizeof(struct compat_raw1394_req) != | ||
2363 | sizeof(struct raw1394_request)) { | ||
2364 | buffer = raw1394_compat_write(buffer); | ||
2365 | if (IS_ERR(buffer)) | ||
2366 | return PTR_ERR(buffer); | ||
2367 | } else | ||
2368 | #endif | ||
2284 | if (count != sizeof(struct raw1394_request)) { | 2369 | if (count != sizeof(struct raw1394_request)) { |
2285 | return -EINVAL; | 2370 | return -EINVAL; |
2286 | } | 2371 | } |
@@ -2893,6 +2978,7 @@ static struct file_operations raw1394_fops = { | |||
2893 | .write = raw1394_write, | 2978 | .write = raw1394_write, |
2894 | .mmap = raw1394_mmap, | 2979 | .mmap = raw1394_mmap, |
2895 | .ioctl = raw1394_ioctl, | 2980 | .ioctl = raw1394_ioctl, |
2981 | // .compat_ioctl = ... someone needs to do this | ||
2896 | .poll = raw1394_poll, | 2982 | .poll = raw1394_poll, |
2897 | .open = raw1394_open, | 2983 | .open = raw1394_open, |
2898 | .release = raw1394_release, | 2984 | .release = raw1394_release, |