From 1b566071577fabd45f7e2b449ac583814d522759 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 3 Jun 2016 19:51:48 +0200 Subject: [PATCH] networkd: also enforce limit on total number of address/routes This covers the address/routers acquire dynamically. --- src/network/networkd-address.c | 48 +++++++++++++++++++++++----------- src/network/networkd-route.c | 47 ++++++++++++++++++++------------- src/network/networkd-route.h | 2 +- 3 files changed, 63 insertions(+), 34 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 4cdb500bd67..9275ccf9a95 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -32,6 +32,7 @@ #include "utf8.h" #include "util.h" +#define ADDRESSES_PER_LINK_MAX 2048U #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U int address_new(Address **ret) { @@ -392,31 +393,38 @@ int address_drop(Address *address) { return 0; } -int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { - Address address = {}, *existing; +int address_get(Link *link, + int family, + const union in_addr_union *in_addr, + unsigned char prefixlen, + Address **ret) { + + Address address, *existing; assert(link); assert(in_addr); - assert(ret); - address.family = family; - address.in_addr = *in_addr; - address.prefixlen = prefixlen; + address = (Address) { + .family = family, + .in_addr = *in_addr, + .prefixlen = prefixlen, + }; existing = set_get(link->addresses, &address); if (existing) { - *ret = existing; - + if (ret) + *ret = existing; return 1; - } else { - existing = set_get(link->addresses_foreign, &address); - if (!existing) - return -ENOENT; } - *ret = existing; + existing = set_get(link->addresses_foreign, &address); + if (existing) { + if (ret) + *ret = existing; + return 0; + } - return 0; + return -ENOENT; } int address_remove( @@ -518,7 +526,12 @@ static int address_acquire(Link *link, Address *original, Address **ret) { return 0; } -int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) { +int address_configure( + Address *address, + Link *link, + sd_netlink_message_handler_t callback, + bool update) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; int r; @@ -529,6 +542,11 @@ int address_configure(Address *address, Link *link, sd_netlink_message_handler_t assert(link->manager); assert(link->manager->rtnl); + /* If this is a new address, then refuse adding more than the limit */ + if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 && + set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) + return -E2BIG; + r = address_acquire(link, address, &address); if (r < 0) return r; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 1b480385c68..0d2a5bb83d2 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -28,6 +28,7 @@ #include "string-util.h" #include "util.h" +#define ROUTES_PER_LINK_MAX 2048U #define STATIC_ROUTES_PER_NETWORK_MAX 1024U int route_new(Route **ret) { @@ -187,39 +188,42 @@ static const struct hash_ops route_hash_ops = { int route_get(Link *link, int family, - union in_addr_union *dst, + const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret) { - Route route = { + + Route route, *existing; + + assert(link); + assert(dst); + + route = (Route) { .family = family, + .dst = *dst, .dst_prefixlen = dst_prefixlen, .tos = tos, .priority = priority, .table = table, - }, *existing; - - assert(link); - assert(dst); - assert(ret); - - route.dst = *dst; + }; existing = set_get(link->routes, &route); if (existing) { - *ret = existing; + if (ret) + *ret = existing; return 1; - } else { - existing = set_get(link->routes_foreign, &route); - if (!existing) - return -ENOENT; } - *ret = existing; + existing = set_get(link->routes_foreign, &route); + if (existing) { + if (ret) + *ret = existing; + return 0; + } - return 0; + return -ENOENT; } static int route_add_internal(Link *link, Set **routes, @@ -460,8 +464,11 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { return 1; } -int route_configure(Route *route, Link *link, - sd_netlink_message_handler_t callback) { +int route_configure( + Route *route, + Link *link, + sd_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; usec_t lifetime; @@ -473,6 +480,10 @@ int route_configure(Route *route, Link *link, assert(link->ifindex > 0); assert(route->family == AF_INET || route->family == AF_INET6); + if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 && + set_size(route->link->routes) >= ROUTES_PER_LINK_MAX) + return -E2BIG; + r = sd_rtnl_message_new_route(link->manager->rtnl, &req, RTM_NEWROUTE, route->family, route->protocol); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 39de8363edd..ddc3e1da57d 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -57,7 +57,7 @@ void route_free(Route *route); int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback); -int route_get(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); +int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); int route_add(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);