]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
input: button_kbd: gracefully handle buttons that fail probe
authorCaleb Connolly <caleb.connolly@linaro.org>
Thu, 11 Apr 2024 17:52:37 +0000 (19:52 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 18 Apr 2024 22:37:10 +0000 (16:37 -0600)
If a button device fails to probe, it will still be added to the uclass
device list, and therefore will still be iterated over in
button_read_keys() resulting in a UAF on the buttons private data.

Resolve this by unbinding button devices that aren't active after
probing, and print a warning so it's clear that the button is broken.

Fixes: e8779962898e ("dm: input: add button_kbd driver")
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
drivers/input/button_kbd.c

index 74fadfca8bb8ce944c2c3f2e4ba54ddbd292e769..c73d3b18be9c6a1e1afb8a41178e50d0f76e07a4 100644 (file)
@@ -34,7 +34,8 @@ static int button_kbd_start(struct udevice *dev)
 {
        struct button_kbd_priv *priv = dev_get_priv(dev);
        int i = 0;
-       struct udevice *button_gpio_devp;
+       struct udevice *button_gpio_devp, *next_devp;
+       struct uclass *uc;
 
        uclass_foreach_dev_probe(UCLASS_BUTTON, button_gpio_devp) {
                struct button_uc_plat *uc_plat = dev_get_uclass_plat(button_gpio_devp);
@@ -46,6 +47,21 @@ static int button_kbd_start(struct udevice *dev)
                i++;
        }
 
+       if (uclass_get(UCLASS_BUTTON, &uc))
+               return -ENOENT;
+
+       /*
+        * Unbind any buttons that failed to probe so we don't iterate over
+        * them when polling.
+        */
+       uclass_foreach_dev_safe(button_gpio_devp, next_devp, uc) {
+               if (!(dev_get_flags(button_gpio_devp) & DM_FLAG_ACTIVATED)) {
+                       log_warning("Button %s failed to probe\n",
+                                   button_gpio_devp->name);
+                       device_unbind(button_gpio_devp);
+               }
+       }
+
        priv->button_size = i;
        priv->old_state = calloc(i, sizeof(int));