diff options
Diffstat (limited to 'src/privsep-inet.c')
-rw-r--r-- | src/privsep-inet.c | 168 |
1 files changed, 96 insertions, 72 deletions
diff --git a/src/privsep-inet.c b/src/privsep-inet.c index 3a192ee0c461..919fe9540b0a 100644 --- a/src/privsep-inet.c +++ b/src/privsep-inet.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-2-Clause */ /* * Privilege Separation for dhcpcd, network proxy - * Copyright (c) 2006-2021 Roy Marples <roy@marples.name> + * Copyright (c) 2006-2023 Roy Marples <roy@marples.name> * All rights reserved * Redistribution and use in source and binary forms, with or without @@ -47,32 +47,37 @@ #include "logerr.h" #include "privsep.h" +/* We expect to have open 2 SEQPACKET, 1 udp, 1 udp6 and 1 raw6 fds */ + #ifdef INET static void -ps_inet_recvbootp(void *arg) +ps_inet_recvbootp(void *arg, unsigned short events) { struct dhcpcd_ctx *ctx = arg; - if (ps_recvmsg(ctx, ctx->udp_rfd, PS_BOOTP, ctx->ps_inet_fd) == -1) + if (ps_recvmsg(ctx->udp_rfd, events, + PS_BOOTP, ctx->ps_inet->psp_fd) == -1) logerr(__func__); } #endif #ifdef INET6 static void -ps_inet_recvra(void *arg) +ps_inet_recvra(void *arg, unsigned short events) { #ifdef __sun struct interface *ifp = arg; struct rs_state *state = RS_STATE(ifp); struct dhcpcd_ctx *ctx = ifp->ctx; - if (ps_recvmsg(ctx, state->nd_fd, PS_ND, ctx->ps_inet_fd) == -1) + if (ps_recvmsg(state->nd_fd, events, + PS_ND, ctx->ps_inet->psp_fd) == -1) logerr(__func__); #else struct dhcpcd_ctx *ctx = arg; - if (ps_recvmsg(ctx, ctx->nd_fd, PS_ND, ctx->ps_inet_fd) == -1) + if (ps_recvmsg(ctx->nd_fd, events, + PS_ND, ctx->ps_inet->psp_fd) == -1) logerr(__func__); #endif } @@ -80,11 +85,12 @@ ps_inet_recvra(void *arg) #ifdef DHCP6 static void -ps_inet_recvdhcp6(void *arg) +ps_inet_recvdhcp6(void *arg, unsigned short events) { struct dhcpcd_ctx *ctx = arg; - if (ps_recvmsg(ctx, ctx->dhcp6_rfd, PS_DHCP6, ctx->ps_inet_fd) == -1) + if (ps_recvmsg(ctx->dhcp6_rfd, events, + PS_DHCP6, ctx->ps_inet->psp_fd) == -1) logerr(__func__); } #endif @@ -112,16 +118,16 @@ ps_inet_canstart(const struct dhcpcd_ctx *ctx) } static int -ps_inet_startcb(void *arg) +ps_inet_startcb(struct ps_process *psp) { - struct dhcpcd_ctx *ctx = arg; + struct dhcpcd_ctx *ctx = psp->psp_ctx; int ret = 0; if (ctx->options & DHCPCD_MANAGER) setproctitle("[network proxy]"); else setproctitle("[network proxy] %s%s%s", - ctx->ifv[0], + ctx->ifc != 0 ? ctx->ifv[0] : "", ctx->options & DHCPCD_IPV4 ? " [ip4]" : "", ctx->options & DHCPCD_IPV6 ? " [ip6]" : ""); @@ -145,7 +151,7 @@ ps_inet_startcb(void *arg) ctx->udp_rfd = -1; } #endif - else if (eloop_event_add(ctx->eloop, ctx->udp_rfd, + else if (eloop_event_add(ctx->eloop, ctx->udp_rfd, ELE_READ, ps_inet_recvbootp, ctx) == -1) { logerr("%s: eloop_event_add DHCP", __func__); @@ -167,7 +173,7 @@ ps_inet_startcb(void *arg) ctx->nd_fd = -1; } #endif - else if (eloop_event_add(ctx->eloop, ctx->nd_fd, + else if (eloop_event_add(ctx->eloop, ctx->nd_fd, ELE_READ, ps_inet_recvra, ctx) == -1) { logerr("%s: eloop_event_add RA", __func__); @@ -191,7 +197,7 @@ ps_inet_startcb(void *arg) ctx->dhcp6_rfd = -1; } #endif - else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, + else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, ELE_READ, ps_inet_recvdhcp6, ctx) == -1) { logerr("%s: eloop_event_add DHCP6", __func__); @@ -299,12 +305,12 @@ dosend: } static void -ps_inet_recvmsg(void *arg) +ps_inet_recvmsg(void *arg, unsigned short events) { - struct dhcpcd_ctx *ctx = arg; + struct ps_process *psp = arg; /* Receive shutdown */ - if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, NULL, NULL) == -1) + if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1) logerr(__func__); } @@ -337,23 +343,32 @@ ps_inet_dispatch(void *arg, struct ps_msghdr *psm, struct msghdr *msg) } static void -ps_inet_dodispatch(void *arg) +ps_inet_dodispatch(void *arg, unsigned short events) { - struct dhcpcd_ctx *ctx = arg; + struct ps_process *psp = arg; - if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, ps_inet_dispatch, ctx) == -1) + if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, + ps_inet_dispatch, psp->psp_ctx) == -1) logerr(__func__); } pid_t ps_inet_start(struct dhcpcd_ctx *ctx) { + struct ps_id id = { + .psi_ifindex = 0, + .psi_cmd = PS_INET, + }; + struct ps_process *psp; pid_t pid; - pid = ps_dostart(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd, - ps_inet_recvmsg, ps_inet_dodispatch, ctx, - ps_inet_startcb, NULL, - PSF_DROPPRIVS); + psp = ctx->ps_inet = ps_newprocess(ctx, &id); + if (psp == NULL) + return -1; + + strlcpy(psp->psp_name, "network proxy", sizeof(psp->psp_name)); + pid = ps_startprocess(psp, ps_inet_recvmsg, ps_inet_dodispatch, + ps_inet_startcb, NULL, PSF_DROPPRIVS); if (pid == 0) ps_entersandbox("stdio", NULL); @@ -365,29 +380,28 @@ int ps_inet_stop(struct dhcpcd_ctx *ctx) { - return ps_dostop(ctx, &ctx->ps_inet_pid, &ctx->ps_inet_fd); + return ps_stopprocess(ctx->ps_inet); } #ifdef INET static void -ps_inet_recvinbootp(void *arg) +ps_inet_recvinbootp(void *arg, unsigned short events) { struct ps_process *psp = arg; - if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd, + if (ps_recvmsg(psp->psp_work_fd, events, PS_BOOTP, psp->psp_ctx->ps_data_fd) == -1) logerr(__func__); } static int -ps_inet_listenin(void *arg) +ps_inet_listenin(struct ps_process *psp) { - struct ps_process *psp = arg; struct in_addr *ia = &psp->psp_id.psi_addr.psa_in_addr; char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, ia, buf, sizeof(buf)); - setproctitle("[network proxy] %s", buf); + setproctitle("[%s proxy] %s", psp->psp_protostr, buf); psp->psp_work_fd = dhcp_openudp(ia); if (psp->psp_work_fd == -1) { @@ -402,14 +416,12 @@ ps_inet_listenin(void *arg) } #endif - if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, + if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ, ps_inet_recvinbootp, psp) == -1) { logerr("%s: eloop_event_add DHCP", __func__); return -1; } - - logdebugx("spawned listener %s on PID %d", buf, getpid()); return 0; } #endif @@ -420,15 +432,14 @@ ps_inet_recvin6nd(void *arg) { struct ps_process *psp = arg; - if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd, + if (ps_recvmsg(psp->psp_work_fd, PS_ND, psp->psp_ctx->ps_data_fd) == -1) logerr(__func__); } static int -ps_inet_listennd(void *arg) +ps_inet_listennd(struct ps_process *psp) { - struct ps_process *psp = arg; setproctitle("[ND network proxy]"); @@ -451,32 +462,29 @@ ps_inet_listennd(void *arg) logerr(__func__); return -1; } - - logdebugx("spawned ND listener on PID %d", getpid()); return 0; } #endif #ifdef DHCP6 static void -ps_inet_recvin6dhcp6(void *arg) +ps_inet_recvin6dhcp6(void *arg, unsigned short events) { struct ps_process *psp = arg; - if (ps_recvmsg(psp->psp_ctx, psp->psp_work_fd, + if (ps_recvmsg(psp->psp_work_fd, events, PS_DHCP6, psp->psp_ctx->ps_data_fd) == -1) logerr(__func__); } static int -ps_inet_listenin6(void *arg) +ps_inet_listenin6(struct ps_process *psp) { - struct ps_process *psp = arg; struct in6_addr *ia = &psp->psp_id.psi_addr.psa_in6_addr; char buf[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, ia, buf, sizeof(buf)); - setproctitle("[network proxy] %s", buf); + setproctitle("[%s proxy] %s", psp->psp_protostr, buf); psp->psp_work_fd = dhcp6_openudp(psp->psp_id.psi_ifindex, ia); if (psp->psp_work_fd == -1) { @@ -491,25 +499,23 @@ ps_inet_listenin6(void *arg) } #endif - if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, + if (eloop_event_add(psp->psp_ctx->eloop, psp->psp_work_fd, ELE_READ, ps_inet_recvin6dhcp6, psp) == -1) { logerr("%s: eloop_event_add DHCP", __func__); return -1; } - - logdebugx("spawned listener %s on PID %d", buf, getpid()); return 0; } #endif static void -ps_inet_recvmsgpsp(void *arg) +ps_inet_recvmsgpsp(void *arg, unsigned short events) { struct ps_process *psp = arg; /* Receive shutdown. */ - if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, NULL, NULL) == -1) + if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, events, NULL, NULL) == -1) logerr(__func__); } @@ -518,8 +524,11 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) { uint16_t cmd; struct ps_process *psp; - int (*start_func)(void *); + int (*start_func)(struct ps_process *); pid_t start; + struct ps_addr *psa = &psm->ps_id.psi_addr; + void *ia; + char buf[INET_MAX_ADDRSTRLEN]; cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP)); if (cmd == psm->ps_cmd) @@ -536,21 +545,40 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) return 0; } + if (!(psm->ps_cmd & PS_START)) { + errno = EINVAL; + return -1; + } + + if (psp != NULL) + return 1; + + psp = ps_newprocess(ctx, &psm->ps_id); + if (psp == NULL) + return -1; + + switch (cmd) { #ifdef INET case PS_BOOTP: start_func = ps_inet_listenin; + psp->psp_protostr = "BOOTP"; + ia = &psa->psa_in_addr; break; #endif #ifdef INET6 #ifdef __sun case PS_ND: start_func = ps_inet_listennd; + psp->psp_protostr = "ND"; + ia = &psa->psa_in6_addr; break; #endif #ifdef DHCP6 case PS_DHCP6: start_func = ps_inet_listenin6; + psp->psp_protostr = "DHCP6"; + ia = &psa->psa_in6_addr; break; #endif #endif @@ -560,23 +588,11 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) return -1; } - if (!(psm->ps_cmd & PS_START)) { - errno = EINVAL; - return -1; - } - - if (psp != NULL) - return 1; - - psp = ps_newprocess(ctx, &psm->ps_id); - if (psp == NULL) - return -1; - - start = ps_dostart(ctx, - &psp->psp_pid, &psp->psp_fd, - ps_inet_recvmsgpsp, NULL, psp, - start_func, NULL, - PSF_DROPPRIVS); + snprintf(psp->psp_name, sizeof(psp->psp_name), + "%s proxy %s", psp->psp_protostr, + inet_ntop(psa->psa_family, ia, buf, sizeof(buf))); + start = ps_startprocess(psp, ps_inet_recvmsgpsp, NULL, + start_func, NULL, PSF_DROPPRIVS); switch (start) { case -1: ps_freeprocess(psp); @@ -585,6 +601,8 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) ps_entersandbox("stdio", NULL); break; default: + logdebugx("%s: spawned %s on PID %d", + psp->psp_ifname, psp->psp_name, psp->psp_pid); break; } return start; @@ -601,11 +619,12 @@ ps_inet_in_docmd(struct ipv4_addr *ia, uint16_t cmd, const struct msghdr *msg) .ps_id = { .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), .psi_ifindex = ia->iface->index, + .psi_addr.psa_family = AF_INET, .psi_addr.psa_in_addr = ia->addr, }, }; - return ps_sendpsmmsg(ctx, ctx->ps_root_fd, &psm, msg); + return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg); } ssize_t @@ -625,8 +644,9 @@ ps_inet_closebootp(struct ipv4_addr *ia) ssize_t ps_inet_sendbootp(struct interface *ifp, const struct msghdr *msg) { + struct dhcpcd_ctx *ctx = ifp->ctx; - return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_BOOTP, 0, msg); + return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_BOOTP, 0, msg); } #endif /* INET */ @@ -641,10 +661,11 @@ ps_inet_ifp_docmd(struct interface *ifp, uint16_t cmd, const struct msghdr *msg) .ps_id = { .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), .psi_ifindex = ifp->index, + .psi_addr.psa_family = AF_INET6, }, }; - return ps_sendpsmmsg(ctx, ctx->ps_root_fd, &psm, msg); + return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg); } ssize_t @@ -671,8 +692,9 @@ ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg) ssize_t ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg) { + struct dhcpcd_ctx *ctx = ifp->ctx; - return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_ND, 0, msg); + return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_ND, 0, msg); } #endif @@ -686,11 +708,12 @@ ps_inet_in6_docmd(struct ipv6_addr *ia, uint16_t cmd, const struct msghdr *msg) .ps_id = { .psi_cmd = (uint8_t)(cmd & ~(PS_START | PS_STOP)), .psi_ifindex = ia->iface->index, + .psi_addr.psa_family = AF_INET6, .psi_addr.psa_in6_addr = ia->addr, }, }; - return ps_sendpsmmsg(ctx, ctx->ps_root_fd, &psm, msg); + return ps_sendpsmmsg(ctx, PS_ROOT_FD(ctx), &psm, msg); } ssize_t @@ -710,8 +733,9 @@ ps_inet_closedhcp6(struct ipv6_addr *ia) ssize_t ps_inet_senddhcp6(struct interface *ifp, const struct msghdr *msg) { + struct dhcpcd_ctx *ctx = ifp->ctx; - return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_DHCP6, 0, msg); + return ps_sendmsg(ctx, PS_ROOT_FD(ctx), PS_DHCP6, 0, msg); } #endif /* DHCP6 */ #endif /* INET6 */ |