From 8c34b963076a1ce7c9102802a13502be82a02cc7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 3 Jun 2016 19:14:12 +0200 Subject: [PATCH] networkd: enforce a limit on the number of statically assigned addresses/routes/fdb entries We should put a limit on everything, hence also on these resources. --- src/network/networkd-address.c | 17 +++++++++++++---- src/network/networkd-fdb.c | 25 +++++++++++++++++-------- src/network/networkd-network.h | 4 ++++ src/network/networkd-route.c | 15 +++++++++++++-- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 367c340e08f..4cdb500bd67 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -32,6 +32,8 @@ #include "utf8.h" #include "util.h" +#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U + int address_new(Address **ret) { _cleanup_address_free_ Address *address = NULL; @@ -54,6 +56,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) { _cleanup_address_free_ Address *address = NULL; int r; + assert(network); + assert(ret); + if (section) { address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section)); if (address) { @@ -64,18 +69,21 @@ int address_new_static(Network *network, unsigned section, Address **ret) { } } + if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX) + return -E2BIG; + r = address_new(&address); if (r < 0) return r; if (section) { address->section = section; - hashmap_put(network->addresses_by_section, - UINT_TO_PTR(address->section), address); + hashmap_put(network->addresses_by_section, UINT_TO_PTR(address->section), address); } address->network = network; LIST_APPEND(addresses, network->static_addresses, address); + network->n_static_addresses++; *ret = address; address = NULL; @@ -89,10 +97,11 @@ void address_free(Address *address) { if (address->network) { LIST_REMOVE(addresses, address->network->static_addresses, address); + assert(address->network->n_static_addresses > 0); + address->network->n_static_addresses--; if (address->section) - hashmap_remove(address->network->addresses_by_section, - UINT_TO_PTR(address->section)); + hashmap_remove(address->network->addresses_by_section, UINT_TO_PTR(address->section)); } if (address->link) { diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index 241f4862117..4d51fa41e27 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -27,14 +27,19 @@ #include "networkd.h" #include "util.h" +#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U + /* create a new FDB entry or get an existing one. */ -int fdb_entry_new_static(Network *const network, - const unsigned section, - FdbEntry **ret) { +int fdb_entry_new_static( + Network *network, + const unsigned section, + FdbEntry **ret) { + _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; struct ether_addr *mac_addr = NULL; assert(network); + assert(ret); /* search entry in hashmap first. */ if (section) { @@ -47,6 +52,9 @@ int fdb_entry_new_static(Network *const network, } } + if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX) + return -E2BIG; + /* allocate space for MAC address. */ mac_addr = new0(struct ether_addr, 1); if (!mac_addr) @@ -54,7 +62,6 @@ int fdb_entry_new_static(Network *const network, /* allocate space for and FDB entry. */ fdb_entry = new0(FdbEntry, 1); - if (!fdb_entry) { /* free previously allocated space for mac_addr. */ free(mac_addr); @@ -66,6 +73,7 @@ int fdb_entry_new_static(Network *const network, fdb_entry->mac_addr = mac_addr; LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry); + network->n_static_fdb_entries++; if (section) { fdb_entry->section = section; @@ -145,12 +153,13 @@ void fdb_entry_free(FdbEntry *fdb_entry) { return; if (fdb_entry->network) { - LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, - fdb_entry); + LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); + + assert(fdb_entry->network->n_static_fdb_entries > 0); + fdb_entry->network->n_static_fdb_entries--; if (fdb_entry->section) - hashmap_remove(fdb_entry->network->fdb_entries_by_section, - UINT_TO_PTR(fdb_entry->section)); + hashmap_remove(fdb_entry->network->fdb_entries_by_section, UINT_TO_PTR(fdb_entry->section)); } free(fdb_entry->mac_addr); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 91099161ce0..248a427e8db 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -169,6 +169,10 @@ struct Network { LIST_HEAD(Route, static_routes); LIST_HEAD(FdbEntry, static_fdb_entries); + unsigned n_static_addresses; + unsigned n_static_routes; + unsigned n_static_fdb_entries; + Hashmap *addresses_by_section; Hashmap *routes_by_section; Hashmap *fdb_entries_by_section; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f001de772ae..1b480385c68 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -28,6 +28,8 @@ #include "string-util.h" #include "util.h" +#define STATIC_ROUTES_PER_NETWORK_MAX 1024U + int route_new(Route **ret) { _cleanup_route_free_ Route *route = NULL; @@ -51,6 +53,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; int r; + assert(network); + assert(ret); + if (section) { route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); if (route) { @@ -61,6 +66,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) { } } + if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX) + return -E2BIG; + r = route_new(&route); if (r < 0) return r; @@ -77,6 +85,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) { route->network = network; LIST_PREPEND(routes, network->static_routes, route); + network->n_static_routes++; *ret = route; route = NULL; @@ -91,9 +100,11 @@ void route_free(Route *route) { if (route->network) { LIST_REMOVE(routes, route->network->static_routes, route); + assert(route->network->n_static_routes > 0); + route->network->n_static_routes--; + if (route->section) - hashmap_remove(route->network->routes_by_section, - UINT_TO_PTR(route->section)); + hashmap_remove(route->network->routes_by_section, UINT_TO_PTR(route->section)); } if (route->link) {