Hi tech@ This is my first attempt at pledging dhcpd(8), right now I don't have time to go further, but this is a working diff I having seating at my tree I want to show you, although tomorrow I intend to get back at it.
Declare usage() as __dead since it never returns, hoist up sync_init() since it calls a setsockopt(2) for multicast not allowed (yet?) by pledge(2) so I (someone else?) can apply pledge ealier on and then finally if dhcpd(8) was NOT called with "-u" parameter (!udpsockmode) then request "inet" since this is a network daemon and therefore needs to perform network operations and "sendfd" to send a msg. For this last annotation I changed sendto(2) to sendmsg(2) in icmp.c so we don't have to give permissions to the daemon it doesn't need and it just sends an ICMP echo request (hey here is a DHCPOFFER) to the host that is requesting an IP address. Index: dhcpd.c =================================================================== RCS file: /cvs/src/usr.sbin/dhcpd/dhcpd.c,v retrieving revision 1.48 diff -u -p -u -r1.48 dhcpd.c --- dhcpd.c 10 Feb 2015 23:06:13 -0000 1.48 +++ dhcpd.c 1 Dec 2015 20:59:27 -0000 @@ -45,7 +45,7 @@ #include <err.h> #include <pwd.h> -void usage(void); +__dead void usage(void); time_t cur_time, last_scan; struct group root_group; @@ -187,16 +187,16 @@ main(int argc, char *argv[]) if (setrtable(rdomain) == -1) error("setrtable (%m)"); - if (udpsockmode) - udpsock_startup(udpaddr); - icmp_startup(1, lease_pinged); - if (syncsend || syncrecv) { syncfd = sync_init(sync_iface, sync_baddr, sync_port); if (syncfd == -1) err(1, "sync init"); } + if (udpsockmode) + udpsock_startup(udpaddr); + icmp_startup(1, lease_pinged); + if ((pw = getpwnam("_dhcp")) == NULL) error("user \"_dhcp\" not found"); @@ -236,6 +236,10 @@ main(int argc, char *argv[]) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) error("can't drop privileges: %m"); + if (!udpsockmode) + if (pledge("stdio inet sendfd", NULL) == -1) + err(1, "pledge"); + add_timeout(cur_time + 5, periodic_scan, NULL); dispatch(); @@ -243,7 +247,7 @@ main(int argc, char *argv[]) exit(0); } -void +__dead void usage(void) { extern char *__progname; Index: icmp.c =================================================================== RCS file: /cvs/src/usr.sbin/dhcpd/icmp.c,v retrieving revision 1.13 diff -u -p -u -r1.13 icmp.c --- icmp.c 25 Oct 2014 03:23:49 -0000 1.13 +++ icmp.c 1 Dec 2015 20:59:31 -0000 @@ -80,6 +80,8 @@ icmp_echorequest(struct iaddr *addr) { struct sockaddr_in to; struct icmp icmp; + struct msghdr msg; + struct iovec iov; int status; if (!icmp_protocol_initialized) @@ -97,11 +99,22 @@ icmp_echorequest(struct iaddr *addr) icmp.icmp_id = getpid() & 0xffff; icmp.icmp_cksum = wrapsum(checksum((unsigned char *)&icmp, - sizeof(icmp), 0)); + sizeof(icmp), 0)); + + iov.iov_base = &icmp; + iov.iov_len = sizeof(struct icmp); + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &to; + msg.msg_namelen = sizeof(to); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = 0; + msg.msg_controllen = 0; + msg.msg_flags = 0; /* Send the ICMP packet... */ - status = sendto(icmp_protocol_fd, &icmp, sizeof(icmp), 0, - (struct sockaddr *)&to, sizeof(to)); + status = sendmsg(icmp_protocol_fd, &msg, 0); if (status == -1) warning("icmp_echorequest %s: %m", inet_ntoa(to.sin_addr));