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.
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;
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__);
}
}
+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,
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 *);
* 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)
{
#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);
#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
* this in a script or something.
*/
+#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
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;
#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
#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