-/***
- This file is part of systemd
-
- Copyright 2014 Ronny Chevalier
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stdio.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <unistd.h>
#include "sd-id128.h"
#include "apparmor-util.h"
#include "architecture.h"
#include "audit-util.h"
+#include "cgroup-util.h"
#include "condition.h"
+#include "cpu-set-util.h"
+#include "efivars.h"
#include "hostname-util.h"
#include "id128-util.h"
#include "ima-util.h"
+#include "limits-util.h"
#include "log.h"
#include "macro.h"
+#include "nulstr-util.h"
+#include "process-util.h"
#include "selinux-util.h"
+#include "set.h"
#include "smack-util.h"
+#include "string-util.h"
#include "strv.h"
-#include "virt.h"
-#include "util.h"
+#include "tests.h"
+#include "tomoyo-util.h"
#include "user-util.h"
+#include "virt.h"
static void test_condition_test_path(void) {
Condition *condition;
condition_free(condition);
}
+static void test_condition_test_control_group_controller(void) {
+ Condition *condition;
+ CGroupMask system_mask;
+ CGroupController controller;
+ _cleanup_free_ char *controller_name = NULL;
+ int r;
+
+ r = cg_unified_flush();
+ if (r < 0) {
+ log_notice_errno(r, "Skipping ConditionControlGroupController tests: %m");
+ return;
+ }
+
+ /* Invalid controllers are ignored */
+ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ assert_se(cg_mask_supported(&system_mask) >= 0);
+
+ /* Individual valid controllers one by one */
+ for (controller = 0; controller < _CGROUP_CONTROLLER_MAX; controller++) {
+ const char *local_controller_name = cgroup_controller_to_string(controller);
+ log_info("chosen controller is '%s'", local_controller_name);
+ if (system_mask & CGROUP_CONTROLLER_TO_MASK(controller)) {
+ 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));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ 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));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+ }
+ }
+
+ /* Multiple valid controllers at the same time */
+ assert_se(cg_mask_to_string(system_mask, &controller_name) >= 0);
+
+ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
static void test_condition_test_ac_power(void) {
Condition *condition;
condition_free(condition);
}
+static void test_condition_test_kernel_version(void) {
+ Condition *condition;
+ struct utsname u;
+ const char *v;
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ 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));
+ condition_free(condition);
+
+ strshorten(u.release, 4);
+ strcpy(strchr(u.release, 0), "*");
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ 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));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ 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));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ assert_se(uname(&u) >= 0);
+
+ v = strjoina(">=", u.release);
+ condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ v = strjoina("= ", u.release);
+ condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ v = strjoina("<=", u.release);
+ condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition));
+ condition_free(condition);
+
+ v = strjoina("> ", u.release);
+ condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+
+ v = strjoina("< ", u.release);
+ condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false);
+ assert_se(condition);
+ assert_se(!condition_test(condition));
+ condition_free(condition);
+}
+
static void test_condition_test_null(void) {
Condition *condition;
condition = condition_new(CONDITION_SECURITY, "selinux", false, true);
assert_se(condition);
- assert_se(condition_test(condition) != mac_selinux_have());
+ assert_se(condition_test(condition) != mac_selinux_use());
condition_free(condition);
- condition = condition_new(CONDITION_SECURITY, "ima", false, false);
+ condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
assert_se(condition);
- assert_se(condition_test(condition) == use_ima());
+ assert_se(condition_test(condition) == mac_apparmor_use());
condition_free(condition);
- condition = condition_new(CONDITION_SECURITY, "apparmor", false, false);
+ condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false);
assert_se(condition);
- assert_se(condition_test(condition) == mac_apparmor_use());
+ assert_se(condition_test(condition) == mac_tomoyo_use());
+ condition_free(condition);
+
+ condition = condition_new(CONDITION_SECURITY, "ima", false, false);
+ assert_se(condition);
+ assert_se(condition_test(condition) == use_ima());
condition_free(condition);
condition = condition_new(CONDITION_SECURITY, "smack", false, false);
assert_se(condition);
assert_se(condition_test(condition) == 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());
+ condition_free(condition);
+}
+
+static void print_securities(void) {
+ log_info("------ enabled security technologies ------");
+ log_info("SELinux: %s", yes_no(mac_selinux_use()));
+ log_info("AppArmor: %s", yes_no(mac_apparmor_use()));
+ log_info("Tomoyo: %s", yes_no(mac_tomoyo_use()));
+ log_info("IMA: %s", yes_no(use_ima()));
+ log_info("SMACK: %s", yes_no(mac_smack_use()));
+ log_info("Audit: %s", yes_no(use_audit()));
+ log_info("UEFI secure boot: %s", yes_no(is_efi_secure_boot()));
+ log_info("-------------------------------------------");
}
static void test_condition_test_virtualization(void) {
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);
+ log_info("ConditionUser=@system → %i", r);
+ if (uid_is_system(getuid()) || uid_is_system(geteuid()))
+ assert_se(r > 0);
+ else
+ assert_se(r == 0);
+ condition_free(condition);
}
static void test_condition_test_group(void) {
char* gid;
char* groupname;
gid_t *gids, max_gid;
- int ngroups_max, r, i;
+ int ngroups_max, ngroups, r, i;
assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF)));
condition = condition_new(CONDITION_GROUP, gid, false, false);
ngroups_max = sysconf(_SC_NGROUPS_MAX);
assert(ngroups_max > 0);
- gids = alloca(sizeof(gid_t) * ngroups_max);
+ gids = newa(gid_t, ngroups_max);
- r = getgroups(ngroups_max, gids);
- assert(r >= 0);
+ ngroups = getgroups(ngroups_max, gids);
+ assert(ngroups >= 0);
max_gid = getgid();
- for (i = 0; i < r; i++) {
+ for (i = 0; i < ngroups; i++) {
assert_se(0 < asprintf(&gid, "%u", gids[i]));
condition = condition_new(CONDITION_GROUP, gid, false, false);
assert_se(condition);
condition_free(condition);
}
+static void test_condition_test_cpus_one(const char *s, bool result) {
+ Condition *condition;
+ int r;
+
+ log_debug("%s=%s", condition_type_to_string(CONDITION_CPUS), s);
+
+ condition = condition_new(CONDITION_CPUS, s, false, false);
+ assert_se(condition);
+
+ r = condition_test(condition);
+ assert_se(r >= 0);
+ assert_se(r == result);
+ condition_free(condition);
+}
+
+static void test_condition_test_cpus(void) {
+ _cleanup_free_ char *t = NULL;
+ int cpus;
+
+ cpus = cpus_in_affinity_mask();
+ assert_se(cpus >= 0);
+
+ test_condition_test_cpus_one("> 0", true);
+ test_condition_test_cpus_one(">= 0", true);
+ test_condition_test_cpus_one("!= 0", true);
+ test_condition_test_cpus_one("<= 0", false);
+ test_condition_test_cpus_one("< 0", false);
+ test_condition_test_cpus_one("= 0", false);
+
+ test_condition_test_cpus_one("> 100000", false);
+ test_condition_test_cpus_one("= 100000", false);
+ test_condition_test_cpus_one(">= 100000", false);
+ test_condition_test_cpus_one("< 100000", true);
+ test_condition_test_cpus_one("!= 100000", true);
+ test_condition_test_cpus_one("<= 100000", true);
+
+ assert_se(asprintf(&t, "= %i", cpus) >= 0);
+ test_condition_test_cpus_one(t, true);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "<= %i", cpus) >= 0);
+ test_condition_test_cpus_one(t, true);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, ">= %i", cpus) >= 0);
+ test_condition_test_cpus_one(t, true);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "!= %i", cpus) >= 0);
+ test_condition_test_cpus_one(t, false);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "< %i", cpus) >= 0);
+ test_condition_test_cpus_one(t, false);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "> %i", cpus) >= 0);
+ test_condition_test_cpus_one(t, false);
+ t = mfree(t);
+}
+
+static void test_condition_test_memory_one(const char *s, bool result) {
+ Condition *condition;
+ int r;
+
+ log_debug("%s=%s", condition_type_to_string(CONDITION_MEMORY), s);
+
+ condition = condition_new(CONDITION_MEMORY, s, false, false);
+ assert_se(condition);
+
+ r = condition_test(condition);
+ assert_se(r >= 0);
+ assert_se(r == result);
+ condition_free(condition);
+}
+
+static void test_condition_test_memory(void) {
+ _cleanup_free_ char *t = NULL;
+ uint64_t memory;
+
+ memory = physical_memory();
+
+ test_condition_test_memory_one("> 0", true);
+ test_condition_test_memory_one(">= 0", true);
+ test_condition_test_memory_one("!= 0", true);
+ test_condition_test_memory_one("<= 0", false);
+ test_condition_test_memory_one("< 0", false);
+ test_condition_test_memory_one("= 0", false);
+
+ test_condition_test_memory_one("> 18446744073709547520", false);
+ test_condition_test_memory_one("= 18446744073709547520", false);
+ test_condition_test_memory_one(">= 18446744073709547520", false);
+ test_condition_test_memory_one("< 18446744073709547520", true);
+ test_condition_test_memory_one("!= 18446744073709547520", true);
+ test_condition_test_memory_one("<= 18446744073709547520", true);
+
+ assert_se(asprintf(&t, "= %" PRIu64, memory) >= 0);
+ test_condition_test_memory_one(t, true);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "<= %" PRIu64, memory) >= 0);
+ test_condition_test_memory_one(t, true);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, ">= %" PRIu64, memory) >= 0);
+ test_condition_test_memory_one(t, true);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "!= %" PRIu64, memory) >= 0);
+ test_condition_test_memory_one(t, false);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "< %" PRIu64, memory) >= 0);
+ test_condition_test_memory_one(t, false);
+ t = mfree(t);
+
+ assert_se(asprintf(&t, "> %" PRIu64, memory) >= 0);
+ test_condition_test_memory_one(t, false);
+ t = mfree(t);
+}
+
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_condition_test_path();
test_condition_test_ac_power();
test_condition_test_host();
test_condition_test_architecture();
test_condition_test_kernel_command_line();
+ test_condition_test_kernel_version();
test_condition_test_null();
test_condition_test_security();
+ print_securities();
test_condition_test_virtualization();
test_condition_test_user();
test_condition_test_group();
+ test_condition_test_control_group_controller();
+ test_condition_test_cpus();
+ test_condition_test_memory();
return 0;
}