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 <kzak@redhat.com>
This commit is contained in:
parent
17c8aa1dc0
commit
27a9eb5359
|
@ -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,
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue