diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-12-05 16:44:42 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-03-24 15:56:37 -0400 |
commit | 1f3125af8ed7410cc0ebcc0acd59bbfc1ae0057a (patch) | |
tree | 3e0cd754d86b8780b164bd507564fd2355c7db29 /drivers | |
parent | bf8e3355ec8f4e472f9841e94203cd759b45226e (diff) |
firewire: cdev: tcodes input validation
The behaviour of fw-transaction.c::fw_send_request is ill-defined for
any other tcodes than read/ write/ lock request tcodes. Therefore
prevent requests with wrong tcodes from entering the transaction layer.
Maybe fw_send_request should check them itself, but I am not inclined to
change it and fw_fill_request from void-valued functions to ones which
return error codes and pass those up. Besides, maybe fw_send_request is
going to support one more tcode than ioctl_send_request in the future
(TCODE_STREAM_DATA).
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/fw-cdev.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 75bbd66f852e..a320ab48edd6 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c | |||
@@ -398,6 +398,7 @@ static int ioctl_send_request(struct client *client, void *buffer) | |||
398 | struct fw_device *device = client->device; | 398 | struct fw_device *device = client->device; |
399 | struct fw_cdev_send_request *request = buffer; | 399 | struct fw_cdev_send_request *request = buffer; |
400 | struct response *response; | 400 | struct response *response; |
401 | int ret; | ||
401 | 402 | ||
402 | /* What is the biggest size we'll accept, really? */ | 403 | /* What is the biggest size we'll accept, really? */ |
403 | if (request->length > 4096) | 404 | if (request->length > 4096) |
@@ -414,8 +415,26 @@ static int ioctl_send_request(struct client *client, void *buffer) | |||
414 | if (request->data && | 415 | if (request->data && |
415 | copy_from_user(response->response.data, | 416 | copy_from_user(response->response.data, |
416 | u64_to_uptr(request->data), request->length)) { | 417 | u64_to_uptr(request->data), request->length)) { |
417 | kfree(response); | 418 | ret = -EFAULT; |
418 | return -EFAULT; | 419 | goto err; |
420 | } | ||
421 | |||
422 | switch (request->tcode) { | ||
423 | case TCODE_WRITE_QUADLET_REQUEST: | ||
424 | case TCODE_WRITE_BLOCK_REQUEST: | ||
425 | case TCODE_READ_QUADLET_REQUEST: | ||
426 | case TCODE_READ_BLOCK_REQUEST: | ||
427 | case TCODE_LOCK_MASK_SWAP: | ||
428 | case TCODE_LOCK_COMPARE_SWAP: | ||
429 | case TCODE_LOCK_FETCH_ADD: | ||
430 | case TCODE_LOCK_LITTLE_ADD: | ||
431 | case TCODE_LOCK_BOUNDED_ADD: | ||
432 | case TCODE_LOCK_WRAP_ADD: | ||
433 | case TCODE_LOCK_VENDOR_DEPENDENT: | ||
434 | break; | ||
435 | default: | ||
436 | ret = -EINVAL; | ||
437 | goto err; | ||
419 | } | 438 | } |
420 | 439 | ||
421 | response->resource.release = release_transaction; | 440 | response->resource.release = release_transaction; |
@@ -434,6 +453,10 @@ static int ioctl_send_request(struct client *client, void *buffer) | |||
434 | return sizeof(request) + request->length; | 453 | return sizeof(request) + request->length; |
435 | else | 454 | else |
436 | return sizeof(request); | 455 | return sizeof(request); |
456 | err: | ||
457 | kfree(response); | ||
458 | |||
459 | return ret; | ||
437 | } | 460 | } |
438 | 461 | ||
439 | struct address_handler { | 462 | struct address_handler { |