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

Reply via email to