Mercurial > hg > dhcpcd
changeset 5260:7571d82b48da draft
privsep: Allow dev plugins to work
For udev at least, it requires a /var/run to be available in the chroot
which is poor. As such, give it a full IPC.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Sun, 24 May 2020 10:30:23 +0000 |
| parents | d569724efab3 |
| children | 33324d44a2e8 |
| files | src/dev.c src/dev.h src/dhcpcd.c src/privsep-root.c src/privsep-root.h src/privsep.c src/privsep.h |
| diffstat | 7 files changed, 146 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dev.c Sun May 24 05:54:40 2020 +0000 +++ b/src/dev.c Sun May 24 10:30:23 2020 +0000 @@ -42,6 +42,12 @@ dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname) { +#ifdef PRIVSEP + if (ctx->options & DHCPCD_PRIVSEP && + !(ctx->options & DHCPCD_PRIVSEPROOT)) + return ps_root_dev_initialized(ctx, ifname); +#endif + if (ctx->dev == NULL) return 1; return ctx->dev->initialized(ifname); @@ -51,6 +57,12 @@ dev_listening(struct dhcpcd_ctx *ctx) { +#ifdef PRIVSEP + if (ctx->options & DHCPCD_PRIVSEP && + !(ctx->options & DHCPCD_PRIVSEPROOT)) + return ps_root_dev_listening(ctx); +#endif + if (ctx->dev == NULL) return 0; return ctx->dev->listening(); @@ -79,17 +91,17 @@ dev_stop(struct dhcpcd_ctx *ctx) { - dev_stop1(ctx,!(ctx->options & DHCPCD_FORKED)); + dev_stop1(ctx, !(ctx->options & DHCPCD_FORKED)); } static int -dev_start2(struct dhcpcd_ctx *ctx, const char *name) +dev_start2(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd, + const char *name) { char file[PATH_MAX]; void *h; void (*fptr)(struct dev *, const struct dev_dhcpcd *); int r; - struct dev_dhcpcd dev_dhcpcd; snprintf(file, sizeof(file), DEVDIR "/%s", name); h = dlopen(file, RTLD_LAZY); @@ -108,8 +120,7 @@ dlclose(h); return -1; } - dev_dhcpcd.handle_interface = &dhcpcd_handleinterface; - fptr(ctx->dev, &dev_dhcpcd); + fptr(ctx->dev, dev_dhcpcd); if (ctx->dev->start == NULL || (r = ctx->dev->start()) == -1) { free(ctx->dev); ctx->dev = NULL; @@ -122,7 +133,7 @@ } static int -dev_start1(struct dhcpcd_ctx *ctx) +dev_start1(struct dhcpcd_ctx *ctx, const struct dev_dhcpcd *dev_dhcpcd) { DIR *dp; struct dirent *d; @@ -134,7 +145,7 @@ } if (ctx->dev_load) - return dev_start2(ctx, ctx->dev_load); + return dev_start2(ctx, dev_dhcpcd, ctx->dev_load); dp = opendir(DEVDIR); if (dp == NULL) { @@ -147,7 +158,7 @@ if (d->d_name[0] == '.') continue; - r = dev_start2(ctx, d->d_name); + r = dev_start2(ctx, dev_dhcpcd, d->d_name); if (r != -1) break; } @@ -167,15 +178,18 @@ } int -dev_start(struct dhcpcd_ctx *ctx) +dev_start(struct dhcpcd_ctx *ctx, int (*handler)(void *, int, const char *)) { + struct dev_dhcpcd dev_dhcpcd = { + .handle_interface = handler, + }; if (ctx->dev_fd != -1) { logerrx("%s: already started on fd %d", __func__, ctx->dev_fd); return ctx->dev_fd; } - ctx->dev_fd = dev_start1(ctx); + ctx->dev_fd = dev_start1(ctx, &dev_dhcpcd); if (ctx->dev_fd != -1) { if (eloop_event_add(ctx->eloop, ctx->dev_fd, dev_handle_data, ctx) == -1)
--- a/src/dev.h Sun May 24 05:54:40 2020 +0000 +++ b/src/dev.h Sun May 24 10:30:23 2020 +0000 @@ -49,7 +49,7 @@ #include "dhcpcd.h" int dev_initialized(struct dhcpcd_ctx *, const char *); int dev_listening(struct dhcpcd_ctx *); -int dev_start(struct dhcpcd_ctx *); +int dev_start(struct dhcpcd_ctx *, int (*)(void *, int, const char *)); void dev_stop(struct dhcpcd_ctx *); #else #define dev_initialized(a, b) (1)
--- a/src/dhcpcd.c Sun May 24 05:54:40 2020 +0000 +++ b/src/dhcpcd.c Sun May 24 10:30:23 2020 +0000 @@ -2258,9 +2258,10 @@ /* Start any dev listening plugin which may want to * change the interface name provided by the kernel */ - if ((ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) == + if (!IN_PRIVSEP(&ctx) && + (ctx.options & (DHCPCD_MASTER | DHCPCD_DEV)) == (DHCPCD_MASTER | DHCPCD_DEV)) - dev_start(&ctx); + dev_start(&ctx, dhcpcd_handleinterface); setproctitle("%s%s%s", ctx.options & DHCPCD_MASTER ? "[master]" : argv[optind],
--- a/src/privsep-root.c Sun May 24 05:54:40 2020 +0000 +++ b/src/privsep-root.c Sun May 24 10:30:23 2020 +0000 @@ -44,6 +44,7 @@ #include <unistd.h> #include "common.h" +#include "dev.h" #include "dhcpcd.h" #include "dhcp6.h" #include "eloop.h" @@ -525,6 +526,14 @@ err = ip6_forwarding(data); break; #endif +#ifdef PLUGIN_DEV + case PS_DEV_INITTED: + err = dev_initialized(ctx, data); + break; + case PS_DEV_LISTENING: + err = dev_listening(ctx); + break; +#endif default: err = ps_root_os(psm, msg); break; @@ -548,6 +557,27 @@ } static int +ps_root_handleinterface(void *arg, int action, const char *ifname) +{ + struct dhcpcd_ctx *ctx = arg; + unsigned long flag; + + if (action == 1) + flag = PS_DEV_IFADDED; + else if (action == -1) + flag = PS_DEV_IFREMOVED; + else if (action == 0) + flag = PS_DEV_IFUPDATED; + else { + errno = EINVAL; + return -1; + } + + return (int)ps_sendcmd(ctx, ctx->ps_data_fd, PS_DEV_IFCMD, flag, + ifname, strlen(ifname) + 1); +} + +static int ps_root_startcb(void *arg) { struct dhcpcd_ctx *ctx = arg; @@ -582,6 +612,12 @@ return -1; #endif + /* Start any dev listening plugin which may want to + * change the interface name provided by the kernel */ + if ((ctx->options & (DHCPCD_MASTER | DHCPCD_DEV)) == + (DHCPCD_MASTER | DHCPCD_DEV)) + dev_start(ctx, ps_root_handleinterface); + return 0; } @@ -603,17 +639,58 @@ eloop_exit(ctx->eloop, sig == SIGTERM ? EXIT_SUCCESS : EXIT_FAILURE); } +int (*handle_interface)(void *, int, const char *); + +#ifdef PLUGIN_DEV +static ssize_t +ps_root_devcb(struct dhcpcd_ctx *ctx, struct ps_msghdr *psm, struct msghdr *msg) +{ + int action; + struct iovec *iov = msg->msg_iov; + + if (msg->msg_iovlen != 1) { + errno = EINVAL; + return -1; + } + + switch(psm->ps_flags) { + case PS_DEV_IFADDED: + action = 1; + break; + case PS_DEV_IFREMOVED: + action = -1; + break; + case PS_DEV_IFUPDATED: + action = 0; + break; + default: + errno = EINVAL; + return -1; + } + + return dhcpcd_handleinterface(ctx, action, iov->iov_base); +} +#endif + static ssize_t ps_root_dispatchcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) { struct dhcpcd_ctx *ctx = arg; ssize_t err; + switch(psm->ps_cmd) { +#ifdef PLUGIN_DEV + case PS_DEV_IFCMD: + err = ps_root_devcb(ctx, psm, msg); + break; +#endif + default: + err = ps_bpf_dispatch(ctx, psm, msg); #ifdef INET - err = ps_bpf_dispatch(ctx, psm, msg); - if (err == -1 && errno == ENOTSUP) + if (err == -1 && errno == ENOTSUP) #endif - err = ps_inet_dispatch(ctx, psm, msg); + err = ps_inet_dispatch(ctx, psm, msg); + } return err; } @@ -826,3 +903,24 @@ return ps_root_readerror(ctx, NULL, 0); } #endif + +#ifdef PLUGIN_DEV +int +ps_root_dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname) +{ + + if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_INITTED, 0, + ifname, strlen(ifname) + 1)== -1) + return -1; + return (int)ps_root_readerror(ctx, NULL, 0); +} + +int +ps_root_dev_listening(struct dhcpcd_ctx * ctx) +{ + + if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_LISTENING, 0, NULL, 0)== -1) + return -1; + return (int)ps_root_readerror(ctx, NULL, 0); +} +#endif
--- a/src/privsep-root.h Sun May 24 05:54:40 2020 +0000 +++ b/src/privsep-root.h Sun May 24 10:30:23 2020 +0000 @@ -59,4 +59,9 @@ ssize_t ps_root_writepathuint(struct dhcpcd_ctx *, const char *, unsigned int); #endif +#ifdef PLUGIN_DEV +int ps_root_dev_initialized(struct dhcpcd_ctx *, const char *); +int ps_root_dev_listening(struct dhcpcd_ctx *); #endif + +#endif
--- a/src/privsep.c Sun May 24 05:54:40 2020 +0000 +++ b/src/privsep.c Sun May 24 10:30:23 2020 +0000 @@ -63,6 +63,7 @@ #include "arp.h" #include "common.h" #include "control.h" +#include "dev.h" #include "dhcp.h" #include "dhcp6.h" #include "eloop.h" @@ -696,6 +697,7 @@ logdebugx("process %d stopping", getpid()); #endif ps_free(ctx); + dev_stop(ctx); eloop_exit(ctx->eloop, len != -1 ? EXIT_SUCCESS : EXIT_FAILURE); return len; }
--- a/src/privsep.h Sun May 24 05:54:40 2020 +0000 +++ b/src/privsep.h Sun May 24 10:30:23 2020 +0000 @@ -57,6 +57,16 @@ #define PS_IP6FORWARDING 0x0104 #define PS_GETIFADDRS 0x0105 +/* Dev Commands */ +#define PS_DEV_LISTENING 0x0201 +#define PS_DEV_INITTED 0x0202 +#define PS_DEV_IFCMD 0x0203 + +/* Dev Interface Commands (via flags) */ +#define PS_DEV_IFADDED 0x0001 +#define PS_DEV_IFREMOVED 0x0002 +#define PS_DEV_IFUPDATED 0x0003 + /* Process commands */ #define PS_START 0x4000 #define PS_STOP 0x8000
