staging: vchiq_arm: avoid crashing the kernel
authorStefan Wahren <stefan.wahren@i2se.com>
Sun, 25 Apr 2021 10:50:53 +0000 (12:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 May 2021 09:19:27 +0000 (11:19 +0200)
Using BUG_ON in a non-essential driver isn't recommend. So better
trigger a stacktrace and bailout.

Reviewed-by: Nicolas Saenz Julienne <nsaenz@kernel.org>
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
Link: https://lore.kernel.org/r/1619347863-16080-2-git-send-email-stefan.wahren@i2se.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c

index e39897c38e6a904aa4cb2fa78261323b78e6e0ba..367fa3d371eb00847f3a32a19a25096abab7ff00 100644 (file)
@@ -602,7 +602,9 @@ service_callback(enum vchiq_reason reason, struct vchiq_header *header,
        DEBUG_TRACE(SERVICE_CALLBACK_LINE);
 
        service = handle_to_service(handle);
-       BUG_ON(!service);
+       if (WARN_ON(!service))
+               return VCHIQ_SUCCESS;
+
        user_service = (struct user_service *)service->base.userdata;
        instance = user_service->instance;
 
@@ -918,8 +920,12 @@ static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance,
                        goto out;
        }
 
-       BUG_ON((int)(user_service->msg_insert -
-               user_service->msg_remove) < 0);
+       if (WARN_ON_ONCE((int)(user_service->msg_insert -
+                        user_service->msg_remove) < 0)) {
+               spin_unlock(&msg_queue_spinlock);
+               ret = -EINVAL;
+               goto out;
+       }
 
        header = user_service->msg_queue[user_service->msg_remove &
                (MSG_QUEUE_SIZE - 1)];
@@ -1937,7 +1943,10 @@ static int vchiq_release(struct inode *inode, struct file *file)
 
                wait_for_completion(&service->remove_event);
 
-               BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
+               if (WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE)) {
+                       unlock_service(service);
+                       break;
+               }
 
                spin_lock(&msg_queue_spinlock);