]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: copy configuration file into chroot
authorRoy Marples <roy@marples.name>
Tue, 21 Jan 2020 20:08:56 +0000 (20:08 +0000)
committerRoy Marples <roy@marples.name>
Tue, 21 Jan 2020 20:08:56 +0000 (20:08 +0000)
Only if it has changed.
Saves having to maintian it outside of dhcpcdm in a script or
something.

src/if-options.c
src/privsep-root.c
src/privsep-root.h
src/privsep.c
src/privsep.h

index 2b4cd1ede1745762a548fae8e622a959ff6ad5ec..e8fb93f0da32e4f18985c83868e9a3f9d492a646 100644 (file)
@@ -2520,6 +2520,11 @@ read_config(struct dhcpcd_ctx *ctx,
        }
 
        /* Parse our options file */
+#ifdef PRIVSEP
+       if (ctx->options & DHCPCD_PRIVSEP &&
+           ps_root_copychroot(ctx, ctx->cffile) == -1)
+               logwarn("%s: ps_root_copychroot `%s'", __func__, ctx->cffile);
+#endif
        fp = fopen(ctx->cffile, "r");
        if (fp == NULL) {
                /* dhcpcd can continue without it, but no DNS options
index b6ba8af890268ed3af79bbb6d0872f5c6a9a0ca3..076d71dec1aebbe50d0724d608561f52467f9b3b 100644 (file)
 
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
@@ -199,7 +203,94 @@ ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len)
 }
 
 static ssize_t
-ps_root_dounlink(void *data, size_t len)
+ps_root_docopy(const char *dir, const char *file)
+{
+
+       char path[PATH_MAX], buf[BUFSIZ], *slash;
+       struct stat from_sb, to_sb;
+       int from_fd, to_fd;
+       ssize_t rcount, wcount, total;
+#ifdef BSD
+       struct timespec ts[2];
+#else
+       struct timeval ts[2];
+#endif
+
+       if (snprintf(path, sizeof(path), "%s/%s", dir, file) == -1)
+               return -1;
+       if (stat(file, &from_sb) == -1)
+               return -1;
+       if (stat(path, &to_sb) == 0) {
+#ifdef BSD
+               if (timespeccmp(&from_sb.st_mtimespec, &to_sb.st_mtimespec, ==))
+                       return 0;
+#else
+               if (from_sb.st_mtime == to_sb.st_mtime)
+                       return 0;
+#endif
+       } else {
+               /* Ensure directory exists */
+               slash = strrchr(path, '/');
+               if (slash != NULL) {
+                       *slash = '\0';
+                       ps_mkdir(path);
+                       *slash = '/';
+               }
+       }
+
+       if (unlink(path) == -1 && errno != ENOENT)
+               return -1;
+       if ((from_fd = open(file, O_RDONLY, 0)) == -1)
+               return -1;
+       if ((to_fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0555)) == -1)
+               return -1;
+
+       total = 0;
+       while ((rcount = read(from_fd, buf, sizeof(buf))) > 0) {
+               wcount = write(to_fd, buf, (size_t)rcount);
+               if (wcount != rcount) {
+                       total = -1;
+                       break;
+               }
+               total += wcount;
+       }
+
+#ifdef BSD
+       ts[0] = from_sb.st_atimespec;
+       ts[1] = from_sb.st_mtimespec;
+       if (futimens(to_fd, ts) == -1)
+               total = -1;
+#else
+       tv[0].tv_sec = from_sb.st_atime;
+       tv[0].tv_usec = 0;
+       tv[1].tv_sec = from_sb.st_mtime;
+       tv[1].tv_usec = 0;
+       if (futimes(to_fd, ts) == -1)
+               total = -1;
+#endif
+       close(from_fd);
+       close(to_fd);
+
+       return total;
+}
+
+static ssize_t
+ps_root_docopy1(const char *file)
+{
+       struct passwd *pw;
+
+       errno = 0;
+       if ((pw = getpwnam(PRIVSEP_USER)) == NULL) {
+               if (errno == 0)
+                       errno = ENOENT;
+               return -1;
+       }
+
+       return ps_root_docopy(pw->pw_dir, file);
+}
+
+static ssize_t
+ps_root_dofileop(void *data, size_t len, uint8_t op)
 {
        char *path = data;
        size_t plen;
@@ -216,7 +307,15 @@ ps_root_dounlink(void *data, size_t len)
                return -1;
        }
 
-       return (ssize_t)unlink(path);
+       switch(op) {
+       case PS_COPY:
+               return ps_root_docopy1(path);
+       case PS_UNLINK:
+               return (ssize_t)unlink(path);
+       default:
+               errno = ENOTSUP;
+               return -1;
+       }
 }
 
 static ssize_t
@@ -288,8 +387,9 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
        case PS_SCRIPT:
                err = ps_root_run_script(ctx, data, len);
                break;
+       case PS_COPY:   /* FALLTHROUGH */
        case PS_UNLINK:
-               err = ps_root_dounlink(data, len);
+               err = ps_root_dofileop(data, len, psm->ps_cmd);
                break;
        default:
                err = ps_root_os(psm, msg);
@@ -461,8 +561,8 @@ ps_root_ioctl(struct dhcpcd_ctx *ctx, ioctl_request_t req, void *data,
        return ps_root_readerror(ctx);
 }
 
-ssize_t
-ps_root_unlink(struct dhcpcd_ctx *ctx, const char *path)
+static ssize_t
+ps_root_fileop(struct dhcpcd_ctx *ctx, const char *path, uint8_t op)
 {
        char buf[PATH_MAX], *p = buf;
        size_t plen = strlen(path) + 1;
@@ -477,7 +577,22 @@ ps_root_unlink(struct dhcpcd_ctx *ctx, const char *path)
        p += sizeof(plen);
        memcpy(p, path, plen);
 
-       if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_UNLINK, 0, buf, len) == -1)
+       if (ps_sendcmd(ctx, ctx->ps_root_fd, op, 0, buf, len) == -1)
                return -1;
        return ps_root_readerror(ctx);
 }
+
+
+ssize_t
+ps_root_copychroot(struct dhcpcd_ctx *ctx, const char *path)
+{
+
+       return ps_root_fileop(ctx, path, PS_COPY);
+}
+
+ssize_t
+ps_root_unlink(struct dhcpcd_ctx *ctx, const char *path)
+{
+
+       return ps_root_fileop(ctx, path, PS_UNLINK);
+}
index b4966bc913c87f9db9f27dd458abc5ab38979186..d7f3148a23c156f262ba03517d81473c1f62f5dd 100644 (file)
@@ -35,6 +35,7 @@ pid_t ps_root_start(struct dhcpcd_ctx *ctx);
 int ps_root_stop(struct dhcpcd_ctx *ctx);
 
 ssize_t ps_root_readerror(struct dhcpcd_ctx *);
+ssize_t ps_root_copychroot(struct dhcpcd_ctx *, const char *);
 ssize_t ps_root_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
 ssize_t ps_root_unlink(struct dhcpcd_ctx *, const char *);
 ssize_t ps_root_os(struct ps_msghdr *, struct msghdr *);
index e9ec25f21c2b0dd8fccb4b2f0623dee85f4087b1..ffd32de0a7ee8cffd4f9c94cc810f7336526e00c 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <util.h>
 #endif
 
+int
+ps_mkdir(char *path)
+{
+       char *slash;
+       bool done;
+
+       slash = path;
+       for (;;) {
+               slash += strspn(slash, "/");
+               slash += strcspn(slash, "/");
+               done = (*slash == '\0');
+               *slash = '\0';
+               if (mkdir(path, 0755) == -1 && errno != EEXIST)
+                       return -1;
+               if (done)
+                       break;
+               *slash = '/';
+       }
+       return 0;
+}
+
 int
 ps_init(struct dhcpcd_ctx *ctx)
 {
        struct passwd *pw;
+       char path[PATH_MAX];
 
        errno = 0;
        if ((pw = getpwnam(PRIVSEP_USER)) == NULL) {
@@ -85,6 +108,13 @@ ps_init(struct dhcpcd_ctx *ctx)
                return -1;
        }
 
+       /* Create the database directory. */
+       if (snprintf(path, sizeof(path), "%s%s", pw->pw_dir, DBDIR) == -1 ||
+           ps_mkdir(path) == -1 ||
+           chown(path, pw->pw_uid, pw->pw_gid) == -1 ||
+           chmod(path, 0755) == -1)
+               logerr("%s: %s", __func__, path);
+
        ctx->options |= DHCPCD_PRIVSEP;
        return 0;
 }
index babcb37c056e55503a63f10e3b06ad85ecfb7057..8372c0e5fb334194a70c8cccb84981c232bfda85 100644 (file)
 #define        PS_ROUTE                0x11    /* Also used for NETLINK */
 #define        PS_SCRIPT               0x12
 #define        PS_UNLINK               0x13
+#define        PS_COPY                 0x14
 
 /* BSD Commands */
-#define        PS_IOCTLLINK            0x14
-#define        PS_IOCTL6               0x15
+#define        PS_IOCTLLINK            0x15
+#define        PS_IOCTL6               0x16
 
 /* Linux commands */
-#define        PS_WRITEPATHUINT        0x16
+#define        PS_WRITEPATHUINT        0x17
 
 #define        PS_DELETE               0x20
 #define        PS_START                0x40
@@ -136,6 +137,7 @@ TAILQ_HEAD(ps_process_head, ps_process);
 #include "privsep-bpf.h"
 #endif
 
+int ps_mkdir(char *);
 int ps_init(struct dhcpcd_ctx *);
 int ps_dropprivs(struct dhcpcd_ctx *);
 int ps_start(struct dhcpcd_ctx *);