From 048a7ffe274280c27fc572ba3ec7150eba6efc40 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 9 Jul 2015 15:18:00 +0200 Subject: [PATCH] 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 Reviewed-by: Viresh Kumar Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/operation.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index 8f99c8e17d70..85394624395e 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -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;