From: networkException Date: Thu, 4 Jan 2024 17:45:25 +0000 (+0100) Subject: parse-helpers: allow port 0 for socket bind items X-Git-Tag: v256-rc1~1259 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dcfac3a3f9d9a32bdb5679cd6dab4bb86a6cd6fe;p=thirdparty%2Fsystemd.git parse-helpers: allow port 0 for socket bind items This patch adds a new parameter to parse_ip_port_range, giving callers the option to allow ranges to have their min be 0 instead of 1. This is then used by parse_ip_ports_token, intern used by parse_socket_bind_item to allow port 0 when restricting bind system calls with SocketBindDeny / SocketBindAllow. With this, users running server software written using the golang standard library will be able to effectively sandbox their software, albeit with a small loss in security protections by allowing the process to bind on a random port in the /proc/sys/net/ipv4/ip_local_port_range. --- diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 0430e33e40d..5971173915a 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -691,7 +691,7 @@ int parse_ip_port(const char *s, uint16_t *ret) { return 0; } -int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high) { +int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high, bool allow_zero) { unsigned l, h; int r; @@ -699,7 +699,10 @@ int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high) { if (r < 0) return r; - if (l <= 0 || l > 65535 || h <= 0 || h > 65535) + if (l > 65535 || h > 65535) + return -EINVAL; + + if (!allow_zero && (l == 0 || h == 0)) return -EINVAL; if (h < l) diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h index 1845f0a876f..c12988ef204 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -139,7 +139,7 @@ int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); int parse_nice(const char *p, int *ret); int parse_ip_port(const char *s, uint16_t *ret); -int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high); +int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high, bool allow_zero); int parse_ip_prefix_length(const char *s, int *ret); diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c index b11fdbbd0de..f333abc6c04 100644 --- a/src/network/netdev/vxlan.c +++ b/src/network/netdev/vxlan.c @@ -289,7 +289,7 @@ int config_parse_port_range( VxLan *v = ASSERT_PTR(userdata); int r; - r = parse_ip_port_range(rvalue, &v->port_range.low, &v->port_range.high); + r = parse_ip_port_range(rvalue, &v->port_range.low, &v->port_range.high, /* allow_zero = */ false); if (r < 0) log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", rvalue); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 6324b044983..914e288aecc 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1408,7 +1408,7 @@ int config_parse_routing_policy_rule_port_range( if (r < 0) return log_oom(); - r = parse_ip_port_range(rvalue, &low, &high); + r = parse_ip_port_range(rvalue, &low, &high, /* allow_zero = */ false); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse routing policy rule port range '%s'", rvalue); return 0; diff --git a/src/shared/parse-helpers.c b/src/shared/parse-helpers.c index 9664b9c773b..bad3af8ebf6 100644 --- a/src/shared/parse-helpers.c +++ b/src/shared/parse-helpers.c @@ -102,6 +102,8 @@ static int parse_ip_ports_token( uint16_t *nr_ports, uint16_t *port_min) { + int r; + assert(token); assert(nr_ports); assert(port_min); @@ -110,7 +112,7 @@ static int parse_ip_ports_token( *nr_ports = *port_min = 0; else { uint16_t mn = 0, mx = 0; - int r = parse_ip_port_range(token, &mn, &mx); + r = parse_ip_port_range(token, &mn, &mx, /* allow_zero = */ true); if (r < 0) return r; @@ -194,6 +196,7 @@ int parse_socket_bind_item( *ip_protocol = proto; *nr_ports = nr; *port_min = mn; + return 0; } diff --git a/src/test/test-parse-helpers.c b/src/test/test-parse-helpers.c index 052e2514f43..49438713791 100644 --- a/src/test/test-parse-helpers.c +++ b/src/test/test-parse-helpers.c @@ -37,6 +37,7 @@ static void test_invalid_item(const char *str) { TEST(valid_items) { test_valid_item("any", AF_UNSPEC, 0, 0, 0); + test_valid_item("0-65535", AF_UNSPEC, 0, 0, 0); test_valid_item("ipv4", AF_INET, 0, 0, 0); test_valid_item("ipv6", AF_INET6, 0, 0, 0); test_valid_item("ipv4:any", AF_INET, 0, 0, 0); @@ -45,6 +46,7 @@ TEST(valid_items) { test_valid_item("udp", AF_UNSPEC, IPPROTO_UDP, 0, 0); test_valid_item("tcp:any", AF_UNSPEC, IPPROTO_TCP, 0, 0); test_valid_item("udp:any", AF_UNSPEC, IPPROTO_UDP, 0, 0); + test_valid_item("0", AF_UNSPEC, 0, 1, 0); test_valid_item("6666", AF_UNSPEC, 0, 1, 6666); test_valid_item("6666-6667", AF_UNSPEC, 0, 2, 6666); test_valid_item("65535", AF_UNSPEC, 0, 1, 65535); @@ -61,6 +63,7 @@ TEST(valid_items) { test_valid_item("ipv6:tcp:6666", AF_INET6, IPPROTO_TCP, 1, 6666); test_valid_item("ipv6:udp:6666-6667", AF_INET6, IPPROTO_UDP, 2, 6666); test_valid_item("ipv6:tcp:any", AF_INET6, IPPROTO_TCP, 0, 0); + test_valid_item("ipv6:tcp:0", AF_INET6, IPPROTO_TCP, 1, 0); } TEST(invalid_items) { @@ -77,9 +80,7 @@ TEST(invalid_items) { test_invalid_item("ipv6::"); test_invalid_item("ipv6:ipv6"); test_invalid_item("ipv6:icmp"); - test_invalid_item("ipv6:tcp:0"); test_invalid_item("65536"); - test_invalid_item("0-65535"); test_invalid_item("ipv6:tcp:6666-6665"); test_invalid_item("ipv6:tcp:6666-100000"); test_invalid_item("ipv6::6666");