diff options
| author | Roy Marples <roy@marples.name> | 2020-05-19 16:19:05 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-05-19 16:19:05 +0100 |
| commit | c5445ce8235c153f4f184067ef58249f598d8629 (patch) | |
| tree | b16a5c64baf8b7e6ecfcf1f09cf38d13aa68ff09 /src/privsep-inet.c | |
| parent | d2fec927e001f2430bb8d5127403968f23b9c316 (diff) | |
| download | dhcpcd-c5445ce8235c153f4f184067ef58249f598d8629.tar.xz | |
privsep: Enable Capsicum for all processes.
Except for the priviledged process.
This is quite an in-depth change:
* ARP is now one process per address
* BPF flags are now returned via privsep
* BPF write filters are locked when supported
* The root process sends to the network
The last step is done by opening RAW sockets and then sending a UDP
header (where applicable) to avoid binding to an address
which is already in use by the reader sockets.
This is slightly wasteful for OS's without sandboxing but does
have the very nice side effect of not needing a source address
to unicast DHCPs replies from which makes the code smaller.
Diffstat (limited to 'src/privsep-inet.c')
| -rw-r--r-- | src/privsep-inet.c | 102 |
1 files changed, 42 insertions, 60 deletions
diff --git a/src/privsep-inet.c b/src/privsep-inet.c index 74cdf722..ee2be9d9 100644 --- a/src/privsep-inet.c +++ b/src/privsep-inet.c @@ -55,7 +55,7 @@ ps_inet_recvbootp(void *arg) { struct dhcpcd_ctx *ctx = arg; - if (ps_recvmsg(ctx, ctx->udp_fd, PS_BOOTP, ctx->ps_inet_fd) == -1) + if (ps_recvmsg(ctx, ctx->udp_rfd, PS_BOOTP, ctx->ps_inet_fd) == -1) logerr(__func__); } #endif @@ -86,7 +86,7 @@ ps_inet_recvdhcp6(void *arg) { struct dhcpcd_ctx *ctx = arg; - if (ps_recvmsg(ctx, ctx->dhcp6_fd, PS_DHCP6, ctx->ps_inet_fd) == -1) + if (ps_recvmsg(ctx, ctx->dhcp6_rfd, PS_DHCP6, ctx->ps_inet_fd) == -1) logerr(__func__); } #endif @@ -99,7 +99,7 @@ ps_inet_startcb(void *arg) #ifdef HAVE_CAPSICUM cap_rights_t rights; - cap_rights_init(&rights, CAP_RECV, CAP_CONNECT, CAP_SEND, CAP_EVENT); + cap_rights_init(&rights, CAP_RECV, CAP_EVENT); #endif if (ctx->options & DHCPCD_MASTER) @@ -120,31 +120,32 @@ ps_inet_startcb(void *arg) if ((ctx->options & (DHCPCD_IPV4 | DHCPCD_MASTER)) == (DHCPCD_IPV4 | DHCPCD_MASTER)) { - ctx->udp_fd = dhcp_openudp(NULL); - if (ctx->udp_fd == -1) + ctx->udp_rfd = dhcp_openudp(NULL); + if (ctx->udp_rfd == -1) logerr("%s: dhcp_open", __func__); #ifdef HAVE_CAPSICUM - else if (cap_rights_limit(ctx->udp_fd, &rights) == -1 + else if (cap_rights_limit(ctx->udp_rfd, &rights) == -1 && errno != ENOSYS) { logerr("%s: cap_rights_limit", __func__); - close(ctx->udp_fd); - ctx->udp_fd = -1; + close(ctx->udp_rfd); + ctx->udp_rfd = -1; } #endif - else if (eloop_event_add(ctx->eloop, ctx->udp_fd, + else if (eloop_event_add(ctx->eloop, ctx->udp_rfd, ps_inet_recvbootp, ctx) == -1) { logerr("%s: eloop_event_add DHCP", __func__); - close(ctx->udp_fd); - ctx->udp_fd = -1; + close(ctx->udp_rfd); + ctx->udp_rfd = -1; } else ret++; } #endif #if defined(INET6) && !defined(__sun) if (ctx->options & DHCPCD_IPV6) { - if (ipv6nd_open(ctx) == -1) + ctx->nd_fd = ipv6nd_open(true); + if (ctx->nd_fd == -1) logerr("%s: ipv6nd_open", __func__); #ifdef HAVE_CAPSICUM else if (cap_rights_limit(ctx->nd_fd, &rights) == -1 @@ -169,24 +170,24 @@ ps_inet_startcb(void *arg) if ((ctx->options & (DHCPCD_DHCP6 | DHCPCD_MASTER)) == (DHCPCD_DHCP6 | DHCPCD_MASTER)) { - ctx->dhcp6_fd = dhcp6_openudp(0, NULL); - if (ctx->dhcp6_fd == -1) + ctx->dhcp6_rfd = dhcp6_openudp(0, NULL); + if (ctx->dhcp6_rfd == -1) logerr("%s: dhcp6_open", __func__); #ifdef HAVE_CAPSICUM - else if (cap_rights_limit(ctx->dhcp6_fd, &rights) == -1 + else if (cap_rights_limit(ctx->dhcp6_rfd, &rights) == -1 && errno != ENOSYS) { logerr("%s: cap_rights_limit", __func__); - close(ctx->dhcp6_fd); - ctx->dhcp6_fd = -1; + close(ctx->dhcp6_rfd); + ctx->dhcp6_rfd = -1; } #endif - else if (eloop_event_add(ctx->eloop, ctx->dhcp6_fd, + else if (eloop_event_add(ctx->eloop, ctx->dhcp6_rfd, ps_inet_recvdhcp6, ctx) == -1) { logerr("%s: eloop_event_add DHCP6", __func__); - close(ctx->dhcp6_fd); - ctx->dhcp6_fd = -1; + close(ctx->dhcp6_rfd); + ctx->dhcp6_rfd = -1; } else ret++; } @@ -200,23 +201,22 @@ ps_inet_startcb(void *arg) } static ssize_t -ps_inet_recvmsg_cb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) +ps_inet_sendmsg(struct dhcpcd_ctx *ctx, + struct ps_msghdr *psm, struct msghdr *msg) { - struct dhcpcd_ctx *ctx = arg; struct ps_process *psp; int s; psp = ps_findprocess(ctx, &psm->ps_id); if (psp != NULL) { s = psp->psp_work_fd; - logerrx("psp found fd %d", s); goto dosend; } switch (psm->ps_cmd) { #ifdef INET case PS_BOOTP: - s = ctx->udp_fd; + s = ctx->udp_wfd; break; #endif #if defined(INET6) && !defined(__sun) @@ -226,7 +226,7 @@ ps_inet_recvmsg_cb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) #endif #ifdef DHCP6 case PS_DHCP6: - s = ctx->dhcp6_fd; + s = ctx->dhcp6_wfd; break; #endif default: @@ -235,17 +235,16 @@ ps_inet_recvmsg_cb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) } dosend: - return sendmsg(s, msg, 0); } -/* Receive from state engine, send message on wire. */ static void ps_inet_recvmsg(void *arg) { struct dhcpcd_ctx *ctx = arg; - if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, ps_inet_recvmsg_cb, ctx) == -1) + /* Receive shutdown */ + if (ps_recvpsmsg(ctx, ctx->ps_inet_fd, NULL, NULL) == -1) logerr(__func__); } @@ -310,11 +309,9 @@ ps_inet_start(struct dhcpcd_ctx *ctx) PSF_DROPPRIVS); #ifdef HAVE_CAPSICUM -#if 0 /* This breaks sendmsg() */ - if (cap_enter() == -1 && errno != ENOSYS) + if (pid == 0 && cap_enter() == -1 && errno != ENOSYS) logerr("%s: cap_enter", __func__); #endif -#endif #ifdef HAVE_PLEDGE if (pid == 0 && pledge("stdio inet", NULL) == -1) logerr("%s: pledge", __func__); @@ -350,7 +347,7 @@ ps_inet_listenin(void *arg) #ifdef HAVE_CAPSICUM cap_rights_t rights; - cap_rights_init(&rights, CAP_RECV, CAP_CONNECT, CAP_SEND, CAP_EVENT); + cap_rights_init(&rights, CAP_RECV, CAP_EVENT); #endif inet_ntop(AF_INET, ia, buf, sizeof(buf)); @@ -401,7 +398,7 @@ ps_inet_listennd(void *arg) #ifdef HAVE_CAPSICUM cap_rights_t rights; - cap_rights_init(&rights, CAP_RECV, CAP_CONNECT, CAP_SEND, CAP_EVENT); + cap_rights_init(&rights, CAP_RECV, CAP_EVENT); #endif setproctitle("[ND network proxy]"); @@ -453,7 +450,7 @@ ps_inet_listenin6(void *arg) #ifdef HAVE_CAPSICUM cap_rights_t rights; - cap_rights_init(&rights, CAP_RECV, CAP_CONNECT, CAP_SEND, CAP_EVENT); + cap_rights_init(&rights, CAP_RECV, CAP_EVENT); #endif inet_ntop(AF_INET6, ia, buf, sizeof(buf)); @@ -486,28 +483,18 @@ ps_inet_listenin6(void *arg) } #endif -static ssize_t -ps_inet_recvmsgpsp_cb(void *arg, __unused struct ps_msghdr *psm, - struct msghdr *msg) -{ - struct ps_process *psp = arg; - - return sendmsg(psp->psp_work_fd, msg, 0); -} - static void ps_inet_recvmsgpsp(void *arg) { struct ps_process *psp = arg; - if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, - ps_inet_recvmsgpsp_cb, psp) == -1) + /* Receive shutdown. */ + if (ps_recvpsmsg(psp->psp_ctx, psp->psp_fd, NULL, NULL) == -1) logerr(__func__); } ssize_t -ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, - __unused struct msghdr *msg) +ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) { uint16_t cmd; struct ps_process *psp; @@ -515,6 +502,9 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, pid_t start; cmd = (uint16_t)(psm->ps_cmd & ~(PS_START | PS_STOP)); + if (cmd == psm->ps_cmd) + return ps_inet_sendmsg(ctx, psm, msg); + psp = ps_findprocess(ctx, &psm->ps_id); #ifdef PRIVSEP_DEBUG @@ -573,11 +563,9 @@ ps_inet_cmd(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, return -1; case 0: #ifdef HAVE_CAPSICUM -#if 0 /* This breaks sendmsg() */ if (cap_enter() == -1 && errno != ENOSYS) logerr("%s: cap_enter", __func__); #endif -#endif #ifdef HAVE_PLEDGE if (pledge("stdio inet", NULL) == -1) logerr("%s: pledge", __func__); @@ -622,13 +610,10 @@ ps_inet_closebootp(struct ipv4_addr *ia) } ssize_t -ps_inet_sendbootp(struct ipv4_addr *ia, const struct msghdr *msg) +ps_inet_sendbootp(struct interface *ifp, const struct msghdr *msg) { - struct dhcpcd_ctx *ctx = ia->iface->ctx; - if (ctx->options & DHCPCD_MASTER) - return ps_sendmsg(ctx, ctx->ps_inet_fd, PS_BOOTP, 0, msg); - return ps_inet_in_docmd(ia, PS_BOOTP, msg); + return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_BOOTP, 0, msg); } #endif /* INET */ @@ -674,7 +659,7 @@ ssize_t ps_inet_sendnd(struct interface *ifp, const struct msghdr *msg) { - return ps_sendmsg(ifp->ctx, ifp->ctx->ps_inet_fd, PS_ND, 0, msg); + return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_ND, 0, msg); } #endif @@ -710,13 +695,10 @@ ps_inet_closedhcp6(struct ipv6_addr *ia) } ssize_t -ps_inet_senddhcp6(struct ipv6_addr *ia, const struct msghdr *msg) +ps_inet_senddhcp6(struct interface *ifp, const struct msghdr *msg) { - struct dhcpcd_ctx *ctx = ia->iface->ctx; - if (ctx->options & DHCPCD_MASTER) - return ps_sendmsg(ctx, ctx->ps_inet_fd, PS_DHCP6, 0, msg); - return ps_inet_in6_docmd(ia, PS_DHCP6, msg); + return ps_sendmsg(ifp->ctx, ifp->ctx->ps_root_fd, PS_DHCP6, 0, msg); } #endif /* DHCP6 */ #endif /* INET6 */ |
