1
0
mirror of https://github.com/systemd/systemd synced 2025-09-23 22:04:45 +02:00

Compare commits

..

11 Commits

Author SHA1 Message Date
Eric DeVolder
f00c36641a pstore: introduce tmpfiles.d/systemd-pstore.conf
The systemd pstore service archives the contents of /sys/fs/pstore
upon boot so that there is room for a subsequent dump.  The issue is
that while the service is present, the kernel still needs to be
configured to write data into the pstore. The kernel has two
parameters, crash_kexec_post_notifiers and printk.always_kmsg_dump,
that control writes into pstore.

The crash_kexec_post_notifiers parameter enables the kernel to write
dmesg (including stack trace) into pstore upon a panic, and
printk.always_kmsg_dump parameter enables the kernel to write dmesg
upon a shutdown (shutdown, reboot, halt).

As it stands today, these parameters are not managed/manipulated by
the systemd pstore service, and are solely reliant upon the user [to
have the foresight] to set them on the kernel command line at boot, or
post boot via sysfs. Furthermore, the user would need to set these
parameters in a persistent fashion so that that they are enabled on
subsequent reboots.

This patch introduces the setting of these two kernel parameters via
the systemd tmpfiles technique.
2020-05-15 23:15:26 +02:00
Topi Miettinen
b4e1563ffb Increase size of /run to 20%
For low memory machines (256MB), 10% of RAM for /run may not be enough for
re-exec of PID1 because 16MB of free space is required and /run may already
contain something.
2020-05-15 21:40:22 +02:00
Zbigniew Jędrzejewski-Szmek
154962d348 docs: policy for systemd-security subscriptions
Replaces #14325.
2020-05-15 20:40:58 +02:00
Lennart Poettering
18fbb567a8
Merge pull request #15817 from poettering/more-conditions
Add ConditionEnvironment= and ConditionIsEncrypted=
2020-05-15 20:25:34 +02:00
Lennart Poettering
bccba5249a update TODO 2020-05-15 16:05:33 +02:00
Lennart Poettering
410abf8304 man: document the two new condition types 2020-05-15 16:05:33 +02:00
Lennart Poettering
a0b191b705 condition: add ConditionEnvironment=
Prompted by the discussions in #15180.

This is a bit more complex than I hoped, since for PID 1 we need to pass
in the synethetic environment block in we generate on demand.
2020-05-15 16:05:33 +02:00
Lennart Poettering
7cd9e4f8a0 limit-util: quieten a very common debug message that is misleading 2020-05-15 15:50:09 +02:00
Lennart Poettering
411e835c50 condition: return (Condition*) NULL from condition_free()
Follow our usual coding style.
2020-05-15 15:50:09 +02:00
Lennart Poettering
dce719f6c1 condition: introduce generic function type for condition_to_string()-like functions
Let's add a typedef for a function type we use at multiple places.
2020-05-15 15:50:09 +02:00
Lennart Poettering
7f19247b5e condition: add ConditionPathIsEncrypted=
It's easy to add, and should be pretty useful, in particular as in
AssertPathIsEncrypted= as it can be used for checking that
some path is encrypted before some service is invoked that might want to
place secure material there.
2020-05-15 15:50:09 +02:00
17 changed files with 356 additions and 143 deletions

2
TODO
View File

@ -68,8 +68,6 @@ Features:
* homed: add a way to "adopt" a home directory, i.e. strip foreign signatures * homed: add a way to "adopt" a home directory, i.e. strip foreign signatures
and insert a local signature instead. and insert a local signature instead.
* Maybe expose path_is_encrypted() as a new ConditionPathIsEncrypted=?
* homed: as an extension to the directory+subvolume backend: if located on * homed: as an extension to the directory+subvolume backend: if located on
especially marked fs, then sync down password into LUKS header of that fs, especially marked fs, then sync down password into LUKS header of that fs,
and always verify passwords against it too. Bootstrapping is a problem and always verify passwords against it too. Bootstrapping is a problem

View File

@ -9,3 +9,5 @@ layout: default
If you discover a security vulnerability, we'd appreciate a non-public disclosure. systemd developers can be contacted privately on the **[systemd-security@redhat.com](mailto:systemd-security@redhat.com) mailing list**. The disclosure will be coordinated with distributions. If you discover a security vulnerability, we'd appreciate a non-public disclosure. systemd developers can be contacted privately on the **[systemd-security@redhat.com](mailto:systemd-security@redhat.com) mailing list**. The disclosure will be coordinated with distributions.
(The [issue tracker](https://github.com/systemd/systemd/issues) and [systemd-devel mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) are fully public.) (The [issue tracker](https://github.com/systemd/systemd/issues) and [systemd-devel mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) are fully public.)
Subscription to the systemd-security mailing list is open to **regular systemd contributors and people working in the security teams of various distributions**. Those conditions should be backed by publicly accessible information (ideally, a track of posts and commits from the mail address in question). If you fall into one of those categories and wish to be subscribed, submit a **[subscription request](https://www.redhat.com/mailman/listinfo/systemd-security)**.

View File

@ -81,6 +81,24 @@
<citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>. <citerefentry><refentrytitle>pstore.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para> </para>
</refsect2> </refsect2>
<refsect2>
<title>Controlling kernel parameters</title>
<para> The kernel has two parameters,
<filename>/sys/module/kernel/parameters/crash_kexec_post_notifiers</filename> and
<filename>/sys/module/printk/parameters/always_kmsg_dump</filename>,
that control writes into pstore.
The crash_kexec_post_notifiers parameter enables the kernel to write
dmesg (including stack trace) into pstore upon a panic or crash, and
printk.always_kmsg_dump parameter enables the kernel to write dmesg
upon a normal shutdown (shutdown, reboot, halt). These kernel
parameters are managed via the
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
mechanism, specifically the file <filename>/usr/lib/tmpfiles/systemd-pstore.conf</filename>.
</para>
</refsect2>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -1226,6 +1226,24 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>ConditionEnvironment=</varname></term>
<listitem><para><varname>ConditionEnvironment=</varname> may be used to check whether a specific
environment variable is set (or if prefixed with the exclamation mark — unset) in the service
manager's environment block.
The argument may be a single word, to check if the variable with this name is defined in the
environment block, or an assignment
(<literal><replaceable>name</replaceable>=<replaceable>value</replaceable></literal>), to check if
the variable with this exact value is defined. Note that the environment block of the service
manager itself is checked, i.e. not any variables defined with <varname>Environment=</varname> or
<varname>EnvironmentFile=</varname>, as described above. This is particularly useful when the
service manager runs inside a containerized environment or as per-user service manager, in order to
check for variables passed in by the enclosing container manager or PAM.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>ConditionSecurity=</varname></term> <term><varname>ConditionSecurity=</varname></term>
@ -1346,6 +1364,18 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>ConditionPathIsEncrypted=</varname></term>
<listitem><para><varname>ConditionPathIsEncrypted=</varname> is similar to
<varname>ConditionPathExists=</varname> but verifies that the underlying file system's backing
block device is encrypted using dm-crypt/LUKS. Note that this check does not cover ext4
per-directory encryption, and only detects block level encryption. Moreover, if the specified path
resides on a file system on top of a loopback block device, only encryption above the loopback device is
detected. It is not detected whether the file system backing the loopback block device is encrypted.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>ConditionDirectoryNotEmpty=</varname></term> <term><varname>ConditionDirectoryNotEmpty=</varname></term>

View File

@ -21,6 +21,7 @@ static const condition_definition condition_definitions[] = {
{ "ConditionPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, { "ConditionPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK },
{ "ConditionPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, { "ConditionPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT },
{ "ConditionPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, { "ConditionPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE },
{ "ConditionPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED },
{ "ConditionDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, { "ConditionDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY },
{ "ConditionFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, { "ConditionFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY },
{ "ConditionFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, { "ConditionFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE },
@ -44,6 +45,7 @@ static const condition_definition condition_definitions[] = {
{ "AssertPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, { "AssertPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK },
{ "AssertPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, { "AssertPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT },
{ "AssertPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, { "AssertPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE },
{ "AssertPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED },
{ "AssertDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, { "AssertDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY },
{ "AssertFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, { "AssertFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY },
{ "AssertFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, { "AssertFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE },
@ -143,11 +145,11 @@ int verify_conditions(char **lines, UnitFileScope scope) {
return r; return r;
} }
r = condition_test_list(u->asserts, assert_type_to_string, log_helper, u); r = condition_test_list(u->asserts, environ, assert_type_to_string, log_helper, u);
if (u->asserts) if (u->asserts)
log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed"); log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed");
q = condition_test_list(u->conditions, condition_type_to_string, log_helper, u); q = condition_test_list(u->conditions, environ, condition_type_to_string, log_helper, u);
if (u->conditions) if (u->conditions)
log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed"); log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed");

View File

@ -41,6 +41,11 @@ uint64_t physical_memory(void) {
} }
if (r > 0) { if (r > 0) {
r = cg_get_attribute("memory", root, "memory.max", &value); r = cg_get_attribute("memory", root, "memory.max", &value);
if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't
* complain. (Note that it might exist on our own root though, if we live
* in a cgroup namespace, hence check anyway instead of not even
* trying.) */
return mem;
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m"); log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
return mem; return mem;

View File

@ -1705,24 +1705,50 @@ static int log_unit_internal(void *userdata, int level, int error, const char *f
} }
static bool unit_test_condition(Unit *u) { static bool unit_test_condition(Unit *u) {
_cleanup_strv_free_ char **env = NULL;
int r;
assert(u); assert(u);
dual_timestamp_get(&u->condition_timestamp); dual_timestamp_get(&u->condition_timestamp);
u->condition_result = condition_test_list(u->conditions, condition_type_to_string, log_unit_internal, u);
r = manager_get_effective_environment(u->manager, &env);
if (r < 0) {
log_unit_error_errno(u, r, "Failed to determine effective environment: %m");
u->condition_result = CONDITION_ERROR;
} else
u->condition_result = condition_test_list(
u->conditions,
env,
condition_type_to_string,
log_unit_internal,
u);
unit_add_to_dbus_queue(u); unit_add_to_dbus_queue(u);
return u->condition_result; return u->condition_result;
} }
static bool unit_test_assert(Unit *u) { static bool unit_test_assert(Unit *u) {
_cleanup_strv_free_ char **env = NULL;
int r;
assert(u); assert(u);
dual_timestamp_get(&u->assert_timestamp); dual_timestamp_get(&u->assert_timestamp);
u->assert_result = condition_test_list(u->asserts, assert_type_to_string, log_unit_internal, u);
r = manager_get_effective_environment(u->manager, &env);
if (r < 0) {
log_unit_error_errno(u, r, "Failed to determine effective environment: %m");
u->assert_result = CONDITION_ERROR;
} else
u->assert_result = condition_test_list(
u->asserts,
env,
assert_type_to_string,
log_unit_internal,
u);
unit_add_to_dbus_queue(u); unit_add_to_dbus_queue(u);
return u->assert_result; return u->assert_result;
} }

View File

@ -2,6 +2,7 @@
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "bond.h" #include "bond.h"
@ -693,7 +694,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
return r; return r;
/* skip out early if configuration does not match the environment */ /* skip out early if configuration does not match the environment */
if (!condition_test_list(netdev_raw->conditions, NULL, NULL, NULL)) { if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
log_debug("%s: Conditions in the file do not match the system environment, skipping.", filename); log_debug("%s: Conditions in the file do not match the system environment, skipping.", filename);
return 0; return 0;
} }

View File

@ -3,6 +3,7 @@
#include <net/if.h> #include <net/if.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <unistd.h>
#include "alloc-util.h" #include "alloc-util.h"
#include "conf-files.h" #include "conf-files.h"
@ -172,7 +173,7 @@ int network_verify(Network *network) {
network->filename); network->filename);
/* skip out early if configuration does not match the environment */ /* skip out early if configuration does not match the environment */
if (!condition_test_list(network->conditions, NULL, NULL, NULL)) if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Conditions in the file do not match the system environment, skipping.", "%s: Conditions in the file do not match the system environment, skipping.",
network->filename); network->filename);

View File

@ -107,7 +107,7 @@ int kernel_route_expiration_supported(void) {
.type = CONDITION_KERNEL_VERSION, .type = CONDITION_KERNEL_VERSION,
.parameter = (char *) ">= 4.5" .parameter = (char *) ">= 4.5"
}; };
r = condition_test(&c); r = condition_test(&c, NULL);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -25,6 +25,7 @@
#include "extract-word.h" #include "extract-word.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h"
#include "glob-util.h" #include "glob-util.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "ima-util.h" #include "ima-util.h"
@ -72,11 +73,11 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger
return c; return c;
} }
void condition_free(Condition *c) { Condition* condition_free(Condition *c) {
assert(c); assert(c);
free(c->parameter); free(c->parameter);
free(c); return mfree(c);
} }
Condition* condition_free_list_type(Condition *head, ConditionType type) { Condition* condition_free_list_type(Condition *head, ConditionType type) {
@ -92,7 +93,7 @@ Condition* condition_free_list_type(Condition *head, ConditionType type) {
return head; return head;
} }
static int condition_test_kernel_command_line(Condition *c) { static int condition_test_kernel_command_line(Condition *c, char **env) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *line = NULL;
const char *p; const char *p;
bool equal; bool equal;
@ -201,7 +202,7 @@ static bool test_order(int k, OrderOperator p) {
} }
} }
static int condition_test_kernel_version(Condition *c) { static int condition_test_kernel_version(Condition *c, char **env) {
OrderOperator order; OrderOperator order;
struct utsname u; struct utsname u;
const char *p; const char *p;
@ -259,7 +260,7 @@ static int condition_test_kernel_version(Condition *c) {
return true; return true;
} }
static int condition_test_memory(Condition *c) { static int condition_test_memory(Condition *c, char **env) {
OrderOperator order; OrderOperator order;
uint64_t m, k; uint64_t m, k;
const char *p; const char *p;
@ -283,7 +284,7 @@ static int condition_test_memory(Condition *c) {
return test_order(CMP(m, k), order); return test_order(CMP(m, k), order);
} }
static int condition_test_cpus(Condition *c) { static int condition_test_cpus(Condition *c, char **env) {
OrderOperator order; OrderOperator order;
const char *p; const char *p;
unsigned k; unsigned k;
@ -309,7 +310,7 @@ static int condition_test_cpus(Condition *c) {
return test_order(CMP((unsigned) n, k), order); return test_order(CMP((unsigned) n, k), order);
} }
static int condition_test_user(Condition *c) { static int condition_test_user(Condition *c, char **env) {
uid_t id; uid_t id;
int r; int r;
_cleanup_free_ char *username = NULL; _cleanup_free_ char *username = NULL;
@ -344,7 +345,7 @@ static int condition_test_user(Condition *c) {
return id == getuid() || id == geteuid(); return id == getuid() || id == geteuid();
} }
static int condition_test_control_group_controller(Condition *c) { static int condition_test_control_group_controller(Condition *c, char **env) {
int r; int r;
CGroupMask system_mask, wanted_mask = 0; CGroupMask system_mask, wanted_mask = 0;
@ -368,7 +369,7 @@ static int condition_test_control_group_controller(Condition *c) {
return FLAGS_SET(system_mask, wanted_mask); return FLAGS_SET(system_mask, wanted_mask);
} }
static int condition_test_group(Condition *c) { static int condition_test_group(Condition *c, char **env) {
gid_t id; gid_t id;
int r; int r;
@ -387,7 +388,7 @@ static int condition_test_group(Condition *c) {
return in_group(c->parameter) > 0; return in_group(c->parameter) > 0;
} }
static int condition_test_virtualization(Condition *c) { static int condition_test_virtualization(Condition *c, char **env) {
int b, v; int b, v;
assert(c); assert(c);
@ -417,7 +418,7 @@ static int condition_test_virtualization(Condition *c) {
return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v)); return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v));
} }
static int condition_test_architecture(Condition *c) { static int condition_test_architecture(Condition *c, char **env) {
int a, b; int a, b;
assert(c); assert(c);
@ -439,7 +440,7 @@ static int condition_test_architecture(Condition *c) {
return a == b; return a == b;
} }
static int condition_test_host(Condition *c) { static int condition_test_host(Condition *c, char **env) {
_cleanup_free_ char *h = NULL; _cleanup_free_ char *h = NULL;
sd_id128_t x, y; sd_id128_t x, y;
int r; int r;
@ -464,7 +465,7 @@ static int condition_test_host(Condition *c) {
return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0;
} }
static int condition_test_ac_power(Condition *c) { static int condition_test_ac_power(Condition *c, char **env) {
int r; int r;
assert(c); assert(c);
@ -478,7 +479,7 @@ static int condition_test_ac_power(Condition *c) {
return (on_ac_power() != 0) == !!r; return (on_ac_power() != 0) == !!r;
} }
static int condition_test_security(Condition *c) { static int condition_test_security(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_SECURITY); assert(c->type == CONDITION_SECURITY);
@ -501,7 +502,7 @@ static int condition_test_security(Condition *c) {
return false; return false;
} }
static int condition_test_capability(Condition *c) { static int condition_test_capability(Condition *c, char **env) {
unsigned long long capabilities = (unsigned long long) -1; unsigned long long capabilities = (unsigned long long) -1;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
int value, r; int value, r;
@ -544,7 +545,7 @@ static int condition_test_capability(Condition *c) {
return !!(capabilities & (1ULL << value)); return !!(capabilities & (1ULL << value));
} }
static int condition_test_needs_update(Condition *c) { static int condition_test_needs_update(Condition *c, char **env) {
const char *p; const char *p;
struct stat usr, other; struct stat usr, other;
@ -610,7 +611,7 @@ static int condition_test_needs_update(Condition *c) {
return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec; return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
} }
static int condition_test_first_boot(Condition *c) { static int condition_test_first_boot(Condition *c, char **env) {
int r; int r;
assert(c); assert(c);
@ -624,7 +625,36 @@ static int condition_test_first_boot(Condition *c) {
return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r; return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r;
} }
static int condition_test_path_exists(Condition *c) { static int condition_test_environment(Condition *c, char **env) {
bool equal;
char **i;
assert(c);
assert(c->parameter);
assert(c->type == CONDITION_ENVIRONMENT);
equal = strchr(c->parameter, '=');
STRV_FOREACH(i, env) {
bool found;
if (equal)
found = streq(c->parameter, *i);
else {
const char *f;
f = startswith(*i, c->parameter);
found = f && IN_SET(*f, 0, '=');
}
if (found)
return true;
}
return false;
}
static int condition_test_path_exists(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_PATH_EXISTS); assert(c->type == CONDITION_PATH_EXISTS);
@ -632,7 +662,7 @@ static int condition_test_path_exists(Condition *c) {
return access(c->parameter, F_OK) >= 0; return access(c->parameter, F_OK) >= 0;
} }
static int condition_test_path_exists_glob(Condition *c) { static int condition_test_path_exists_glob(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_PATH_EXISTS_GLOB); assert(c->type == CONDITION_PATH_EXISTS_GLOB);
@ -640,7 +670,7 @@ static int condition_test_path_exists_glob(Condition *c) {
return glob_exists(c->parameter) > 0; return glob_exists(c->parameter) > 0;
} }
static int condition_test_path_is_directory(Condition *c) { static int condition_test_path_is_directory(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_DIRECTORY); assert(c->type == CONDITION_PATH_IS_DIRECTORY);
@ -648,7 +678,7 @@ static int condition_test_path_is_directory(Condition *c) {
return is_dir(c->parameter, true) > 0; return is_dir(c->parameter, true) > 0;
} }
static int condition_test_path_is_symbolic_link(Condition *c) { static int condition_test_path_is_symbolic_link(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK); assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK);
@ -656,7 +686,7 @@ static int condition_test_path_is_symbolic_link(Condition *c) {
return is_symlink(c->parameter) > 0; return is_symlink(c->parameter) > 0;
} }
static int condition_test_path_is_mount_point(Condition *c) { static int condition_test_path_is_mount_point(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_MOUNT_POINT); assert(c->type == CONDITION_PATH_IS_MOUNT_POINT);
@ -664,7 +694,7 @@ static int condition_test_path_is_mount_point(Condition *c) {
return path_is_mount_point(c->parameter, NULL, AT_SYMLINK_FOLLOW) > 0; return path_is_mount_point(c->parameter, NULL, AT_SYMLINK_FOLLOW) > 0;
} }
static int condition_test_path_is_read_write(Condition *c) { static int condition_test_path_is_read_write(Condition *c, char **env) {
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_READ_WRITE); assert(c->type == CONDITION_PATH_IS_READ_WRITE);
@ -672,7 +702,21 @@ static int condition_test_path_is_read_write(Condition *c) {
return path_is_read_only_fs(c->parameter) <= 0; return path_is_read_only_fs(c->parameter) <= 0;
} }
static int condition_test_directory_not_empty(Condition *c) { static int condition_test_path_is_encrypted(Condition *c, char **env) {
int r;
assert(c);
assert(c->parameter);
assert(c->type == CONDITION_PATH_IS_ENCRYPTED);
r = path_is_encrypted(c->parameter);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to determine if '%s' is encrypted: %m", c->parameter);
return r > 0;
}
static int condition_test_directory_not_empty(Condition *c, char **env) {
int r; int r;
assert(c); assert(c);
@ -683,7 +727,7 @@ static int condition_test_directory_not_empty(Condition *c) {
return r <= 0 && r != -ENOENT; return r <= 0 && r != -ENOENT;
} }
static int condition_test_file_not_empty(Condition *c) { static int condition_test_file_not_empty(Condition *c, char **env) {
struct stat st; struct stat st;
assert(c); assert(c);
@ -695,7 +739,7 @@ static int condition_test_file_not_empty(Condition *c) {
st.st_size > 0); st.st_size > 0);
} }
static int condition_test_file_is_executable(Condition *c) { static int condition_test_file_is_executable(Condition *c, char **env) {
struct stat st; struct stat st;
assert(c); assert(c);
@ -707,7 +751,7 @@ static int condition_test_file_is_executable(Condition *c) {
(st.st_mode & 0111)); (st.st_mode & 0111));
} }
static int condition_test_null(Condition *c) { static int condition_test_null(Condition *c, char **env) {
assert(c); assert(c);
assert(c->type == CONDITION_NULL); assert(c->type == CONDITION_NULL);
@ -716,15 +760,16 @@ static int condition_test_null(Condition *c) {
return true; return true;
} }
int condition_test(Condition *c) { int condition_test(Condition *c, char **env) {
static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = { static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c, char **env) = {
[CONDITION_PATH_EXISTS] = condition_test_path_exists, [CONDITION_PATH_EXISTS] = condition_test_path_exists,
[CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob, [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob,
[CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory, [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory,
[CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link, [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link,
[CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point, [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point,
[CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write, [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write,
[CONDITION_PATH_IS_ENCRYPTED] = condition_test_path_is_encrypted,
[CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty, [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty,
[CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty, [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty,
[CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable, [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable,
@ -744,6 +789,7 @@ int condition_test(Condition *c) {
[CONDITION_NULL] = condition_test_null, [CONDITION_NULL] = condition_test_null,
[CONDITION_CPUS] = condition_test_cpus, [CONDITION_CPUS] = condition_test_cpus,
[CONDITION_MEMORY] = condition_test_memory, [CONDITION_MEMORY] = condition_test_memory,
[CONDITION_ENVIRONMENT] = condition_test_environment,
}; };
int r, b; int r, b;
@ -752,7 +798,7 @@ int condition_test(Condition *c) {
assert(c->type >= 0); assert(c->type >= 0);
assert(c->type < _CONDITION_TYPE_MAX); assert(c->type < _CONDITION_TYPE_MAX);
r = condition_tests[c->type](c); r = condition_tests[c->type](c, env);
if (r < 0) { if (r < 0) {
c->result = CONDITION_ERROR; c->result = CONDITION_ERROR;
return r; return r;
@ -763,7 +809,13 @@ int condition_test(Condition *c) {
return b; return b;
} }
bool condition_test_list(Condition *first, const char *(*to_string)(ConditionType t), condition_test_logger_t logger, void *userdata) { bool condition_test_list(
Condition *first,
char **env,
condition_to_string_t to_string,
condition_test_logger_t logger,
void *userdata) {
Condition *c; Condition *c;
int triggered = -1; int triggered = -1;
@ -779,7 +831,7 @@ bool condition_test_list(Condition *first, const char *(*to_string)(ConditionTyp
LIST_FOREACH(conditions, c, first) { LIST_FOREACH(conditions, c, first) {
int r; int r;
r = condition_test(c); r = condition_test(c, env);
if (logger) { if (logger) {
const char *p = c->type == CONDITION_NULL ? "true" : c->parameter; const char *p = c->type == CONDITION_NULL ? "true" : c->parameter;
@ -812,9 +864,10 @@ bool condition_test_list(Condition *first, const char *(*to_string)(ConditionTyp
return triggered != 0; return triggered != 0;
} }
void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { void condition_dump(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string) {
assert(c); assert(c);
assert(f); assert(f);
assert(to_string);
prefix = strempty(prefix); prefix = strempty(prefix);
@ -828,7 +881,7 @@ void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_
condition_result_to_string(c->result)); condition_result_to_string(c->result));
} }
void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { void condition_dump_list(Condition *first, FILE *f, const char *prefix, condition_to_string_t to_string) {
Condition *c; Condition *c;
LIST_FOREACH(conditions, c, first) LIST_FOREACH(conditions, c, first)
@ -852,6 +905,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink", [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
[CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint", [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
[CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite", [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite",
[CONDITION_PATH_IS_ENCRYPTED] = "ConditionPathIsEncrypted",
[CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty", [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty", [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
[CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable", [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
@ -861,6 +915,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_NULL] = "ConditionNull", [CONDITION_NULL] = "ConditionNull",
[CONDITION_CPUS] = "ConditionCPUs", [CONDITION_CPUS] = "ConditionCPUs",
[CONDITION_MEMORY] = "ConditionMemory", [CONDITION_MEMORY] = "ConditionMemory",
[CONDITION_ENVIRONMENT] = "ConditionEnvironment",
}; };
DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
@ -882,6 +937,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink", [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink",
[CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint", [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint",
[CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite", [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite",
[CONDITION_PATH_IS_ENCRYPTED] = "AssertPathIsEncrypted",
[CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty", [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty",
[CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty", [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty",
[CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable", [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable",
@ -891,6 +947,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_NULL] = "AssertNull", [CONDITION_NULL] = "AssertNull",
[CONDITION_CPUS] = "AssertCPUs", [CONDITION_CPUS] = "AssertCPUs",
[CONDITION_MEMORY] = "AssertMemory", [CONDITION_MEMORY] = "AssertMemory",
[CONDITION_ENVIRONMENT] = "AssertEnvironment",
}; };
DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType); DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType);

View File

@ -18,6 +18,7 @@ typedef enum ConditionType {
CONDITION_AC_POWER, CONDITION_AC_POWER,
CONDITION_MEMORY, CONDITION_MEMORY,
CONDITION_CPUS, CONDITION_CPUS,
CONDITION_ENVIRONMENT,
CONDITION_NEEDS_UPDATE, CONDITION_NEEDS_UPDATE,
CONDITION_FIRST_BOOT, CONDITION_FIRST_BOOT,
@ -28,6 +29,7 @@ typedef enum ConditionType {
CONDITION_PATH_IS_SYMBOLIC_LINK, CONDITION_PATH_IS_SYMBOLIC_LINK,
CONDITION_PATH_IS_MOUNT_POINT, CONDITION_PATH_IS_MOUNT_POINT,
CONDITION_PATH_IS_READ_WRITE, CONDITION_PATH_IS_READ_WRITE,
CONDITION_PATH_IS_ENCRYPTED,
CONDITION_DIRECTORY_NOT_EMPTY, CONDITION_DIRECTORY_NOT_EMPTY,
CONDITION_FILE_NOT_EMPTY, CONDITION_FILE_NOT_EMPTY,
CONDITION_FILE_IS_EXECUTABLE, CONDITION_FILE_IS_EXECUTABLE,
@ -66,18 +68,20 @@ typedef struct Condition {
} Condition; } Condition;
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate); Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
void condition_free(Condition *c); Condition* condition_free(Condition *c);
Condition* condition_free_list_type(Condition *first, ConditionType type); Condition* condition_free_list_type(Condition *first, ConditionType type);
static inline Condition* condition_free_list(Condition *first) { static inline Condition* condition_free_list(Condition *first) {
return condition_free_list_type(first, _CONDITION_TYPE_INVALID); return condition_free_list_type(first, _CONDITION_TYPE_INVALID);
} }
int condition_test(Condition *c); int condition_test(Condition *c, char **env);
typedef int (*condition_test_logger_t)(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8);
bool condition_test_list(Condition *first, const char *(*to_string)(ConditionType t), condition_test_logger_t logger, void *userdata);
void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)); typedef int (*condition_test_logger_t)(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8);
void condition_dump_list(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)); typedef const char* (*condition_to_string_t)(ConditionType t) _const_;
bool condition_test_list(Condition *first, char **env, condition_to_string_t to_string, condition_test_logger_t logger, void *userdata);
void condition_dump(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string);
void condition_dump_list(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string);
const char* condition_type_to_string(ConditionType t) _const_; const char* condition_type_to_string(ConditionType t) _const_;
ConditionType condition_type_from_string(const char *s) _pure_; ConditionType condition_type_from_string(const char *s) _pure_;
@ -96,6 +100,7 @@ static inline bool condition_takes_path(ConditionType t) {
CONDITION_PATH_IS_SYMBOLIC_LINK, CONDITION_PATH_IS_SYMBOLIC_LINK,
CONDITION_PATH_IS_MOUNT_POINT, CONDITION_PATH_IS_MOUNT_POINT,
CONDITION_PATH_IS_READ_WRITE, CONDITION_PATH_IS_READ_WRITE,
CONDITION_PATH_IS_ENCRYPTED,
CONDITION_DIRECTORY_NOT_EMPTY, CONDITION_DIRECTORY_NOT_EMPTY,
CONDITION_FILE_NOT_EMPTY, CONDITION_FILE_NOT_EMPTY,
CONDITION_FILE_IS_EXECUTABLE, CONDITION_FILE_IS_EXECUTABLE,

View File

@ -13,12 +13,15 @@
#define TMPFS_LIMITS_EMPTY_OR_ALMOST ",size=4m,nr_inodes=1k" #define TMPFS_LIMITS_EMPTY_OR_ALMOST ",size=4m,nr_inodes=1k"
#define TMPFS_LIMITS_SYS TMPFS_LIMITS_EMPTY_OR_ALMOST #define TMPFS_LIMITS_SYS TMPFS_LIMITS_EMPTY_OR_ALMOST
#define TMPFS_LIMITS_SYS_FS_CGROUP TMPFS_LIMITS_EMPTY_OR_ALMOST #define TMPFS_LIMITS_SYS_FS_CGROUP TMPFS_LIMITS_EMPTY_OR_ALMOST
/* On an extremely small device with only 256MB of RAM, 20% of RAM for /run should be enough for re-exec of
PID1 because 16MB of free space is required. */
#define TMPFS_LIMITS_RUN ",size=20%,nr_inodes=800k"
/* 10% of RAM (using 16GB of RAM as a baseline) translates to 400k inodes (assuming 4k each) and 25% /* 10% of RAM (using 16GB of RAM as a baseline) translates to 400k inodes (assuming 4k each) and 25%
translates to 1M inodes */ translates to 1M inodes */
#define TMPFS_LIMITS_TMP ",size=10%,nr_inodes=400k" #define TMPFS_LIMITS_TMP ",size=10%,nr_inodes=400k"
#define TMPFS_LIMITS_DEV_SHM TMPFS_LIMITS_TMP #define TMPFS_LIMITS_DEV_SHM TMPFS_LIMITS_TMP
#define TMPFS_LIMITS_RUN TMPFS_LIMITS_TMP
#define TMPFS_LIMITS_TEMPORARY_FS TMPFS_LIMITS_TMP #define TMPFS_LIMITS_TEMPORARY_FS TMPFS_LIMITS_TMP
/* More space for volatile root and /var */
#define TMPFS_LIMITS_VAR ",size=25%,nr_inodes=1m" #define TMPFS_LIMITS_VAR ",size=25%,nr_inodes=1m"
#define TMPFS_LIMITS_ROOTFS TMPFS_LIMITS_VAR #define TMPFS_LIMITS_ROOTFS TMPFS_LIMITS_VAR
#define TMPFS_LIMITS_VOLATILE_STATE TMPFS_LIMITS_VAR #define TMPFS_LIMITS_VOLATILE_STATE TMPFS_LIMITS_VAR

View File

@ -39,82 +39,87 @@ static void test_condition_test_path(void) {
condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false); condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition)); assert_se(condition_test(condition, environ));
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false); condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false); condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false); condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false); condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false); condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false); condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_ENCRYPTED, "/sys", false, false);
assert_se(condition);
assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false); condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
} }
@ -134,12 +139,12 @@ static void test_condition_test_control_group_controller(void) {
/* Invalid controllers are ignored */ /* Invalid controllers are ignored */
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
assert_se(cg_mask_supported(&system_mask) >= 0); assert_se(cg_mask_supported(&system_mask) >= 0);
@ -152,23 +157,23 @@ static void test_condition_test_control_group_controller(void) {
log_info("this controller is available"); log_info("this controller is available");
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
} else { } else {
log_info("this controller is unavailable"); log_info("this controller is unavailable");
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
} }
} }
@ -178,12 +183,12 @@ static void test_condition_test_control_group_controller(void) {
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
} }
@ -192,17 +197,17 @@ static void test_condition_test_ac_power(void) {
condition = condition_new(CONDITION_AC_POWER, "true", false, false); condition = condition_new(CONDITION_AC_POWER, "true", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == on_ac_power()); assert_se(condition_test(condition, environ) == on_ac_power());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_AC_POWER, "false", false, false); condition = condition_new(CONDITION_AC_POWER, "false", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) != on_ac_power()); assert_se(condition_test(condition, environ) != on_ac_power());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_AC_POWER, "false", false, true); condition = condition_new(CONDITION_AC_POWER, "false", false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == on_ac_power()); assert_se(condition_test(condition, environ) == on_ac_power());
condition_free(condition); condition_free(condition);
} }
@ -219,17 +224,17 @@ static void test_condition_test_host(void) {
condition = condition_new(CONDITION_HOST, sid, false, false); condition = condition_new(CONDITION_HOST, sid, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_HOST, sid, false, true); condition = condition_new(CONDITION_HOST, sid, false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
hostname = gethostname_malloc(); hostname = gethostname_malloc();
@ -241,7 +246,7 @@ static void test_condition_test_host(void) {
else { else {
condition = condition_new(CONDITION_HOST, hostname, false, false); condition = condition_new(CONDITION_HOST, hostname, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
} }
} }
@ -259,17 +264,17 @@ static void test_condition_test_architecture(void) {
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false); condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
} }
@ -279,7 +284,7 @@ static void test_condition_test_kernel_command_line(void) {
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
if (ERRNO_IS_PRIVILEGE(r)) if (ERRNO_IS_PRIVILEGE(r))
return; return;
assert_se(r == 0); assert_se(r == 0);
@ -287,7 +292,7 @@ static void test_condition_test_kernel_command_line(void) {
condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
} }
@ -298,26 +303,26 @@ static void test_condition_test_kernel_version(void) {
condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
/* An artificially empty condition. It evaluates to true, but normally /* An artificially empty condition. It evaluates to true, but normally
* such condition cannot be created, because the condition list is reset instead. */ * such condition cannot be created, because the condition list is reset instead. */
condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
assert_se(uname(&u) >= 0); assert_se(uname(&u) >= 0);
condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
strshorten(u.release, 4); strshorten(u.release, 4);
@ -325,79 +330,79 @@ static void test_condition_test_kernel_version(void) {
condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
/* 0.1.2 would be a very very very old kernel */ /* 0.1.2 would be a very very very old kernel */
condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == -EINVAL); assert_se(condition_test(condition, environ) == -EINVAL);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == -EINVAL); assert_se(condition_test(condition, environ) == -EINVAL);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
/* 4711.8.15 is a very very very future kernel */ /* 4711.8.15 is a very very very future kernel */
condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false); condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
assert_se(uname(&u) >= 0); assert_se(uname(&u) >= 0);
@ -405,31 +410,31 @@ static void test_condition_test_kernel_version(void) {
v = strjoina(">=", u.release); v = strjoina(">=", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
v = strjoina("= ", u.release); v = strjoina("= ", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
v = strjoina("<=", u.release); v = strjoina("<=", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
v = strjoina("> ", u.release); v = strjoina("> ", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
v = strjoina("< ", u.release); v = strjoina("< ", u.release);
condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
} }
@ -438,12 +443,12 @@ static void test_condition_test_null(void) {
condition = condition_new(CONDITION_NULL, NULL, false, false); condition = condition_new(CONDITION_NULL, NULL, false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) > 0); assert_se(condition_test(condition, environ) > 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_NULL, NULL, false, true); condition = condition_new(CONDITION_NULL, NULL, false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
} }
@ -452,42 +457,42 @@ static void test_condition_test_security(void) {
condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false); condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == 0); assert_se(condition_test(condition, environ) == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "selinux", false, true); condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) != mac_selinux_use()); assert_se(condition_test(condition, environ) != mac_selinux_use());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "apparmor", false, false); condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == mac_apparmor_use()); assert_se(condition_test(condition, environ) == mac_apparmor_use());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false); condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == mac_tomoyo_use()); assert_se(condition_test(condition, environ) == mac_tomoyo_use());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "ima", false, false); condition = condition_new(CONDITION_SECURITY, "ima", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == use_ima()); assert_se(condition_test(condition, environ) == use_ima());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "smack", false, false); condition = condition_new(CONDITION_SECURITY, "smack", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == mac_smack_use()); assert_se(condition_test(condition, environ) == mac_smack_use());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "audit", false, false); condition = condition_new(CONDITION_SECURITY, "audit", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == use_audit()); assert_se(condition_test(condition, environ) == use_audit());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "uefi-secureboot", false, false); condition = condition_new(CONDITION_SECURITY, "uefi-secureboot", false, false);
assert_se(condition); assert_se(condition);
assert_se(condition_test(condition) == is_efi_secure_boot()); assert_se(condition_test(condition, environ) == is_efi_secure_boot());
condition_free(condition); condition_free(condition);
} }
@ -510,7 +515,7 @@ static void test_condition_test_virtualization(void) {
condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false); condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
if (ERRNO_IS_PRIVILEGE(r)) if (ERRNO_IS_PRIVILEGE(r))
return; return;
log_info("ConditionVirtualization=garbage → %i", r); log_info("ConditionVirtualization=garbage → %i", r);
@ -519,21 +524,21 @@ static void test_condition_test_virtualization(void) {
condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false); condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionVirtualization=container → %i", r); log_info("ConditionVirtualization=container → %i", r);
assert_se(r == !!detect_container()); assert_se(r == !!detect_container());
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false); condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionVirtualization=vm → %i", r); log_info("ConditionVirtualization=vm → %i", r);
assert_se(r == (detect_vm() && !detect_container())); assert_se(r == (detect_vm() && !detect_container()));
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false); condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionVirtualization=private-users → %i", r); log_info("ConditionVirtualization=private-users → %i", r);
assert_se(r == !!running_in_userns()); assert_se(r == !!running_in_userns());
condition_free(condition); condition_free(condition);
@ -554,7 +559,7 @@ static void test_condition_test_virtualization(void) {
condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false); condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionVirtualization=%s → %i", virt, r); log_info("ConditionVirtualization=%s → %i", virt, r);
assert_se(r >= 0); assert_se(r >= 0);
condition_free(condition); condition_free(condition);
@ -569,7 +574,7 @@ static void test_condition_test_user(void) {
condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false); condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=garbage → %i", r); log_info("ConditionUser=garbage → %i", r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
@ -577,7 +582,7 @@ static void test_condition_test_user(void) {
assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0); assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0);
condition = condition_new(CONDITION_USER, uid, false, false); condition = condition_new(CONDITION_USER, uid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=%s → %i", uid, r); log_info("ConditionUser=%s → %i", uid, r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
@ -586,7 +591,7 @@ static void test_condition_test_user(void) {
assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0); assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0);
condition = condition_new(CONDITION_USER, uid, false, false); condition = condition_new(CONDITION_USER, uid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=%s → %i", uid, r); log_info("ConditionUser=%s → %i", uid, r);
assert_se(r > 0); assert_se(r > 0);
condition_free(condition); condition_free(condition);
@ -595,7 +600,7 @@ static void test_condition_test_user(void) {
assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0); assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0);
condition = condition_new(CONDITION_USER, uid, false, false); condition = condition_new(CONDITION_USER, uid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=%s → %i", uid, r); log_info("ConditionUser=%s → %i", uid, r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
@ -605,7 +610,7 @@ static void test_condition_test_user(void) {
assert_se(username); assert_se(username);
condition = condition_new(CONDITION_USER, username, false, false); condition = condition_new(CONDITION_USER, username, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=%s → %i", username, r); log_info("ConditionUser=%s → %i", username, r);
assert_se(r > 0); assert_se(r > 0);
condition_free(condition); condition_free(condition);
@ -614,14 +619,14 @@ static void test_condition_test_user(void) {
username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root"); username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root");
condition = condition_new(CONDITION_USER, username, false, false); condition = condition_new(CONDITION_USER, username, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=%s → %i", username, r); log_info("ConditionUser=%s → %i", username, r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
condition = condition_new(CONDITION_USER, "@system", false, false); condition = condition_new(CONDITION_USER, "@system", false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionUser=@system → %i", r); log_info("ConditionUser=@system → %i", r);
if (uid_is_system(getuid()) || uid_is_system(geteuid())) if (uid_is_system(getuid()) || uid_is_system(geteuid()))
assert_se(r > 0); assert_se(r > 0);
@ -640,7 +645,7 @@ static void test_condition_test_group(void) {
assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF))); assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF)));
condition = condition_new(CONDITION_GROUP, gid, false, false); condition = condition_new(CONDITION_GROUP, gid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionGroup=%s → %i", gid, r); log_info("ConditionGroup=%s → %i", gid, r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
@ -649,7 +654,7 @@ static void test_condition_test_group(void) {
assert_se(0 < asprintf(&gid, "%u", getgid())); assert_se(0 < asprintf(&gid, "%u", getgid()));
condition = condition_new(CONDITION_GROUP, gid, false, false); condition = condition_new(CONDITION_GROUP, gid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionGroup=%s → %i", gid, r); log_info("ConditionGroup=%s → %i", gid, r);
assert_se(r > 0); assert_se(r > 0);
condition_free(condition); condition_free(condition);
@ -668,7 +673,7 @@ static void test_condition_test_group(void) {
assert_se(0 < asprintf(&gid, "%u", gids[i])); assert_se(0 < asprintf(&gid, "%u", gids[i]));
condition = condition_new(CONDITION_GROUP, gid, false, false); condition = condition_new(CONDITION_GROUP, gid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionGroup=%s → %i", gid, r); log_info("ConditionGroup=%s → %i", gid, r);
assert_se(r > 0); assert_se(r > 0);
condition_free(condition); condition_free(condition);
@ -679,7 +684,7 @@ static void test_condition_test_group(void) {
assert_se(groupname); assert_se(groupname);
condition = condition_new(CONDITION_GROUP, groupname, false, false); condition = condition_new(CONDITION_GROUP, groupname, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionGroup=%s → %i", groupname, r); log_info("ConditionGroup=%s → %i", groupname, r);
assert_se(r > 0); assert_se(r > 0);
condition_free(condition); condition_free(condition);
@ -690,7 +695,7 @@ static void test_condition_test_group(void) {
assert_se(0 < asprintf(&gid, "%u", max_gid+1)); assert_se(0 < asprintf(&gid, "%u", max_gid+1));
condition = condition_new(CONDITION_GROUP, gid, false, false); condition = condition_new(CONDITION_GROUP, gid, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionGroup=%s → %i", gid, r); log_info("ConditionGroup=%s → %i", gid, r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
@ -699,7 +704,7 @@ static void test_condition_test_group(void) {
groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root"); groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root");
condition = condition_new(CONDITION_GROUP, groupname, false, false); condition = condition_new(CONDITION_GROUP, groupname, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
log_info("ConditionGroup=%s → %i", groupname, r); log_info("ConditionGroup=%s → %i", groupname, r);
assert_se(r == 0); assert_se(r == 0);
condition_free(condition); condition_free(condition);
@ -714,7 +719,7 @@ static void test_condition_test_cpus_one(const char *s, bool result) {
condition = condition_new(CONDITION_CPUS, s, false, false); condition = condition_new(CONDITION_CPUS, s, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
assert_se(r >= 0); assert_se(r >= 0);
assert_se(r == result); assert_se(r == result);
condition_free(condition); condition_free(condition);
@ -775,7 +780,7 @@ static void test_condition_test_memory_one(const char *s, bool result) {
condition = condition_new(CONDITION_MEMORY, s, false, false); condition = condition_new(CONDITION_MEMORY, s, false, false);
assert_se(condition); assert_se(condition);
r = condition_test(condition); r = condition_test(condition, environ);
assert_se(r >= 0); assert_se(r >= 0);
assert_se(r == result); assert_se(r == result);
condition_free(condition); condition_free(condition);
@ -826,6 +831,34 @@ static void test_condition_test_memory(void) {
t = mfree(t); t = mfree(t);
} }
static void test_condition_test_environment_one(const char *s, bool result) {
Condition *condition;
int r;
log_debug("%s=%s", condition_type_to_string(CONDITION_ENVIRONMENT), s);
condition = condition_new(CONDITION_ENVIRONMENT, s, false, false);
assert_se(condition);
r = condition_test(condition, environ);
assert_se(r >= 0);
assert_se(r == result);
condition_free(condition);
}
static void test_condition_test_environment(void) {
assert_se(setenv("EXISTINGENVVAR", "foo", false) >= 0);
test_condition_test_environment_one("MISSINGENVVAR", false);
test_condition_test_environment_one("MISSINGENVVAR=foo", false);
test_condition_test_environment_one("MISSINGENVVAR=", false);
test_condition_test_environment_one("EXISTINGENVVAR", true);
test_condition_test_environment_one("EXISTINGENVVAR=foo", true);
test_condition_test_environment_one("EXISTINGENVVAR=bar", false);
test_condition_test_environment_one("EXISTINGENVVAR=", false);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG); test_setup_logging(LOG_DEBUG);
@ -844,6 +877,7 @@ int main(int argc, char *argv[]) {
test_condition_test_control_group_controller(); test_condition_test_control_group_controller();
test_condition_test_cpus(); test_condition_test_cpus();
test_condition_test_memory(); test_condition_test_memory();
test_condition_test_environment();
return 0; return 0;
} }

View File

@ -2,6 +2,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <netinet/ether.h> #include <netinet/ether.h>
#include <unistd.h>
#include "sd-device.h" #include "sd-device.h"
#include "sd-netlink.h" #include "sd-netlink.h"
@ -173,7 +174,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
return 0; return 0;
} }
if (!condition_test_list(link->conditions, NULL, NULL, NULL)) { if (!condition_test_list(link->conditions, environ, NULL, NULL, NULL)) {
log_debug("%s: Conditions do not match the system environment, skipping.", filename); log_debug("%s: Conditions do not match the system environment, skipping.", filename);
return 0; return 0;
} }

View File

@ -8,6 +8,7 @@ tmpfiles = [['home.conf', ''],
['systemd-nspawn.conf', 'ENABLE_MACHINED'], ['systemd-nspawn.conf', 'ENABLE_MACHINED'],
['systemd-tmp.conf', ''], ['systemd-tmp.conf', ''],
['portables.conf', 'ENABLE_PORTABLED'], ['portables.conf', 'ENABLE_PORTABLED'],
['systemd-pstore.conf', 'ENABLE_PSTORE'],
['tmp.conf', ''], ['tmp.conf', ''],
['x11.conf', ''], ['x11.conf', ''],
['legacy.conf', 'HAVE_SYSV_COMPAT'], ['legacy.conf', 'HAVE_SYSV_COMPAT'],

View File

@ -0,0 +1,29 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# The systemd-pstore.service(1) archives the contents of /sys/fs/pstore
# upon boot so that there is room for a subsequent dump. This service
# is enabled with:
# systemctl enable systemd-pstore
#
# With the service enabled, the kernel still needs to be configured
# to write data into the pstore. The kernel has two parameters,
# crash_kexec_post_notifiers and printk.always_kmsg_dump, that
# control writes into pstore.
#
# The crash_kexec_post_notifiers parameter enables the kernel to write
# dmesg (including stack trace) into pstore upon a panic, and
# printk.always_kmsg_dump parameter enables the kernel to write dmesg
# upon a normal shutdown (shutdown, reboot, halt).
#
# To configure the kernel parameters, uncomment the appropriate
# line(s) below. The value written is either 'Y' to enable the
# kernel parameter, or 'N' to disable the kernel parameter.
#
# After making a change to this file, do:
# systemd-tmpfiles --create path/to/tmpfiles.d/systemd-pstore.conf
#
# These changes are automatically applied on future re-boots.
d /var/lib/systemd/pstore 0755 root root 14d
#w /sys/module/printk/parameters/always_kmsg_dump - - - - Y
w /sys/module/kernel/parameters/crash_kexec_post_notifiers - - - - Y