From: Karel Zak Date: Thu, 29 Oct 2015 10:18:21 +0000 (+0100) Subject: logger: use --id as local socket credentials X-Git-Tag: v2.28-rc1~293 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=27a9eb53;p=thirdparty%2Futil-linux.git logger: use --id as local socket credentials If you have really paranoid syslog (or systemd who listens on /dev/log) then it replaces in the message PID with a real PID from socket header credentials: # echo $PPID 1550 # logger -p info --stderr --id=$PPID "This is message baby!" <14>Oct 29 11:22:13 kzak[1550]: This is message baby! # journald -n 1 Oct 29 11:22:13 ws kzak[22100]: This is message baby! ^^^^^ This patch forces kernel to accept another *valid* PID if logger(1) executed with root permissions; improved version: # logger -p info --stderr --id=$PPID "This is message baby!" <14>Oct 29 11:26:00 kzak[1550]: This is message baby! # journald -n 1 Oct 29 11:26:00 ws kzak[1550]: This is message baby! Signed-off-by: Karel Zak --- diff --git a/misc-utils/logger.1 b/misc-utils/logger.1 index fe525042f7..81751f217a 100644 --- a/misc-utils/logger.1 +++ b/misc-utils/logger.1 @@ -71,6 +71,14 @@ Log the PID of the logger process with each line. When the optional argument \fIid\fR is specified, then it is used instead of the logger command's PID. The use of \fB\-\-id=$$\fR (PPID) is recommended in scripts that send several messages. + +Note that system logging infrastructure (for example systemd when listen on +/dev/log) may follow local socket credentials to overwrite in the message +specified PID. +.BR logger(1) +is able to to set the socket credentials to the \fIid\fR if you have +root permissions and process with the specified PID exists, otherwise +the socket credentials are not modified and the problem is silently ignored. .TP .BR \-\-journald [ =\fIfile ] Write a systemd journal entry. The entry is read from the given \fIfile\fR, diff --git a/misc-utils/logger.c b/misc-utils/logger.c index d5683b6913..e4cb12ae99 100644 --- a/misc-utils/logger.c +++ b/misc-utils/logger.c @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include "all-io.h" #include "c.h" @@ -444,6 +446,12 @@ static void write_output(const struct logger_ctl *ctl, const char *const msg) if (!ctl->noact) { struct msghdr msg = { 0 }; + struct cmsghdr *cmhp; + struct ucred *cred; + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(struct ucred))]; + } cbuf; /* 4) add extra \n to make sure message is terminated */ if ((ctl->socket_type == TYPE_TCP) && !ctl->octet_count) @@ -452,6 +460,26 @@ static void write_output(const struct logger_ctl *ctl, const char *const msg) msg.msg_iov = iov; msg.msg_iovlen = iovlen; + /* syslog/journald may follow local socket credentials rather + * than in the message PID. If we use --id as root than we can + * force kernel to accept another valid PID than the real logger(1) + * PID. + */ + if (ctl->pid && !ctl->server && ctl->pid != getpid() + && geteuid() == 0 && kill(ctl->pid, 0) == 0) { + + msg.msg_control = cbuf.control; + msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); //sizeof(cbuf); + + cmhp = CMSG_FIRSTHDR(&msg); + cmhp->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + cmhp->cmsg_level = SOL_SOCKET; + cmhp->cmsg_type = SCM_CREDENTIALS; + cred = (struct ucred *) CMSG_DATA(cmhp); + + cred->pid = ctl->pid; + } + if (sendmsg(ctl->fd, &msg, 0) < 0) warn(_("send message failed")); }