#include "main-func.h"
#include "memfd-util.h"
#include "mkdir-label.h"
+#include "notify-util.h"
#include "os-util.h"
#include "process-util.h"
#include "service-util.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager *, manager_free);
static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- char buf[NOTIFY_BUFFER_MAX+1];
- struct iovec iovec = {
- .iov_base = buf,
- .iov_len = sizeof(buf)-1,
- };
- CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control;
- struct msghdr msghdr = {
- .msg_iov = &iovec,
- .msg_iovlen = 1,
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- };
- struct ucred *ucred;
Manager *m = ASSERT_PTR(userdata);
- Job *j;
- ssize_t n;
- char *version, *progress, *errno_str, *ready;
-
- n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (ERRNO_IS_NEG_TRANSIENT(n))
- return 0;
- if (n == -ECHRNG) {
- log_warning_errno(n, "Got message with truncated control data (unexpected fds sent?), ignoring.");
- return 0;
- }
- if (n == -EXFULL) {
- log_warning_errno(n, "Got message with truncated payload data, ignoring.");
- return 0;
- }
- if (n < 0)
- return (int) n;
+ int r;
- cmsg_close_all(&msghdr);
+ assert(fd >= 0);
- ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
- if (!ucred || ucred->pid <= 0) {
- log_warning("Got notification datagram lacking credential information, ignoring.");
+ _cleanup_(pidref_done) PidRef sender_pidref = PIDREF_NULL;
+ _cleanup_free_ char *buf = NULL;
+ r = notify_recv(fd, &buf, /* ret_ucred= */ NULL, &sender_pidref);
+ if (r == -EAGAIN)
return 0;
- }
+ if (r < 0)
+ return log_warning_errno(r, "Failed to receive notification message: %m");
+ Job *j;
HASHMAP_FOREACH(j, m->jobs) {
- pid_t pid;
- assert_se(sd_event_source_get_child_pid(j->child, &pid) >= 0);
+ PidRef child_pidref = PIDREF_NULL;
+
+ r = event_source_get_child_pidref(j->child, &child_pidref);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to get child pidref: %m");
- if (ucred->pid == pid)
+ if (pidref_equal(&sender_pidref, &child_pidref))
break;
}
-
if (!j) {
log_warning("Got notification datagram from unexpected peer, ignoring.");
return 0;
}
- buf[n] = 0;
-
- version = find_line_startswith(buf, "X_SYSUPDATE_VERSION=");
- progress = find_line_startswith(buf, "X_SYSUPDATE_PROGRESS=");
- errno_str = find_line_startswith(buf, "ERRNO=");
- ready = find_line_startswith(buf, "READY=1");
-
+ char *version = find_line_startswith(buf, "X_SYSUPDATE_VERSION=");
if (version)
job_on_version(j, truncate_nl(version));
+ char *progress = find_line_startswith(buf, "X_SYSUPDATE_PROGRESS=");
if (progress)
job_on_progress(j, truncate_nl(progress));
+ char *errno_str = find_line_startswith(buf, "ERRNO=");
if (errno_str)
job_on_errno(j, truncate_nl(errno_str));
/* Should come last, since this might actually detach the job */
+ const char *ready = find_line_startswith(buf, "READY=1");
if (ready)
job_on_ready(j);
if (r < 0)
return r;
+ r = setsockopt_int(notify_fd, SOL_SOCKET, SO_PASSPIDFD, true);
+ if (r < 0)
+ log_debug_errno(r, "Failed to enable SO_PASSPIDFD, ignoring: %m");
+
r = sd_event_add_io(m->event, &m->notify_event, notify_fd, EPOLLIN, manager_on_notify, m);
if (r < 0)
return r;