greybus: Ensure gb->mutex is held when adding timer
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>
Wed, 16 Mar 2016 11:29:59 +0000 (11:29 +0000)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 17 Mar 2016 04:49:31 +0000 (21:49 -0700)
Currently in loopback on the async path we issue an operation and then add
a timer to time-out that operation should it fail to complete. Looking at a
backtrace given in its feasible op_async->pending can be true and
del_timer() can run before add_timer() has run. In the callback handler we
already hold gb->mutex. This patch fixes that potential race by ensuring we
hold gb->mutex both when we are adding and when we are removing the
relevant timer.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reported-and-tested-by: Axel Haslam <ahaslam@baylibre.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/loopback.c

index 9b732a8664559da21151f2b12336326349cde5f7..5e009e1955abd6dd46cec8b46278f4e460c39f23 100644 (file)
@@ -626,6 +626,7 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type,
        do_gettimeofday(&op_async->ts);
        op_async->pending = true;
        atomic_inc(&gb->outstanding_operations);
+       mutex_lock(&gb->mutex);
        ret = gb_operation_request_send(operation,
                                        gb_loopback_async_operation_callback,
                                        GFP_KERNEL);
@@ -637,9 +638,11 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type,
        op_async->timer.data = (unsigned long)operation->id;
        add_timer(&op_async->timer);
 
-       return ret;
+       goto done;
 error:
        gb_loopback_async_operation_put(op_async);
+done:
+       mutex_unlock(&gb->mutex);
        return ret;
 }