diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-12-04 20:16:49 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2011-12-04 20:16:52 +0100 |
commit | a6baf95e700f1abe8dafe71f5f8722baea6b6ac2 (patch) | |
tree | 900da16fa2c9c762759d3ed6745d1e9b3b640342 | |
parent | 8d18904bc241fef09ad6e8b7c2e1f93a4b4bb082 (diff) |
fix use-after-free on device free codepath due to recursion issues, and fix dev->parent refcounting issues
-rw-r--r-- | device.c | 19 | ||||
-rw-r--r-- | device.h | 7 |
2 files changed, 17 insertions, 9 deletions
@@ -68,12 +68,17 @@ static int set_device_state(struct device *dev, bool state) static int simple_device_set_state(struct device *dev, bool state) { + struct device *pdev; int ret = 0; - if (state && !dev->parent.dev) - dev->parent.dev = system_if_get_parent(dev); + pdev = dev->parent.dev; + if (state && !pdev) { + pdev = system_if_get_parent(dev); + if (pdev) + device_add_user(&dev->parent, pdev); + } - if (dev->parent.dev) { + if (pdev) { if (state) ret = device_claim(&dev->parent); else @@ -425,6 +430,14 @@ void device_add_user(struct device_user *dep, struct device *dev) } } +void +device_free(struct device *dev) +{ + __devlock++; + dev->type->free(dev); + __devlock--; +} + static void __device_free_unused(struct device *dev) { @@ -148,12 +148,7 @@ void device_release(struct device_user *dep); int device_check_state(struct device *dev); void device_dump_status(struct blob_buf *b, struct device *dev); -static inline void -device_free(struct device *dev) -{ - dev->type->free(dev); -} - +void device_free(struct device *dev); void device_free_unused(struct device *dev); struct device *get_vlan_device_chain(const char *ifname, bool create); |