From: Roy Marples Date: Fri, 12 Nov 2021 14:24:11 +0000 (+0000) Subject: privsep: Only set RLIMIT_NOFILES for supported platforms X-Git-Tag: v10.0.0~70 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43de9416e6a8484a911f4936198b121fba364c13;p=thirdparty%2Fdhcpcd.git privsep: Only set RLIMIT_NOFILES for supported platforms Basically only for NetBSD, DragonFlyBSD, kqueue or epoll platforms. All others will use poll(2) and return EINVAL if nfds > RLIMIT_NOFILES. Trying to work out our nfs limit relies on already listening to all FD's which may not be the case and was problematic. Luckily all platforms aside from Solaris have new file creation sandboxed away aside from accept(2) so this should still be safe. --- diff --git a/src/privsep.c b/src/privsep.c index 8b8e159a..f08b4028 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -145,35 +145,27 @@ ps_dropprivs(struct dhcpcd_ctx *ctx) struct rlimit rzero = { .rlim_cur = 0, .rlim_max = 0 }; + /* Prohibit new files, sockets, etc */ + /* + * If poll(2) is called with nfds>RLIMIT_NOFILE then it returns EINVAL. + * We don't know the final value of nfds at this point *easily*. + * Sadly, this is a POSIX limitation and most platforms adhere to it. + * However, some are not that strict and are whitelisted below. + * Also, if we're not using poll then we can be restrictive. + * + * For the non whitelisted platforms there should be a sandbox to + * fallback to where we don't allow new files, etc: + * Linux:seccomp, FreeBSD:capsicum, OpenBSD:pledge + * Solaris users are sadly out of luck on both counts. + */ +#if defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(HAVE_KQUEUE) || defined(HAVE_EPOLL) + /* The control proxy *does* need to create new fd's via accept(2). */ if (ctx->ps_ctl == NULL || ctx->ps_ctl->psp_pid != getpid()) { - /* Prohibit new files, sockets, etc */ -#if (defined(__linux__) || defined(__sun) || defined(__OpenBSD__)) && \ - !defined(HAVE_KQUEUE) && !defined(HAVE_EPOLL) - /* - * If poll(2) is called with nfds > RLIMIT_NOFILE - * then it returns EINVAL. - * This blows. - * Do the best we can and limit to what we need. - * An attacker could potentially close a file and - * open a new one still, but that cannot be helped. - */ - unsigned long maxfd; - maxfd = (unsigned long)eloop_event_count(ctx->eloop); - if (IN_PRIVSEP_SE(ctx)) - maxfd++; /* why? */ - - struct rlimit rmaxfd = { - .rlim_cur = maxfd, - .rlim_max = maxfd - }; - - if (setrlimit(RLIMIT_NOFILE, &rmaxfd) == -1) - logerr("setrlimit RLIMIT_NOFILE"); -#else if (setrlimit(RLIMIT_NOFILE, &rzero) == -1) logerr("setrlimit RLIMIT_NOFILE"); -#endif } +#endif #define DHC_NOCHKIO (DHCPCD_STARTED | DHCPCD_DAEMONISE) /* Prohibit writing to files.