mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 16:37:19 +09:00
coredump: parse signal number at the same time as parsing other fields
This commit is contained in:
@@ -301,3 +301,19 @@ const struct sigaction sigaction_default = {
|
||||
.sa_handler = SIG_DFL,
|
||||
.sa_flags = SA_RESTART,
|
||||
};
|
||||
|
||||
int parse_signo(const char *s, int *ret) {
|
||||
int sig, r;
|
||||
|
||||
r = safe_atoi(s, &sig);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!SIGNAL_VALID(sig))
|
||||
return -EINVAL;
|
||||
|
||||
if (ret)
|
||||
*ret = sig;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -68,3 +68,5 @@ void propagate_signal(int sig, siginfo_t *siginfo);
|
||||
|
||||
extern const struct sigaction sigaction_ignore;
|
||||
extern const struct sigaction sigaction_default;
|
||||
|
||||
int parse_signo(const char *s, int *ret);
|
||||
|
||||
@@ -143,6 +143,7 @@ typedef struct Context {
|
||||
PidRef pidref;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
int signo;
|
||||
bool is_pid1;
|
||||
bool is_journald;
|
||||
int mount_tree_fd;
|
||||
@@ -1016,7 +1017,7 @@ static int submit_coredump(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_parse_iovw(Context *context, const struct iovec_wrapper *iovw) {
|
||||
static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
|
||||
const char *unit;
|
||||
int r;
|
||||
|
||||
@@ -1027,9 +1028,8 @@ static int context_parse_iovw(Context *context, const struct iovec_wrapper *iovw
|
||||
/* Converts the data in the iovec array iovw into separate fields. Fills in context->meta[] (for
|
||||
* which no memory is allocated, it just contains direct pointers into the iovec array memory). */
|
||||
|
||||
for (size_t n = 0; n < iovw->count; n++) {
|
||||
struct iovec *iovec = iovw->iovec + n;
|
||||
|
||||
bool have_signal_name = false;
|
||||
FOREACH_ARRAY(iovec, iovw->iovec, iovw->count) {
|
||||
for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) {
|
||||
/* Note that these strings are NUL terminated, because we made sure that a
|
||||
* trailing NUL byte is in the buffer, though not included in the iov_len
|
||||
@@ -1043,6 +1043,9 @@ static int context_parse_iovw(Context *context, const struct iovec_wrapper *iovw
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
have_signal_name = have_signal_name ||
|
||||
memory_startswith(iovec->iov_base, iovec->iov_len, "COREDUMP_SIGNAL_NAME=");
|
||||
}
|
||||
|
||||
if (!context->meta[META_ARGV_PID])
|
||||
@@ -1070,10 +1073,19 @@ static int context_parse_iovw(Context *context, const struct iovec_wrapper *iovw
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse GID \"%s\": %m", context->meta[META_ARGV_GID]);
|
||||
|
||||
r = parse_signo(context->meta[META_ARGV_SIGNAL], &context->signo);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse signal number \"%s\", ignoring: %m", context->meta[META_ARGV_SIGNAL]);
|
||||
|
||||
unit = context->meta[META_UNIT];
|
||||
context->is_pid1 = streq(context->meta[META_ARGV_PID], "1") || streq_ptr(unit, SPECIAL_INIT_SCOPE);
|
||||
context->is_journald = streq_ptr(unit, SPECIAL_JOURNALD_SERVICE);
|
||||
|
||||
/* After parsing everything, let's also synthesize a new iovw field for the textual signal name if it
|
||||
* isn't already set. */
|
||||
if (SIGNAL_VALID(context->signo) && !have_signal_name)
|
||||
(void) iovw_put_string_field(iovw, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(context->signo));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1316,7 +1328,7 @@ static int gather_pid_metadata_from_argv(
|
||||
Context *context,
|
||||
int argc, char **argv) {
|
||||
|
||||
int r, signo;
|
||||
int r;
|
||||
|
||||
assert(iovw);
|
||||
assert(context);
|
||||
@@ -1333,9 +1345,7 @@ static int gather_pid_metadata_from_argv(
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
const char *t = argv[i];
|
||||
|
||||
switch (i) {
|
||||
|
||||
case META_ARGV_TIMESTAMP:
|
||||
if (i == META_ARGV_TIMESTAMP) {
|
||||
/* The journal fields contain the timestamp padded with six
|
||||
* zeroes, so that the kernel-supplied 1s granularity timestamps
|
||||
* becomes 1μs granularity, i.e. the granularity systemd usually
|
||||
@@ -1345,17 +1355,6 @@ static int gather_pid_metadata_from_argv(
|
||||
return log_oom();
|
||||
|
||||
t = buf;
|
||||
break;
|
||||
|
||||
case META_ARGV_SIGNAL:
|
||||
/* For signal, record its pretty name too */
|
||||
if (safe_atoi(argv[i], &signo) >= 0 && SIGNAL_VALID(signo))
|
||||
(void) iovw_put_string_field(iovw, "COREDUMP_SIGNAL_NAME=SIG",
|
||||
signal_to_string(signo));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
r = iovw_put_string_field(iovw, meta_field_names[i], t);
|
||||
@@ -1636,7 +1635,6 @@ static int forward_coredump_to_container(Context *context) {
|
||||
(void) iovw_put_string_field(iovw, "COREDUMP_FORWARDED=", "1");
|
||||
|
||||
for (int i = 0; i < _META_ARGV_MAX; i++) {
|
||||
int signo;
|
||||
char buf[DECIMAL_STR_MAX(pid_t)];
|
||||
const char *t = context->meta[i];
|
||||
|
||||
@@ -1658,13 +1656,6 @@ static int forward_coredump_to_container(Context *context) {
|
||||
t = buf;
|
||||
break;
|
||||
|
||||
case META_ARGV_SIGNAL:
|
||||
if (safe_atoi(t, &signo) >= 0 && SIGNAL_VALID(signo))
|
||||
(void) iovw_put_string_field(iovw,
|
||||
"COREDUMP_SIGNAL_NAME=SIG",
|
||||
signal_to_string(signo));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1793,7 +1784,7 @@ static int gather_pid_mount_tree_fd(const Context *context, int *ret_fd) {
|
||||
static int process_kernel(int argc, char* argv[]) {
|
||||
_cleanup_(iovw_free_freep) struct iovec_wrapper *iovw = NULL;
|
||||
_cleanup_(context_done) Context context = CONTEXT_NULL;
|
||||
int r, signo;
|
||||
int r;
|
||||
|
||||
/* When we're invoked by the kernel, stdout/stderr are closed which is dangerous because the fds
|
||||
* could get reallocated. To avoid hard to debug issues, let's instead bind stdout/stderr to
|
||||
@@ -1824,9 +1815,9 @@ static int process_kernel(int argc, char* argv[]) {
|
||||
|
||||
/* Log minimal metadata now, so it is not lost if the system is about to shut down. */
|
||||
log_info("Process %s (%s) of user %s terminated abnormally with signal %s/%s, processing...",
|
||||
context.meta[META_ARGV_PID], context.meta[META_COMM],
|
||||
context.meta[META_ARGV_UID], context.meta[META_ARGV_SIGNAL],
|
||||
strna(safe_atoi(context.meta[META_ARGV_SIGNAL], &signo) >= 0 ? signal_to_string(signo) : NULL));
|
||||
context.meta[META_ARGV_PID], context.meta[META_COMM],
|
||||
context.meta[META_ARGV_UID], context.meta[META_ARGV_SIGNAL],
|
||||
signal_to_string(context.signo));
|
||||
|
||||
r = in_same_namespace(getpid_cached(), context.pidref.pid, NAMESPACE_PID);
|
||||
if (r < 0)
|
||||
|
||||
Reference in New Issue
Block a user