summaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-cdev.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-08-11 12:57:01 +0200
committerIngo Molnar <mingo@elte.hu>2008-08-11 12:57:01 +0200
commit6de9c70882ecdee63a652d493bf2353963bd4c22 (patch)
tree9d219e705492331c97f5f7dccce3b0b1a29251bf /drivers/firewire/fw-cdev.c
parentd406d21d90dce2e66c7eb4a44605aac947fe55fb (diff)
parent796aadeb1b2db9b5d463946766c5bbfd7717158c (diff)
downloadkernel-crypto-6de9c70882ecdee63a652d493bf2353963bd4c22.tar.gz
kernel-crypto-6de9c70882ecdee63a652d493bf2353963bd4c22.tar.xz
kernel-crypto-6de9c70882ecdee63a652d493bf2353963bd4c22.zip
Merge branch 'linus' into x86/cleanups
Diffstat (limited to 'drivers/firewire/fw-cdev.c')
-rw-r--r--drivers/firewire/fw-cdev.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index c639915fc3c..2e6d5848d21 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -369,22 +369,33 @@ complete_transaction(struct fw_card *card, int rcode,
struct response *response = data;
struct client *client = response->client;
unsigned long flags;
+ struct fw_cdev_event_response *r = &response->response;
- if (length < response->response.length)
- response->response.length = length;
+ if (length < r->length)
+ r->length = length;
if (rcode == RCODE_COMPLETE)
- memcpy(response->response.data, payload,
- response->response.length);
+ memcpy(r->data, payload, r->length);
spin_lock_irqsave(&client->lock, flags);
list_del(&response->resource.link);
spin_unlock_irqrestore(&client->lock, flags);
- response->response.type = FW_CDEV_EVENT_RESPONSE;
- response->response.rcode = rcode;
- queue_event(client, &response->event,
- &response->response, sizeof(response->response),
- response->response.data, response->response.length);
+ r->type = FW_CDEV_EVENT_RESPONSE;
+ r->rcode = rcode;
+
+ /*
+ * In the case that sizeof(*r) doesn't align with the position of the
+ * data, and the read is short, preserve an extra copy of the data
+ * to stay compatible with a pre-2.6.27 bug. Since the bug is harmless
+ * for short reads and some apps depended on it, this is both safe
+ * and prudent for compatibility.
+ */
+ if (r->length <= sizeof(*r) - offsetof(typeof(*r), data))
+ queue_event(client, &response->event, r, sizeof(*r),
+ r->data, r->length);
+ else
+ queue_event(client, &response->event, r, sizeof(*r) + r->length,
+ NULL, 0);
}
static int ioctl_send_request(struct client *client, void *buffer)