diff options
author | Daniel Mack <github@zonque.org> | 2015-07-01 19:26:01 -0400 |
---|---|---|
committer | Daniel Mack <github@zonque.org> | 2015-07-01 19:26:01 -0400 |
commit | 138879ccad87148cc5d805471183789a6ad688c6 (patch) | |
tree | 67991a36b23a7f55157ee6b0a1c31c502605160b | |
parent | c9b9e8e9e2fa14fc3d4dd93240eb7d0b3df8732e (diff) | |
parent | 62e2d5bbabf0e6a5a262e9e1bed184552d98b0d9 (diff) |
Merge pull request #409 from teg/networkd-enslave-segfault
fix segfault when cancelling enslaving of links by netdevs
-rw-r--r-- | src/network/networkd-link.c | 3 | ||||
-rw-r--r-- | src/network/networkd-netdev.c | 13 |
2 files changed, 13 insertions, 3 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 16243a5352..dff81a5cf0 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1360,8 +1360,7 @@ static int link_joined(Link *link) { return link_enter_set_addresses(link); } -static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { +static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index ece9ecc251..6949b403c8 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -92,10 +92,11 @@ static void netdev_cancel_callbacks(NetDev *netdev) { assert(netdev->manager); assert(netdev->manager->rtnl); - callback->callback(netdev->manager->rtnl, m, link); + callback->callback(netdev->manager->rtnl, m, callback->link); } LIST_REMOVE(callbacks, netdev->callbacks, callback); + link_unref(callback->link); free(callback); } } @@ -177,6 +178,8 @@ int netdev_get(Manager *manager, const char *name, NetDev **ret) { static int netdev_enter_failed(NetDev *netdev) { netdev->state = NETDEV_STATE_FAILED; + netdev_cancel_callbacks(netdev); + return 0; } @@ -266,12 +269,20 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call int r; assert(netdev); + assert(netdev->manager); + assert(netdev->manager->rtnl); assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND)); if (netdev->state == NETDEV_STATE_READY) { r = netdev_enslave_ready(netdev, link, callback); if (r < 0) return r; + } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) { + _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL; + + r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m); + if (r >= 0) + callback(netdev->manager->rtnl, m, link); } else { /* the netdev is not yet read, save this request for when it is */ netdev_join_callback *cb; |