From: Roy Marples Date: Fri, 30 Oct 2020 14:19:16 +0000 (+0000) Subject: privsep: Allow logfile reopening in a chroot X-Git-Tag: v9.3.2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c963b6033c4bf32c4c72c725f05a0374d32bd370;p=thirdparty%2Fdhcpcd.git privsep: Allow logfile reopening in a chroot 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. --- diff --git a/src/dhcpcd.8.in b/src/dhcpcd.8.in index 9309250a..50964565 100644 --- a/src/dhcpcd.8.in +++ b/src/dhcpcd.8.in @@ -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 diff --git a/src/dhcpcd.c b/src/dhcpcd.c index bd4cb74f..169aeec1 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -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 diff --git a/src/dhcpcd.h b/src/dhcpcd.h index b3cdf941..97d7a322 100644 --- a/src/dhcpcd.h +++ b/src/dhcpcd.h @@ -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 */ diff --git a/src/logerr.c b/src/logerr.c index 6d793082..f407b2db 100644 --- a/src/logerr.c +++ b/src/logerr.c @@ -48,14 +48,15 @@ #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; } diff --git a/src/logerr.h b/src/logerr.h index c1b80153..baa43362 100644 --- a/src/logerr.h +++ b/src/logerr.h @@ -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); diff --git a/src/privsep-root.c b/src/privsep-root.c index 209f2624..afe9c8f6 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -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) diff --git a/src/privsep-root.h b/src/privsep-root.h index 146622b1..9d8a1597 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -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 diff --git a/src/privsep.h b/src/privsep.h index 4fd33e7f..87c84eb9 100644 --- a/src/privsep.h +++ b/src/privsep.h @@ -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