Mercurial > hg > dhcpcd
changeset 5310:0a6bde63868b draft
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.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Fri, 05 Jun 2020 11:12:21 +0100 |
| parents | 700fa2afe696 |
| children | fd78486b12a7 |
| files | src/dhcpcd.c src/if-bsd.c src/if.h src/privsep-bsd.c src/privsep-root.h src/privsep.h |
| diffstat | 6 files changed, 73 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dhcpcd.c Thu Jun 04 21:49:37 2020 +0100 +++ b/src/dhcpcd.c Fri Jun 05 11:12:21 2020 +0100 @@ -2309,7 +2309,7 @@ } #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; }
--- a/src/if-bsd.c Thu Jun 04 21:49:37 2020 +0100 +++ b/src/if-bsd.c Fri Jun 05 11:12:21 2020 +0100 @@ -292,6 +292,38 @@ return false; } +#ifdef SIOCGIFGROUP +int +if_ignoregroup(int s, const char *ifname) +{ + struct ifgroupreq ifgr = { .ifgr_len = 0 }; + struct ifg_req *ifg; + size_t ifg_len; + + /* Sadly it is possible to remove the device name + * from the interface groups, but hopefully this + * will be very unlikely.... */ + + strlcpy(ifgr.ifgr_name, ifname, sizeof(ifgr.ifgr_name)); + if (ioctl(s, SIOCGIFGROUP, &ifgr) == -1 || + (ifgr.ifgr_groups = malloc(ifgr.ifgr_len)) == NULL || + ioctl(s, SIOCGIFGROUP, &ifgr) == -1) + { + logerr(__func__); + return -1; + } + + for (ifg = ifgr.ifgr_groups, ifg_len = ifgr.ifgr_len; + ifg && ifg_len >= sizeof(*ifg); + ifg++, ifg_len -= sizeof(*ifg)) + { + if (if_ignore1(ifg->ifgrq_group)) + return 1; + } + return 0; +} +#endif + bool if_ignore(struct dhcpcd_ctx *ctx, const char *ifname) { @@ -304,38 +336,17 @@ return true; #ifdef SIOCGIFGROUP -#ifdef HAVE_PLEDGE -#warning Fix SIOCGIFGROUP to use privsep to remove inet pledge requirement +#if defined(PRIVSEP) && defined(HAVE_PLEDGE) + if (IN_PRIVSEP(ctx)) + return ps_root_ifignoregroup(ctx, ifname) == 1 ? true : false; #endif - struct ifgroupreq ifgr = { .ifgr_len = 0 }; - struct ifg_req *ifg; - size_t ifg_len; - - /* Sadly it is possible to remove the device name - * from the interface groups, but hopefully this - * will be very unlikely.... */ - - strlcpy(ifgr.ifgr_name, ifname, sizeof(ifgr.ifgr_name)); - if (ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1 || - (ifgr.ifgr_groups = malloc(ifgr.ifgr_len)) == NULL || - ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1) - { - logerr(__func__); - return false; - } - - for (ifg = ifgr.ifgr_groups, ifg_len = ifgr.ifgr_len; - ifg && ifg_len >= sizeof(*ifg); - ifg++, ifg_len -= sizeof(*ifg)) - { - if (if_ignore1(ifg->ifgrq_group)) - return true; - } + else + return if_ignoregroup(ctx->pf_inet_fd, ifname) == 1 ? + true : false; #else UNUSED(ctx); + return false; #endif - - return false; } int
--- a/src/if.h Thu Jun 04 21:49:37 2020 +0100 +++ b/src/if.h Fri Jun 05 11:12:21 2020 +0100 @@ -182,6 +182,7 @@ 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 *);
--- a/src/privsep-bsd.c Thu Jun 04 21:49:37 2020 +0100 +++ b/src/privsep-bsd.c Fri Jun 05 11:12:21 2020 +0100 @@ -136,6 +136,24 @@ 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 @@ 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 @@ 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
--- a/src/privsep-root.h Thu Jun 04 21:49:37 2020 +0100 +++ b/src/privsep-root.h Fri Jun 05 11:12:21 2020 +0100 @@ -54,6 +54,7 @@ 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 *);
