tree-wide: only use .si_pid field in siginfo_t, if .si_code indicates that's safe
Fixes: #37498
This commit is contained in:
committed by
Zbigniew Jędrzejewski-Szmek
parent
91c60ff528
commit
1105f8d20f
+1
-1
@@ -1507,7 +1507,7 @@ DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
|
||||
void log_received_signal(int level, const struct signalfd_siginfo *si) {
|
||||
assert(si);
|
||||
|
||||
if (pid_is_valid(si->ssi_pid)) {
|
||||
if (si_code_from_process(si->ssi_code) && pid_is_valid(si->ssi_pid)) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
(void) pid_get_comm(si->ssi_pid, &p);
|
||||
|
||||
@@ -71,3 +71,25 @@ extern const struct sigaction sigaction_default;
|
||||
extern const struct sigaction sigaction_nop_nocldstop;
|
||||
|
||||
int parse_signo(const char *s, int *ret);
|
||||
|
||||
static inline bool si_code_from_process(int si_code) {
|
||||
/* Returns true if the .si_code field of siginfo_t or the .ssi_code field of struct signalfd_siginfo
|
||||
* indicate that the signal originates from a userspace process, and hence the .si_pid/.ssi_pid field
|
||||
* is valid. This check is not obvious, since on one hand SI_USER/SI_QUEUE are supposed to be the
|
||||
* values that kill() and sigqueue() set, and that's documented in sigaction(2), but on the other
|
||||
* hand rt_sigqueueinfo(2) says userspace can actually set any value below zero. Hence check for
|
||||
* either.
|
||||
*
|
||||
* Also quoting POSIX:
|
||||
*
|
||||
* "On systems not supporting the XSI option, the si_pid and si_uid members of siginfo_t are only
|
||||
* required to be valid when si_code is SI_USER or SI_QUEUE. On XSI-conforming systems, they are also
|
||||
* valid for all si_code values less than or equal to 0; however, it is unspecified whether SI_USER
|
||||
* and SI_QUEUE have values less than or equal to zero, and therefore XSI applications should check
|
||||
* whether si_code has the value SI_USER or SI_QUEUE or is less than or equal to 0 to tell whether
|
||||
* si_pid and si_uid are valid."
|
||||
*
|
||||
* From: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html */
|
||||
|
||||
return si_code < 0 || IN_SET(si_code, SI_USER, SI_QUEUE);
|
||||
}
|
||||
|
||||
@@ -104,7 +104,11 @@ _noreturn_ static void crash(int sig, siginfo_t *siginfo, void *context) {
|
||||
siginfo_t status;
|
||||
|
||||
if (siginfo) {
|
||||
if (siginfo->si_pid == 0)
|
||||
if (!si_code_from_process(siginfo->si_code))
|
||||
log_struct(LOG_EMERG,
|
||||
LOG_MESSAGE("Caught <%s>.", signal_to_string(sig)),
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_CRASH_UNKNOWN_SIGNAL_STR));
|
||||
else if (siginfo->si_pid == 0)
|
||||
log_struct(LOG_EMERG,
|
||||
LOG_MESSAGE("Caught <%s>, from unknown sender process.", signal_to_string(sig)),
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_CRASH_UNKNOWN_SIGNAL_STR));
|
||||
|
||||
@@ -1170,7 +1170,9 @@ static void sigterm_handler(int signal, siginfo_t *info, void *ucontext) {
|
||||
|
||||
/* If the sender is not us, propagate the signal to all processes in
|
||||
* the same process group */
|
||||
if (pid_is_valid(info->si_pid) && info->si_pid != getpid_cached())
|
||||
if (si_code_from_process(info->si_code) &&
|
||||
pid_is_valid(info->si_pid) &&
|
||||
info->si_pid != getpid_cached())
|
||||
(void) kill(0, signal);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "process-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
@@ -1645,9 +1646,15 @@ void manager_full_flush(Manager *m) {
|
||||
|
||||
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
assert(si);
|
||||
|
||||
if (!si_code_from_process(si->ssi_code)) {
|
||||
log_warning("Received SIGUSR1 with unexpected .si_code %i, ignoring.", si->ssi_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m->namespace) {
|
||||
log_error("Received SIGUSR1 signal from PID %u, but flushing runtime journals not supported for namespaced instances.", si->ssi_pid);
|
||||
log_warning("Received SIGUSR1 signal from PID %u, but flushing runtime journals not supported for namespaced instances, ignoring.", si->ssi_pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1681,6 +1688,12 @@ void manager_full_rotate(Manager *m) {
|
||||
|
||||
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
assert(si);
|
||||
|
||||
if (!si_code_from_process(si->ssi_code)) {
|
||||
log_warning("Received SIGUSR2 with unexpected .si_code %i, ignoring.", si->ssi_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("Received SIGUSR2 signal from PID %u, as request to rotate journal, rotating.", si->ssi_pid);
|
||||
manager_full_rotate(m);
|
||||
@@ -1785,6 +1798,12 @@ void manager_full_sync(Manager *m, bool wait) {
|
||||
|
||||
static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
assert(si);
|
||||
|
||||
if (!si_code_from_process(si->ssi_code)) {
|
||||
log_warning("Received SIGRTMIN1 with unexpected .si_code %i, ignoring.", si->ssi_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("Received SIGRTMIN1 signal from PID %u, as request to sync.", si->ssi_pid);
|
||||
manager_full_sync(m, /* wait = */ false);
|
||||
|
||||
@@ -21,6 +21,11 @@ int sigrtmin18_handler(sd_event_source *s, const struct signalfd_siginfo *si, vo
|
||||
assert(s);
|
||||
assert(si);
|
||||
|
||||
if (!si_code_from_process(si->ssi_code)) {
|
||||
log_notice("Received control signal %s with unexpected .si_code %i, ignoring.", signal_to_string(si->ssi_signo), si->ssi_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) pid_get_comm(si->ssi_pid, &comm);
|
||||
|
||||
if (si->ssi_code != SI_QUEUE) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "process-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "udev-manager.h"
|
||||
@@ -611,6 +612,11 @@ int manager_remove_watch(Manager *manager, sd_device *dev) {
|
||||
static int on_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
UdevWorker *worker = ASSERT_PTR(userdata);
|
||||
|
||||
if (!si_code_from_process(si->ssi_code)) {
|
||||
log_debug("Received SIGUSR1 with unexpected .si_code %i, ignoring.", si->ssi_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((pid_t) si->ssi_pid != worker->manager_pid) {
|
||||
log_debug("Received SIGUSR1 from unexpected process [%"PRIu32"], ignoring.", si->ssi_pid);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user