From a0b191b705ff4bcc4f7b49aec060dfa713e2325a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 14 May 2020 19:13:03 +0200 Subject: [PATCH] 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. --- src/analyze/analyze-condition.c | 4 +- src/core/unit.c | 34 ++++- src/network/netdev/netdev.c | 3 +- src/network/networkd-network.c | 3 +- src/network/networkd-util.c | 2 +- src/shared/condition.c | 93 +++++++++----- src/shared/condition.h | 7 +- src/test/test-condition.c | 211 ++++++++++++++++++-------------- src/udev/net/link-config.c | 3 +- 9 files changed, 226 insertions(+), 134 deletions(-) diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c index 370256b433..d18ee9d043 100644 --- a/src/analyze/analyze-condition.c +++ b/src/analyze/analyze-condition.c @@ -145,11 +145,11 @@ int verify_conditions(char **lines, UnitFileScope scope) { 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) 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) log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed"); diff --git a/src/core/unit.c b/src/core/unit.c index 6f65ff7d05..c5eb72163b 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -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) { + _cleanup_strv_free_ char **env = NULL; + int r; + assert(u); 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); - return u->condition_result; } static bool unit_test_assert(Unit *u) { + _cleanup_strv_free_ char **env = NULL; + int r; + assert(u); 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); - return u->assert_result; } diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index bc85d4babb..997dafa719 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -2,6 +2,7 @@ #include #include +#include #include "alloc-util.h" #include "bond.h" @@ -693,7 +694,7 @@ int netdev_load_one(Manager *manager, const char *filename) { return r; /* 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); return 0; } diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index d9646a21cb..4ba46d28e3 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "alloc-util.h" #include "conf-files.h" @@ -172,7 +173,7 @@ int network_verify(Network *network) { network->filename); /* 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), "%s: Conditions in the file do not match the system environment, skipping.", network->filename); diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c index 5471e74592..d9ad647a15 100644 --- a/src/network/networkd-util.c +++ b/src/network/networkd-util.c @@ -107,7 +107,7 @@ int kernel_route_expiration_supported(void) { .type = CONDITION_KERNEL_VERSION, .parameter = (char *) ">= 4.5" }; - r = condition_test(&c); + r = condition_test(&c, NULL); if (r < 0) return r; diff --git a/src/shared/condition.c b/src/shared/condition.c index 3c76c86a0f..c83a4ba0eb 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -93,7 +93,7 @@ Condition* condition_free_list_type(Condition *head, ConditionType type) { 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; const char *p; bool equal; @@ -202,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; struct utsname u; const char *p; @@ -260,7 +260,7 @@ static int condition_test_kernel_version(Condition *c) { return true; } -static int condition_test_memory(Condition *c) { +static int condition_test_memory(Condition *c, char **env) { OrderOperator order; uint64_t m, k; const char *p; @@ -284,7 +284,7 @@ static int condition_test_memory(Condition *c) { 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; const char *p; unsigned k; @@ -310,7 +310,7 @@ static int condition_test_cpus(Condition *c) { 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; int r; _cleanup_free_ char *username = NULL; @@ -345,7 +345,7 @@ static int condition_test_user(Condition *c) { 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; CGroupMask system_mask, wanted_mask = 0; @@ -369,7 +369,7 @@ static int condition_test_control_group_controller(Condition *c) { 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; int r; @@ -388,7 +388,7 @@ static int condition_test_group(Condition *c) { 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; assert(c); @@ -418,7 +418,7 @@ static int condition_test_virtualization(Condition *c) { 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; assert(c); @@ -440,7 +440,7 @@ static int condition_test_architecture(Condition *c) { return a == b; } -static int condition_test_host(Condition *c) { +static int condition_test_host(Condition *c, char **env) { _cleanup_free_ char *h = NULL; sd_id128_t x, y; int r; @@ -465,7 +465,7 @@ static int condition_test_host(Condition *c) { 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; assert(c); @@ -479,7 +479,7 @@ static int condition_test_ac_power(Condition *c) { 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->parameter); assert(c->type == CONDITION_SECURITY); @@ -502,7 +502,7 @@ static int condition_test_security(Condition *c) { 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; _cleanup_fclose_ FILE *f = NULL; int value, r; @@ -545,7 +545,7 @@ static int condition_test_capability(Condition *c) { 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; struct stat usr, other; @@ -611,7 +611,7 @@ static int condition_test_needs_update(Condition *c) { 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; assert(c); @@ -625,7 +625,36 @@ static int condition_test_first_boot(Condition *c) { 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->parameter); assert(c->type == CONDITION_PATH_EXISTS); @@ -633,7 +662,7 @@ static int condition_test_path_exists(Condition *c) { 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->parameter); assert(c->type == CONDITION_PATH_EXISTS_GLOB); @@ -641,7 +670,7 @@ static int condition_test_path_exists_glob(Condition *c) { 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->parameter); assert(c->type == CONDITION_PATH_IS_DIRECTORY); @@ -649,7 +678,7 @@ static int condition_test_path_is_directory(Condition *c) { 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->parameter); assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK); @@ -657,7 +686,7 @@ static int condition_test_path_is_symbolic_link(Condition *c) { 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->parameter); assert(c->type == CONDITION_PATH_IS_MOUNT_POINT); @@ -665,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; } -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->parameter); assert(c->type == CONDITION_PATH_IS_READ_WRITE); @@ -673,7 +702,7 @@ static int condition_test_path_is_read_write(Condition *c) { return path_is_read_only_fs(c->parameter) <= 0; } -static int condition_test_path_is_encrypted(Condition *c) { +static int condition_test_path_is_encrypted(Condition *c, char **env) { int r; assert(c); @@ -687,7 +716,7 @@ static int condition_test_path_is_encrypted(Condition *c) { return r > 0; } -static int condition_test_directory_not_empty(Condition *c) { +static int condition_test_directory_not_empty(Condition *c, char **env) { int r; assert(c); @@ -698,7 +727,7 @@ static int condition_test_directory_not_empty(Condition *c) { 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; assert(c); @@ -710,7 +739,7 @@ static int condition_test_file_not_empty(Condition *c) { 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; assert(c); @@ -722,7 +751,7 @@ static int condition_test_file_is_executable(Condition *c) { (st.st_mode & 0111)); } -static int condition_test_null(Condition *c) { +static int condition_test_null(Condition *c, char **env) { assert(c); assert(c->type == CONDITION_NULL); @@ -731,9 +760,9 @@ static int condition_test_null(Condition *c) { 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_GLOB] = condition_test_path_exists_glob, [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory, @@ -760,6 +789,7 @@ int condition_test(Condition *c) { [CONDITION_NULL] = condition_test_null, [CONDITION_CPUS] = condition_test_cpus, [CONDITION_MEMORY] = condition_test_memory, + [CONDITION_ENVIRONMENT] = condition_test_environment, }; int r, b; @@ -768,7 +798,7 @@ int condition_test(Condition *c) { assert(c->type >= 0); assert(c->type < _CONDITION_TYPE_MAX); - r = condition_tests[c->type](c); + r = condition_tests[c->type](c, env); if (r < 0) { c->result = CONDITION_ERROR; return r; @@ -781,6 +811,7 @@ int condition_test(Condition *c) { bool condition_test_list( Condition *first, + char **env, condition_to_string_t to_string, condition_test_logger_t logger, void *userdata) { @@ -800,7 +831,7 @@ bool condition_test_list( LIST_FOREACH(conditions, c, first) { int r; - r = condition_test(c); + r = condition_test(c, env); if (logger) { const char *p = c->type == CONDITION_NULL ? "true" : c->parameter; @@ -884,6 +915,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_NULL] = "ConditionNull", [CONDITION_CPUS] = "ConditionCPUs", [CONDITION_MEMORY] = "ConditionMemory", + [CONDITION_ENVIRONMENT] = "ConditionEnvironment", }; DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); @@ -915,6 +947,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_NULL] = "AssertNull", [CONDITION_CPUS] = "AssertCPUs", [CONDITION_MEMORY] = "AssertMemory", + [CONDITION_ENVIRONMENT] = "AssertEnvironment", }; DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType); diff --git a/src/shared/condition.h b/src/shared/condition.h index 11dfc7425b..fea74d228d 100644 --- a/src/shared/condition.h +++ b/src/shared/condition.h @@ -18,6 +18,7 @@ typedef enum ConditionType { CONDITION_AC_POWER, CONDITION_MEMORY, CONDITION_CPUS, + CONDITION_ENVIRONMENT, CONDITION_NEEDS_UPDATE, CONDITION_FIRST_BOOT, @@ -73,11 +74,11 @@ static inline Condition* condition_free_list(Condition *first) { 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); -typedef const char* (*condition_to_string_t)(ConditionType t); -bool condition_test_list(Condition *first, condition_to_string_t, condition_test_logger_t logger, void *userdata); +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); diff --git a/src/test/test-condition.c b/src/test/test-condition.c index 0c78194185..ddf2e669c0 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -39,87 +39,87 @@ static void test_condition_test_path(void) { condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false); assert_se(condition); - assert_se(condition_test(condition)); + assert_se(condition_test(condition, environ)); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true); 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_DIRECTORY, "/bin", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false); 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_MOUNT_POINT, "/proc", false, false); 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_MOUNT_POINT, "/", false, false); 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_MOUNT_POINT, "/bin", false, false); 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_READ_WRITE, "/tmp", false, false); 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) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); } @@ -139,12 +139,12 @@ static void test_condition_test_control_group_controller(void) { /* Invalid controllers are ignored */ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); assert_se(cg_mask_supported(&system_mask) >= 0); @@ -157,23 +157,23 @@ static void test_condition_test_control_group_controller(void) { log_info("this controller is available"); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); } else { log_info("this controller is unavailable"); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); } } @@ -183,12 +183,12 @@ static void test_condition_test_control_group_controller(void) { condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); } @@ -197,17 +197,17 @@ static void test_condition_test_ac_power(void) { condition = condition_new(CONDITION_AC_POWER, "true", false, false); assert_se(condition); - assert_se(condition_test(condition) == on_ac_power()); + assert_se(condition_test(condition, environ) == on_ac_power()); condition_free(condition); condition = condition_new(CONDITION_AC_POWER, "false", false, false); assert_se(condition); - assert_se(condition_test(condition) != on_ac_power()); + assert_se(condition_test(condition, environ) != on_ac_power()); condition_free(condition); condition = condition_new(CONDITION_AC_POWER, "false", false, true); assert_se(condition); - assert_se(condition_test(condition) == on_ac_power()); + assert_se(condition_test(condition, environ) == on_ac_power()); condition_free(condition); } @@ -224,17 +224,17 @@ static void test_condition_test_host(void) { condition = condition_new(CONDITION_HOST, sid, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_HOST, sid, false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); hostname = gethostname_malloc(); @@ -246,7 +246,7 @@ static void test_condition_test_host(void) { else { condition = condition_new(CONDITION_HOST, hostname, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); } } @@ -264,17 +264,17 @@ static void test_condition_test_architecture(void) { condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); } @@ -284,7 +284,7 @@ static void test_condition_test_kernel_command_line(void) { condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); if (ERRNO_IS_PRIVILEGE(r)) return; assert_se(r == 0); @@ -292,7 +292,7 @@ static void test_condition_test_kernel_command_line(void) { condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); } @@ -303,26 +303,26 @@ static void test_condition_test_kernel_version(void) { condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); /* An artificially empty condition. It evaluates to true, but normally * such condition cannot be created, because the condition list is reset instead. */ condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); assert_se(uname(&u) >= 0); condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); strshorten(u.release, 4); @@ -330,79 +330,79 @@ static void test_condition_test_kernel_version(void) { condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); /* 0.1.2 would be a very very very old kernel */ condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false); assert_se(condition); - assert_se(condition_test(condition) == -EINVAL); + assert_se(condition_test(condition, environ) == -EINVAL); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false); assert_se(condition); - assert_se(condition_test(condition) == -EINVAL); + assert_se(condition_test(condition, environ) == -EINVAL); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); /* 4711.8.15 is a very very very future kernel */ condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); assert_se(uname(&u) >= 0); @@ -410,31 +410,31 @@ static void test_condition_test_kernel_version(void) { v = strjoina(">=", u.release); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); v = strjoina("= ", u.release); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); v = strjoina("<=", u.release); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); v = strjoina("> ", u.release); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); v = strjoina("< ", u.release); condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); } @@ -443,12 +443,12 @@ static void test_condition_test_null(void) { condition = condition_new(CONDITION_NULL, NULL, false, false); assert_se(condition); - assert_se(condition_test(condition) > 0); + assert_se(condition_test(condition, environ) > 0); condition_free(condition); condition = condition_new(CONDITION_NULL, NULL, false, true); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); } @@ -457,42 +457,42 @@ static void test_condition_test_security(void) { condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false); assert_se(condition); - assert_se(condition_test(condition) == 0); + assert_se(condition_test(condition, environ) == 0); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "selinux", false, true); assert_se(condition); - assert_se(condition_test(condition) != mac_selinux_use()); + assert_se(condition_test(condition, environ) != mac_selinux_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "apparmor", false, false); assert_se(condition); - assert_se(condition_test(condition) == mac_apparmor_use()); + assert_se(condition_test(condition, environ) == mac_apparmor_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false); assert_se(condition); - assert_se(condition_test(condition) == mac_tomoyo_use()); + assert_se(condition_test(condition, environ) == mac_tomoyo_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "ima", false, false); assert_se(condition); - assert_se(condition_test(condition) == use_ima()); + assert_se(condition_test(condition, environ) == use_ima()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "smack", false, false); assert_se(condition); - assert_se(condition_test(condition) == mac_smack_use()); + assert_se(condition_test(condition, environ) == mac_smack_use()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "audit", false, false); assert_se(condition); - assert_se(condition_test(condition) == use_audit()); + assert_se(condition_test(condition, environ) == use_audit()); condition_free(condition); condition = condition_new(CONDITION_SECURITY, "uefi-secureboot", false, false); 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); } @@ -515,7 +515,7 @@ static void test_condition_test_virtualization(void) { condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); if (ERRNO_IS_PRIVILEGE(r)) return; log_info("ConditionVirtualization=garbage → %i", r); @@ -524,21 +524,21 @@ static void test_condition_test_virtualization(void) { condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionVirtualization=container → %i", r); assert_se(r == !!detect_container()); condition_free(condition); condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionVirtualization=vm → %i", r); assert_se(r == (detect_vm() && !detect_container())); condition_free(condition); condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionVirtualization=private-users → %i", r); assert_se(r == !!running_in_userns()); condition_free(condition); @@ -559,7 +559,7 @@ static void test_condition_test_virtualization(void) { condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionVirtualization=%s → %i", virt, r); assert_se(r >= 0); condition_free(condition); @@ -574,7 +574,7 @@ static void test_condition_test_user(void) { condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=garbage → %i", r); assert_se(r == 0); condition_free(condition); @@ -582,7 +582,7 @@ static void test_condition_test_user(void) { assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0); condition = condition_new(CONDITION_USER, uid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=%s → %i", uid, r); assert_se(r == 0); condition_free(condition); @@ -591,7 +591,7 @@ static void test_condition_test_user(void) { assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0); condition = condition_new(CONDITION_USER, uid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=%s → %i", uid, r); assert_se(r > 0); condition_free(condition); @@ -600,7 +600,7 @@ static void test_condition_test_user(void) { assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0); condition = condition_new(CONDITION_USER, uid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=%s → %i", uid, r); assert_se(r == 0); condition_free(condition); @@ -610,7 +610,7 @@ static void test_condition_test_user(void) { assert_se(username); condition = condition_new(CONDITION_USER, username, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=%s → %i", username, r); assert_se(r > 0); condition_free(condition); @@ -619,14 +619,14 @@ static void test_condition_test_user(void) { username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root"); condition = condition_new(CONDITION_USER, username, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=%s → %i", username, r); assert_se(r == 0); condition_free(condition); condition = condition_new(CONDITION_USER, "@system", false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionUser=@system → %i", r); if (uid_is_system(getuid()) || uid_is_system(geteuid())) assert_se(r > 0); @@ -645,7 +645,7 @@ static void test_condition_test_group(void) { assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF))); condition = condition_new(CONDITION_GROUP, gid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionGroup=%s → %i", gid, r); assert_se(r == 0); condition_free(condition); @@ -654,7 +654,7 @@ static void test_condition_test_group(void) { assert_se(0 < asprintf(&gid, "%u", getgid())); condition = condition_new(CONDITION_GROUP, gid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionGroup=%s → %i", gid, r); assert_se(r > 0); condition_free(condition); @@ -673,7 +673,7 @@ static void test_condition_test_group(void) { assert_se(0 < asprintf(&gid, "%u", gids[i])); condition = condition_new(CONDITION_GROUP, gid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionGroup=%s → %i", gid, r); assert_se(r > 0); condition_free(condition); @@ -684,7 +684,7 @@ static void test_condition_test_group(void) { assert_se(groupname); condition = condition_new(CONDITION_GROUP, groupname, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionGroup=%s → %i", groupname, r); assert_se(r > 0); condition_free(condition); @@ -695,7 +695,7 @@ static void test_condition_test_group(void) { assert_se(0 < asprintf(&gid, "%u", max_gid+1)); condition = condition_new(CONDITION_GROUP, gid, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionGroup=%s → %i", gid, r); assert_se(r == 0); condition_free(condition); @@ -704,7 +704,7 @@ static void test_condition_test_group(void) { groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root"); condition = condition_new(CONDITION_GROUP, groupname, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); log_info("ConditionGroup=%s → %i", groupname, r); assert_se(r == 0); condition_free(condition); @@ -719,7 +719,7 @@ static void test_condition_test_cpus_one(const char *s, bool result) { condition = condition_new(CONDITION_CPUS, s, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); assert_se(r >= 0); assert_se(r == result); condition_free(condition); @@ -780,7 +780,7 @@ static void test_condition_test_memory_one(const char *s, bool result) { condition = condition_new(CONDITION_MEMORY, s, false, false); assert_se(condition); - r = condition_test(condition); + r = condition_test(condition, environ); assert_se(r >= 0); assert_se(r == result); condition_free(condition); @@ -831,6 +831,34 @@ static void test_condition_test_memory(void) { 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[]) { test_setup_logging(LOG_DEBUG); @@ -849,6 +877,7 @@ int main(int argc, char *argv[]) { test_condition_test_control_group_controller(); test_condition_test_cpus(); test_condition_test_memory(); + test_condition_test_environment(); return 0; } diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index e4ace761b7..530ef57e73 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -2,6 +2,7 @@ #include #include +#include #include "sd-device.h" #include "sd-netlink.h" @@ -173,7 +174,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) { 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); return 0; }