summaryrefslogtreecommitdiff
path: root/interface.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2021-09-27 18:56:21 +0200
committerFelix Fietkau <nbd@nbd.name>2021-09-27 18:58:01 +0200
commit5a4ac30c7a15712d01110befec1acfe86c2cbed0 (patch)
treead52b0310a781078efb9b016fbe80d89ca50001d /interface.c
parent08e954e137ffcf7770200bbd6476dc36bbd326f5 (diff)
downloadnetifd-5a4ac30c7a15712d01110befec1acfe86c2cbed0.tar.gz
netifd: rework/fix device free handling
Instead of explicitly preventing free in specific code sections using device_lock/device_unlock, defer all device free handling via uloop timeout This avoids an entire class of lurking use-after-free bugs triggered by device event processing and simplifies the code Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'interface.c')
-rw-r--r--interface.c31
1 files changed, 8 insertions, 23 deletions
diff --git a/interface.c b/interface.c
index 2391e12..6cf0d30 100644
--- a/interface.c
+++ b/interface.c
@@ -637,8 +637,6 @@ interface_claim_device(struct interface *iface)
if (iface->parent_iface.iface)
interface_remove_user(&iface->parent_iface);
- device_lock();
-
if (iface->parent_ifname) {
parent = vlist_find(&interfaces, iface->parent_ifname, parent, node);
iface->parent_iface.cb = interface_alias_cb;
@@ -654,8 +652,6 @@ interface_claim_device(struct interface *iface)
if (dev)
interface_set_main_dev(iface, dev);
- device_unlock();
-
if (iface->proto_handler->flags & PROTO_FLAG_INIT_AVAILABLE)
interface_set_available(iface, true);
}
@@ -1087,30 +1083,19 @@ interface_handle_link(struct interface *iface, const char *name,
struct blob_attr *vlan, bool add, bool link_ext)
{
struct device *dev;
- int ret;
-
- device_lock();
dev = device_get(name, add ? (link_ext ? 2 : 1) : 0);
- if (!dev) {
- ret = UBUS_STATUS_NOT_FOUND;
- goto out;
- }
+ if (!dev)
+ return UBUS_STATUS_NOT_FOUND;
- if (add) {
- interface_set_device_config(iface, dev);
- if (!link_ext)
- device_set_present(dev, true);
+ if (!add)
+ return interface_remove_link(iface, dev, vlan);
- ret = interface_add_link(iface, dev, vlan, link_ext);
- } else {
- ret = interface_remove_link(iface, dev, vlan);
- }
+ interface_set_device_config(iface, dev);
+ if (!link_ext)
+ device_set_present(dev, true);
-out:
- device_unlock();
-
- return ret;
+ return interface_add_link(iface, dev, vlan, link_ext);
}
void