Hello!
Any testers out there that could provide some feedback on this?
I tested it and didn't have any problems with any parameters, except UDP
that I don't have how to test it, although it kept running without
problems as well.
On 02/12/2015 12:14, Ricardo Mestre wrote:
> Hi tech@
>
> This is a revised version of pledging dhcpd(8) with earler pledging.
>
> Hoist up sync_init() due to a multicast setsockopt(2) (IP_MULTICAST_TTL) that
> pledge doesn't allow, also hoist up the daemon(3) section, getpwnam(3) and the
> check if arguments -A, -C or -L were used (pf table handling) since it calls
> 2 ioctl(2)'s that pledge pf doesn't allow.
>
> After this if !udpsockmode then apply the following annotations:
>
> "rpath":
> icmp_startup()->getprotobyname(3)->read /etc/protocols
> "inet":
> icmp_startup()->socket(2)
> "sendfd":
> for sendmsg(2) in ICMP echo request
> "proc/id"
> chroot(2) and privdrop section
>
> If in udpsockmode then the pledge needs to happen inside udpsock_startup()
> instead of main() since setsockopt(2) IP_RECVIF is not allowed by pledge.
> After
> that happens then apply the same pledge with the annotations above, although
> additionally this code path also needs "route" for ioctl(2) SIOCGIFADDR.
>
> Just before the main loop of the program then it can drop to "stdio inet route
> sendfd" if in udpsockmode or else just to "stdio inet sendfd".
>
> Any comments with this implementation? Specifically for the UDP code path
> since
> I don't have at the moment a way to test DHCPINFORM requests on non Ethernet
> packets?
>
> 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 2 Dec 2015 11:28:50 -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,22 +187,18 @@ 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 ((pw = getpwnam("_dhcp")) == NULL)
> - error("user \"_dhcp\" not found");
> -
> if (daemonize)
> daemon(0, 0);
>
> + if ((pw = getpwnam("_dhcp")) == NULL)
> + error("user \"_dhcp\" not found");
> +
> /* don't go near /dev/pf unless we actually intend to use it */
> if ((abandoned_tab != NULL) ||
> (changedmac_tab != NULL) ||
> @@ -227,6 +223,15 @@ main(int argc, char *argv[])
> }
> }
>
> + if (udpsockmode) {
> + udpsock_startup(udpaddr);
> + } else {
> + if (pledge("stdio rpath inet sendfd proc id", NULL) == -1)
> + err(1, "pledge");
> + }
> +
> + icmp_startup(1, lease_pinged);
> +
> if (chroot(_PATH_VAREMPTY) == -1)
> error("chroot %s: %m", _PATH_VAREMPTY);
> if (chdir("/") == -1)
> @@ -236,6 +241,14 @@ 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 route sendfd", NULL) == -1)
> + err(1, "pledge");
> + } else {
> + if (pledge("stdio inet sendfd", NULL) == -1)
> + err(1, "pledge");
> + }
> +
> add_timeout(cur_time + 5, periodic_scan, NULL);
> dispatch();
>
> @@ -243,7 +256,7 @@ main(int argc, char *argv[])
> exit(0);
> }
>
> -void
> +__dead void
> usage(void)
> {
> extern char *__progname;
> Index: udpsock.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/dhcpd/udpsock.c,v
> retrieving revision 1.2
> diff -u -p -u -r1.2 udpsock.c
> --- udpsock.c 16 Jan 2015 06:40:16 -0000 1.2
> +++ udpsock.c 2 Dec 2015 11:28:55 -0000
> @@ -56,6 +56,9 @@ udpsock_startup(struct in_addr bindaddr)
> error("setsocketopt IP_RECVIF failed for udp: %s",
> strerror(errno));
>
> + if (pledge("stdio rpath inet route sendfd proc id", NULL) == -1)
> + error("pledge: %s", strerror(errno));
> +
> sin4.sin_family = AF_INET;
> sin4.sin_len = sizeof(sin4);
> sin4.sin_addr = bindaddr;
>