diff -Nru systemd-229/debian/changelog systemd-229/debian/changelog --- systemd-229/debian/changelog 2016-07-12 17:37:42.000000000 +0200 +++ systemd-229/debian/changelog 2016-08-12 19:41:43.000000000 +0200 @@ -1,3 +1,10 @@ +systemd (229-4ubuntu8) xenial-proposed; urgency=medium + + * core: use an AF_UNIX/SOCK_DGRAM socket for cgroup agent notification. + (LP: #1591411) + + -- Ɓukasz 'sil2100' Zemczak Fri, 12 Aug 2016 19:35:08 +0200 + systemd (229-4ubuntu7) xenial-proposed; urgency=medium * Add pre-dependency to dpkg >= 1.17.14 on udev, to ensure that diff -Nru systemd-229/debian/patches/core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-agent-no.patch systemd-229/debian/patches/core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-agent-no.patch --- systemd-229/debian/patches/core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-agent-no.patch 1970-01-01 01:00:00.000000000 +0100 +++ systemd-229/debian/patches/core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-agent-no.patch 2016-08-12 19:41:36.000000000 +0200 @@ -0,0 +1,1048 @@ +From: Lennart Poettering +Date: Thu, 5 May 2016 22:26:09 +0200 +Subject: core: use an AF_UNIX/SOCK_DGRAM socket for cgroup agent notification + +Index: systemd-229/src/basic/log.c +=================================================================== +--- systemd-229.orig/src/basic/log.c ++++ systemd-229/src/basic/log.c +@@ -165,7 +165,7 @@ static int log_open_syslog(void) { + goto fail; + } + +- if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { ++ if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + safe_close(syslog_fd); + + /* Some legacy syslog systems still use stream +@@ -177,7 +177,7 @@ static int log_open_syslog(void) { + goto fail; + } + +- if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { ++ if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + r = -errno; + goto fail; + } +@@ -215,7 +215,7 @@ static int log_open_journal(void) { + goto fail; + } + +- if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { ++ if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + r = -errno; + goto fail; + } +Index: systemd-229/src/basic/socket-util.h +=================================================================== +--- systemd-229.orig/src/basic/socket-util.h ++++ systemd-229/src/basic/socket-util.h +@@ -137,3 +137,14 @@ ssize_t next_datagram_size_fd(int fd); + + #define CMSG_FOREACH(cmsg, mh) \ + for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) ++ ++/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */ ++#define SOCKADDR_UN_LEN(sa) \ ++ ({ \ ++ const struct sockaddr_un *_sa = &(sa); \ ++ assert(_sa->sun_family == AF_UNIX); \ ++ offsetof(struct sockaddr_un, sun_path) + \ ++ (_sa->sun_path[0] == 0 ? \ ++ 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \ ++ strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \ ++ }) +Index: systemd-229/src/cgroups-agent/cgroups-agent.c +=================================================================== +--- systemd-229.orig/src/cgroups-agent/cgroups-agent.c ++++ systemd-229/src/cgroups-agent/cgroups-agent.c +@@ -18,15 +18,22 @@ + ***/ + + #include ++#include + +-#include "sd-bus.h" +- +-#include "bus-util.h" ++#include "fd-util.h" + #include "log.h" ++#include "socket-util.h" + + int main(int argc, char *argv[]) { +- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; +- int r; ++ ++ static const union sockaddr_union sa = { ++ .un.sun_family = AF_UNIX, ++ .un.sun_path = "/run/systemd/cgroups-agent", ++ }; ++ ++ _cleanup_close_ int fd = -1; ++ ssize_t n; ++ size_t l; + + if (argc != 2) { + log_error("Incorrect number of arguments."); +@@ -37,27 +44,22 @@ int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); + +- /* We send this event to the private D-Bus socket and then the +- * system instance will forward this to the system bus. We do +- * this to avoid an activation loop when we start dbus when we +- * are called when the dbus service is shut down. */ +- +- r = bus_connect_system_systemd(&bus); +- if (r < 0) { +- /* If we couldn't connect we assume this was triggered +- * while systemd got restarted/transitioned from +- * initrd to the system, so let's ignore this */ +- log_debug_errno(r, "Failed to get D-Bus connection: %m"); ++ fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); ++ if (fd < 0) { ++ log_debug_errno(errno, "Failed to allocate socket: %m"); ++ return EXIT_FAILURE; ++ } ++ ++ l = strlen(argv[1]); ++ ++ n = sendto(fd, argv[1], l, 0, &sa.sa, SOCKADDR_UN_LEN(sa.un)); ++ if (n < 0) { ++ log_debug_errno(errno, "Failed to send cgroups agent message: %m"); + return EXIT_FAILURE; + } + +- r = sd_bus_emit_signal(bus, +- "/org/freedesktop/systemd1/agent", +- "org.freedesktop.systemd1.Agent", +- "Released", +- "s", argv[1]); +- if (r < 0) { +- log_debug_errno(r, "Failed to send signal message on private connection: %m"); ++ if ((size_t) n != l) { ++ log_debug("Datagram size mismatch"); + return EXIT_FAILURE; + } + +Index: systemd-229/src/core/cgroup.c +=================================================================== +--- systemd-229.orig/src/core/cgroup.c ++++ systemd-229/src/core/cgroup.c +@@ -1312,7 +1312,9 @@ int manager_setup_cgroup(Manager *m) { + if (r < 0) + return log_error_errno(r, "Failed to watch control group inotify object: %m"); + +- r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_IDLE - 5); ++ /* Process cgroup empty notifications early, but after service notifications and SIGCHLD. Also ++ * see handling of cgroup agent notifications, for the classic cgroup hierarchy support. */ ++ r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-5); + if (r < 0) + return log_error_errno(r, "Failed to set priority of inotify event source: %m"); + +@@ -1458,6 +1460,8 @@ int manager_notify_cgroup_empty(Manager + assert(m); + assert(cgroup); + ++ log_debug("Got cgroup empty notification for: %s", cgroup); ++ + u = manager_get_unit_by_cgroup(m, cgroup); + if (!u) + return 0; +Index: systemd-229/src/core/dbus.c +=================================================================== +--- systemd-229.orig/src/core/dbus.c ++++ systemd-229/src/core/dbus.c +@@ -71,28 +71,42 @@ int bus_send_queued_message(Manager *m) + return 0; + } + ++int bus_forward_agent_released(Manager *m, const char *path) { ++ int r; ++ ++ assert(m); ++ assert(path); ++ ++ if (!MANAGER_IS_SYSTEM(m)) ++ return 0; ++ ++ if (!m->system_bus) ++ return 0; ++ ++ /* If we are running a system instance we forward the agent message on the system bus, so that the user ++ * instances get notified about this, too */ ++ ++ r = sd_bus_emit_signal(m->system_bus, ++ "/org/freedesktop/systemd1/agent", ++ "org.freedesktop.systemd1.Agent", ++ "Released", ++ "s", path); ++ if (r < 0) ++ return log_warning_errno(r, "Failed to propagate agent release message: %m"); ++ ++ return 1; ++} ++ + static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; +- const char *cgroup, *me; + Manager *m = userdata; ++ const char *cgroup; + uid_t sender_uid; +- sd_bus *bus; + int r; + + assert(message); + assert(m); + +- /* ignore recursive events sent by us on the system/user bus */ +- bus = sd_bus_message_get_bus(message); +- if (!sd_bus_is_server(bus)) { +- r = sd_bus_get_unique_name(bus, &me); +- if (r < 0) +- return r; +- +- if (streq_ptr(sd_bus_message_get_sender(message), me)) +- return 0; +- } +- + /* only accept org.freedesktop.systemd1.Agent from UID=0 */ + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) +@@ -111,15 +125,6 @@ static int signal_agent_released(sd_bus_ + + manager_notify_cgroup_empty(m, cgroup); + +- /* if running as system-instance, forward under our name */ +- if (m->running_as == MANAGER_SYSTEM && m->system_bus) { +- r = sd_bus_message_rewind(message, 1); +- if (r >= 0) +- r = sd_bus_send(m->system_bus, message, NULL); +- if (r < 0) +- log_warning_errno(r, "Failed to forward Released message: %m"); +- } +- + return 0; + } + +@@ -690,25 +695,6 @@ static int bus_on_connection(sd_event_so + return 0; + } + +- if (m->running_as == MANAGER_SYSTEM) { +- /* When we run as system instance we get the Released +- * signal via a direct connection */ +- +- r = sd_bus_add_match( +- bus, +- NULL, +- "type='signal'," +- "interface='org.freedesktop.systemd1.Agent'," +- "member='Released'," +- "path='/org/freedesktop/systemd1/agent'", +- signal_agent_released, m); +- +- if (r < 0) { +- log_warning_errno(r, "Failed to register Released match on new connection bus: %m"); +- return 0; +- } +- } +- + r = bus_setup_disconnected_match(m, bus); + if (r < 0) + return 0; +@@ -906,8 +892,8 @@ static int bus_setup_system(Manager *m, + assert(m); + assert(bus); + +- /* On kdbus or if we are a user instance we get the Released message via the system bus */ +- if (m->running_as == MANAGER_USER || m->kdbus_fd >= 0) { ++ /* if we are a user instance we get the Released message via the system bus */ ++ if (m->running_as == MANAGER_USER) { + r = sd_bus_add_match( + bus, + NULL, +@@ -990,7 +976,7 @@ static int bus_init_private(Manager *m) + return 0; + + strcpy(sa.un.sun_path, "/run/systemd/private"); +- salen = offsetof(union sockaddr_union, un.sun_path) + strlen("/run/systemd/private"); ++ salen = SOCKADDR_UN_LEN(sa.un); + } else { + size_t left = sizeof(sa.un.sun_path); + char *p = sa.un.sun_path; +Index: systemd-229/src/core/dbus.h +=================================================================== +--- systemd-229.orig/src/core/dbus.h ++++ systemd-229/src/core/dbus.h +@@ -40,3 +40,5 @@ int bus_verify_manage_units_async(Manage + int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error); + int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error); + int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error); ++ ++int bus_forward_agent_released(Manager *m, const char *path); +Index: systemd-229/src/core/execute.c +=================================================================== +--- systemd-229.orig/src/core/execute.c ++++ systemd-229/src/core/execute.c +@@ -271,7 +271,7 @@ static int connect_journal_socket(int fd + } + } + +- r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); ++ r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + r = -errno; + +Index: systemd-229/src/core/manager.c +=================================================================== +--- systemd-229.orig/src/core/manager.c ++++ systemd-229/src/core/manager.c +@@ -85,6 +85,7 @@ + #include "watchdog.h" + + #define NOTIFY_RCVBUF_SIZE (8*1024*1024) ++#define CGROUPS_AGENT_RCVBUF_SIZE (8*1024*1024) + + /* Initial delay and the interval for printing status messages about running jobs */ + #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) +@@ -92,6 +93,7 @@ + #define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3 + + static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); ++static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); + static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); + static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); + static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +@@ -483,11 +485,11 @@ static int manager_setup_signals(Manager + + (void) sd_event_source_set_description(m->signal_event_source, "manager-signal"); + +- /* Process signals a bit earlier than the rest of things, but +- * later than notify_fd processing, so that the notify +- * processing can still figure out to which process/service a +- * message belongs, before we reap the process. */ +- r = sd_event_source_set_priority(m->signal_event_source, SD_EVENT_PRIORITY_NORMAL-5); ++ /* Process signals a bit earlier than the rest of things, but later than notify_fd processing, so that the ++ * notify processing can still figure out to which process/service a message belongs, before we reap the ++ * process. Also, process this before handling cgroup notifications, so that we always collect child exit ++ * status information before detecting that there's no process in a cgroup. */ ++ r = sd_event_source_set_priority(m->signal_event_source, SD_EVENT_PRIORITY_NORMAL-6); + if (r < 0) + return r; + +@@ -586,12 +588,12 @@ int manager_new(ManagerRunningAs running + + m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1; + +- m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = +- m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = -1; ++ m->pin_cgroupfs_fd = m->notify_fd = m->cgroups_agent_fd = m->signal_fd = m->time_change_fd = ++ m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = ++ m->ask_password_inotify_fd = -1; + + m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ + +- m->ask_password_inotify_fd = -1; + m->have_ask_password = -EINVAL; /* we don't know */ + m->first_boot = -1; + +@@ -713,7 +715,7 @@ static int manager_setup_notify(Manager + (void) unlink(m->notify_socket); + + strncpy(sa.un.sun_path, m->notify_socket, sizeof(sa.un.sun_path)-1); +- r = bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); ++ r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + +@@ -732,8 +734,8 @@ static int manager_setup_notify(Manager + if (r < 0) + return log_error_errno(r, "Failed to allocate notify event source: %m"); + +- /* Process signals a bit earlier than SIGCHLD, so that we can +- * still identify to which service an exit message belongs */ ++ /* Process notification messages a bit earlier than SIGCHLD, so that we can still identify to which ++ * service an exit message belongs. */ + r = sd_event_source_set_priority(m->notify_event_source, SD_EVENT_PRIORITY_NORMAL-7); + if (r < 0) + return log_error_errno(r, "Failed to set priority of notify event source: %m"); +@@ -744,6 +746,79 @@ static int manager_setup_notify(Manager + return 0; + } + ++static int manager_setup_cgroups_agent(Manager *m) { ++ ++ static const union sockaddr_union sa = { ++ .un.sun_family = AF_UNIX, ++ .un.sun_path = "/run/systemd/cgroups-agent", ++ }; ++ int r; ++ ++ /* This creates a listening socket we receive cgroups agent messages on. We do not use D-Bus for delivering ++ * these messages from the cgroups agent binary to PID 1, as the cgroups agent binary is very short-living, and ++ * each instance of it needs a new D-Bus connection. Since D-Bus connections are SOCK_STREAM/AF_UNIX, on ++ * overloaded systems the backlog of the D-Bus socket becomes relevant, as not more than the configured number ++ * of D-Bus connections may be queued until the kernel will start dropping further incoming connections, ++ * possibly resulting in lost cgroups agent messages. To avoid this, we'll use a private SOCK_DGRAM/AF_UNIX ++ * socket, where no backlog is relevant as communication may take place without an actual connect() cycle, and ++ * we thus won't lose messages. ++ * ++ * Note that PID 1 will forward the agent message to system bus, so that the user systemd instance may listen ++ * to it. The system instance hence listens on this special socket, but the user instances listen on the system ++ * bus for these messages. */ ++ ++ if (m->test_run) ++ return 0; ++ ++ if (!MANAGER_IS_SYSTEM(m)) ++ return 0; ++ ++ if (cg_unified() > 0) /* We don't need this anymore on the unified hierarchy */ ++ return 0; ++ ++ if (m->cgroups_agent_fd < 0) { ++ _cleanup_close_ int fd = -1; ++ ++ /* First free all secondary fields */ ++ m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source); ++ ++ fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); ++ if (fd < 0) ++ return log_error_errno(errno, "Failed to allocate cgroups agent socket: %m"); ++ ++ fd_inc_rcvbuf(fd, CGROUPS_AGENT_RCVBUF_SIZE); ++ ++ (void) unlink(sa.un.sun_path); ++ ++ /* Only allow root to connect to this socket */ ++ RUN_WITH_UMASK(0077) ++ r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); ++ if (r < 0) ++ return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); ++ ++ m->cgroups_agent_fd = fd; ++ fd = -1; ++ } ++ ++ if (!m->cgroups_agent_event_source) { ++ r = sd_event_add_io(m->event, &m->cgroups_agent_event_source, m->cgroups_agent_fd, EPOLLIN, manager_dispatch_cgroups_agent_fd, m); ++ if (r < 0) ++ return log_error_errno(r, "Failed to allocate cgroups agent event source: %m"); ++ ++ /* Process cgroups notifications early, but after having processed service notification messages or ++ * SIGCHLD signals, so that a cgroup running empty is always just the last safety net of notification, ++ * and we collected the metadata the notification and SIGCHLD stuff offers first. Also see handling of ++ * cgroup inotify for the unified cgroup stuff. */ ++ r = sd_event_source_set_priority(m->cgroups_agent_event_source, SD_EVENT_PRIORITY_NORMAL-5); ++ if (r < 0) ++ return log_error_errno(r, "Failed to set priority of cgroups agent event source: %m"); ++ ++ (void) sd_event_source_set_description(m->cgroups_agent_event_source, "manager-cgroups-agent"); ++ } ++ ++ return 0; ++} ++ + static int manager_setup_kdbus(Manager *m) { + _cleanup_free_ char *p = NULL; + +@@ -954,12 +1029,14 @@ Manager* manager_free(Manager *m) { + + sd_event_source_unref(m->signal_event_source); + sd_event_source_unref(m->notify_event_source); ++ sd_event_source_unref(m->cgroups_agent_event_source); + sd_event_source_unref(m->time_change_event_source); + sd_event_source_unref(m->jobs_in_progress_event_source); + sd_event_source_unref(m->run_queue_event_source); + + safe_close(m->signal_fd); + safe_close(m->notify_fd); ++ safe_close(m->cgroups_agent_fd); + safe_close(m->time_change_fd); + safe_close(m->kdbus_fd); + +@@ -1159,6 +1236,10 @@ int manager_startup(Manager *m, FILE *se + if (q < 0 && r == 0) + r = q; + ++ q = manager_setup_cgroups_agent(m); ++ if (q < 0 && r == 0) ++ r = q; ++ + /* We might have deserialized the kdbus control fd, but if we + * didn't, then let's create the bus now. */ + manager_setup_kdbus(m); +@@ -1492,6 +1573,35 @@ static unsigned manager_dispatch_dbus_qu + return n; + } + ++static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { ++ Manager *m = userdata; ++ char buf[PATH_MAX+1]; ++ ssize_t n; ++ ++ n = recv(fd, buf, sizeof(buf), 0); ++ if (n < 0) ++ return log_error_errno(errno, "Failed to read cgroups agent message: %m"); ++ if (n == 0) { ++ log_error("Got zero-length cgroups agent message, ignoring."); ++ return 0; ++ } ++ if ((size_t) n >= sizeof(buf)) { ++ log_error("Got overly long cgroups agent message, ignoring."); ++ return 0; ++ } ++ ++ if (memchr(buf, 0, n)) { ++ log_error("Got cgroups agent message with embedded NUL byte, ignoring."); ++ return 0; ++ } ++ buf[n] = 0; ++ ++ manager_notify_cgroup_empty(m, buf); ++ bus_forward_agent_released(m, buf); ++ ++ return 0; ++} ++ + static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) { + _cleanup_strv_free_ char **tags = NULL; + +@@ -2146,11 +2256,10 @@ void manager_send_unit_audit(Manager *m, + } + + void manager_send_unit_plymouth(Manager *m, Unit *u) { +- union sockaddr_union sa = PLYMOUTH_SOCKET; +- +- int n = 0; ++ static const union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_free_ char *message = NULL; + _cleanup_close_ int fd = -1; ++ int n = 0; + + /* Don't generate plymouth events if the service was already + * started and we're just deserializing */ +@@ -2176,7 +2285,7 @@ void manager_send_unit_plymouth(Manager + return; + } + +- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) { ++ if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + + if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) + log_error_errno(errno, "connect() failed: %m"); +@@ -2276,6 +2385,16 @@ int manager_serialize(Manager *m, FILE * + fprintf(f, "notify-socket=%s\n", m->notify_socket); + } + ++ if (m->cgroups_agent_fd >= 0) { ++ int copy; ++ ++ copy = fdset_put_dup(fds, m->cgroups_agent_fd); ++ if (copy < 0) ++ return copy; ++ ++ fprintf(f, "cgroups-agent-fd=%i\n", copy); ++ } ++ + if (m->kdbus_fd >= 0) { + int copy; + +@@ -2443,6 +2562,17 @@ int manager_deserialize(Manager *m, FILE + free(m->notify_socket); + m->notify_socket = n; + ++ } else if (startswith(l, "cgroups-agent-fd=")) { ++ int fd; ++ ++ if (safe_atoi(l + 17, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) ++ log_debug("Failed to parse cgroups agent fd: %s", l + 10); ++ else { ++ m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source); ++ safe_close(m->cgroups_agent_fd); ++ m->cgroups_agent_fd = fdset_remove(fds, fd); ++ } ++ + } else if (startswith(l, "kdbus-fd=")) { + int fd; + +@@ -2567,6 +2697,10 @@ int manager_reload(Manager *m) { + if (q < 0 && r >= 0) + r = q; + ++ q = manager_setup_cgroups_agent(m); ++ if (q < 0 && r >= 0) ++ r = q; ++ + /* Third, fire things up! */ + manager_coldplug(m); + +Index: systemd-229/src/core/manager.h +=================================================================== +--- systemd-229.orig/src/core/manager.h ++++ systemd-229/src/core/manager.h +@@ -132,6 +132,9 @@ struct Manager { + int notify_fd; + sd_event_source *notify_event_source; + ++ int cgroups_agent_fd; ++ sd_event_source *cgroups_agent_event_source; ++ + int signal_fd; + sd_event_source *signal_event_source; + +Index: systemd-229/src/coredump/coredump.c +=================================================================== +--- systemd-229.orig/src/coredump/coredump.c ++++ systemd-229/src/coredump/coredump.c +@@ -848,7 +848,7 @@ static int send_iovec(const struct iovec + if (fd < 0) + return log_error_errno(errno, "Failed to create coredump socket: %m"); + +- if (connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)) < 0) ++ if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return log_error_errno(errno, "Failed to connect to coredump service: %m"); + + for (i = 0; i < n_iovec; i++) { +Index: systemd-229/src/fsck/fsck.c +=================================================================== +--- systemd-229.orig/src/fsck/fsck.c ++++ systemd-229/src/fsck/fsck.c +@@ -262,7 +262,7 @@ static int fsck_progress_socket(void) { + if (fd < 0) + return log_warning_errno(errno, "socket(): %m"); + +- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { ++ if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + r = log_full_errno(errno == ECONNREFUSED || errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + errno, "Failed to connect to progress socket %s, ignoring: %m", sa.un.sun_path); + safe_close(fd); +Index: systemd-229/src/import/importd.c +=================================================================== +--- systemd-229.orig/src/import/importd.c ++++ systemd-229/src/import/importd.c +@@ -677,7 +677,7 @@ static int manager_new(Manager **ret) { + (void) mkdir_parents_label(sa.un.sun_path, 0755); + (void) unlink(sa.un.sun_path); + +- if (bind(m->notify_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)) < 0) ++ if (bind(m->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return -errno; + + if (setsockopt(m->notify_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) +Index: systemd-229/src/journal/journal-send.c +=================================================================== +--- systemd-229.orig/src/journal/journal-send.c ++++ systemd-229/src/journal/journal-send.c +@@ -208,13 +208,13 @@ _public_ int sd_journal_sendv(const stru + struct iovec *w; + uint64_t *l; + int i, j = 0; +- struct sockaddr_un sa = { +- .sun_family = AF_UNIX, +- .sun_path = "/run/systemd/journal/socket", ++ static const union sockaddr_union sa = { ++ .un.sun_family = AF_UNIX, ++ .un.sun_path = "/run/systemd/journal/socket", + }; + struct msghdr mh = { +- .msg_name = &sa, +- .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path), ++ .msg_name = (struct sockaddr*) &sa.sa, ++ .msg_namelen = SOCKADDR_UN_LEN(sa.un), + }; + ssize_t k; + bool have_syslog_identifier = false; +@@ -392,7 +392,7 @@ _public_ int sd_journal_perror(const cha + } + + _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) { +- union sockaddr_union sa = { ++ static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/stdout", + }; +@@ -408,7 +408,7 @@ _public_ int sd_journal_stream_fd(const + if (fd < 0) + return -errno; + +- r = connect(fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); ++ r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return -errno; + +Index: systemd-229/src/journal/journald-native.c +=================================================================== +--- systemd-229.orig/src/journal/journald-native.c ++++ systemd-229/src/journal/journald-native.c +@@ -448,24 +448,24 @@ void server_process_native_file( + } + + int server_open_native_socket(Server*s) { ++ ++ static const union sockaddr_union sa = { ++ .un.sun_family = AF_UNIX, ++ .un.sun_path = "/run/systemd/journal/socket", ++ }; + static const int one = 1; + int r; + + assert(s); + + if (s->native_fd < 0) { +- union sockaddr_union sa = { +- .un.sun_family = AF_UNIX, +- .un.sun_path = "/run/systemd/journal/socket", +- }; +- + s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->native_fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + +- unlink(sa.un.sun_path); ++ (void) unlink(sa.un.sun_path); + +- r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); ++ r = bind(s->native_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + +Index: systemd-229/src/journal/journald-server.c +=================================================================== +--- systemd-229.orig/src/journal/journald-server.c ++++ systemd-229/src/journal/journald-server.c +@@ -1691,7 +1691,7 @@ static int server_connect_notify(Server + if (sa.un.sun_path[0] == '@') + sa.un.sun_path[0] = 0; + +- r = connect(s->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(e)); ++ r = connect(s->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "Failed to connect to notify socket: %m"); + +Index: systemd-229/src/journal/journald-stream.c +=================================================================== +--- systemd-229.orig/src/journal/journald-stream.c ++++ systemd-229/src/journal/journald-stream.c +@@ -700,23 +700,22 @@ fail: + } + + int server_open_stdout_socket(Server *s) { ++ static const union sockaddr_union sa = { ++ .un.sun_family = AF_UNIX, ++ .un.sun_path = "/run/systemd/journal/stdout", ++ }; + int r; + + assert(s); + + if (s->stdout_fd < 0) { +- union sockaddr_union sa = { +- .un.sun_family = AF_UNIX, +- .un.sun_path = "/run/systemd/journal/stdout", +- }; +- + s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->stdout_fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + +- unlink(sa.un.sun_path); ++ (void) unlink(sa.un.sun_path); + +- r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); ++ r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + +Index: systemd-229/src/journal/journald-syslog.c +=================================================================== +--- systemd-229.orig/src/journal/journald-syslog.c ++++ systemd-229/src/journal/journald-syslog.c +@@ -52,8 +52,7 @@ static void forward_syslog_iovec(Server + .msg_iov = (struct iovec *) iovec, + .msg_iovlen = n_iovec, + .msg_name = (struct sockaddr*) &sa.sa, +- .msg_namelen = offsetof(union sockaddr_union, un.sun_path) +- + strlen("/run/systemd/journal/syslog"), ++ .msg_namelen = SOCKADDR_UN_LEN(sa.un), + }; + struct cmsghdr *cmsg; + union { +@@ -316,12 +315,12 @@ static void syslog_skip_date(char **buf) + } + + void server_process_syslog_message( +- Server *s, +- const char *buf, +- const struct ucred *ucred, +- const struct timeval *tv, +- const char *label, +- size_t label_len) { ++ Server *s, ++ const char *buf, ++ const struct ucred *ucred, ++ const struct timeval *tv, ++ const char *label, ++ size_t label_len) { + + char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)], + syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)]; +@@ -365,14 +364,12 @@ void server_process_syslog_message( + + if (identifier) { + syslog_identifier = strjoina("SYSLOG_IDENTIFIER=", identifier); +- if (syslog_identifier) +- IOVEC_SET_STRING(iovec[n++], syslog_identifier); ++ IOVEC_SET_STRING(iovec[n++], syslog_identifier); + } + + if (pid) { + syslog_pid = strjoina("SYSLOG_PID=", pid); +- if (syslog_pid) +- IOVEC_SET_STRING(iovec[n++], syslog_pid); ++ IOVEC_SET_STRING(iovec[n++], syslog_pid); + } + + message = strjoina("MESSAGE=", buf); +@@ -383,24 +380,24 @@ void server_process_syslog_message( + } + + int server_open_syslog_socket(Server *s) { ++ ++ static const union sockaddr_union sa = { ++ .un.sun_family = AF_UNIX, ++ .un.sun_path = "/run/systemd/journal/dev-log", ++ }; + static const int one = 1; + int r; + + assert(s); + + if (s->syslog_fd < 0) { +- static const union sockaddr_union sa = { +- .un.sun_family = AF_UNIX, +- .un.sun_path = "/run/systemd/journal/dev-log", +- }; +- + s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->syslog_fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + +- unlink(sa.un.sun_path); ++ (void) unlink(sa.un.sun_path); + +- r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)); ++ r = bind(s->syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + +@@ -437,6 +434,7 @@ int server_open_syslog_socket(Server *s) + + void server_maybe_warn_forward_syslog_missed(Server *s) { + usec_t n; ++ + assert(s); + + if (s->n_forward_syslog_missed <= 0) +Index: systemd-229/src/libsystemd/sd-bus/sd-bus.c +=================================================================== +--- systemd-229.orig/src/libsystemd/sd-bus/sd-bus.c ++++ systemd-229/src/libsystemd/sd-bus/sd-bus.c +@@ -839,7 +839,7 @@ static int parse_container_unix_address( + + b->sockaddr.un.sun_family = AF_UNIX; + strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path)); +- b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + strlen("/var/run/dbus/system_bus_socket"); ++ b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un); + + return 0; + } +Index: systemd-229/src/libsystemd/sd-daemon/sd-daemon.c +=================================================================== +--- systemd-229.orig/src/libsystemd/sd-daemon/sd-daemon.c ++++ systemd-229/src/libsystemd/sd-daemon/sd-daemon.c +@@ -458,9 +458,7 @@ _public_ int sd_pid_notify_with_fds(pid_ + if (sockaddr.un.sun_path[0] == '@') + sockaddr.un.sun_path[0] = 0; + +- msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); +- if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) +- msghdr.msg_namelen = sizeof(struct sockaddr_un); ++ msghdr.msg_namelen = SOCKADDR_UN_LEN(sockaddr.un); + + have_pid = pid != 0 && pid != getpid(); + +Index: systemd-229/src/login/pam_systemd.c +=================================================================== +--- systemd-229.orig/src/login/pam_systemd.c ++++ systemd-229/src/login/pam_systemd.c +@@ -150,7 +150,7 @@ static int get_seat_from_display(const c + if (fd < 0) + return -errno; + +- if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) ++ if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return -errno; + + r = getpeercred(fd, &ucred); +Index: systemd-229/src/reply-password/reply-password.c +=================================================================== +--- systemd-229.orig/src/reply-password/reply-password.c ++++ systemd-229/src/reply-password/reply-password.c +@@ -26,14 +26,12 @@ + #include "fd-util.h" + #include "log.h" + #include "macro.h" ++#include "socket-util.h" + #include "string-util.h" + #include "util.h" + + static int send_on_socket(int fd, const char *socket_name, const void *packet, size_t size) { +- union { +- struct sockaddr sa; +- struct sockaddr_un un; +- } sa = { ++ union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + }; + +@@ -43,7 +41,7 @@ static int send_on_socket(int fd, const + + strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path)); + +- if (sendto(fd, packet, size, MSG_NOSIGNAL, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)) < 0) ++ if (sendto(fd, packet, size, MSG_NOSIGNAL, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return log_error_errno(errno, "Failed to send: %m"); + + return 0; +Index: systemd-229/src/shared/ask-password-api.c +=================================================================== +--- systemd-229.orig/src/shared/ask-password-api.c ++++ systemd-229/src/shared/ask-password-api.c +@@ -431,7 +431,7 @@ static int create_socket(char **name) { + snprintf(sa.un.sun_path, sizeof(sa.un.sun_path)-1, "/run/systemd/ask-password/sck.%" PRIx64, random_u64()); + + RUN_WITH_UMASK(0177) { +- if (bind(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) ++ if (bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return -errno; + } + +Index: systemd-229/src/socket-proxy/socket-proxyd.c +=================================================================== +--- systemd-229.orig/src/socket-proxy/socket-proxyd.c ++++ systemd-229/src/socket-proxy/socket-proxyd.c +@@ -400,28 +400,19 @@ static int resolve_remote(Connection *c) + + union sockaddr_union sa = {}; + const char *node, *service; +- socklen_t salen; + int r; + + if (path_is_absolute(arg_remote_host)) { + sa.un.sun_family = AF_UNIX; +- strncpy(sa.un.sun_path, arg_remote_host, sizeof(sa.un.sun_path)-1); +- sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0; +- +- salen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path); +- +- return connection_start(c, &sa.sa, salen); ++ strncpy(sa.un.sun_path, arg_remote_host, sizeof(sa.un.sun_path)); ++ return connection_start(c, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + } + + if (arg_remote_host[0] == '@') { + sa.un.sun_family = AF_UNIX; + sa.un.sun_path[0] = 0; +- strncpy(sa.un.sun_path+1, arg_remote_host+1, sizeof(sa.un.sun_path)-2); +- sa.un.sun_path[sizeof(sa.un.sun_path)-1] = 0; +- +- salen = offsetof(union sockaddr_union, un.sun_path) + 1 + strlen(sa.un.sun_path + 1); +- +- return connection_start(c, &sa.sa, salen); ++ strncpy(sa.un.sun_path+1, arg_remote_host+1, sizeof(sa.un.sun_path)-1); ++ return connection_start(c, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + } + + service = strrchr(arg_remote_host, ':'); +Index: systemd-229/src/test/test-socket-util.c +=================================================================== +--- systemd-229.orig/src/test/test-socket-util.c ++++ systemd-229/src/test/test-socket-util.c +@@ -343,6 +343,21 @@ static void test_sockaddr_equal(void) { + assert_se(!sockaddr_equal(&b, &c)); + } + ++static void test_sockaddr_un_len(void) { ++ static const struct sockaddr_un fs = { ++ .sun_family = AF_UNIX, ++ .sun_path = "/foo/bar/waldo", ++ }; ++ ++ static const struct sockaddr_un abstract = { ++ .sun_family = AF_UNIX, ++ .sun_path = "\0foobar", ++ }; ++ ++ assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path)); ++ assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1)); ++} ++ + int main(int argc, char *argv[]) { + + log_set_max_level(LOG_DEBUG); +@@ -363,5 +378,7 @@ int main(int argc, char *argv[]) { + + test_sockaddr_equal(); + ++ test_sockaddr_un_len(); ++ + return 0; + } +Index: systemd-229/src/tty-ask-password-agent/tty-ask-password-agent.c +=================================================================== +--- systemd-229.orig/src/tty-ask-password-agent/tty-ask-password-agent.c ++++ systemd-229/src/tty-ask-password-agent/tty-ask-password-agent.c +@@ -65,8 +65,8 @@ static int ask_password_plymouth( + const char *flag_file, + char ***ret) { + ++ static const union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_close_ int fd = -1, notify = -1; +- union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_free_ char *packet = NULL; + ssize_t k; + int r, n; +@@ -94,7 +94,7 @@ static int ask_password_plymouth( + if (fd < 0) + return -errno; + +- r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)); ++ r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return -errno; + +@@ -269,8 +269,7 @@ static int send_passwords(const char *so + + strncpy(sa.un.sun_path, socket_name, sizeof(sa.un.sun_path)); + +- r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, +- offsetof(struct sockaddr_un, sun_path) + strlen(socket_name)); ++ r = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + r = log_debug_errno(errno, "sendto(): %m"); + +Index: systemd-229/src/udev/udev-ctrl.c +=================================================================== +--- systemd-229.orig/src/udev/udev-ctrl.c ++++ systemd-229/src/udev/udev-ctrl.c +@@ -105,7 +105,7 @@ struct udev_ctrl *udev_ctrl_new_from_fd( + + uctrl->saddr.un.sun_family = AF_LOCAL; + strscpy(uctrl->saddr.un.sun_path, sizeof(uctrl->saddr.un.sun_path), "/run/udev/control"); +- uctrl->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(uctrl->saddr.un.sun_path); ++ uctrl->addrlen = SOCKADDR_UN_LEN(uctrl->saddr.un); + return uctrl; + } + diff -Nru systemd-229/debian/patches/series systemd-229/debian/patches/series --- systemd-229/debian/patches/series 2016-07-12 17:37:42.000000000 +0200 +++ systemd-229/debian/patches/series 2016-08-12 19:25:56.000000000 +0200 @@ -73,3 +73,4 @@ systemctl-Don-t-forward-telinit-u-to-upstart.patch Provide-shutdown-fallback-for-upstart.patch udev-Don-t-kill-peer-processes-if-we-don-t-run-in-a-cgrou.patch +core-use-an-AF_UNIX-SOCK_DGRAM-socket-for-cgroup-agent-no.patch