Он получает pid через вспомогательные данные SCM_CREDENTIALS
на сокете unix с помощью recvmsg()
, см. unix(7)
. Учетные данные не обязательно отправлять явно.
Пример:
$ cc -Wall scm_cred.c -o scm_cred
$./scm_cred
scm_cred: received from 10114: pid=10114 uid=2000 gid=2000
Процессы с данными CAP_SYS_ADMIN
могут отправлять любой pid через SCM_CREDENTIALS
; в случае systemd-journald
это означает, что они могут подделывать записи, как если бы они были зарегистрированы другим процессом:
# cc -Wall fake.c -o fake
# setcap CAP_SYS_ADMIN+ep fake
$./fake `pgrep -f /usr/sbin/sshd`
# journalctl --no-pager -n 1
...
Dec 29 11:04:57 debin sshd[419]: fake log message from 14202
# rm fake
# lsb_release -d
Description: Debian GNU/Linux 9.6 (stretch)
systemd-journald
обрабатывает дейтаграммы и учетные данные, отправленные через вспомогательные данные, в функцииserver_process_datagram()
из journald-server.c
. Обе стандартные функции syslog(3)
из libc
и sd_journal_sendv()
из libsystemd
будут отправлять свои данные через сокет SOCK_DGRAM
по умолчанию, а getsockopt(SO_PEERCRED)
не работает с дейтаграммами (без установления соединения ). Ни systemd-journald
, ни rsyslogd
не принимают соединения SOCK_STREAM
на /dev/log
.
скм _доп.с
#define _GNU_SOURCE 1
#include
#include
#include
#include
int main(void){
int fd[2]; pid_t pid;
if(socketpair(AF_LOCAL, SOCK_DGRAM, 0, fd)) err(1, "socketpair");
if((pid = fork()) == -1) err(1, "fork");
if(pid){ /* parent */
int on = 1;
union {
struct cmsghdr h;
char data[CMSG_SPACE(sizeof(struct ucred))];
} buf;
struct msghdr m = {0};
struct ucred *uc = (struct ucred*)CMSG_DATA(&buf.h);
m.msg_control = &buf;
m.msg_controllen = sizeof buf;
if(setsockopt(fd[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof on))
err(1, "setsockopt");
if(recvmsg(fd[0], &m, 0) == -1) err(1, "recvmsg");
warnx("received from %d: pid=%d uid=%d gid=%d", pid,
uc->pid, uc->uid, uc->gid);
}else /* child */
write(fd[1], 0, 0);
return 0;
}
фейк.с
#define _GNU_SOURCE 1
#include
#include
#include
#include
#include
#include
int main(int ac, char **av){
union {
struct cmsghdr h;
char data[CMSG_SPACE(sizeof(struct ucred))];
} cm;
int fd; char buf[256];
struct ucred *uc = (struct ucred*)CMSG_DATA(&cm.h);
struct msghdr m = {0};
struct sockaddr_un ua = {AF_UNIX, "/dev/log"};
struct iovec iov = {buf};
if((fd = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1) err(1, "socket");
if(connect(fd, (struct sockaddr*)&ua, SUN_LEN(&ua))) err(1, "connect");
m.msg_control = &cm;
m.msg_controllen = cm.h.cmsg_len = CMSG_LEN(sizeof(struct ucred));
cm.h.cmsg_level = SOL_SOCKET;
cm.h.cmsg_type = SCM_CREDENTIALS;
uc->pid = ac > 1 ? atoi(av[1]) : getpid();
uc->uid = ac > 2 ? atoi(av[2]) : geteuid();
uc->gid = ac > 3 ? atoi(av[3]) : getegid();
iov.iov_len = snprintf(buf, sizeof buf, "<13>%s from %d",
ac > 4 ? av[4] : "fake log message", getpid());
if(iov.iov_len >= sizeof buf) errx(1, "message too long");
m.msg_iov = &iov;
m.msg_iovlen = 1;
if(sendmsg(fd, &m, 0) == -1) err(1, "sendmsg");
return 0;
}
Похоже, что ссылки на скачивание содержат ошибку. На странице загрузки версии KDE ссылка для скачивания :
.https://download.manjaro.org/kde/21.0.1/manjaro-kde-21.0.1-210410-linux510.iso/download
Если убрать /download
в конце, ссылка будет работать корректно:
https://download.manjaro.org/kde/21.0.1/manjaro-kde-21.0.1-210410-linux510.iso