]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
vchiq_arm: Access the dequeue_pending flag locked
authorPhil Elwell <phil@raspberrypi.org>
Wed, 23 Mar 2016 14:16:25 +0000 (14:16 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 19 Sep 2017 10:07:47 +0000 (12:07 +0200)
Reading through this code looking for another problem (now found in userland)
the use of dequeue_pending outside a lock didn't seem safe.

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c

index d5f5c904f15b4fdbf1055befbec0bfe33b805efc..c5ce19c965e0475e6a44f708cd9a8f61ceeac500 100644 (file)
@@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
        USER_SERVICE_T *user_service;
        VCHIQ_SERVICE_T *service;
        VCHIQ_INSTANCE_T instance;
+       int skip_completion = 0;
        DEBUG_INITIALISE(g_state.local)
 
        DEBUG_TRACE(SERVICE_CALLBACK_LINE);
@@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
                user_service->msg_queue[user_service->msg_insert &
                        (MSG_QUEUE_SIZE - 1)] = header;
                user_service->msg_insert++;
-               spin_unlock(&msg_queue_spinlock);
-
-               up(&user_service->insert_event);
 
                /* If there is a thread waiting in DEQUEUE_MESSAGE, or if
                ** there is a MESSAGE_AVAILABLE in the completion queue then
@@ -356,13 +354,22 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
                if (((user_service->message_available_pos -
                        instance->completion_remove) >= 0) ||
                        user_service->dequeue_pending) {
-                       DEBUG_TRACE(SERVICE_CALLBACK_LINE);
                        user_service->dequeue_pending = 0;
-                       return VCHIQ_SUCCESS;
+                       skip_completion = 1;
                }
 
+               spin_unlock(&msg_queue_spinlock);
+
+               up(&user_service->insert_event);
+
                header = NULL;
        }
+
+       if (skip_completion) {
+               DEBUG_TRACE(SERVICE_CALLBACK_LINE);
+               return VCHIQ_SUCCESS;
+       }
+
        DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 
        return add_completion(instance, reason, header, user_service,