]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
USB: appledisplay: close race between probe and completion handler
authorOliver Neukum <oneukum@suse.com>
Thu, 12 Sep 2024 12:32:59 +0000 (14:32 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 13 Sep 2024 05:54:23 +0000 (07:54 +0200)
There is a small window during probing when IO is running
but the backlight is not registered. Processing events
during that time will crash. The completion handler
needs to check for a backlight before scheduling work.

The bug is as old as the driver.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
CC: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20240912123317.1026049-1-oneukum@suse.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/misc/appledisplay.c

index c8098e9b432e13f5438fa44858ece61eba3c4dfb..62b5a30edc42679dbafd7de4f3c35da7749ffd14 100644 (file)
@@ -107,7 +107,12 @@ static void appledisplay_complete(struct urb *urb)
        case ACD_BTN_BRIGHT_UP:
        case ACD_BTN_BRIGHT_DOWN:
                pdata->button_pressed = 1;
-               schedule_delayed_work(&pdata->work, 0);
+               /*
+                * there is a window during which no device
+                * is registered
+                */
+               if (pdata->bd )
+                       schedule_delayed_work(&pdata->work, 0);
                break;
        case ACD_BTN_NONE:
        default:
@@ -202,6 +207,7 @@ static int appledisplay_probe(struct usb_interface *iface,
        const struct usb_device_id *id)
 {
        struct backlight_properties props;
+       struct backlight_device *backlight;
        struct appledisplay *pdata;
        struct usb_device *udev = interface_to_usbdev(iface);
        struct usb_endpoint_descriptor *endpoint;
@@ -272,13 +278,14 @@ static int appledisplay_probe(struct usb_interface *iface,
        memset(&props, 0, sizeof(struct backlight_properties));
        props.type = BACKLIGHT_RAW;
        props.max_brightness = 0xff;
-       pdata->bd = backlight_device_register(bl_name, NULL, pdata,
+       backlight = backlight_device_register(bl_name, NULL, pdata,
                                              &appledisplay_bl_data, &props);
-       if (IS_ERR(pdata->bd)) {
+       if (IS_ERR(backlight)) {
                dev_err(&iface->dev, "Backlight registration failed\n");
-               retval = PTR_ERR(pdata->bd);
+               retval = PTR_ERR(backlight);
                goto error;
        }
+       pdata->bd = backlight;
 
        /* Try to get brightness */
        brightness = appledisplay_bl_get_brightness(pdata->bd);