summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libsystemd/sd-daemon/sd-daemon.c61
1 files changed, 27 insertions, 34 deletions
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 0842aba9cb..82ac72c72a 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -350,12 +350,10 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char
.msg_iovlen = 1,
.msg_name = &sockaddr,
};
- struct cmsghdr *control;
_cleanup_close_ int fd = -1;
struct cmsghdr *cmsg = NULL;
const char *e;
- size_t controllen_without_ucred = 0;
- bool try_without_ucred = false;
+ bool have_pid;
int r;
if (!state) {
@@ -394,42 +392,37 @@ _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);
- control = alloca(CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * n_fds));
+ have_pid = pid != 0 && pid != getpid();
- if (n_fds > 0) {
- msghdr.msg_control = control;
- msghdr.msg_controllen = CMSG_LEN(sizeof(int) * n_fds);
+ if (n_fds > 0 || have_pid) {
+ msghdr.msg_controllen = CMSG_SPACE(sizeof(int) * n_fds) +
+ CMSG_SPACE(sizeof(struct ucred) * have_pid);
+ msghdr.msg_control = alloca(msghdr.msg_controllen);
cmsg = CMSG_FIRSTHDR(&msghdr);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
+ if (n_fds > 0) {
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
- memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
- }
-
- if (pid != 0 && pid != getpid()) {
- struct ucred *ucred;
-
- try_without_ucred = true;
- controllen_without_ucred = msghdr.msg_controllen;
+ memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
- msghdr.msg_control = control;
- msghdr.msg_controllen += CMSG_LEN(sizeof(struct ucred));
+ if (have_pid)
+ assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg));
+ }
- if (cmsg)
- cmsg = CMSG_NXTHDR(&msghdr, cmsg);
- else
- cmsg = CMSG_FIRSTHDR(&msghdr);
+ if (have_pid) {
+ struct ucred *ucred;
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_CREDENTIALS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_CREDENTIALS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
- ucred = (struct ucred*) CMSG_DATA(cmsg);
- ucred->pid = pid;
- ucred->uid = getuid();
- ucred->gid = getgid();
+ ucred = (struct ucred*) CMSG_DATA(cmsg);
+ ucred->pid = pid;
+ ucred->uid = getuid();
+ ucred->gid = getgid();
+ }
}
/* First try with fake ucred data, as requested */
@@ -439,10 +432,10 @@ _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 (try_without_ucred) {
- if (controllen_without_ucred <= 0)
+ if (have_pid) {
+ msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
+ if (msghdr.msg_controllen == 0)
msghdr.msg_control = NULL;
- msghdr.msg_controllen = controllen_without_ucred;
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
r = 1;