From 5e2a51d588dde4b52c6017ea80b75c16e6e23431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 20 Feb 2019 22:50:25 +0100 Subject: [PATCH] networkd: use OrderedSets instead of strvs to store lists of domains We were already using OrderedSets in the manager object, but strvs in the configuration parsing code. Using sets gives us better scaling when many domains are used. In oss-fuzz #13059 the attached reproducer takes approximately 30.5 s to be parsed. Converting to sets makes this go down to 10s. This is not _vastly_ faster, but using sets seems like a nicer approach anyway. In particular, we avoid the quadratic de-unification operation after each addition. --- src/network/networkd-link.c | 8 +--- src/network/networkd-manager.c | 4 +- src/network/networkd-network.c | 48 +++++++++---------- src/network/networkd-network.h | 6 ++- src/network/networkd-radv.c | 9 +++- test/fuzz/fuzz-network-parser/oss-fuzz-13059 | Bin 0 -> 407131 bytes 6 files changed, 39 insertions(+), 36 deletions(-) create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-13059 diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 2aea0b839c..8418d66089 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -4083,9 +4083,7 @@ int link_save(Link *link) { (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains); } - fputs("DOMAINS=", f); - space = false; - fputstrv(f, link->network->search_domains, NULL, &space); + ordered_set_print(f, "DOMAINS=", link->network->search_domains); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) { NDiscDNSSL *dd; @@ -4103,9 +4101,7 @@ int link_save(Link *link) { fputc('\n', f); - fputs("ROUTE_DOMAINS=", f); - space = false; - fputstrv(f, link->network->route_domains, NULL, &space); + ordered_set_print(f, "ROUTE_DOMAINS=", link->network->route_domains); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) { NDiscDNSSL *dd; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 758132d39d..8ee7bca435 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1108,11 +1108,11 @@ static int manager_save(Manager *m) { if (r < 0) return r; - r = ordered_set_put_strdupv(search_domains, link->network->search_domains); + r = ordered_set_put_string_set(search_domains, link->network->search_domains); if (r < 0) return r; - r = ordered_set_put_strdupv(route_domains, link->network->route_domains); + r = ordered_set_put_string_set(route_domains, link->network->route_domains); if (r < 0) return r; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 727b2da9f4..a83df49038 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -385,11 +385,11 @@ void network_free(Network *network) { strv_free(network->ntp); free(network->dns); - strv_free(network->search_domains); - strv_free(network->route_domains); + ordered_set_free_free(network->search_domains); + ordered_set_free_free(network->route_domains); strv_free(network->bind_carrier); - strv_free(network->router_search_domains); + ordered_set_free_free(network->router_search_domains); free(network->router_dns); netdev_unref(network->bridge); @@ -553,8 +553,8 @@ int network_apply(Network *network, Link *link) { if (network->n_dns > 0 || !strv_isempty(network->ntp) || - !strv_isempty(network->search_domains) || - !strv_isempty(network->route_domains)) + !ordered_set_isempty(network->search_domains) || + !ordered_set_isempty(network->route_domains)) link_dirty(link); return 0; @@ -686,8 +686,8 @@ int config_parse_domains( assert(rvalue); if (isempty(rvalue)) { - n->search_domains = strv_free(n->search_domains); - n->route_domains = strv_free(n->route_domains); + n->search_domains = ordered_set_free_free(n->search_domains); + n->route_domains = ordered_set_free_free(n->route_domains); return 0; } @@ -733,17 +733,16 @@ int config_parse_domains( } } - if (is_route) - r = strv_extend(&n->route_domains, domain); - else - r = strv_extend(&n->search_domains, domain); + OrderedSet **set = is_route ? &n->route_domains : &n->search_domains; + r = ordered_set_ensure_allocated(set, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_set_put_strdup(*set, domain); if (r < 0) return log_oom(); } - strv_uniq(n->route_domains); - strv_uniq(n->search_domains); - return 0; } @@ -1218,16 +1217,17 @@ int config_parse_radv_search_domains( log_syntax(unit, LOG_ERR, filename, line, r, "Failed to apply IDNA to domain name '%s', ignoring: %m", w); continue; - } - if (r > 0) { - r = strv_push(&n->router_search_domains, idna); - if (r >= 0) - idna = NULL; - } else { - r = strv_push(&n->router_search_domains, w); - if (r >= 0) - w = NULL; - } + } else if (r == 0) + /* transfer ownership to simplify subsequent operations */ + idna = TAKE_PTR(w); + + r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna)); + if (r < 0) + return r; } return 0; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index e61c391c76..5681e8d212 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -20,6 +20,7 @@ #include "networkd-route.h" #include "networkd-routing-policy-rule.h" #include "networkd-util.h" +#include "ordered-set.h" #include "resolve-util.h" #define DHCP_ROUTE_METRIC 1024 @@ -173,7 +174,7 @@ struct Network { usec_t router_dns_lifetime_usec; struct in6_addr *router_dns; unsigned n_router_dns; - char **router_search_domains; + OrderedSet *router_search_domains; bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O' RA flag is set, see RFC 7084, WPD-4 */ @@ -267,7 +268,8 @@ struct Network { /* All kinds of DNS configuration */ struct in_addr_data *dns; unsigned n_dns; - char **search_domains, **route_domains; + OrderedSet *search_domains, *route_domains; + int dns_default_route; ResolveSupport llmnr; ResolveSupport mdns; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 92cead052a..ecf984e226 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -391,8 +391,9 @@ static int radv_set_dns(Link *link, Link *uplink) { } static int radv_set_domains(Link *link, Link *uplink) { - char **search_domains; + OrderedSet *search_domains; usec_t lifetime_usec; + _cleanup_free_ char **s = NULL; /* just free() because the strings are owned by the set */ if (!link->network->router_emit_domains) return 0; @@ -423,9 +424,13 @@ static int radv_set_domains(Link *link, Link *uplink) { return 0; set_domains: + s = ordered_set_get_strv(search_domains); + if (!s) + return log_oom(); + return sd_radv_set_dnssl(link->radv, DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), - search_domains); + s); } diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-13059 b/test/fuzz/fuzz-network-parser/oss-fuzz-13059 new file mode 100644 index 0000000000000000000000000000000000000000..a605c791700dc6c2da6120c686a2a09c72b6d1c6 GIT binary patch literal 407131 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