Mercurial > hg > dhcpcd
changeset 5331:d075e31eb148 draft
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.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Tue, 09 Jun 2020 22:39:05 +0100 |
| parents | 7b6f2daea002 |
| children | b22045bba8b9 |
| files | src/dhcpcd.c src/eloop.c src/eloop.h src/privsep-control.c src/privsep-control.h src/privsep-root.h src/privsep.c src/privsep.h |
| diffstat | 8 files changed, 68 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dhcpcd.c Tue Jun 09 20:36:22 2020 +0100 +++ b/src/dhcpcd.c Tue Jun 09 22:39:05 2020 +0100 @@ -2321,6 +2321,10 @@ 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 @@ 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__);
--- a/src/eloop.c Tue Jun 09 20:36:22 2020 +0100 +++ b/src/eloop.c Tue Jun 09 22:39:05 2020 +0100 @@ -297,6 +297,13 @@ } } +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,
--- a/src/eloop.h Tue Jun 09 20:36:22 2020 +0100 +++ b/src/eloop.h Tue Jun 09 22:39:05 2020 +0100 @@ -54,6 +54,7 @@ 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 *);
--- a/src/privsep-control.c Tue Jun 09 20:36:22 2020 +0100 +++ b/src/privsep-control.c Tue Jun 09 22:39:05 2020 +0100 @@ -26,8 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/resource.h> - #include <errno.h> #include <stdlib.h> #include <string.h> @@ -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) {
--- a/src/privsep-control.h Tue Jun 09 20:36:22 2020 +0100 +++ b/src/privsep-control.h Tue Jun 09 22:39:05 2020 +0100 @@ -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);
--- a/src/privsep-root.h Tue Jun 09 20:36:22 2020 +0100 +++ b/src/privsep-root.h Tue Jun 09 22:39:05 2020 +0100 @@ -64,7 +64,6 @@ #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
--- a/src/privsep.c Tue Jun 09 20:36:22 2020 +0100 +++ b/src/privsep.c Tue Jun 09 22:39:05 2020 +0100 @@ -39,6 +39,7 @@ * this in a script or something. */ +#include <sys/resource.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> @@ -128,11 +129,57 @@ 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; -#elif !defined(HAVE_CAPSIUM) && !defined(HAVE_PLEDGE) -#warning No sandbox support + } + +#ifdef RLIMIT_NPROC + /* Prohibit forks */ + if (setrlimit(RLIMIT_NPROC, &rzero) == -1) { + logerr("setrlimit RLIMIT_NPROC"); + return -1; + } +#endif #endif return 0;
--- a/src/privsep.h Tue Jun 09 20:36:22 2020 +0100 +++ b/src/privsep.h Tue Jun 09 22:39:05 2020 +0100 @@ -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
