]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: For Linux and Solaris, set RLIMIT_NOFILES to nevents
authorRoy Marples <roy@marples.name>
Tue, 9 Jun 2020 21:39:05 +0000 (22:39 +0100)
committerRoy Marples <roy@marples.name>
Tue, 9 Jun 2020 21:39:05 +0000 (22:39 +0100)
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.

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

index 234761c69da240df5d465d65209b06a30416e754..0ccfe8ac016f7abeee88d79e98d2c3503f2ada90 100644 (file)
@@ -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__);
index ae63241eb6b986b3330aa7ee59e9ed5161a42253..6579a20c6db5ce9e6bc1ea93acde2813cb3f8d06 100644 (file)
@@ -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,
index 9001c1b7840e8b2b99da88d85ee37cb7229293be..c7d81e348d83dbbaa4e1326fac8edb1ae0e7fa72 100644 (file)
@@ -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 *);
index 114603a9de74547b75a4672914660794f53eee2a..bd74198e20cc1c6174c1c032775206f44c13d24f 100644 (file)
@@ -26,8 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/resource.h>
-
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #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)
 {
index 7f0e473a7803080f77e38cd0f2ed00516eaea492..3d9522adf092c5469cb9cec923e98b846dfca7c4 100644 (file)
@@ -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);
index 1de284bf24cd86daff27474d9cbb68a6ae76dc75..5d6e1248bf15437aa686441699b038d3b91c17e7 100644 (file)
@@ -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
index a4b03fde255f7ef5f8f37c1b9664bcb63c4017c1..c93f00b09678a327c1a51423c991a046fe6d8877 100644 (file)
@@ -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 @@ 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;
index 7428adc786d1392cb75c4f886bfe0af232861c0e..2bc9bac344b0e10b5978444a8683639ce072698a 100644 (file)
@@ -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