diff options
author | Felix Fietkau <nbd@nbd.name> | 2023-04-17 13:11:53 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2023-04-17 13:13:25 +0200 |
commit | 7de5440a520f9c6687358c7ef88ac4aad0ff98a5 (patch) | |
tree | 1834e6eec859f8eb2e53a41d177031a6b73f011f | |
parent | 463a1207f0766417866e2c28316e58a96f84370b (diff) | |
download | netifd-7de5440a520f9c6687358c7ef88ac4aad0ff98a5.tar.gz |
device: fix segfault when recreating devices
Depending on the configuration, the callback on device_release could end up
deleting the device_dep from the list. If that happens, it must not be added
back to the recreated device, since that leads to use-after-free issues.
Check dep->dev before adding it back.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r-- | device.c | 8 |
1 files changed, 6 insertions, 2 deletions
@@ -1037,14 +1037,18 @@ device_apply_config(struct device *dev, struct device_type *type, static void device_replace(struct device *dev, struct device *odev) { - struct device_user *dep, *tmp; + struct device_user *dep; __devlock++; if (odev->present) device_set_present(odev, false); - list_for_each_entry_safe(dep, tmp, &odev->users.list, list.list) { + while (!list_empty(&odev->users.list)) { + dep = list_first_entry(&odev->users.list, struct device_user, list.list); device_release(dep); + if (!dep->dev) + continue; + safe_list_del(&dep->list); __device_add_user(dep, dev); } |