aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/raw1394.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394/raw1394.c')
-rw-r--r--drivers/ieee1394/raw1394.c96
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
411struct 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
427static 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
447static int
448raw1394_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
409static ssize_t raw1394_read(struct file *file, char __user * buffer, 469static 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
2277static ssize_t raw1394_write(struct file *file, const char __user * buffer, 2353static 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,