|
28 | 28 | #include "sd-event.h" |
29 | 29 |
|
30 | 30 | #include "alloc-util.h" |
| 31 | +#include "cgroup-setup.h" |
31 | 32 | #include "cgroup-util.h" |
32 | 33 | #include "cpu-set-util.h" |
33 | 34 | #include "dev-setup.h" |
|
48 | 49 | #include "mkdir.h" |
49 | 50 | #include "netlink-util.h" |
50 | 51 | #include "parse-util.h" |
| 52 | +#include "path-util.h" |
51 | 53 | #include "pretty-print.h" |
52 | 54 | #include "proc-cmdline.h" |
53 | 55 | #include "process-util.h" |
@@ -85,7 +87,7 @@ typedef struct Manager { |
85 | 87 | sd_event *event; |
86 | 88 | Hashmap *workers; |
87 | 89 | LIST_HEAD(Event, events); |
88 | | - const char *cgroup; |
| 90 | + char *cgroup; |
89 | 91 | pid_t pid; /* the process that originally allocated the manager object */ |
90 | 92 | int log_level; |
91 | 93 |
|
@@ -238,6 +240,7 @@ static Manager* manager_free(Manager *manager) { |
238 | 240 | safe_close(manager->inotify_fd); |
239 | 241 | safe_close_pair(manager->worker_watch); |
240 | 242 |
|
| 243 | + free(manager->cgroup); |
241 | 244 | return mfree(manager); |
242 | 245 | } |
243 | 246 |
|
@@ -1722,20 +1725,71 @@ static int parse_argv(int argc, char *argv[]) { |
1722 | 1725 | return 1; |
1723 | 1726 | } |
1724 | 1727 |
|
1725 | | -static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) { |
| 1728 | +static int create_subcgroup(char **ret) { |
| 1729 | + _cleanup_free_ char *cgroup = NULL, *subcgroup = NULL; |
| 1730 | + int r; |
| 1731 | + |
| 1732 | + if (getppid() != 1) |
| 1733 | + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not invoked by PID1."); |
| 1734 | + |
| 1735 | + r = sd_booted(); |
| 1736 | + if (r < 0) |
| 1737 | + return log_debug_errno(r, "Failed to check if systemd is running: %m"); |
| 1738 | + if (r == 0) |
| 1739 | + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "systemd is not running."); |
| 1740 | + |
| 1741 | + /* Get our own cgroup, we regularly kill everything udev has left behind. |
| 1742 | + * We only do this on systemd systems, and only if we are directly spawned |
| 1743 | + * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */ |
| 1744 | + |
| 1745 | + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); |
| 1746 | + if (r < 0) { |
| 1747 | + if (IN_SET(r, -ENOENT, -ENOMEDIUM)) |
| 1748 | + return log_debug_errno(r, "Dedicated cgroup not found: %m"); |
| 1749 | + return log_debug_errno(r, "Failed to get cgroup: %m"); |
| 1750 | + } |
| 1751 | + |
| 1752 | + r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, cgroup, "trusted.delegate"); |
| 1753 | + if (IN_SET(r, 0, -ENODATA)) |
| 1754 | + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "The cgroup %s is not delegated to us.", cgroup); |
| 1755 | + if (r < 0) |
| 1756 | + return log_debug_errno(r, "Failed to read trusted.delegate attribute: %m"); |
| 1757 | + |
| 1758 | + /* We are invoked with our own delegated cgroup tree, let's move us one level down, so that we |
| 1759 | + * don't collide with the "no processes in inner nodes" rule of cgroups, when the service |
| 1760 | + * manager invokes the ExecReload= job in the .control/ subcgroup. */ |
| 1761 | + |
| 1762 | + subcgroup = path_join(cgroup, "/udev"); |
| 1763 | + if (!subcgroup) |
| 1764 | + return log_oom_debug(); |
| 1765 | + |
| 1766 | + r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, subcgroup, 0); |
| 1767 | + if (r < 0) |
| 1768 | + return log_debug_errno(r, "Failed to create %s subcgroup: %m", subcgroup); |
| 1769 | + |
| 1770 | + log_debug("Created %s subcgroup.", subcgroup); |
| 1771 | + if (ret) |
| 1772 | + *ret = TAKE_PTR(subcgroup); |
| 1773 | + return 0; |
| 1774 | +} |
| 1775 | + |
| 1776 | +static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent) { |
1726 | 1777 | _cleanup_(manager_freep) Manager *manager = NULL; |
| 1778 | + _cleanup_free_ char *cgroup = NULL; |
1727 | 1779 | int r; |
1728 | 1780 |
|
1729 | 1781 | assert(ret); |
1730 | 1782 |
|
| 1783 | + (void) create_subcgroup(&cgroup); |
| 1784 | + |
1731 | 1785 | manager = new(Manager, 1); |
1732 | 1786 | if (!manager) |
1733 | 1787 | return log_oom(); |
1734 | 1788 |
|
1735 | 1789 | *manager = (Manager) { |
1736 | 1790 | .inotify_fd = -1, |
1737 | 1791 | .worker_watch = { -1, -1 }, |
1738 | | - .cgroup = cgroup, |
| 1792 | + .cgroup = TAKE_PTR(cgroup), |
1739 | 1793 | }; |
1740 | 1794 |
|
1741 | 1795 | r = udev_ctrl_new_from_fd(&manager->ctrl, fd_ctrl); |
@@ -1880,7 +1934,6 @@ static int main_loop(Manager *manager) { |
1880 | 1934 | } |
1881 | 1935 |
|
1882 | 1936 | int run_udevd(int argc, char *argv[]) { |
1883 | | - _cleanup_free_ char *cgroup = NULL; |
1884 | 1937 | _cleanup_(manager_freep) Manager *manager = NULL; |
1885 | 1938 | int fd_ctrl = -1, fd_uevent = -1; |
1886 | 1939 | int r; |
@@ -1937,24 +1990,11 @@ int run_udevd(int argc, char *argv[]) { |
1937 | 1990 | if (r < 0 && r != -EEXIST) |
1938 | 1991 | return log_error_errno(r, "Failed to create /run/udev: %m"); |
1939 | 1992 |
|
1940 | | - if (getppid() == 1 && sd_booted() > 0) { |
1941 | | - /* Get our own cgroup, we regularly kill everything udev has left behind. |
1942 | | - * We only do this on systemd systems, and only if we are directly spawned |
1943 | | - * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */ |
1944 | | - r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); |
1945 | | - if (r < 0) { |
1946 | | - if (IN_SET(r, -ENOENT, -ENOMEDIUM)) |
1947 | | - log_debug_errno(r, "Dedicated cgroup not found: %m"); |
1948 | | - else |
1949 | | - log_warning_errno(r, "Failed to get cgroup: %m"); |
1950 | | - } |
1951 | | - } |
1952 | | - |
1953 | 1993 | r = listen_fds(&fd_ctrl, &fd_uevent); |
1954 | 1994 | if (r < 0) |
1955 | 1995 | return log_error_errno(r, "Failed to listen on fds: %m"); |
1956 | 1996 |
|
1957 | | - r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); |
| 1997 | + r = manager_new(&manager, fd_ctrl, fd_uevent); |
1958 | 1998 | if (r < 0) |
1959 | 1999 | return log_error_errno(r, "Failed to create manager: %m"); |
1960 | 2000 |
|
|
0 commit comments