Skip to content

Commit

Permalink
privsep: Capsicum needs root to access ipv6 forwarding sysctl
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rsmarples committed Sep 4, 2024
1 parent ae3d1b5 commit b22ef29
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 23 deletions.
56 changes: 37 additions & 19 deletions src/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ipv6nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/privsep-root.c
Original file line number Diff line number Diff line change
Expand Up @@ -1173,7 +1173,7 @@ ps_root_getifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **ifahead)
}
#endif

#if defined(__linux__) || defined(HAVE_PLEDGE)
#ifdef PRIVSEP_SYSCTL
ssize_t
ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname)
{
Expand Down
11 changes: 9 additions & 2 deletions src/privsep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit b22ef29

Please sign in to comment.