From 385623fee3fcc66d719525c81b44c10bc485bc60 Mon Sep 17 00:00:00 2001 From: dongshengyuan <545258830@qq.com> Date: Tue, 28 Jul 2026 14:06:06 +0800 Subject: [PATCH] test: cover DeviceAllow parsing Add unit coverage for config_parse_device_allow(). Verify valid device paths and subsystem patterns, invalid specifiers and rights, default permissions, and reset handling. Follow-up for: 20d52ab60e7ba40f7cf23c148bcead8bd05bea3a --- TODO.md | 3 -- src/test/test-load-fragment.c | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 0be8601cb4..190788aab0 100644 --- a/TODO.md +++ b/TODO.md @@ -2684,9 +2684,6 @@ SPDX-License-Identifier: LGPL-2.1-or-later automatically support reverting back to older OS version images if newer ones fail to boot. -- **test/:** - - add unit tests for config_parse_device_allow() - - The bind(AF_UNSPEC) construct (for resetting sockets to their initial state) should be blocked in many cases because it punches holes in many sandboxes. diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c index 259bd142e4..00f26bd2bf 100644 --- a/src/test/test-load-fragment.c +++ b/src/test/test-load-fragment.c @@ -9,6 +9,7 @@ #include "all-units.h" #include "alloc-util.h" #include "capability-util.h" +#include "cgroup.h" #include "conf-parser.h" #include "fileio.h" #include "format-util.h" @@ -39,6 +40,15 @@ STATIC_DESTRUCTOR_REGISTER(runtime_dir, rm_rf_physical_and_freep); /* For testing type compatibility. */ _unused_ static ConfigPerfItemLookup unused_lookup = load_fragment_gperf_lookup; +static size_t cgroup_device_allow_count(const CGroupContext *c) { + size_t n = 0; + + LIST_FOREACH(device_allow, a, c->device_allow) + n++; + + return n; +} + TEST_RET(unit_file_get_list) { int r; _cleanup_hashmap_free_ Hashmap *h = NULL; @@ -878,6 +888,62 @@ TEST(config_parse_memory_limit) { } } +TEST(config_parse_device_allow) { + _cleanup_(cgroup_context_done) CGroupContext c = {}; + _cleanup_(manager_freep) Manager *m = NULL; + _cleanup_(unit_freep) Unit *u = NULL; + CGroupDeviceAllow *a; + int r; + + r = manager_new(RUNTIME_SCOPE_USER, MANAGER_TEST_RUN_MINIMAL, &m); + if (manager_errno_skip_test(r)) + return (void) log_tests_skipped_errno(r, "manager_new() failed"); + + ASSERT_OK(r); + + ASSERT_NOT_NULL(u = unit_new(m, sizeof(Service))); + ASSERT_OK_ZERO(unit_add_name(u, "null.service")); + + ASSERT_OK_ZERO(config_parse_device_allow(u->id, "fake", 1, "Service", 1, + "DeviceAllow", 0, "/dev/%N rw", + &c, u)); + ASSERT_EQ(cgroup_device_allow_count(&c), 1U); + ASSERT_NOT_NULL(a = c.device_allow); + ASSERT_STREQ(a->path, "/dev/null"); + ASSERT_EQ(a->permissions, CGROUP_DEVICE_READ|CGROUP_DEVICE_WRITE); + + ASSERT_OK_ZERO(config_parse_device_allow(u->id, "fake", 2, "Service", 1, + "DeviceAllow", 0, "char-pts rwm", + &c, u)); + ASSERT_EQ(cgroup_device_allow_count(&c), 2U); + ASSERT_NOT_NULL(a = c.device_allow); + ASSERT_STREQ(a->path, "char-pts"); + ASSERT_EQ(a->permissions, CGROUP_DEVICE_READ|CGROUP_DEVICE_WRITE|CGROUP_DEVICE_MKNOD); + + ASSERT_OK_ZERO(config_parse_device_allow(u->id, "fake", 3, "Service", 1, + "DeviceAllow", 0, "%Q rw", + &c, u)); + ASSERT_EQ(cgroup_device_allow_count(&c), 2U); + + ASSERT_OK_ZERO(config_parse_device_allow(u->id, "fake", 4, "Service", 1, + "DeviceAllow", 0, "/dev/zero invalid", + &c, u)); + ASSERT_EQ(cgroup_device_allow_count(&c), 2U); + + ASSERT_OK_ZERO(config_parse_device_allow(u->id, "fake", 5, "Service", 1, + "DeviceAllow", 0, "/dev/zero", + &c, u)); + ASSERT_EQ(cgroup_device_allow_count(&c), 3U); + ASSERT_NOT_NULL(a = c.device_allow); + ASSERT_STREQ(a->path, "/dev/zero"); + ASSERT_EQ(a->permissions, _CGROUP_DEVICE_PERMISSIONS_ALL); + + ASSERT_OK_ZERO(config_parse_device_allow(u->id, "fake", 6, "Service", 1, + "DeviceAllow", 0, "", + &c, u)); + ASSERT_NULL(c.device_allow); +} + TEST(contains_instance_specifier_superset) { ASSERT_TRUE(contains_instance_specifier_superset("foobar@a%i")); ASSERT_TRUE(contains_instance_specifier_superset("foobar@%ia"));