Commit 1f3125af authored by Stefan Richter's avatar Stefan Richter

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: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent bf8e3355
...@@ -398,6 +398,7 @@ static int ioctl_send_request(struct client *client, void *buffer) ...@@ -398,6 +398,7 @@ static int ioctl_send_request(struct client *client, void *buffer)
struct fw_device *device = client->device; struct fw_device *device = client->device;
struct fw_cdev_send_request *request = buffer; struct fw_cdev_send_request *request = buffer;
struct response *response; struct response *response;
int ret;
/* What is the biggest size we'll accept, really? */ /* What is the biggest size we'll accept, really? */
if (request->length > 4096) if (request->length > 4096)
...@@ -414,8 +415,26 @@ static int ioctl_send_request(struct client *client, void *buffer) ...@@ -414,8 +415,26 @@ static int ioctl_send_request(struct client *client, void *buffer)
if (request->data && if (request->data &&
copy_from_user(response->response.data, copy_from_user(response->response.data,
u64_to_uptr(request->data), request->length)) { u64_to_uptr(request->data), request->length)) {
kfree(response); ret = -EFAULT;
return -EFAULT; goto err;
}
switch (request->tcode) {
case TCODE_WRITE_QUADLET_REQUEST:
case TCODE_WRITE_BLOCK_REQUEST:
case TCODE_READ_QUADLET_REQUEST:
case TCODE_READ_BLOCK_REQUEST:
case TCODE_LOCK_MASK_SWAP:
case TCODE_LOCK_COMPARE_SWAP:
case TCODE_LOCK_FETCH_ADD:
case TCODE_LOCK_LITTLE_ADD:
case TCODE_LOCK_BOUNDED_ADD:
case TCODE_LOCK_WRAP_ADD:
case TCODE_LOCK_VENDOR_DEPENDENT:
break;
default:
ret = -EINVAL;
goto err;
} }
response->resource.release = release_transaction; response->resource.release = release_transaction;
...@@ -434,6 +453,10 @@ static int ioctl_send_request(struct client *client, void *buffer) ...@@ -434,6 +453,10 @@ static int ioctl_send_request(struct client *client, void *buffer)
return sizeof(request) + request->length; return sizeof(request) + request->length;
else else
return sizeof(request); return sizeof(request);
err:
kfree(response);
return ret;
} }
struct address_handler { struct address_handler {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment