From d06dfdde758e178d1ae20756890302a5c265ac08 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 5 Jan 2018 13:24:58 +0100
Subject: [PATCH] sd-dameon: also sent ucred when our UID differs from EUID
Let's be explicit, and always send the messages from our UID and never
our EUID. Previously this behaviour was conditionalized only on whether
the PID was specified, which made this non-obvious.
(cherry picked from commit 9e1d021ee3f147486c5cfac69b3cbf6f4b36eb79)
Related: #1663143
---
src/libsystemd/sd-daemon/sd-daemon.c | 39 +++++++++++++++++++---------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 2c4dd9d225..82483a38e6 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -40,6 +40,8 @@
#include "socket-util.h"
#include "sd-daemon.h"
+#define SNDBUF_SIZE (8*1024*1024)
+
_public_ int sd_listen_fds(int unset_environment) {
const char *e;
unsigned n;
@@ -340,7 +342,13 @@ _public_ int sd_is_mq(int fd, const char *path) {
return 1;
}
-_public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds) {
+_public_ int sd_pid_notify_with_fds(
+ pid_t pid,
+ int unset_environment,
+ const char *state,
+ const int *fds,
+ unsigned n_fds) {
+
union sockaddr_union sockaddr = {
.sa.sa_family = AF_UNIX,
};
@@ -355,7 +363,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
_cleanup_close_ int fd = -1;
struct cmsghdr *cmsg = NULL;
const char *e;
- bool have_pid;
+ bool send_ucred;
int r;
if (!state) {
@@ -384,6 +392,8 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
goto finish;
}
+ (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
+
iovec.iov_len = strlen(state);
strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
@@ -394,13 +404,18 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
msghdr.msg_namelen = sizeof(struct sockaddr_un);
- have_pid = pid != 0 && pid != getpid();
+ send_ucred =
+ (pid != 0 && pid != getpid()) ||
+ getuid() != geteuid() ||
+ getgid() != getegid();
+
+ if (n_fds > 0 || send_ucred) {
+ /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
+ msghdr.msg_controllen =
+ (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
+ (send_ucred ? CMSG_SPACE(sizeof(struct ucred)) : 0);
- if (n_fds > 0 || have_pid) {
- /* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */
- msghdr.msg_controllen = (n_fds ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
- CMSG_SPACE(sizeof(struct ucred)) * have_pid;
- msghdr.msg_control = alloca(msghdr.msg_controllen);
+ msghdr.msg_control = alloca0(msghdr.msg_controllen);
cmsg = CMSG_FIRSTHDR(&msghdr);
if (n_fds > 0) {
@@ -410,11 +425,11 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
- if (have_pid)
+ if (send_ucred)
assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg));
}
- if (have_pid) {
+ if (send_ucred) {
struct ucred *ucred;
cmsg->cmsg_level = SOL_SOCKET;
@@ -422,7 +437,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
ucred = (struct ucred*) CMSG_DATA(cmsg);
- ucred->pid = pid;
+ ucred->pid = pid != 0 ? pid : getpid();
ucred->uid = getuid();
ucred->gid = getgid();
}
@@ -435,7 +450,7 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
}
/* If that failed, try with our own ucred instead */
- if (have_pid) {
+ if (send_ucred) {
msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
if (msghdr.msg_controllen == 0)
msghdr.msg_control = NULL;