From: Roy Marples Date: Tue, 9 Jun 2020 21:39:05 +0000 (+0100) Subject: privsep: For Linux and Solaris, set RLIMIT_NOFILES to nevents X-Git-Tag: v9.1.2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d196c8b662de184e1e79600b16eb53498517ea1f;p=thirdparty%2Fdhcpcd.git privsep: For Linux and Solaris, set RLIMIT_NOFILES to nevents Because poll(2) returns EINVAL if nfds is higher. This really blows chunks, but it is what it is. An attacker could close a fd and open something else, but it's the best we can do. --- diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 234761c6..0ccfe8ac 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -2321,6 +2321,10 @@ printpidfile: if (dhcp_vendor(ctx.vendor, sizeof(ctx.vendor)) == -1) logerrx("dhcp_vendor"); + /* Start handling kernel messages for interfaces, addresses and + * routes. */ + eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx); + #ifdef PRIVSEP if (IN_PRIVSEP(&ctx) && ps_mastersandbox(&ctx) == -1) goto exit_failure; @@ -2331,10 +2335,6 @@ printpidfile: if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND)) ctx.options |= DHCPCD_WAITIP; - /* Start handling kernel messages for interfaces, addresses and - * routes. */ - eloop_event_add(ctx.eloop, ctx.link_fd, dhcpcd_handlelink, &ctx); - ctx.ifaces = if_discover(&ctx, &ifaddrs, ctx.ifc, ctx.ifv); if (ctx.ifaces == NULL) { logerr("%s: if_discover", __func__); diff --git a/src/eloop.c b/src/eloop.c index ae63241e..6579a20c 100644 --- a/src/eloop.c +++ b/src/eloop.c @@ -297,6 +297,13 @@ eloop_event_setup_fds(struct eloop *eloop) } } +size_t +eloop_event_count(const struct eloop *eloop) +{ + + return eloop->nevents; +} + int eloop_event_add_rw(struct eloop *eloop, int fd, void (*read_cb)(void *), void *read_cb_arg, diff --git a/src/eloop.h b/src/eloop.h index 9001c1b7..c7d81e34 100644 --- a/src/eloop.h +++ b/src/eloop.h @@ -54,6 +54,7 @@ struct eloop; unsigned long long eloop_timespec_diff(const struct timespec *tsp, const struct timespec *usp, unsigned int *nsp); +size_t eloop_event_count(const struct eloop *); int eloop_event_add_rw(struct eloop *, int, void (*)(void *), void *, void (*)(void *), void *); diff --git a/src/privsep-control.c b/src/privsep-control.c index 114603a9..bd74198e 100644 --- a/src/privsep-control.c +++ b/src/privsep-control.c @@ -26,8 +26,6 @@ * SUCH DAMAGE. */ -#include - #include #include #include @@ -38,34 +36,6 @@ #include "logerr.h" #include "privsep.h" -int -ps_ctl_limitresources(struct dhcpcd_ctx *ctx) -{ - struct rlimit rzero = { .rlim_cur = 0, .rlim_max = 0 }; - - if (ctx->ps_control_pid != getpid()) { - /* Prohibit new files, sockets, etc */ - if (setrlimit(RLIMIT_NOFILE, &rzero) == -1) { - logerr("setrlimit RLIMIT_NOFILE"); - return -1; - } - } - - /* Prohibit large files */ - if (setrlimit(RLIMIT_FSIZE, &rzero) == -1) { - logerr("setrlimit RLIMIT_FSIZE"); - return -1; - } - - /* Prohibit forks */ - if (setrlimit(RLIMIT_NPROC, &rzero) == -1) { - logerr("setrlimit RLIMIT_NPROC"); - return -1; - } - - return 0; -} - static int ps_ctl_startcb(void *arg) { diff --git a/src/privsep-control.h b/src/privsep-control.h index 7f0e473a..3d9522ad 100644 --- a/src/privsep-control.h +++ b/src/privsep-control.h @@ -32,7 +32,6 @@ #define IN_PRIVSEP_CONTROLLER(ctx) \ (IN_PRIVSEP((ctx)) && (ctx)->ps_control_pid == getpid()) -int ps_ctl_limitresources(struct dhcpcd_ctx *); pid_t ps_ctl_start(struct dhcpcd_ctx *); int ps_ctl_stop(struct dhcpcd_ctx *); ssize_t ps_ctl_handleargs(struct fd_list *, char *, size_t); diff --git a/src/privsep-root.h b/src/privsep-root.h index 1de284bf..5d6e1248 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -64,7 +64,6 @@ ssize_t ps_root_ifignoregroup(struct dhcpcd_ctx *, const char *); #endif #ifdef __linux__ ssize_t ps_root_sendnetlink(struct dhcpcd_ctx *, int, struct msghdr *); -ssize_t ps_root_writepathuint(struct dhcpcd_ctx *, const char *, unsigned int); #endif #ifdef PLUGIN_DEV diff --git a/src/privsep.c b/src/privsep.c index a4b03fde..c93f00b0 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -39,6 +39,7 @@ * this in a script or something. */ +#include #include #include #include @@ -128,11 +129,57 @@ ps_dropprivs(struct dhcpcd_ctx *ctx) return -1; } -#ifdef PRIVSEP_CONTROLLER - if (ps_ctl_limitresources(ctx) == -1) + struct rlimit rzero = { .rlim_cur = 0, .rlim_max = 0 }; + +#if defined(HAVE_CAPSICUM) || defined(HAVE_PLEDGE) + /* These sandbox technologies do not work well with + * resource limits. */ +#else + if (ctx->ps_control_pid != getpid()) { + /* Prohibit new files, sockets, etc */ +#if defined(__linux__) || defined(__sun) + /* + * 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++; /* XXX why? */ + + struct rlimit rmaxfd = { + .rlim_cur = (unsigned long)maxfd, + .rlim_max = (unsigned long)maxfd + }; + if (setrlimit(RLIMIT_NOFILE, &rmaxfd) == -1) { + logerr("setrlimit RLIMIT_NOFILE"); + return -1; + } +#else + if (setrlimit(RLIMIT_NOFILE, &rzero) == -1) { + logerr("setrlimit RLIMIT_NOFILE"); + return -1; + } +#endif + } + + /* Prohibit large files */ + if (setrlimit(RLIMIT_FSIZE, &rzero) == -1) { + logerr("setrlimit RLIMIT_FSIZE"); + return -1; + } + +#ifdef RLIMIT_NPROC + /* Prohibit forks */ + if (setrlimit(RLIMIT_NPROC, &rzero) == -1) { + logerr("setrlimit RLIMIT_NPROC"); return -1; -#elif !defined(HAVE_CAPSIUM) && !defined(HAVE_PLEDGE) -#warning No sandbox support + } +#endif #endif return 0; diff --git a/src/privsep.h b/src/privsep.h index 7428adc7..2bc9bac3 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -62,9 +62,9 @@ #define PS_IFIGNOREGRP 0x0106 /* Dev Commands */ -#define PS_DEV_LISTENING 0x0201 -#define PS_DEV_INITTED 0x0202 -#define PS_DEV_IFCMD 0x0203 +#define PS_DEV_LISTENING 0x1001 +#define PS_DEV_INITTED 0x1002 +#define PS_DEV_IFCMD 0x1003 /* Dev Interface Commands (via flags) */ #define PS_DEV_IFADDED 0x0001 @@ -72,8 +72,8 @@ #define PS_DEV_IFUPDATED 0x0003 /* Control Type (via flags) */ -#define PS_CTL_PRIV 0x0301 -#define PS_CTL_UNPRIV 0x0302 +#define PS_CTL_PRIV 0x0004 +#define PS_CTL_UNPRIV 0x0005 /* Process commands */ #define PS_START 0x4000