greybus: operation: fix outgoing-response corruption

Fix potential corruption of outgoing responses by verifying that the
operations is indeed outgoing when receiving a response.

Failure to do so could lead to an incoming response corrupting an
outgoing response that uses the same operation id.

Reported-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Johan Hovold 2015-07-09 15:18:00 +02:00 committed by Greg Kroah-Hartman
parent 0581f28efb
commit 048a7ffe27
1 changed files with 6 additions and 5 deletions

View File

@ -115,11 +115,11 @@ int gb_operation_result(struct gb_operation *operation)
EXPORT_SYMBOL_GPL(gb_operation_result);
/*
* Looks up an operation on a connection and returns a refcounted pointer if
* found, or NULL otherwise.
* Looks up an outgoing operation on a connection and returns a refcounted
* pointer if found, or NULL otherwise.
*/
static struct gb_operation *
gb_operation_find(struct gb_connection *connection, u16 operation_id)
gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id)
{
struct gb_operation *operation;
unsigned long flags;
@ -127,7 +127,8 @@ gb_operation_find(struct gb_connection *connection, u16 operation_id)
spin_lock_irqsave(&gb_operations_lock, flags);
list_for_each_entry(operation, &connection->operations, links)
if (operation->id == operation_id) {
if (operation->id == operation_id &&
!gb_operation_is_incoming(operation)) {
gb_operation_get(operation);
found = true;
break;
@ -778,7 +779,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
int errno = gb_operation_status_map(result);
size_t message_size;
operation = gb_operation_find(connection, operation_id);
operation = gb_operation_find_outgoing(connection, operation_id);
if (!operation) {
dev_err(&connection->dev, "operation not found\n");
return;