From f9631f1553deb3c66a714987864949b7405ee583 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 10 Dec 2017 10:07:54 +0000 Subject: [PATCH] Move privileged initialization from frontend to main process. Needed for future work where we will spin up children via fork - privdrop - exec. Child processes will no longer come up with root privileges. --- sbin/slaacd/control.c | 6 +-- sbin/slaacd/frontend.c | 95 +++++++++++++++++++----------------------- sbin/slaacd/frontend.h | 4 +- sbin/slaacd/slaacd.c | 87 ++++++++++++++++++++++++++++++-------- sbin/slaacd/slaacd.h | 7 ++-- 5 files changed, 122 insertions(+), 77 deletions(-) diff --git a/sbin/slaacd/control.c b/sbin/slaacd/control.c index 76b0f3b15ea..6fd83bbc80a 100644 --- a/sbin/slaacd/control.c +++ b/sbin/slaacd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.1 2017/06/03 10:00:29 florian Exp $ */ +/* $OpenBSD: control.c,v 1.2 2017/12/10 10:07:54 florian Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -85,9 +85,7 @@ control_init(char *path) return (-1); } - control_state.fd = fd; - - return (0); + return (fd); } int diff --git a/sbin/slaacd/frontend.c b/sbin/slaacd/frontend.c index 8998e3d2785..3a193e2a00f 100644 --- a/sbin/slaacd/frontend.c +++ b/sbin/slaacd/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.9 2017/11/04 17:23:05 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.10 2017/12/10 10:07:54 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -84,7 +84,7 @@ struct nd_router_solicit rs; struct nd_opt_hdr nd_opt_hdr; struct ether_addr nd_opt_source_link_addr; struct sockaddr_in6 dst; -int icmp6sock, routesock, ioctlsock; +int icmp6sock = -1, ioctlsock; struct icmp6_ev { struct event ev; @@ -112,24 +112,21 @@ frontend_sig_handler(int sig, short event, void *bula) } void -frontend(int debug, int verbose, char *sockname) +frontend(int debug, int verbose) { struct event ev_sigint, ev_sigterm; struct passwd *pw; - struct icmp6_filter filt; struct in6_pktinfo *pi; struct cmsghdr *cm; size_t rcvcmsglen, sndcmsglen; - int hoplimit = 255, on = 1, rtfilter; + int hoplimit = 255; uint8_t *rcvcmsgbuf, *sndcmsgbuf; log_init(debug, LOG_DAEMON); log_setverbose(verbose); #ifndef SMALL - /* Create slaacd control socket outside chroot. */ - if (control_init(sockname) == -1) - fatalx("control socket setup failed"); + control_state.fd = -1; #endif /* SMALL */ if ((pw = getpwnam(SLAACD_USER)) == NULL) @@ -144,12 +141,6 @@ frontend(int debug, int verbose, char *sockname) setproctitle("%s", log_procnames[slaacd_process]); log_procinit(log_procnames[slaacd_process]); - if ((icmp6sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) - fatal("ICMPv6 socket"); - - if ((routesock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) - fatal("route socket"); - if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) fatal("socket"); @@ -158,27 +149,6 @@ frontend(int debug, int verbose, char *sockname) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("can't drop privileges"); - if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, - sizeof(on)) < 0) - fatal("IPV6_RECVPKTINFO"); - - if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, - sizeof(on)) < 0) - fatal("IPV6_RECVHOPLIMIT"); - - /* only router advertisements */ - ICMP6_FILTER_SETBLOCKALL(&filt); - ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); - if (setsockopt(icmp6sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, - sizeof(filt)) == -1) - fatal("ICMP6_FILTER"); - - rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | - ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_PROPOSAL); - if (setsockopt(routesock, PF_ROUTE, ROUTE_MSGFILTER, - &rtfilter, sizeof(rtfilter)) < 0) - fatal("setsockopt(ROUTE_MSGFILTER)"); - if (pledge("stdio inet recvfd route", NULL) == -1) fatal("pledge"); @@ -202,18 +172,6 @@ frontend(int debug, int verbose, char *sockname) iev_main->handler, iev_main); event_add(&iev_main->ev, NULL); -#ifndef SMALL - /* Listen on control socket. */ - TAILQ_INIT(&ctl_conns); - control_listen(); -#endif /* SMALL */ - - event_set(&ev_route, routesock, EV_READ | EV_PERSIST, route_receive, - NULL); - - event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST, icmp6_receive, - NULL); - rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) @@ -369,12 +327,38 @@ frontend_dispatch_main(int fd, short event, void *bula) event_set(&iev_engine->ev, iev_engine->ibuf.fd, iev_engine->events, iev_engine->handler, iev_engine); event_add(&iev_engine->ev, NULL); - - if (pledge("stdio inet route", NULL) == -1) - fatal("pledge"); - + break; + case IMSG_ICMP6SOCK: + if ((icmp6sock = imsg.fd) == -1) + fatalx("%s: expected to receive imsg " + "ICMPv6 fd but didn't receive any", + __func__); + event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST, + icmp6_receive, NULL); + break; + case IMSG_ROUTESOCK: + if ((fd = imsg.fd) == -1) + fatalx("%s: expected to receive imsg " + "routesocket fd but didn't receive any", + __func__); + event_set(&ev_route, fd, EV_READ | EV_PERSIST, + route_receive, NULL); + break; +#ifndef SMALL + case IMSG_CONTROLFD: + if ((fd = imsg.fd) == -1) + fatalx("%s: expected to receive imsg " + "control fd but didn't receive any", + __func__); + control_state.fd = fd; + /* Listen on control socket. */ + TAILQ_INIT(&ctl_conns); + control_listen(); +#endif /* SMALL */ break; case IMSG_STARTUP: + if (pledge("stdio inet route", NULL) == -1) + fatal("pledge"); frontend_startup(); break; #ifndef SMALL @@ -616,7 +600,16 @@ frontend_startup(void) { struct if_nameindex *ifnidxp, *ifnidx; + if (!event_initialized(&ev_route)) + fatalx("%s: did not receive a route socket from the main " + "process", __func__); + event_add(&ev_route, NULL); + + if (!event_initialized(&icmp6ev.ev)) + fatalx("%s: did not receive a icmp6 socket fd from the main " + "process", __func__); + event_add(&icmp6ev.ev, NULL); if ((ifnidxp = if_nameindex()) == NULL) diff --git a/sbin/slaacd/frontend.h b/sbin/slaacd/frontend.h index 531d720f8d4..061f5423a60 100644 --- a/sbin/slaacd/frontend.h +++ b/sbin/slaacd/frontend.h @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.h,v 1.2 2017/07/06 15:02:53 florian Exp $ */ +/* $OpenBSD: frontend.h,v 1.3 2017/12/10 10:07:54 florian Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby @@ -20,7 +20,7 @@ TAILQ_HEAD(ctl_conns, ctl_conn) ctl_conns; #endif /* SMALL */ -void frontend(int, int, char *); +void frontend(int, int); void frontend_dispatch_main(int, short, void *); void frontend_dispatch_engine(int, short, void *); int frontend_imsg_compose_main(int, pid_t, void *, uint16_t); diff --git a/sbin/slaacd/slaacd.c b/sbin/slaacd/slaacd.c index 02c801161ea..88dc4ec70f6 100644 --- a/sbin/slaacd/slaacd.c +++ b/sbin/slaacd/slaacd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacd.c,v 1.12 2017/11/03 12:28:41 florian Exp $ */ +/* $OpenBSD: slaacd.c,v 1.13 2017/12/10 10:07:54 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,9 @@ const char* imsg_type_name[] = { "IMSG_UPDATE_ADDRESS", "IMSG_CTL_SEND_SOLICITATION", "IMSG_SOCKET_IPC", + "IMSG_ICMP6SOCK", + "IMSG_ROUTESOCK", + "IMSG_CONTROLFD", "IMSG_STARTUP", "IMSG_UPDATE_IF", "IMSG_REMOVE_IF", @@ -87,7 +91,7 @@ __dead void main_shutdown(void); void main_sig_handler(int, short, void *); -static pid_t start_child(int, char *, int, int, int, char *); +static pid_t start_child(int, char *, int, int, int); void main_dispatch_frontend(int, short, void *); void main_dispatch_engine(int, short, void *); @@ -98,6 +102,9 @@ void add_gateway(struct imsg_configure_dfr *); void delete_gateway(struct imsg_configure_dfr *); static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); +int main_imsg_compose_frontend(int, pid_t, void *, uint16_t); +int main_imsg_compose_frontend_fd(int, pid_t, int); +int main_imsg_compose_engine(int, pid_t, void *, uint16_t); struct imsgev *iev_frontend; struct imsgev *iev_engine; @@ -144,13 +151,17 @@ usage(void) int main(int argc, char *argv[]) { - struct event ev_sigint, ev_sigterm, ev_sighup; - int ch; - int debug = 0, engine_flag = 0, frontend_flag = 0; - int verbose = 0; - char *saved_argv0; - int pipe_main2frontend[2]; - int pipe_main2engine[2]; + struct event ev_sigint, ev_sigterm, ev_sighup; + struct icmp6_filter filt; + int ch; + int debug = 0, engine_flag = 0, frontend_flag = 0; + int verbose = 0; + char *saved_argv0; + int pipe_main2frontend[2]; + int pipe_main2engine[2]; + int icmp6sock, on = 1; + int frontend_routesock, rtfilter; + int control_fd; csock = SLAACD_SOCKET; @@ -191,7 +202,7 @@ main(int argc, char *argv[]) if (engine_flag) engine(debug, verbose); else if (frontend_flag) - frontend(debug, verbose, csock); + frontend(debug, verbose); /* Check for root privileges. */ if (geteuid()) @@ -218,9 +229,9 @@ main(int argc, char *argv[]) /* Start children. */ engine_pid = start_child(PROC_ENGINE, saved_argv0, pipe_main2engine[1], - debug, verbose, NULL); + debug, verbose); frontend_pid = start_child(PROC_FRONTEND, saved_argv0, - pipe_main2frontend[1], debug, verbose, csock); + pipe_main2frontend[1], debug, verbose); slaacd_process = PROC_MAIN; @@ -274,6 +285,42 @@ BROKEN if (pledge("rpath stdio sendfd cpath", NULL) == -1) fatal("pledge"); #endif + if ((icmp6sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) + fatal("ICMPv6 socket"); + + if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, + sizeof(on)) < 0) + fatal("IPV6_RECVPKTINFO"); + + if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, + sizeof(on)) < 0) + fatal("IPV6_RECVHOPLIMIT"); + + /* only router advertisements */ + ICMP6_FILTER_SETBLOCKALL(&filt); + ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); + if (setsockopt(icmp6sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, + sizeof(filt)) == -1) + fatal("ICMP6_FILTER"); + + main_imsg_compose_frontend_fd(IMSG_ICMP6SOCK, 0, icmp6sock); + + if ((frontend_routesock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) + fatal("route socket"); + + rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | + ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_PROPOSAL); + if (setsockopt(frontend_routesock, PF_ROUTE, ROUTE_MSGFILTER, + &rtfilter, sizeof(rtfilter)) < 0) + fatal("setsockopt(ROUTE_MSGFILTER)"); + + main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); + + if ((control_fd = control_init(csock)) == -1) + fatalx("control socket setup failed"); + + main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); + main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); event_dispatch(); @@ -318,7 +365,7 @@ main_shutdown(void) } static pid_t -start_child(int p, char *argv0, int fd, int debug, int verbose, char *sockname) +start_child(int p, char *argv0, int fd, int debug, int verbose) { char *argv[8]; int argc = 0; @@ -354,10 +401,6 @@ start_child(int p, char *argv0, int fd, int debug, int verbose, char *sockname) argv[argc++] = "-v"; if (verbose > 1) argv[argc++] = "-v"; - if (sockname) { - argv[argc++] = "-s"; - argv[argc++] = sockname; - } argv[argc++] = NULL; execvp(argv0, argv); @@ -530,6 +573,16 @@ main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) return (-1); } +int +main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) +{ + if (iev_frontend) + return (imsg_compose_event(iev_frontend, type, 0, pid, fd, + NULL, 0)); + else + return (-1); +} + int main_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen) { diff --git a/sbin/slaacd/slaacd.h b/sbin/slaacd/slaacd.h index d32270a1e03..9e2fe0fc5b8 100644 --- a/sbin/slaacd/slaacd.h +++ b/sbin/slaacd/slaacd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacd.h,v 1.10 2017/08/23 15:49:08 florian Exp $ */ +/* $OpenBSD: slaacd.h,v 1.11 2017/12/10 10:07:54 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -55,6 +55,9 @@ enum imsg_type { #endif /* SMALL */ IMSG_CTL_SEND_SOLICITATION, IMSG_SOCKET_IPC, + IMSG_ICMP6SOCK, + IMSG_ROUTESOCK, + IMSG_CONTROLFD, IMSG_STARTUP, IMSG_UPDATE_IF, IMSG_REMOVE_IF, @@ -189,8 +192,6 @@ struct imsg_ra { }; /* slaacd.c */ -int main_imsg_compose_frontend(int, pid_t, void *, uint16_t); -int main_imsg_compose_engine(int, pid_t, void *, uint16_t); void imsg_event_add(struct imsgev *); int imsg_compose_event(struct imsgev *, uint16_t, uint32_t, pid_t, int, void *, uint16_t); -- 2.20.1