summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cgroup.c41
-rw-r--r--src/core/cgroup.h1
-rw-r--r--src/core/dbus-unit.c70
-rw-r--r--src/core/dbus.c13
-rw-r--r--src/core/dbus.h1
-rw-r--r--src/core/killall.c6
-rw-r--r--src/core/manager.c12
-rw-r--r--src/core/unit.c20
8 files changed, 118 insertions, 46 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 1e78f871c7..9a025cf929 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -507,15 +507,20 @@ CGroupMask unit_get_own_mask(Unit *u) {
return 0;
/* If delegation is turned on, then turn on all cgroups,
- * unless the process we fork into it is known to drop
- * privileges anyway, and shouldn't get access to the
- * controllers anyway. */
+ * unless we are on the legacy hierarchy and the process we
+ * fork into it is known to drop privileges, and hence
+ * shouldn't get access to the controllers.
+ *
+ * Note that on the unified hierarchy it is safe to delegate
+ * controllers to unprivileged services. */
if (c->delegate) {
ExecContext *e;
e = unit_get_exec_context(u);
- if (!e || exec_context_maintains_privileges(e))
+ if (!e ||
+ exec_context_maintains_privileges(e) ||
+ cg_unified() > 0)
return _CGROUP_MASK_ALL;
}
@@ -1378,9 +1383,8 @@ Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
}
}
-Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
+Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) {
_cleanup_free_ char *cgroup = NULL;
- Unit *u;
int r;
assert(m);
@@ -1388,22 +1392,33 @@ Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
if (pid <= 0)
return NULL;
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
+ if (r < 0)
+ return NULL;
+
+ return manager_get_unit_by_cgroup(m, cgroup);
+}
+
+Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
+ Unit *u;
+
+ assert(m);
+
+ if (pid <= 0)
+ return NULL;
+
if (pid == 1)
return hashmap_get(m->units, SPECIAL_INIT_SCOPE);
- u = hashmap_get(m->watch_pids1, LONG_TO_PTR(pid));
+ u = hashmap_get(m->watch_pids1, PID_TO_PTR(pid));
if (u)
return u;
- u = hashmap_get(m->watch_pids2, LONG_TO_PTR(pid));
+ u = hashmap_get(m->watch_pids2, PID_TO_PTR(pid));
if (u)
return u;
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
- if (r < 0)
- return NULL;
-
- return manager_get_unit_by_cgroup(m, cgroup);
+ return manager_get_unit_by_pid_cgroup(m, pid);
}
int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 1ce21f43f2..438f5bf50f 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -130,6 +130,7 @@ void manager_shutdown_cgroup(Manager *m, bool delete);
unsigned manager_dispatch_cgroup_queue(Manager *m);
Unit *manager_get_unit_by_cgroup(Manager *m, const char *cgroup);
+Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid);
Unit* manager_get_unit_by_pid(Manager *m, pid_t pid);
int unit_search_main_pid(Unit *u, pid_t *ret);
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 31016b6c4a..f9275ed935 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -391,6 +391,29 @@ static int property_get_load_error(
return sd_bus_message_append(reply, "(ss)", e.name, e.message);
}
+static int bus_verify_manage_units_async_full(
+ Unit *u,
+ const char *verb,
+ int capability,
+ const char *polkit_message,
+ sd_bus_message *call,
+ sd_bus_error *error) {
+
+ const char *details[9] = {
+ "unit", u->id,
+ "verb", verb,
+ };
+
+ if (polkit_message) {
+ details[4] = "polkit.message";
+ details[5] = polkit_message;
+ details[6] = "polkit.gettext_domain";
+ details[7] = GETTEXT_PACKAGE;
+ }
+
+ return bus_verify_polkit_async(call, capability, "org.freedesktop.systemd1.manage-units", details, false, UID_INVALID, &u->manager->polkit_registry, error);
+}
+
int bus_unit_method_start_generic(
sd_bus_message *message,
Unit *u,
@@ -400,6 +423,14 @@ int bus_unit_method_start_generic(
const char *smode;
JobMode mode;
+ _cleanup_free_ char *verb = NULL;
+ static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
+ [JOB_START] = N_("Authentication is required to start '$(unit)'."),
+ [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
+ [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
+ [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
+ [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
+ };
int r;
assert(message);
@@ -418,7 +449,20 @@ int bus_unit_method_start_generic(
if (mode < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
- r = bus_verify_manage_units_async(u->manager, message, error);
+ if (reload_if_possible)
+ verb = strjoin("reload-or-", job_type_to_string(job_type), NULL);
+ else
+ verb = strdup(job_type_to_string(job_type));
+ if (!verb)
+ return -ENOMEM;
+
+ r = bus_verify_manage_units_async_full(
+ u,
+ verb,
+ CAP_SYS_ADMIN,
+ job_type < _JOB_TYPE_MAX ? polkit_message_for_job[job_type] : NULL,
+ message,
+ error);
if (r < 0)
return r;
if (r == 0)
@@ -484,7 +528,13 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *
if (signo <= 0 || signo >= _NSIG)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
- r = bus_verify_manage_units_async_for_kill(u->manager, message, error);
+ r = bus_verify_manage_units_async_full(
+ u,
+ "kill",
+ CAP_KILL,
+ N_("Authentication is required to kill '$(unit)'."),
+ message,
+ error);
if (r < 0)
return r;
if (r == 0)
@@ -508,7 +558,13 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus
if (r < 0)
return r;
- r = bus_verify_manage_units_async(u->manager, message, error);
+ r = bus_verify_manage_units_async_full(
+ u,
+ "reset-failed",
+ CAP_SYS_ADMIN,
+ N_("Authentication is required to reset the \"failed\" state of '$(unit)'."),
+ message,
+ error);
if (r < 0)
return r;
if (r == 0)
@@ -534,7 +590,13 @@ int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_b
if (r < 0)
return r;
- r = bus_verify_manage_units_async(u->manager, message, error);
+ r = bus_verify_manage_units_async_full(
+ u,
+ "set-property",
+ CAP_SYS_ADMIN,
+ N_("Authentication is required to set properties on '$(unit)'."),
+ message,
+ error);
if (r < 0)
return r;
if (r == 0)
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 7ad16aa42b..0a2180c6a7 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -1198,22 +1198,17 @@ int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) {
}
int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
- return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
-}
-
-/* Same as bus_verify_manage_unit_async(), but checks for CAP_KILL instead of CAP_SYS_ADMIN */
-int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error) {
- return bus_verify_polkit_async(call, CAP_KILL, "org.freedesktop.systemd1.manage-units", false, UID_INVALID, &m->polkit_registry, error);
+ return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error);
}
int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
- return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", false, UID_INVALID, &m->polkit_registry, error);
+ return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error);
}
int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
- return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", false, UID_INVALID, &m->polkit_registry, error);
+ return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error);
}
int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
- return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", false, UID_INVALID, &m->polkit_registry, error);
+ return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error);
}
diff --git a/src/core/dbus.h b/src/core/dbus.h
index 4832722069..4f06ad11c4 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -37,7 +37,6 @@ int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l);
int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error);
-int bus_verify_manage_units_async_for_kill(Manager *m, sd_bus_message *call, sd_bus_error *error);
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);
diff --git a/src/core/killall.c b/src/core/killall.c
index 2a9d72c901..ee5d388560 100644
--- a/src/core/killall.c
+++ b/src/core/killall.c
@@ -108,7 +108,7 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
return;
}
- set_remove(pids, ULONG_TO_PTR(pid));
+ (void) set_remove(pids, PID_TO_PTR(pid));
}
/* Now explicitly check who might be remaining, who
@@ -117,7 +117,7 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
/* We misuse getpgid as a check whether a
* process still exists. */
- if (getpgid((pid_t) PTR_TO_ULONG(p)) >= 0)
+ if (getpgid(PTR_TO_PID(p)) >= 0)
continue;
if (errno != ESRCH)
@@ -179,7 +179,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
if (kill(pid, sig) >= 0) {
if (pids) {
- r = set_put(pids, ULONG_TO_PTR(pid));
+ r = set_put(pids, PID_TO_PTR(pid));
if (r < 0)
log_oom();
}
diff --git a/src/core/manager.c b/src/core/manager.c
index c3327e37f5..fc10ddb5d9 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1585,19 +1585,19 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
/* Notify every unit that might be interested, but try
* to avoid notifying the same one multiple times. */
- u1 = manager_get_unit_by_pid(m, ucred->pid);
+ u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid);
if (u1) {
manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds);
found = true;
}
- u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
+ u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid));
if (u2 && u2 != u1) {
manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds);
found = true;
}
- u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
+ u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid));
if (u3 && u3 != u2 && u3 != u1) {
manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds);
found = true;
@@ -1663,13 +1663,13 @@ static int manager_dispatch_sigchld(Manager *m) {
/* And now figure out the unit this belongs
* to, it might be multiple... */
- u1 = manager_get_unit_by_pid(m, si.si_pid);
+ u1 = manager_get_unit_by_pid_cgroup(m, si.si_pid);
if (u1)
invoke_sigchld_event(m, u1, &si);
- u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(si.si_pid));
+ u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(si.si_pid));
if (u2 && u2 != u1)
invoke_sigchld_event(m, u2, &si);
- u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(si.si_pid));
+ u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(si.si_pid));
if (u3 && u3 != u2 && u3 != u1)
invoke_sigchld_event(m, u3, &si);
}
diff --git a/src/core/unit.c b/src/core/unit.c
index 8c07c6140d..a5714adf38 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1995,16 +1995,16 @@ int unit_watch_pid(Unit *u, pid_t pid) {
if (r < 0)
return r;
- r = hashmap_put(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
+ r = hashmap_put(u->manager->watch_pids1, PID_TO_PTR(pid), u);
if (r == -EEXIST) {
r = hashmap_ensure_allocated(&u->manager->watch_pids2, NULL);
if (r < 0)
return r;
- r = hashmap_put(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
+ r = hashmap_put(u->manager->watch_pids2, PID_TO_PTR(pid), u);
}
- q = set_put(u->pids, LONG_TO_PTR(pid));
+ q = set_put(u->pids, PID_TO_PTR(pid));
if (q < 0)
return q;
@@ -2015,16 +2015,16 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
assert(u);
assert(pid >= 1);
- (void) hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
- (void) hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
- (void) set_remove(u->pids, LONG_TO_PTR(pid));
+ (void) hashmap_remove_value(u->manager->watch_pids1, PID_TO_PTR(pid), u);
+ (void) hashmap_remove_value(u->manager->watch_pids2, PID_TO_PTR(pid), u);
+ (void) set_remove(u->pids, PID_TO_PTR(pid));
}
void unit_unwatch_all_pids(Unit *u) {
assert(u);
while (!set_isempty(u->pids))
- unit_unwatch_pid(u, PTR_TO_LONG(set_first(u->pids)));
+ unit_unwatch_pid(u, PTR_TO_PID(set_first(u->pids)));
u->pids = set_free(u->pids);
}
@@ -2038,7 +2038,7 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) {
/* Cleans dead PIDs from our list */
SET_FOREACH(e, u->pids, i) {
- pid_t pid = PTR_TO_LONG(e);
+ pid_t pid = PTR_TO_PID(e);
if (pid == except1 || pid == except2)
continue;
@@ -2993,13 +2993,13 @@ static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
/* Exclude the main/control pids from being killed via the cgroup */
if (main_pid > 0) {
- r = set_put(pid_set, LONG_TO_PTR(main_pid));
+ r = set_put(pid_set, PID_TO_PTR(main_pid));
if (r < 0)
goto fail;
}
if (control_pid > 0) {
- r = set_put(pid_set, LONG_TO_PTR(control_pid));
+ r = set_put(pid_set, PID_TO_PTR(control_pid));
if (r < 0)
goto fail;
}