From: Roy Marples Date: Fri, 5 Jun 2020 10:12:21 +0000 (+0100) Subject: privsep: Remove pledges inet and dns from the master process X-Git-Tag: v9.1.2~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=14af21e525d20018c73466f4c90afc3c4c2567fc;p=thirdparty%2Fdhcpcd.git privsep: Remove pledges inet and dns from the master process Achieved by adding IPC to ignore interfaces names based on the interface group. This means every process just pledges stdio for IPC which the exception of the master process which also pledges route so it can access the routing table. --- diff --git a/src/dhcpcd.c b/src/dhcpcd.c index 1363b3c7..dddf3281 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -2309,7 +2309,7 @@ printpidfile: } #endif #ifdef HAVE_PLEDGE - if (pledge("stdio inet route dns", NULL) == -1) { + if (pledge("stdio route", NULL) == -1) { logerr("%s: pledge", __func__); goto exit_failure; } diff --git a/src/if-bsd.c b/src/if-bsd.c index 78735c7b..495d9acb 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -292,21 +292,10 @@ if_ignore1(const char *drvname) return false; } -bool -if_ignore(struct dhcpcd_ctx *ctx, const char *ifname) -{ - struct if_spec spec; - - if (if_nametospec(ifname, &spec) != 0) - return false; - - if (if_ignore1(spec.drvname)) - return true; - #ifdef SIOCGIFGROUP -#ifdef HAVE_PLEDGE -#warning Fix SIOCGIFGROUP to use privsep to remove inet pledge requirement -#endif +int +if_ignoregroup(int s, const char *ifname) +{ struct ifgroupreq ifgr = { .ifgr_len = 0 }; struct ifg_req *ifg; size_t ifg_len; @@ -316,12 +305,12 @@ if_ignore(struct dhcpcd_ctx *ctx, const char *ifname) * will be very unlikely.... */ strlcpy(ifgr.ifgr_name, ifname, sizeof(ifgr.ifgr_name)); - if (ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1 || + if (ioctl(s, SIOCGIFGROUP, &ifgr) == -1 || (ifgr.ifgr_groups = malloc(ifgr.ifgr_len)) == NULL || - ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1) + ioctl(s, SIOCGIFGROUP, &ifgr) == -1) { logerr(__func__); - return false; + return -1; } for (ifg = ifgr.ifgr_groups, ifg_len = ifgr.ifgr_len; @@ -329,13 +318,35 @@ if_ignore(struct dhcpcd_ctx *ctx, const char *ifname) ifg++, ifg_len -= sizeof(*ifg)) { if (if_ignore1(ifg->ifgrq_group)) - return true; + return 1; } -#else - UNUSED(ctx); + return 0; +} #endif +bool +if_ignore(struct dhcpcd_ctx *ctx, const char *ifname) +{ + struct if_spec spec; + + if (if_nametospec(ifname, &spec) != 0) + return false; + + if (if_ignore1(spec.drvname)) + return true; + +#ifdef SIOCGIFGROUP +#if defined(PRIVSEP) && defined(HAVE_PLEDGE) + if (IN_PRIVSEP(ctx)) + return ps_root_ifignoregroup(ctx, ifname) == 1 ? true : false; +#endif + else + return if_ignoregroup(ctx->pf_inet_fd, ifname) == 1 ? + true : false; +#else + UNUSED(ctx); return false; +#endif } int diff --git a/src/if.h b/src/if.h index e644afc8..8abf079a 100644 --- a/src/if.h +++ b/src/if.h @@ -182,6 +182,7 @@ int if_nametospec(const char *, struct if_spec *); int if_conf(struct interface *); int if_init(struct interface *); int if_getssid(struct interface *); +int if_ignoregroup(int, const char *); bool if_ignore(struct dhcpcd_ctx *, const char *); int if_vimaster(struct dhcpcd_ctx *ctx, const char *); unsigned short if_vlanid(const struct interface *); diff --git a/src/privsep-bsd.c b/src/privsep-bsd.c index 28b74354..d09686d8 100644 --- a/src/privsep-bsd.c +++ b/src/privsep-bsd.c @@ -136,6 +136,24 @@ ps_root_doindirectioctl(unsigned long req, void *data, size_t len) return ps_root_doioctldom(PF_INET, req, &ifr, sizeof(ifr)); } + +static ssize_t +ps_root_doifignoregroup(void *data, size_t len) +{ + int s, err; + + if (len == 0 || ((const char *)data)[len - 1] != '\0') { + errno = EINVAL; + return -1; + } + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s == -1) + return -1; + err = if_ignoregroup(s, data); + close(s); + return err; +} #endif ssize_t @@ -160,6 +178,8 @@ ps_root_os(struct ps_msghdr *psm, struct msghdr *msg, case PS_IOCTLINDIRECT: err = ps_root_doindirectioctl(psm->ps_flags, data, len); break; + case PS_IFIGNOREGRP: + return ps_root_doifignoregroup(data, len); #endif default: errno = ENOTSUP; @@ -228,4 +248,14 @@ ps_root_indirectioctl(struct dhcpcd_ctx *ctx, unsigned long request, return -1; return ps_root_readerror(ctx, data, len); } + +ssize_t +ps_root_ifignoregroup(struct dhcpcd_ctx *ctx, const char *ifname) +{ + + if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_IFIGNOREGRP, 0, + ifname, strlen(ifname) + 1) == -1) + return -1; + return ps_root_readerror(ctx, NULL, 0); +} #endif diff --git a/src/privsep-root.h b/src/privsep-root.h index a8e34227..371431bf 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -54,6 +54,7 @@ ssize_t ps_root_ioctllink(struct dhcpcd_ctx *, unsigned long, void *, size_t); ssize_t ps_root_ioctl6(struct dhcpcd_ctx *, unsigned long, void *, size_t); ssize_t ps_root_indirectioctl(struct dhcpcd_ctx *, unsigned long, const char *, void *, size_t); +ssize_t ps_root_ifignoregroup(struct dhcpcd_ctx *, const char *); #endif #ifdef __linux__ ssize_t ps_root_sendnetlink(struct dhcpcd_ctx *, int, struct msghdr *); diff --git a/src/privsep.h b/src/privsep.h index f1fee41e..b22dfd9f 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -57,6 +57,7 @@ #define PS_IOCTLINDIRECT 0x0103 #define PS_IP6FORWARDING 0x0104 #define PS_GETIFADDRS 0x0105 +#define PS_IFIGNOREGRP 0x0106 /* Dev Commands */ #define PS_DEV_LISTENING 0x0201