Merge pull request #23962 from keszybz/taint-flag-support-ended

Taint flag "support-ended"
This commit is contained in:
Luca Boccassi 2022-07-10 22:42:56 +01:00 committed by GitHub
commit 8924cbf34a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 189 additions and 37 deletions

4
README
View file

@ -359,7 +359,7 @@ WARNINGS and TAINT FLAGS:
will break if /usr is on a separate late-mounted partition, many of its
dependencies very likely will break sooner or later in one form or
another. For example, udev rules tend to refer to binaries in /usr,
binaries that link to libraries in /usr or binaries that refer to data
binaries that link to libraries in /usr, or binaries that refer to data
files in /usr. Since these breakages are not always directly visible,
systemd will warn about this. Such setups are not really supported by
the basic set of Linux OS components. Taint flag 'split-usr' will be
@ -393,6 +393,8 @@ WARNINGS and TAINT FLAGS:
busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Tainted
See org.freedesktop.systemd1(5) for more information.
VALGRIND:
To run systemd under valgrind, compile with meson option
-Dvalgrind=true and have valgrind development headers installed

View file

@ -1494,21 +1494,96 @@ node /org/freedesktop/systemd1 {
it is not part of the public API.</para>
<para><varname>Features</varname> encodes the features that have been enabled and disabled for this
build. Enabled options are prefixed with +, disabled options with -.</para>
build. Enabled options are prefixed with <literal>+</literal>, disabled options with
<literal>-</literal>.</para>
<para><varname>Tainted</varname> encodes a couple of taint flags as a colon-separated list. When
systemd detects it is running on a system with certain problems, it will set an appropriate taint
flag. Taints may be used to lower the chance of bogus bug reports. The following taints are currently
known: <literal>split-usr</literal>, <literal>mtab-not-symlink</literal>,
<literal>cgroups-missing</literal>, <literal>local-hwclock</literal>. <literal>split-usr</literal> is
set if <filename>/usr/</filename> is not pre-mounted when systemd is first invoked. See
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken">
Booting Without /usr is Broken</ulink>
for details why this is bad. <literal>mtab-not-symlink</literal> indicates that
<filename>/etc/mtab</filename> is not a symlink to <filename>/proc/self/mounts</filename> as
required. <literal>cgroups-missing</literal> indicates that control groups have not been enabled in the
kernel. <literal>local-hwclock</literal> indicates that the local RTC is configured to be in local time
rather than UTC.</para>
<para><varname>Tainted</varname> encodes taint flags as a colon-separated list. When systemd detects it
is running on a system with a certain problem, it will set an appropriate taint flag. Taints may be
used to lower the chance of bogus bug reports. The following taints are currently known:</para>
<variablelist>
<varlistentry>
<term><literal>split-usr</literal></term>
<listitem><para><filename>/usr/</filename> was not available when systemd was first invoked. It
must either be part of the root file system, or it must be mounted before
<command>systemd</command> is invoked. See
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken">
Booting Without /usr is Broken</ulink> for details why this is bad.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>unmerged-usr</literal></term>
<listitem><para><filename>/bin</filename>, <filename>/sbin</filename> and
<filename>/lib*</filename> are not symlinks to their counterparts under <filename>/usr/</filename>.
For more information on this issue consult
<ulink url="https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge">
The Case for the /usr Merge
</ulink>.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>cgroups-missing</literal></term>
<listitem><para>Support for cgroups is unavailable.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>cgroupsv1</literal></term>
<listitem><para>The system is using the old cgroup hierarchy.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>local-hwclock</literal></term>
<listitem><para>The local hardware clock (RTC) is configured to be in local time rather than
UTC.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>support-ended</literal></term>
<listitem><para>The system is running past the end of support declared by the vendor. See the
description of <varname>SUPPORT_END=</varname> in
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>old-kernel</literal></term>
<listitem><para>The system is running a kernel version that is older than the minimum supported by
this version of systemd.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>var-run-bad</literal></term>
<listitem><para><filename>/run/</filename> does not exist or <filename>/var/run</filename> is not a
symlink to <filename>/run/</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>overflowuid-not-65534</literal></term>
<term><literal>overflowgid-not-65534</literal></term>
<listitem><para>The kernel overflow UID or GID have a value other than 65534.</para></listitem>
</varlistentry>
<varlistentry>
<term><literal>short-uid-range</literal></term>
<term><literal>short-gid-range</literal></term>
<listitem><para>The UID or GID range assigned to the running systemd instance covers less than
0…65534.</para></listitem>
</varlistentry>
<!-- mtab-not-symlink was removed in b492ce8a22d4527c1372b2d3fbd580627d70c917 -->
</variablelist>
<para><varname>FirmwareTimestamp</varname>, <varname>FirmwareTimestampMonotonic</varname>,
<varname>LoaderTimestamp</varname>, <varname>LoaderTimestampMonotonic</varname>,

View file

@ -355,9 +355,12 @@
<listitem><para>The date at which support for this version of the OS ends. (What exactly "lack of
support" means varies between vendors, but generally users should assume that updates, including
security fixes, will not be provided.) The value is a date in the format
<literal>YYYY-MM-DD</literal>, and specifies the last day on which support <emphasis>is</emphasis>
provided.</para></listitem>
security fixes, will not be provided.) The value is a date in the ISO 8601 format
<literal>YYYY-MM-DD</literal>, and specifies the first day on which support <emphasis>is
not</emphasis> provided.</para>
<para>For example, <literal>SUPPORT_END=2001-01-01</literal> means that the system was supported
until the end of the last day of the previous millenium.</para></listitem>
</varlistentry>
<varlistentry>

View file

@ -317,3 +317,38 @@ int load_extension_release_pairs(const char *root, const char *extension, char *
return load_env_file_pairs(f, p, ret);
}
int os_release_support_ended(const char *support_end, bool quiet) {
_cleanup_free_ char *_support_end_alloc = NULL;
int r;
if (!support_end) {
/* If the caller has the variably handy, they can pass it in. If not, we'll read it
* ourselves. */
r = parse_os_release(NULL,
"SUPPORT_END", &_support_end_alloc);
if (r < 0)
return log_full_errno((r == -ENOENT || quiet) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
if (!_support_end_alloc)
return false; /* no end date defined */
support_end = _support_end_alloc;
}
struct tm tm = {};
const char *k = strptime(support_end, "%Y-%m-%d", &tm);
if (!k || *k)
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
"Failed to parse SUPPORT_END= in os-release file, ignoring: %m");
time_t eol = mktime(&tm);
if (eol == (time_t) -1)
return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL),
"Failed to convert SUPPORT_END= in os-release file, ignoring: %m");
usec_t ts = now(CLOCK_REALTIME);
return DIV_ROUND_UP(ts, USEC_PER_SEC) > (usec_t) eol;
}

View file

@ -31,3 +31,5 @@ int _parse_os_release(const char *root, ...) _sentinel_;
int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
int load_os_release_pairs(const char *root, char ***ret);
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
int os_release_support_ended(const char *support_end, bool quiet);

View file

@ -1312,29 +1312,46 @@ static int enforce_syscall_archs(Set *archs) {
return 0;
}
static int status_welcome(void) {
_cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
static int os_release_status(void) {
_cleanup_free_ char *pretty_name = NULL, *name = NULL, *version = NULL,
*ansi_color = NULL, *support_end = NULL;
int r;
if (!show_status_on(arg_show_status))
return 0;
r = parse_os_release(NULL,
"PRETTY_NAME", &pretty_name,
"ANSI_COLOR", &ansi_color);
"NAME", &name,
"VERSION", &version,
"ANSI_COLOR", &ansi_color,
"SUPPORT_END", &support_end);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
if (log_get_show_color())
return status_printf(NULL, 0,
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",
isempty(ansi_color) ? "1" : ansi_color,
isempty(pretty_name) ? "Linux" : pretty_name);
else
return status_printf(NULL, 0,
"\nWelcome to %s!\n",
isempty(pretty_name) ? "Linux" : pretty_name);
const char *label = empty_to_null(pretty_name) ?: empty_to_null(name) ?: "Linux";
if (show_status_on(arg_show_status)) {
if (log_get_show_color())
status_printf(NULL, 0,
"\nWelcome to \x1B[%sm%s\x1B[0m!\n",
empty_to_null(ansi_color) ?: "1",
label);
else
status_printf(NULL, 0,
"\nWelcome to %s!\n",
label);
}
if (support_end && os_release_support_ended(support_end, false) > 0)
/* pretty_name may include the version already, so we'll print the version only if we
* have it and we're not using pretty_name. */
status_printf(ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, 0,
"This OS version (%s%s%s) is past its end-of-support date (%s)",
label,
(pretty_name || !version) ? "" : " version ",
(pretty_name || !version) ? "" : version,
support_end);
return 0;
}
static int write_container_id(void) {
@ -2100,7 +2117,7 @@ static int initialize_runtime(
return r;
}
status_welcome();
(void) os_release_status();
(void) hostname_setup(true);
/* Force transient machine-id on first boot. */
machine_id_setup(NULL, first_boot, arg_machine_id, NULL);

View file

@ -61,6 +61,7 @@
#include "manager-serialize.h"
#include "memory-util.h"
#include "mkdir-label.h"
#include "os-util.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
@ -4475,7 +4476,7 @@ char* manager_taint_string(const Manager *m) {
assert(m);
const char* stage[12] = {};
const char* stage[13] = {};
size_t n = 0;
if (m->taint_usr)
@ -4494,6 +4495,9 @@ char* manager_taint_string(const Manager *m) {
if (clock_is_localtime(NULL) > 0)
stage[n++] = "local-hwclock";
if (os_release_support_ended(NULL, true) > 0)
stage[n++] = "support-ended";
_cleanup_free_ char *destination = NULL;
if (readlink_malloc("/var/run", &destination) < 0 ||
!PATH_IN_SET(destination, "../run", "/run"))

View file

@ -72,4 +72,18 @@ TEST(load_os_release_pairs) {
assert_se(unsetenv("SYSTEMD_OS_RELEASE") == 0);
}
TEST(os_release_support_ended) {
int r;
assert_se(os_release_support_ended("1999-01-01", false) == true);
assert_se(os_release_support_ended("2037-12-31", false) == false);
assert_se(os_release_support_ended("-1-1-1", true) == -EINVAL);
r = os_release_support_ended(NULL, false);
if (r < 0)
log_info_errno(r, "Failed to check host: %m");
else
log_info_errno(r, "Host is supported: %s", yes_no(!r));
}
DEFINE_TEST_MAIN(LOG_DEBUG);