]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Allow logfile reopening in a chroot
authorRoy Marples <roy@marples.name>
Fri, 30 Oct 2020 14:19:16 +0000 (14:19 +0000)
committerRoy Marples <roy@marples.name>
Fri, 30 Oct 2020 14:19:16 +0000 (14:19 +0000)
Now that only the privileged actioneer does the actual logging
we can safely reopen the file we are logging to.
This also closes and re-opens the syslog connection.

src/dhcpcd.8.in
src/dhcpcd.c
src/dhcpcd.h
src/logerr.c
src/logerr.h
src/privsep-root.c
src/privsep-root.h
src/privsep.h

index 9309250aa4814a69110ae6da83baa8f89617a7e8..509645659f66725a87637497a305c36fef7351ea 100644 (file)
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd September 2, 2020
+.Dd October 30, 2020
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -846,13 +846,5 @@ RFC\ 6603, RFC\ 6704, RFC\ 7217, RFC\ 7550, RFC\ 7844.
 .Sh AUTHORS
 .An Roy Marples Aq Mt roy@marples.name
 .Sh BUGS
-If
-.Nm
-is running in a
-.Xr chroot 2
-then re-opening the
-.Fl Fl logfile
-from SIGUSR2 may not work.
-.Pp
 Please report them to
 .Lk http://roy.marples.name/projects/dhcpcd
index bd4cb74f77e5839e67eb7a71158a284f171afd67..169aeec100bbd29ccd8076b8b5063660dd630985 100644 (file)
@@ -1422,10 +1422,14 @@ dhcpcd_signal_cb(int sig, void *arg)
                return;
        case SIGUSR2:
                loginfox(sigmsg, "SIGUSR2", "reopening log");
-               /* XXX This may not work that well in a chroot */
-               logclose();
-               if (logopen(ctx->logfile) == -1)
-                       logerr(__func__);
+               if (IN_PRIVSEP(ctx)) {
+                       if (ps_root_logreopen(ctx) == -1)
+                               logerr("ps_root_logreopen");
+               } else {
+                       logclose();
+                       if (logopen(ctx->logfile) == -1)
+                               logerr("logopen");
+               }
                return;
        case SIGCHLD:
                while (waitpid(-1, NULL, WNOHANG) > 0)
@@ -1860,7 +1864,7 @@ main(int argc, char **argv, char **envp)
        ctx.dhcp6_wfd = -1;
 #endif
 #ifdef PRIVSEP
-       ctx.ps_root_fd = ctx.ps_syslog_fd = ctx.ps_data_fd = -1;
+       ctx.ps_root_fd = ctx.ps_log_fd = ctx.ps_data_fd = -1;
        ctx.ps_inet_fd = ctx.ps_control_fd = -1;
        TAILQ_INIT(&ctx.ps_processes);
 #endif
@@ -2328,6 +2332,7 @@ printpidfile:
        /* We have now forked, setsid, forked once more.
         * From this point on, we are the controlling daemon. */
        ctx.options |= DHCPCD_STARTED;
+       logdebugx("spawned master process on PID %d", getpid());
        if ((pid = pidfile_lock(ctx.pidfile)) != 0) {
                logerr("%s: pidfile_lock %d", __func__, pid);
 #ifdef PRIVSEP
index b3cdf9419971b389bf9d6b508deb466236c28ea1..97d7a322e7258055d0fa11cd768d899bb3b75a87 100644 (file)
@@ -199,7 +199,7 @@ struct dhcpcd_ctx {
        struct passwd *ps_user; /* struct passwd for privsep user */
        pid_t ps_root_pid;
        int ps_root_fd;         /* Privileged Actioneer commands */
-       int ps_syslog_fd;       /* syslog(3) wrapper */
+       int ps_log_fd;          /* chroot logging */
        int ps_data_fd;         /* Data from root spawned processes */
        struct eloop *ps_eloop; /* eloop for polling root data */
        struct ps_process_head ps_processes;    /* List of spawned processes */
index 6d793082cb6042847fb45eedb0b7e21cf41205c4..f407b2db588fa95f4bbf8130338522a8f8baf281 100644 (file)
 #endif
 
 /* syslog protocol is 1k message max, RFC 3164 section 4.1 */
-#define LOGERR_SYSLOGBUF       1024 + sizeof(int)
+#define LOGERR_SYSLOGBUF       1024 + sizeof(int) + sizeof(pid_t)
 
 #define UNUSED(a)              (void)(a)
 
 struct logctx {
        char             log_buf[BUFSIZ];
        unsigned int     log_opts;
-       int              log_syslogfd;
+       int              log_fd;
+       pid_t            log_pid;
 #ifndef SMALL
        FILE            *log_file;
 #ifdef LOGERR_TAG
@@ -67,7 +68,8 @@ struct logctx {
 static struct logctx _logctx = {
        /* syslog style, but without the hostname or tag. */
        .log_opts = LOGERR_LOG | LOGERR_LOG_DATE | LOGERR_LOG_PID,
-       .log_syslogfd = -1,
+       .log_fd = -1,
+       .log_pid = 0,
 };
 
 #if defined(__linux__)
@@ -155,7 +157,13 @@ vlogprintf_r(struct logctx *ctx, FILE *stream, const char *fmt, va_list args)
        log_pid = ((stream == stderr && ctx->log_opts & LOGERR_ERR_PID) ||
            (stream != stderr && ctx->log_opts & LOGERR_LOG_PID));
        if (log_pid) {
-               if ((e = fprintf(stream, "[%d]", getpid())) == -1)
+               pid_t pid;
+
+               if (ctx->log_pid == 0)
+                       pid = getpid();
+               else
+                       pid = ctx->log_pid;
+               if ((e = fprintf(stream, "[%d]", pid)) == -1)
                        return -1;
                len += e;
        }
@@ -206,15 +214,19 @@ vlogmessage(int pri, const char *fmt, va_list args)
        struct logctx *ctx = &_logctx;
        int len = 0;
 
-       if (ctx->log_syslogfd != -1) {
+       if (ctx->log_fd != -1) {
                char buf[LOGERR_SYSLOGBUF];
+               pid_t pid;
 
                memcpy(buf, &pri, sizeof(pri));
-               len = vsnprintf(buf + sizeof(pri), sizeof(buf) - sizeof(pri),
+               pid = getpid();
+               memcpy(buf + sizeof(pri), &pid, sizeof(pid));
+               len = vsnprintf(buf + sizeof(pri) + sizeof(pid),
+                   sizeof(buf) - sizeof(pri) - sizeof(pid),
                    fmt, args);
                if (len != -1)
-                       len = (int)write(ctx->log_syslogfd, buf,
-                           ((size_t)++len) + sizeof(pri));
+                       len = (int)write(ctx->log_fd, buf,
+                           ((size_t)++len) + sizeof(pri) + sizeof(pid));
                return len;
        }
 
@@ -351,24 +363,31 @@ log_errx(const char *fmt, ...)
 }
 
 int
-loggetsyslogfd(void)
+loggetfd(void)
 {
        struct logctx *ctx = &_logctx;
 
-       return ctx->log_syslogfd;
+       return ctx->log_fd;
 }
 
 void
-logsetsyslogfd(int fd)
+logsetfd(int fd)
 {
        struct logctx *ctx = &_logctx;
 
-       ctx->log_syslogfd = fd;
+       ctx->log_fd = fd;
+#ifndef SMALL
+       if (fd != -1 && ctx->log_file != NULL) {
+               fclose(ctx->log_file);
+               ctx->log_file = NULL;
+       }
+#endif
 }
 
 int
-loghandlesyslogfd(int fd)
+logreadfd(int fd)
 {
+       struct logctx *ctx = &_logctx;
        char buf[LOGERR_SYSLOGBUF];
        int len, pri;
 
@@ -376,14 +395,18 @@ loghandlesyslogfd(int fd)
        if (len == -1)
                return -1;
 
-       /* Ensure we have pri and a terminator */
-       if (len < (int)sizeof(pri) + 1 || buf[len - 1] != '\0') {
+       /* Ensure we have pri, pid and a terminator */
+       if (len < (int)(sizeof(pri) + sizeof(pid_t) + 1) ||
+           buf[len - 1] != '\0')
+       {
                errno = EINVAL;
                return -1;
        }
 
        memcpy(&pri, buf, sizeof(pri));
-       logmessage(pri, "%s", buf + sizeof(pri));
+       memcpy(&ctx->log_pid, buf + sizeof(pri), sizeof(ctx->log_pid));
+       logmessage(pri, "%s", buf + sizeof(pri) + sizeof(ctx->log_pid));
+       ctx->log_pid = 0;
        return len;
 }
 
index c1b80153766220ed82d93326772f2fbbe8964046..baa43362e3fe81f7789d751faba097304d153548 100644 (file)
@@ -76,10 +76,10 @@ __printflike(2, 3) void logerrmessage(int pri, const char *fmt, ...);
 #define logerr(...)    log_err(__VA_ARGS__)
 #define logerrx(...)   log_errx(__VA_ARGS__)
 
-/* For syslog in a chroot */
-int loggetsyslogfd(void);
-void logsetsyslogfd(int);
-int loghandlesyslogfd(int);
+/* For logging in a chroot */
+int loggetfd(void);
+void logsetfd(int);
+int logreadfd(int);
 
 unsigned int loggetopts(void);
 void logsetopts(unsigned int);
index 209f2624f38d3c6e1973eb0e369a72d620538e97..afe9c8f68c3108b6b35aeafc8832ac4d74506cc6 100644 (file)
@@ -561,6 +561,10 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
                        rlen = sizeof(mtime);
                }
                break;
+       case PS_LOGREOPEN:
+               logclose();
+               err = logopen(ctx->logfile);
+               break;
 #ifdef AUTH
        case PS_AUTH_MONORDM:
                err = ps_root_monordm(data, len);
@@ -781,11 +785,11 @@ ps_root_dispatch(void *arg)
 }
 
 static void
-ps_root_syslog(void *arg)
+ps_root_log(void *arg)
 {
        struct dhcpcd_ctx *ctx = arg;
 
-       if (loghandlesyslogfd(ctx->ps_syslog_fd) == -1)
+       if (logreadfd(ctx->ps_log_fd) == -1)
                logerr(__func__);
 }
 
@@ -816,9 +820,9 @@ ps_root_start(struct dhcpcd_ctx *ctx)
            ps_root_startcb, ps_root_signalcb, 0);
 
        if (pid == 0) {
-               ctx->ps_syslog_fd = logfd[1];
-               if (eloop_event_add(ctx->eloop, ctx->ps_syslog_fd,
-                   ps_root_syslog, ctx) == -1)
+               ctx->ps_log_fd = logfd[1];
+               if (eloop_event_add(ctx->eloop, ctx->ps_log_fd,
+                   ps_root_log, ctx) == -1)
                        return -1;
                close(logfd[0]);
                ctx->ps_data_fd = datafd[1];
@@ -827,7 +831,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
        } else if (pid == -1)
                return -1;
 
-       logsetsyslogfd(logfd[0]);
+       logsetfd(logfd[0]);
        close(logfd[1]);
 
        ctx->ps_data_fd = datafd[0];
@@ -930,6 +934,15 @@ ps_root_filemtime(struct dhcpcd_ctx *ctx, const char *file, time_t *time)
        return ps_root_readerror(ctx, time, sizeof(*time));
 }
 
+ssize_t
+ps_root_logreopen(struct dhcpcd_ctx *ctx)
+{
+
+       if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_LOGREOPEN, 0, NULL, 0) == -1)
+               return -1;
+       return ps_root_readerror(ctx, NULL, 0);
+}
+
 #ifdef PRIVSEP_GETIFADDRS
 int
 ps_root_getifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **ifahead)
index 146622b1a10dd00e1882684b9d9aa7eaa81ee992..9d8a1597cb7f20f7b85d6458c6a4aecf5d94c209 100644 (file)
@@ -47,6 +47,7 @@ ssize_t ps_root_filemtime(struct dhcpcd_ctx *, const char *, time_t *);
 ssize_t ps_root_readfile(struct dhcpcd_ctx *, const char *, void *, size_t);
 ssize_t ps_root_writefile(struct dhcpcd_ctx *, const char *, mode_t,
     const void *, size_t);
+ssize_t ps_root_logreopen(struct dhcpcd_ctx *);
 ssize_t ps_root_script(struct dhcpcd_ctx *, const void *, size_t);
 int ps_root_getauthrdm(struct dhcpcd_ctx *, uint64_t *);
 #ifdef PRIVSEP_GETIFADDRS
index 4fd33e7fe74cc6cd1bbf4d44e6ec2c2e7b4caff6..87c84eb955c8727f15c9a2baa5671c5bb6dcfa29 100644 (file)
@@ -52,6 +52,7 @@
 #define        PS_AUTH_MONORDM         0x0017
 #define        PS_CTL                  0x0018
 #define        PS_CTL_EOF              0x0019
+#define        PS_LOGREOPEN            0x0020
 
 /* BSD Commands */
 #define        PS_IOCTLLINK            0x0101