]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Allow dev plugins to work
authorRoy Marples <roy@marples.name>
Sun, 24 May 2020 10:30:23 +0000 (10:30 +0000)
committerRoy Marples <roy@marples.name>
Sun, 24 May 2020 10:30:23 +0000 (10:30 +0000)
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.

src/dev.c
src/dev.h
src/dhcpcd.c
src/privsep-root.c
src/privsep-root.h
src/privsep.c
src/privsep.h

index 7e49d5aca71b11a359481490e6dc76ed8ea74302..f7da67e4dea586a0beb29bdbc8cb53f2108a4122 100644 (file)
--- a/src/dev.c
+++ b/src/dev.c
@@ -42,6 +42,12 @@ int
 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 @@ int
 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 @@ void
 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 @@ dev_start2(struct dhcpcd_ctx *ctx, const char *name)
                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 @@ dev_start2(struct dhcpcd_ctx *ctx, const char *name)
 }
 
 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 @@ dev_start1(struct dhcpcd_ctx *ctx)
        }
 
        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 @@ dev_start1(struct dhcpcd_ctx *ctx)
                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 @@ dev_handle_data(void *arg)
 }
 
 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)
index 74a693e6a7c8df62f7959a20f093ccf9255efc7f..8ce4eb71039c0432d553392bc5bf7dfc5954d8c1 100644 (file)
--- a/src/dev.h
+++ b/src/dev.h
@@ -49,7 +49,7 @@ int dev_init(struct dev *, const struct dev_dhcpcd *);
 #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)
index e2501d6f3c8a9704af2624b950a26b41c7758290..0c32098cf9724f15386b876cdcac202b40677e2d 100644 (file)
@@ -2258,9 +2258,10 @@ printpidfile:
 
        /* 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],
index b42167609305c620eaea75bdf8508e0ae362e3e4..6a82fb6b60f17d8ba21d1e2f5e7aa22f80c61133 100644 (file)
@@ -44,6 +44,7 @@
 #include <unistd.h>
 
 #include "common.h"
+#include "dev.h"
 #include "dhcpcd.h"
 #include "dhcp6.h"
 #include "eloop.h"
@@ -524,6 +525,14 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
        case PS_IP6FORWARDING:
                 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);
@@ -547,6 +556,27 @@ ps_root_recvmsg(void *arg)
                logerr(__func__);
 }
 
+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)
 {
@@ -582,6 +612,12 @@ ps_root_startcb(void *arg)
                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 @@ ps_root_signalcb(int sig, void *arg)
        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 @@ ps_root_ip6forwarding(struct dhcpcd_ctx *ctx, const char *ifname)
        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
index 998c78303ceee596755ab172ec1c4b2d8e569a17..a56e30af0348090a6a146f35d8987334ea52f154 100644 (file)
@@ -59,4 +59,9 @@ 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
+int ps_root_dev_initialized(struct dhcpcd_ctx *, const char *);
+int ps_root_dev_listening(struct dhcpcd_ctx *);
+#endif
+
 #endif
index 92804a99cac6c7a28a737f037fd425ab073ad341..3ee508bec8418aa47981aa85b9007723895897ba 100644 (file)
@@ -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 @@ ps_recvpsmsg(struct dhcpcd_ctx *ctx, int fd,
                logdebugx("process %d stopping", getpid());
 #endif
                ps_free(ctx);
+               dev_stop(ctx);
                eloop_exit(ctx->eloop, len != -1 ? EXIT_SUCCESS : EXIT_FAILURE);
                return len;
        }
index 09bfa897381db7ef0724cfc63af4c1b97820291c..930582257591f3427aa59c91e78a796485e77fc4 100644 (file)
 #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