1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-31 16:21:26 +03:00

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).
-------
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2017-12-20 10:17:37 +01:00 committed by Lennart Poettering
parent af126c9623
commit 281bb5c110
2 changed files with 11 additions and 11 deletions

View File

@ -138,7 +138,7 @@ static void netdev_free(NetDev *netdev) {
netdev_cancel_callbacks(netdev); netdev_cancel_callbacks(netdev);
if (netdev->ifname) if (netdev->ifname && netdev->manager)
hashmap_remove(netdev->manager->netdevs, netdev->ifname); hashmap_remove(netdev->manager->netdevs, netdev->ifname);
free(netdev->filename); 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) { static int netdev_load_one(Manager *manager, const char *filename) {
_cleanup_netdev_unref_ NetDev *netdev = NULL; _cleanup_netdev_unref_ NetDev *netdev_raw = NULL, *netdev = NULL;
_cleanup_free_ NetDev *netdev_raw = NULL;
_cleanup_fclose_ FILE *file = NULL; _cleanup_fclose_ FILE *file = NULL;
const char *dropin_dirname; const char *dropin_dirname;
bool independent = false; bool independent = false;
@ -628,9 +627,11 @@ static int netdev_load_one(Manager *manager, const char *filename) {
if (!netdev_raw) if (!netdev_raw)
return log_oom(); return log_oom();
netdev_raw->n_ref = 1;
netdev_raw->kind = _NETDEV_KIND_INVALID; 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, r = config_parse_many(filename, network_dirs, dropin_dirname,
"Match\0NetDev\0", "Match\0NetDev\0",
config_item_perf_lookup, network_netdev_gperf_lookup, 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) if (r < 0)
return r; return r;
r = fseek(file, 0, SEEK_SET);
if (r < 0)
return -errno;
/* skip out early if configuration does not match the environment */ /* skip out early if configuration does not match the environment */
if (net_match_config(NULL, NULL, NULL, NULL, NULL, if (net_match_config(NULL, NULL, NULL, NULL, NULL,
netdev_raw->match_host, netdev_raw->match_virt, netdev_raw->match_host, netdev_raw->match_virt,
@ -659,15 +656,18 @@ static int netdev_load_one(Manager *manager, const char *filename) {
return 0; return 0;
} }
r = fseek(file, 0, SEEK_SET);
if (r < 0)
return -errno;
netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size); netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
if (!netdev) if (!netdev)
return log_oom(); return log_oom();
netdev->n_ref = 1; netdev->n_ref = 1;
netdev->manager = manager; netdev->manager = manager;
netdev->state = _NETDEV_STATE_INVALID;
netdev->kind = netdev_raw->kind; netdev->kind = netdev_raw->kind;
netdev->ifname = netdev_raw->ifname; netdev->state = _NETDEV_STATE_INVALID;
if (NETDEV_VTABLE(netdev)->init) if (NETDEV_VTABLE(netdev)->init)
NETDEV_VTABLE(netdev)->init(netdev); NETDEV_VTABLE(netdev)->init(netdev);

View File

@ -143,7 +143,7 @@ typedef struct NetDevVTable {
extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; 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 */ /* For casting a netdev into the various netdev kinds */
#define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \ #define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \