From 564c72b1c6f753f562e42c2a30a5dc50c194be0f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 7 Apr 2015 11:27:13 +0200 Subject: [PATCH] greybus: operation: fix unaligned memory accesses in receive path The buffer received from our current host driver is 1-byte aligned and will therefore cause unaligned memory accesses if simply cast to an operation-message header. Fix this by making a properly aligned copy of the header in gb_connection_recv_response before accessing its fields. Note that this does not affect protocol drivers as the whole buffer is copied when creating the corresponding request or response before being forwarded. Signed-off-by: Johan Hovold Reviewed-by: Alex Elder Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/operation.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 260774e414f3..0fd77c9ef5a6 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -885,7 +885,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, void gb_connection_recv(struct gb_connection *connection, void *data, size_t size) { - struct gb_operation_msg_hdr *header; + struct gb_operation_msg_hdr header; size_t msg_size; u16 operation_id; @@ -895,27 +895,28 @@ void gb_connection_recv(struct gb_connection *connection, return; } - if (size < sizeof(*header)) { + if (size < sizeof(header)) { dev_err(&connection->dev, "message too small\n"); return; } - header = data; - msg_size = le16_to_cpu(header->size); + /* Use memcpy as data may be unaligned */ + memcpy(&header, data, sizeof(header)); + msg_size = le16_to_cpu(header.size); if (size < msg_size) { dev_err(&connection->dev, "incomplete message received: 0x%04x (%zu < %zu)\n", - le16_to_cpu(header->operation_id), size, msg_size); + le16_to_cpu(header.operation_id), size, msg_size); return; /* XXX Should still complete operation */ } - operation_id = le16_to_cpu(header->operation_id); - if (header->type & GB_OPERATION_TYPE_RESPONSE) + operation_id = le16_to_cpu(header.operation_id); + if (header.type & GB_OPERATION_TYPE_RESPONSE) gb_connection_recv_response(connection, operation_id, - header->result, data, msg_size); + header.result, data, msg_size); else gb_connection_recv_request(connection, operation_id, - header->type, data, msg_size); + header.type, data, msg_size); } /* -- 2.20.1