diff --git a/src/control.c b/src/control.c index b1ade2aa..9164b7ab 100644 --- a/src/control.c +++ b/src/control.c @@ -546,7 +546,7 @@ control_start1(struct dhcpcd_ctx *ctx, const char *ifname, sa_family_t family) goto err; #ifdef PRIVSEP_RIGHTS - if (IN_PRIVSEP(ctx) && ps_rights_limit_fd_fctnl(fd) == -1) + if (IN_PRIVSEP(ctx) && ps_rights_limit_fd_getsockopt(fd) == -1) goto err; #endif diff --git a/src/dhcpcd.c b/src/dhcpcd.c index f015fa05..e4a8872a 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -2487,9 +2487,10 @@ main(int argc, char **argv, char **envp) ctx.options |= DHCPCD_FORKED; /* avoid socket unlink */ if (!(ctx.options & DHCPCD_MANAGER)) ctx.control_fd = control_open(argv[optind], family); - if (!(ctx.options & DHCPCD_MANAGER) && ctx.control_fd == -1) + if (!(ctx.options & DHCPCD_MANAGER) && ctx.control_fd == -1 && + errno != EACCES) ctx.control_fd = control_open(argv[optind], AF_UNSPEC); - if (ctx.control_fd == -1) + if (ctx.control_fd == -1 && errno != EACCES) ctx.control_fd = control_open(NULL, AF_UNSPEC); if (ctx.control_fd != -1) { if (!(ctx.options & DHCPCD_DUMPLEASE)) diff --git a/src/privsep.c b/src/privsep.c index 65955007..f35502e0 100644 --- a/src/privsep.c +++ b/src/privsep.c @@ -198,6 +198,18 @@ ps_rights_limit_ioctl(int fd) return 0; } +int +ps_rights_limit_fd_getsockopt(int fd) +{ + cap_rights_t rights; + + cap_rights_init(&rights, CAP_READ, CAP_WRITE, CAP_EVENT, CAP_ACCEPT, + CAP_GETSOCKOPT | CAP_FCNTL); + if (cap_rights_limit(fd, &rights) == -1 && errno != ENOSYS) + return -1; + return 0; +} + int ps_rights_limit_fd_fctnl(int fd) { diff --git a/src/privsep.h b/src/privsep.h index 39e49340..7fe4d1f2 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -217,6 +217,7 @@ ssize_t ps_recvpsmsg(struct dhcpcd_ctx *, int, unsigned short, #ifdef PRIVSEP_RIGHTS int ps_rights_limit_ioctl(int); +int ps_rights_limit_fd_getsockopt(int); int ps_rights_limit_fd_fctnl(int); int ps_rights_limit_fd_rdonly(int); int ps_rights_limit_fd_sockopt(int);