diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2017-12-20 10:17:37 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2017-12-20 16:17:29 +0100 |
commit | 281bb5c1102e573accdf665f1ab923e750e09217 (patch) | |
tree | 99f65e85227158ab56d5a4ae2689c70e7747e0db /src | |
parent | Merge pull request #7710 from jwrdegoede/hwdb-accel-chuwi-vi8-teclast-x80-pro (diff) | |
download | systemd-281bb5c1102e573accdf665f1ab923e750e09217.tar.xz systemd-281bb5c1102e573accdf665f1ab923e750e09217.zip |
network: fix memory leak when an netdev was skipped
In general we'd leak anything that was allocated in the first parsing of
netdev, e.g. netdev name, host name, etc. Use normal netdev_unref to make sure
everything is freed.
--- command ---
/home/zbyszek/src/systemd/build2/test-network
--- stderr ---
/etc/systemd/network/wg0.netdev:3: Failed to parse netdev kind, ignoring: wireguard
/etc/systemd/network/wg0.netdev:5: Unknown section 'WireGuard'. Ignoring.
/etc/systemd/network/wg0.netdev:9: Unknown section 'WireGuardPeer'. Ignoring.
NetDev has no Kind configured in /etc/systemd/network/wg0.netdev. Ignoring
/etc/systemd/network/br0.network:13: Unknown lvalue 'NetDev' in section 'Network'
br0: netdev ready
=================================================================
==11666==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4 byte(s) in 1 object(s) allocated from:
#0 0x7f3a314cf238 in __interceptor_strdup (/lib64/libasan.so.4+0x77238)
#1 0x7f3a30e71ad1 in free_and_strdup ../src/basic/string-util.c:870
#2 0x7f3a30d34fba in config_parse_ifname ../src/shared/conf-parser.c:981
#3 0x7f3a30d2f5b0 in next_assignment ../src/shared/conf-parser.c:155
#4 0x7f3a30d30303 in parse_line ../src/shared/conf-parser.c:273
#5 0x7f3a30d30dee in config_parse ../src/shared/conf-parser.c:390
#6 0x7f3a30d310a5 in config_parse_many_files ../src/shared/conf-parser.c:428
#7 0x7f3a30d3181c in config_parse_many ../src/shared/conf-parser.c:487
#8 0x55b4200f9b00 in netdev_load_one ../src/network/netdev/netdev.c:634
#9 0x55b4200fb562 in netdev_load ../src/network/netdev/netdev.c:778
#10 0x55b4200c607a in manager_load_config ../src/network/networkd-manager.c:1299
#11 0x55b4200818e0 in test_load_config ../src/network/test-network.c:128
#12 0x55b42008343b in main ../src/network/test-network.c:254
#13 0x7f3a305f8889 in __libc_start_main (/lib64/libc.so.6+0x20889)
SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
-------
Diffstat (limited to 'src')
-rw-r--r-- | src/network/netdev/netdev.c | 20 | ||||
-rw-r--r-- | src/network/netdev/netdev.h | 2 |
2 files changed, 11 insertions, 11 deletions
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 5530760e19..7afe30f7fb 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -138,7 +138,7 @@ static void netdev_free(NetDev *netdev) { netdev_cancel_callbacks(netdev); - if (netdev->ifname) + if (netdev->ifname && netdev->manager) hashmap_remove(netdev->manager->netdevs, netdev->ifname); free(netdev->filename); @@ -601,8 +601,7 @@ int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t callbac } static int netdev_load_one(Manager *manager, const char *filename) { - _cleanup_netdev_unref_ NetDev *netdev = NULL; - _cleanup_free_ NetDev *netdev_raw = NULL; + _cleanup_netdev_unref_ NetDev *netdev_raw = NULL, *netdev = NULL; _cleanup_fclose_ FILE *file = NULL; const char *dropin_dirname; bool independent = false; @@ -628,9 +627,11 @@ static int netdev_load_one(Manager *manager, const char *filename) { if (!netdev_raw) return log_oom(); + netdev_raw->n_ref = 1; netdev_raw->kind = _NETDEV_KIND_INVALID; - dropin_dirname = strjoina(basename(filename), ".d"); + netdev_raw->state = _NETDEV_STATE_INVALID; + dropin_dirname = strjoina(basename(filename), ".d"); r = config_parse_many(filename, network_dirs, dropin_dirname, "Match\0NetDev\0", config_item_perf_lookup, network_netdev_gperf_lookup, @@ -638,10 +639,6 @@ static int netdev_load_one(Manager *manager, const char *filename) { if (r < 0) return r; - r = fseek(file, 0, SEEK_SET); - if (r < 0) - return -errno; - /* skip out early if configuration does not match the environment */ if (net_match_config(NULL, NULL, NULL, NULL, NULL, netdev_raw->match_host, netdev_raw->match_virt, @@ -659,15 +656,18 @@ static int netdev_load_one(Manager *manager, const char *filename) { return 0; } + r = fseek(file, 0, SEEK_SET); + if (r < 0) + return -errno; + netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size); if (!netdev) return log_oom(); netdev->n_ref = 1; netdev->manager = manager; - netdev->state = _NETDEV_STATE_INVALID; netdev->kind = netdev_raw->kind; - netdev->ifname = netdev_raw->ifname; + netdev->state = _NETDEV_STATE_INVALID; if (NETDEV_VTABLE(netdev)->init) NETDEV_VTABLE(netdev)->init(netdev); diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index ec65251464..24915b2b04 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -143,7 +143,7 @@ typedef struct NetDevVTable { extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; -#define NETDEV_VTABLE(n) netdev_vtable[(n)->kind] +#define NETDEV_VTABLE(n) ((n)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(n)->kind] : NULL) /* For casting a netdev into the various netdev kinds */ #define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \ |