summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2023-04-17 13:11:53 +0200
committerFelix Fietkau <nbd@nbd.name>2023-04-17 13:13:25 +0200
commit7de5440a520f9c6687358c7ef88ac4aad0ff98a5 (patch)
tree1834e6eec859f8eb2e53a41d177031a6b73f011f
parent463a1207f0766417866e2c28316e58a96f84370b (diff)
downloadnetifd-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.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/device.c b/device.c
index d6610c7..1e89219 100644
--- a/device.c
+++ b/device.c
@@ -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);
}