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));