]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
logger: use --id as local socket credentials
authorKarel Zak <kzak@redhat.com>
Thu, 29 Oct 2015 10:18:21 +0000 (11:18 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 29 Oct 2015 10:18:21 +0000 (11:18 +0100)
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 <kzak@redhat.com>
misc-utils/logger.1
misc-utils/logger.c

index fe525042f775552906a2e717a51608631c50833e..81751f217ab2be26c40347c43fc6219e986ac652 100644 (file)
@@ -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,
index d5683b69130f2f4cd90c02ecb6574ce170353fce..e4cb12ae9968b29a2030b96f3374e490df7b7fe0 100644 (file)
@@ -51,6 +51,8 @@
 #include <netdb.h>
 #include <getopt.h>
 #include <pwd.h>
+#include <sys/types.h>
+#include <signal.h>
 
 #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"));
        }