core: be stricter when handling PID files and MAINPID sd_notify() messages
Let's be more restrictive when validating PID files and MAINPID= messages: don't accept PIDs that make no sense, and if the configuration source is not trusted, don't accept out-of-cgroup PIDs. A configuratin source is considered trusted when the PID file is owned by root, or the message was received from root. This should lock things down a bit, in case service authors write out PID files from unprivileged code or use NotifyAccess=all with unprivileged code. Note that doing so was always problematic, just now it's a bit less problematic. When we open the PID file we'll now use the CHASE_SAFE chase_symlinks() logic, to ensure that we won't follow an unpriviled-owned symlink to a privileged-owned file thinking this was a valid privileged PID file, even though it really isn't. Fixes: #6632
This commit is contained in:
+12
-5
@@ -1879,11 +1879,18 @@ static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, ui
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, FDSet *fds) {
|
||||
static void manager_invoke_notify_message(
|
||||
Manager *m,
|
||||
Unit *u,
|
||||
const struct ucred *ucred,
|
||||
const char *buf,
|
||||
FDSet *fds) {
|
||||
|
||||
_cleanup_strv_free_ char **tags = NULL;
|
||||
|
||||
assert(m);
|
||||
assert(u);
|
||||
assert(ucred);
|
||||
assert(buf);
|
||||
|
||||
tags = strv_split(buf, NEWLINE);
|
||||
@@ -1893,7 +1900,7 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const
|
||||
}
|
||||
|
||||
if (UNIT_VTABLE(u)->notify_message)
|
||||
UNIT_VTABLE(u)->notify_message(u, pid, tags, fds);
|
||||
UNIT_VTABLE(u)->notify_message(u, ucred, tags, fds);
|
||||
else if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *x = NULL, *y = NULL;
|
||||
|
||||
@@ -2001,15 +2008,15 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
* to avoid notifying the same one multiple times. */
|
||||
u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid);
|
||||
if (u1)
|
||||
manager_invoke_notify_message(m, u1, ucred->pid, buf, fds);
|
||||
manager_invoke_notify_message(m, u1, ucred, buf, fds);
|
||||
|
||||
u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid));
|
||||
if (u2 && u2 != u1)
|
||||
manager_invoke_notify_message(m, u2, ucred->pid, buf, fds);
|
||||
manager_invoke_notify_message(m, u2, ucred, buf, fds);
|
||||
|
||||
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, fds);
|
||||
manager_invoke_notify_message(m, u3, ucred, buf, fds);
|
||||
|
||||
if (!u1 && !u2 && !u3)
|
||||
log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid);
|
||||
|
||||
Reference in New Issue
Block a user