mt76: do not use devm API for led classdev
authorFelix Fietkau <nbd@nbd.name>
Sun, 29 Sep 2019 20:04:37 +0000 (22:04 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 20 Nov 2019 12:23:49 +0000 (13:23 +0100)
With the devm API, the unregister happens after the device cleanup is done,
after which the struct mt76_dev which contains the led_cdev has already been
freed. This leads to a use-after-free bug that can crash the system.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mac80211.c

index d493437..c4eb00d 100644 (file)
@@ -105,7 +105,15 @@ static int mt76_led_init(struct mt76_dev *dev)
                dev->led_al = of_property_read_bool(np, "led-active-low");
        }
 
-       return devm_led_classdev_register(dev->dev, &dev->led_cdev);
+       return led_classdev_register(dev->dev, &dev->led_cdev);
+}
+
+static void mt76_led_cleanup(struct mt76_dev *dev)
+{
+       if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set)
+               return;
+
+       led_classdev_unregister(&dev->led_cdev);
 }
 
 static void mt76_init_stream_cap(struct mt76_dev *dev,
@@ -362,6 +370,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
 {
        struct ieee80211_hw *hw = dev->hw;
 
+       mt76_led_cleanup(dev);
        mt76_tx_status_check(dev, NULL, true);
        ieee80211_unregister_hw(hw);
 }