]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Capsicum needs root to access ipv6 forwarding sysctl
authorRoy Marples <roy@marples.name>
Tue, 3 Sep 2024 08:37:47 +0000 (09:37 +0100)
committerRoy Marples <roy@marples.name>
Wed, 4 Sep 2024 09:51:12 +0000 (10:51 +0100)
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
src/ipv6nd.c
src/privsep-root.c
src/privsep.h

index f08c661c16deb25126a87faf93b5e187db456d29..28f31fc9e887c679b540da4d9923490d78ba74df 100644 (file)
@@ -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;
 }
index 913c84fec53fd62a38420cc086efd27cbea1da3e..11f5dc5f49966eee4c6030a723aa0eef5edd9526 100644 (file)
@@ -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;
index d6e4c992589860109d6ff7f05e5783c13d5ac923..50cd294149c9c29d21891ccd6a6ae647e8abee66 100644 (file)
@@ -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)
 {
index 4ff4d2ae87c108586d870a102be048359238a4e0..82324a9b3a8fa4890598d1913b2b0b541bb158b5 100644 (file)
 
 #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)