From 2642d22adc66771bd8bbb4187dc3de5472d04ad6 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 26 Jan 2023 22:18:47 +0100 Subject: [PATCH 1/2] nspawn: Drop CAP_NET_BIND_SERVICE when in userns but not in netns If we're in a user namespace but not unsharing the network namespace, we won't be able to bind any privileged ports even with CAP_NET_BIND_SERVICE, so let's drop it from the retained capabilities so services can condition themselves on that. --- src/nspawn/nspawn.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 25f77509124..f16d9506eb3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1717,7 +1717,16 @@ static int parse_argv(int argc, char *argv[]) { * --directory=". */ arg_directory = TAKE_PTR(arg_template); - arg_caps_retain = (arg_caps_retain | plus | (arg_private_network ? UINT64_C(1) << CAP_NET_ADMIN : 0)) & ~minus; + arg_caps_retain |= plus; + arg_caps_retain |= arg_private_network ? UINT64_C(1) << CAP_NET_ADMIN : 0; + + /* If we're not unsharing the network namespace and are unsharing the user namespace, we won't have + * permissions to bind ports in the container, so let's drop the CAP_NET_BIND_SERVICE capability to + * indicate that. */ + if (!arg_private_network && arg_userns_mode != USER_NAMESPACE_NO && arg_uid_shift > 0) + arg_caps_retain &= ~(UINT64_C(1) << CAP_NET_BIND_SERVICE); + + arg_caps_retain &= ~minus; /* Make sure to parse environment before we reset the settings mask below */ r = parse_environment(); From 0398c084efba664e44625d82f2be72e18c952678 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 26 Jan 2023 22:20:01 +0100 Subject: [PATCH 2/2] resolve: Skip creating stubs if missing CAP_NET_BIND_SERVICE If we don't have CAP_NET_BIND_SERVICE, we won't be able to bind the stub listener socket, so let's skip creating it and log a warning. We do the same for the extra stubs if they're configured on privileged ports. --- src/resolve/resolved-dns-stub.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index facd95aeb8a..3a7d6977f67 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -3,6 +3,7 @@ #include #include +#include "capability-util.h" #include "errno-util.h" #include "fd-util.h" #include "missing_network.h" @@ -1237,6 +1238,12 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty if (*event_source) return sd_event_source_get_io_fd(*event_source); + if (!have_effective_cap(CAP_NET_BIND_SERVICE) && dns_stub_listener_extra_port(l) < 1024) { + log_warning("Missing CAP_NET_BIND_SERVICE capability, not creating extra stub listener on port %hu.", + dns_stub_listener_extra_port(l)); + return 0; + } + if (l->family == AF_INET) sa = (union sockaddr_union) { .in.sin_family = l->family, @@ -1332,6 +1339,8 @@ int manager_dns_stub_start(Manager *m) { if (m->dns_stub_listener_mode == DNS_STUB_LISTENER_NO) log_debug("Not creating stub listener."); + else if (!have_effective_cap(CAP_NET_BIND_SERVICE)) + log_warning("Missing CAP_NET_BIND_SERVICE capability, not creating stub listener on port 53."); else { static const struct { uint32_t addr;