summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/operation.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2015-07-09 15:18:00 +0200
committerGreg Kroah-Hartman <gregkh@google.com>2015-07-13 15:29:27 -0700
commit048a7ffe274280c27fc572ba3ec7150eba6efc40 (patch)
tree7e6c096e6fee721bf8af089389377c2d7e7affe6 /drivers/staging/greybus/operation.c
parent0581f28efb86d8eb7e7f6baf712578477f7c868e (diff)
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>
Diffstat (limited to 'drivers/staging/greybus/operation.c')
-rw-r--r--drivers/staging/greybus/operation.c11
1 files 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;