greybus: operation: fix use-after-free and infinite loop on unhandled requests
authorJohan Hovold <johan@hovoldconsulting.com>
Fri, 27 Mar 2015 11:41:15 +0000 (12:41 +0100)
committerGreg Kroah-Hartman <greg@kroah.com>
Mon, 30 Mar 2015 13:13:01 +0000 (15:13 +0200)
Make sure to return a proper response in case we get a request we do not
recognise.

This fixes an infinite loop and use-after-free bug, where the freed
operations structure would get re-added to the work queue indefinitely.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/staging/greybus/operation.c

index dcf987f..f194b1e 100644 (file)
@@ -208,14 +208,11 @@ static void gb_message_cancel(struct gb_message *message)
 static void gb_operation_request_handle(struct gb_operation *operation)
 {
        struct gb_protocol *protocol = operation->connection->protocol;
+       int ret;
 
        if (!protocol)
                return;
 
-       /*
-        * If the protocol has no incoming request handler, report
-        * an error and mark the request bad.
-        */
        if (protocol->request_recv) {
                protocol->request_recv(operation->type, operation);
                return;
@@ -223,10 +220,14 @@ static void gb_operation_request_handle(struct gb_operation *operation)
 
        dev_err(&operation->connection->dev,
                "unexpected incoming request type 0x%02hhx\n", operation->type);
-       if (gb_operation_result_set(operation, -EPROTONOSUPPORT))
-               queue_work(gb_operation_workqueue, &operation->work);
-       else
-               WARN(true, "failed to mark request bad\n");
+
+       ret = gb_operation_response_send(operation, -EPROTONOSUPPORT);
+       if (ret) {
+               dev_err(&operation->connection->dev,
+                       "failed to send response %d: %d\n",
+                       -EPROTONOSUPPORT, ret);
+                       return;
+       }
 }
 
 /*