1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-14 04:58:28 +03:00

core/condition: fix segfault when key not found in os-release

'ConditionOSRelease=|ID_LIKE$=*rhel*' results in a segfault.
The key 'ID_LIKE' is not present in Fedora's os-release file.

I think the most reasonable behaviour is to treat missing keys as empty.
This matches the "shell-like" sprit, since in a shell empty keys would
by default be treated as empty too. Thus, "ID_LIKE=" would match, if
ID_LIKE is not present in the file, and ID_LIKE=!$foo" would also match.
The other option would be to make those matches fail, but I think that'd
make the feature harder to use, esp. with negative matches.

Documentation is updated to clarify the new behaviour.

https://bugzilla.redhat.com/show_bug.cgi?id=2345544
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2025-02-13 15:49:50 +01:00
parent 411bc7c96c
commit de02b551ad
3 changed files with 23 additions and 1 deletions

View File

@ -1960,6 +1960,8 @@
wildcard comparisons (<literal>*</literal>, <literal>?</literal>, <literal>[]</literal>) are
supported with the <literal>$=</literal> (match) and <literal>!$=</literal> (non-match).</para>
<para>If the given key is not found in the file, the match is done against an empty value.</para>
<xi:include href="version-info.xml" xpointer="v249"/>
</listitem>
</varlistentry>

View File

@ -275,7 +275,9 @@ static int condition_test_osrelease(Condition *c, char **env) {
if (r < 0)
return log_debug_errno(r, "Failed to parse os-release: %m");
r = version_or_fnmatch_compare(operator, actual_value, word);
/* If not found, use "". This means that missing and empty assignments
* in the file have the same result. */
r = version_or_fnmatch_compare(operator, strempty(actual_value), word);
if (r < 0)
return r;
if (!r)

View File

@ -1095,6 +1095,24 @@ TEST(condition_test_os_release) {
ASSERT_OK_POSITIVE(condition_test(condition, environ));
condition_free(condition);
/* Test shell style globs */
ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_LIKE$=*THISHOPEFULLYWONTEXIST*", false, false));
ASSERT_OK_ZERO(condition_test(condition, environ));
condition_free(condition);
ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_THISHOPEFULLYWONTEXIST$=*rhel*", false, false));
ASSERT_OK_ZERO(condition_test(condition, environ));
condition_free(condition);
ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_LIKE!$=*THISHOPEFULLYWONTEXIST*", false, false));
ASSERT_OK_POSITIVE(condition_test(condition, environ));
condition_free(condition);
ASSERT_NOT_NULL(condition = condition_new(CONDITION_OS_RELEASE, "ID_THISHOPEFULLYWONTEXIST!$=*rhel*", false, false));
ASSERT_OK_POSITIVE(condition_test(condition, environ));
condition_free(condition);
/* load_os_release_pairs() removes quotes, we have to add them back,
* otherwise we get a string: "PRETTY_NAME=Debian GNU/Linux 10 (buster)"
* which is wrong, as the value is not quoted anymore. */