Commit 564c72b1 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

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: default avatarJohan Hovold <johan@hovoldconsulting.com>
Reviewed-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent c15ccabe
...@@ -885,7 +885,7 @@ static void gb_connection_recv_response(struct gb_connection *connection, ...@@ -885,7 +885,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
void gb_connection_recv(struct gb_connection *connection, void gb_connection_recv(struct gb_connection *connection,
void *data, size_t size) void *data, size_t size)
{ {
struct gb_operation_msg_hdr *header; struct gb_operation_msg_hdr header;
size_t msg_size; size_t msg_size;
u16 operation_id; u16 operation_id;
...@@ -895,27 +895,28 @@ void gb_connection_recv(struct gb_connection *connection, ...@@ -895,27 +895,28 @@ void gb_connection_recv(struct gb_connection *connection,
return; return;
} }
if (size < sizeof(*header)) { if (size < sizeof(header)) {
dev_err(&connection->dev, "message too small\n"); dev_err(&connection->dev, "message too small\n");
return; return;
} }
header = data; /* Use memcpy as data may be unaligned */
msg_size = le16_to_cpu(header->size); memcpy(&header, data, sizeof(header));
msg_size = le16_to_cpu(header.size);
if (size < msg_size) { if (size < msg_size) {
dev_err(&connection->dev, dev_err(&connection->dev,
"incomplete message received: 0x%04x (%zu < %zu)\n", "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 */ return; /* XXX Should still complete operation */
} }
operation_id = le16_to_cpu(header->operation_id); operation_id = le16_to_cpu(header.operation_id);
if (header->type & GB_OPERATION_TYPE_RESPONSE) if (header.type & GB_OPERATION_TYPE_RESPONSE)
gb_connection_recv_response(connection, operation_id, gb_connection_recv_response(connection, operation_id,
header->result, data, msg_size); header.result, data, msg_size);
else else
gb_connection_recv_request(connection, operation_id, gb_connection_recv_request(connection, operation_id,
header->type, data, msg_size); header.type, data, msg_size);
} }
/* /*
......
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