From d8eb10d61a68d4fe6eefae583f1808458a1df09c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 21 Jan 2018 23:17:54 +1100 Subject: [PATCH] core: delay logging the taint string until after basic.target is reached (#7935) This happens to be almost the same moment as when we send READY=1 in the user instance, but the logic is slightly different, since we log taint when basic.target is reached in the system manager, but we send the notification only in the user manager. So add a separate flag for this and propagate it across reloads. Fixes #7683. --- src/core/main.c | 21 --------------------- src/core/manager.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ src/core/manager.h | 4 ++++ 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index c850f6f..a088913 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2218,25 +2218,6 @@ static void test_summary(Manager *m) { manager_dump_jobs(m, stdout, "\t"); } -static void log_taint_string(Manager *m) { - _cleanup_free_ char *taint = NULL; - - assert(m); - - if (!arg_system) - return; - - taint = manager_taint_string(m); - if (isempty(taint)) - return; - - log_struct(LOG_NOTICE, - LOG_MESSAGE("System is tainted: %s", taint), - "TAINT=%s", taint, - "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR, - NULL); -} - static int collect_fds(FDSet **ret_fds, const char **ret_error_message) { int r; @@ -2550,8 +2531,6 @@ int main(int argc, char *argv[]) { "Loaded units and determined initial transaction in %s.", format_timespan(timespan, sizeof(timespan), after_startup - before_startup, 100 * USEC_PER_MSEC)); - log_taint_string(m); - if (arg_action == ACTION_TEST) { test_summary(m); retval = EXIT_SUCCESS; diff --git a/src/core/manager.c b/src/core/manager.c index f922202..ee9ff15 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2658,6 +2658,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs); fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr)); fprintf(f, "ready-sent=%s\n", yes_no(m->ready_sent)); + fprintf(f, "taint-logged=%s\n", yes_no(m->taint_logged)); for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { /* The userspace and finish timestamps only apply to the host system, hence only serialize them there */ @@ -2820,6 +2821,15 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { else m->ready_sent = m->ready_sent || b; + } else if ((val = startswith(l, "taint-logged="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse taint-logged flag %s", val); + else + m->taint_logged = m->taint_logged || b; + } else if (startswith(l, "env=")) { r = deserialize_environment(&m->environment, l); if (r == -ENOMEM) @@ -3077,6 +3087,27 @@ bool manager_unit_inactive_or_pending(Manager *m, const char *name) { return unit_inactive_or_pending(u); } +static void log_taint_string(Manager *m) { + _cleanup_free_ char *taint = NULL; + + assert(m); + + if (MANAGER_IS_USER(m) || m->taint_logged) + return; + + m->taint_logged = true; /* only check for taint once */ + + taint = manager_taint_string(m); + if (isempty(taint)) + return; + + log_struct(LOG_NOTICE, + LOG_MESSAGE("System is tainted: %s", taint), + "TAINT=%s", taint, + "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR, + NULL); +} + static void manager_notify_finished(Manager *m) { char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX]; usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec; @@ -3149,6 +3180,8 @@ static void manager_notify_finished(Manager *m) { "STATUS=Startup finished in %s.", format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)); m->ready_sent = true; + + log_taint_string(m); } void manager_check_finished(Manager *m) { @@ -3163,16 +3196,22 @@ void manager_check_finished(Manager *m) { if (m->exit_code != MANAGER_OK) return; - /* For user managers, send out READY=1 as soon as we reach basic.target */ - if (MANAGER_IS_USER(m) && !m->ready_sent) { + if (!m->ready_sent || !m->taint_logged) { Unit *u; u = manager_get_unit(m, SPECIAL_BASIC_TARGET); if (u && !u->job) { - sd_notifyf(false, - "READY=1\n" - "STATUS=Reached " SPECIAL_BASIC_TARGET "."); - m->ready_sent = true; + /* Log the taint string as soon as we reach basic.target */ + log_taint_string(m); + + /* For user managers, send out READY=1 as soon as we reach basic.target */ + if (MANAGER_IS_USER(m) && !m->ready_sent) { + sd_notifyf(false, + "READY=1\n" + "STATUS=Reached " SPECIAL_BASIC_TARGET "."); + + m->ready_sent = true; + } } } diff --git a/src/core/manager.h b/src/core/manager.h index 902af26..1531374 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -261,8 +261,12 @@ struct Manager { bool taint_usr:1; + /* Have we already sent out the READY=1 notification? */ bool ready_sent:1; + /* Have we already printed the taint line if necessary? */ + bool taint_logged:1; + unsigned test_run_flags:8; /* If non-zero, exit with the following value when the systemd -- 2.7.4