summaryrefslogtreecommitdiffstats
path: root/src/privsep.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-06-09 22:39:05 +0100
committerRoy Marples <roy@marples.name>2020-06-09 22:39:05 +0100
commitd196c8b662de184e1e79600b16eb53498517ea1f (patch)
tree37ec3cade59bf03e850606123b3e5cbfd343a7d3 /src/privsep.c
parent6b6a7cb1d0700ca404f58854e477aa00d64e97f9 (diff)
downloaddhcpcd-d196c8b662de184e1e79600b16eb53498517ea1f.tar.xz
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.
Diffstat (limited to 'src/privsep.c')
-rw-r--r--src/privsep.c55
1 files changed, 51 insertions, 4 deletions
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 <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;