From b22ef29e3efadac6ac3b7b69b36304592150b19b Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 3 Sep 2024 09:37:47 +0100 Subject: [PATCH] privsep: Capsicum needs root to access ipv6 forwarding sysctl Optimise the flow so that if we do have a global address on the source interface we avoid the sysctl via the privileged process. Generally the only time we don't is when we de-configure an interface or we are configuring an interface where there is no autoconf prefix from the RA and the only globals come from a DHCPv6 Prefix Delegation to other interfaces which requires us to be a router. --- src/ipv6.c | 56 ++++++++++++++++++++++++++++++---------------- src/ipv6nd.c | 2 +- src/privsep-root.c | 2 +- src/privsep.h | 11 +++++++-- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/ipv6.c b/src/ipv6.c index f08c661c..28f31fc9 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -1108,43 +1108,61 @@ ipv6_getstate(struct interface *ifp) return state; } +static struct ipv6_addr * +ipv6_ifanyglobal(struct interface *ifp) +{ + struct ipv6_state *state; + struct ipv6_addr *ia; + + state = IPV6_STATE(ifp); + if (state == NULL) + return NULL; + + TAILQ_FOREACH(ia, &state->addrs, next) { + if (IN6_IS_ADDR_LINKLOCAL(&ia->addr) || + IN6_IS_ADDR_LOOPBACK(&ia->addr)) + continue; + /* Let's be optimistic. + * Any decent OS won't forward or accept traffic + * from/to tentative or detached addresses. */ + if (!(ia->addr_flags & IN6_IFF_DUPLICATED)) + return ia; + } + + return NULL; +} + struct ipv6_addr * ipv6_anyglobal(struct interface *sifp) { - struct interface *ifp; - struct ipv6_state *state; struct ipv6_addr *ia; + struct interface *ifp; bool forwarding; + ia = ipv6_ifanyglobal(sifp); + if (ia != NULL) + return ia; + /* BSD forwarding is either on or off. * Linux forwarding is technically the same as it's * configured by the "all" interface. * Per interface only affects IsRouter of NA messages. */ -#if defined(PRIVSEP) && (defined(HAVE_PLEDGE) || defined(__linux__)) +#ifdef PRIVSEP_SYSCTL if (IN_PRIVSEP(sifp->ctx)) forwarding = ps_root_ip6forwarding(sifp->ctx, NULL) != 0; else #endif forwarding = ip6_forwarding(NULL) != 0; - TAILQ_FOREACH(ifp, sifp->ctx->ifaces, next) { - if (ifp != sifp && !forwarding) - continue; + if (!forwarding) + return NULL; - state = IPV6_STATE(ifp); - if (state == NULL) + TAILQ_FOREACH(ifp, sifp->ctx->ifaces, next) { + if (ifp == sifp) continue; - - TAILQ_FOREACH(ia, &state->addrs, next) { - if (IN6_IS_ADDR_LINKLOCAL(&ia->addr) || - IN6_IS_ADDR_LOOPBACK(&ia->addr)) - continue; - /* Let's be optimistic. - * Any decent OS won't forward or accept traffic - * from/to tentative or detached addresses. */ - if (!(ia->addr_flags & IN6_IFF_DUPLICATED)) - return ia; - } + ia = ipv6_ifanyglobal(ifp); + if (ia != NULL) + return ia; } return NULL; } diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 913c84fe..11f5dc5f 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -566,7 +566,7 @@ ipv6nd_advertise(struct ipv6_addr *ia) na->nd_na_type = ND_NEIGHBOR_ADVERT; na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE; -#if defined(PRIVSEP) && (defined(__linux__) || defined(HAVE_PLEDGE)) +#ifdef PRIVSEP_SYSCTL if (IN_PRIVSEP(ctx)) { if (ps_root_ip6forwarding(ctx, ifp->name) != 0) na->nd_na_flags_reserved |= ND_NA_FLAG_ROUTER; diff --git a/src/privsep-root.c b/src/privsep-root.c index d6e4c992..50cd2941 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -1173,7 +1173,7 @@ err: } #endif -#if defined(__linux__) || defined(HAVE_PLEDGE) +#ifdef PRIVSEP_SYSCTL ssize_t ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname) { diff --git a/src/privsep.h b/src/privsep.h index 4ff4d2ae..82324a9b 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -110,8 +110,15 @@ #define PS_PROCESS_TIMEOUT 5 /* seconds to stop all processes */ -#if defined(PRIVSEP) && defined(HAVE_CAPSICUM) -#define PRIVSEP_RIGHTS +#ifdef PRIVSEP +# ifdef HAVE_CAPSICUM +# define PRIVSEP_RIGHTS +# endif +/* Pledge and Capsicum deny nearly all sysctls. + * Linux needs directory access to sysctls. */ +# if defined(HAVE_CAPSICUM) ||defined(HAVE_PLEDGE) || defined(__linux__) +# define PRIVSEP_SYSCTL +# endif #endif #define PS_ROOT_FD(ctx) ((ctx)->ps_root ? (ctx)->ps_root->psp_fd : -1) -- 2.47.2