]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
condition: split condition_test_list() to minimize dlopen dependencies 42908/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 9 Jul 2026 03:47:04 +0000 (12:47 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 10 Jul 2026 07:35:19 +0000 (16:35 +0900)
Even though systemd-networkd and systemd-udevd do not support
ConditionSecurity= in .network, .netdev, and .link files, the unified
condition_test() function maintained a function pointer table that
unconditionally referenced condition_test_security(). Consequently,
linker garbage collection (--gc-sections) could not drop the security
test code, inadvertently pulling in dlopen dependencies and ELF notes
for apparmor, audit, and tpm2 libraries into these binaries.

To resolve this, introduce condition_test_net() and condition_test_list_net(),
which utilize a trimmed-down function pointer table that excludes
security-related condition evaluators.

By migrating networkd and udevd to these new network-specific variants,
the reference to condition_test_security() is completely severed in
their dependency chains. This allows the compiler and linker to
successfully garbage-collect the unused security logic and safely drops
the unnecessary dlopen notes from those binaries.

src/network/netdev/netdev.c
src/network/networkd-network.c
src/network/networkd.c
src/shared/condition.c
src/shared/condition.h
src/udev/net/link-config.c
src/udev/udevadm.c

index bde8d2db05fb39320b62cb2d6a78625a14ec9922..658eb1808f1da0ab2ea8872f329f8ef859cd4a20 100644 (file)
@@ -1044,7 +1044,7 @@ int netdev_load_one(Manager *manager, const char *filename, NetDev **ret) {
                 return r; /* config_parse_many() logs internally. */
 
         /* skip out early if configuration does not match the environment */
-        if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL))
+        if (!condition_test_list_net(netdev_raw->conditions, environ, NULL, NULL, NULL))
                 return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "%s: Conditions in the file do not match the system environment, skipping.", filename);
 
         if (netdev_raw->kind == _NETDEV_KIND_INVALID)
index 1e3fd33bcaaf8745ad82fb033a8f28e222832335..087a6ba121fd27b757309bcf6bf50f0886982c1d 100644 (file)
@@ -138,7 +138,7 @@ int network_verify(Network *network) {
                                          network->filename);
 
         /* skip out early if configuration does not match the environment */
-        if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
+        if (!condition_test_list_net(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);
index 9415c090257160248718105da8d001c259701318..cbdf3896b2a96afc0151e000566ef17c4e8630d6 100644 (file)
@@ -25,14 +25,9 @@ static int run(int argc, char *argv[]) {
         _unused_ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
         int r;
 
-        LIBAPPARMOR_NOTE(recommended);
-        LIBAUDIT_NOTE(recommended);
         LIBIDN2_NOTE(suggested);
         LIBMOUNT_NOTE(recommended);
         LIBSELINUX_NOTE(recommended);
-        LIBTSS2_ESYS_NOTE(suggested);
-        LIBTSS2_MU_NOTE(suggested);
-        LIBTSS2_RC_NOTE(suggested);
 
         log_setup();
 
index 2b4a29ed5c60d204109a58bd6b265175fac4deae..fc77d9f06eba1579c6d6c0065aa1776ba4173b2c 100644 (file)
@@ -1340,9 +1340,45 @@ static int condition_test_kernel_module_loaded(Condition *c, char **env) {
         return true;
 }
 
-int condition_test(Condition *c, char **env) {
+typedef int (*condition_test_func_t)(Condition *c, char **env);
+
+static int condition_test_impl(Condition *c, char **env, const condition_test_func_t table[]) {
+        int r, b;
+
+        assert(c);
+        assert(c->type >= 0);
+        assert(c->type < _CONDITION_TYPE_MAX);
+        assert(table);
+        assert(table[c->type]);
+
+        r = table[c->type](c, env);
+        if (r < 0) {
+                c->result = CONDITION_ERROR;
+                return r;
+        }
 
-        static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c, char **env) = {
+        b = (r > 0) == !c->negate;
+        c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED;
+        return b;
+}
+
+static int condition_test_net(Condition *c, char **env) {
+        static const condition_test_func_t table_net[_CONDITION_TYPE_MAX] = {
+                [CONDITION_KERNEL_COMMAND_LINE]      = condition_test_kernel_command_line,
+                [CONDITION_VERSION]                  = condition_test_version,
+                [CONDITION_CREDENTIAL]               = condition_test_credential,
+                [CONDITION_VIRTUALIZATION]           = condition_test_virtualization,
+                [CONDITION_HOST]                     = condition_test_host,
+                [CONDITION_ARCHITECTURE]             = condition_test_architecture,
+                [CONDITION_FIRMWARE]                 = condition_test_firmware,
+                [CONDITION_MACHINE_TAG]              = condition_test_machine_tag,
+        };
+
+        return condition_test_impl(c, env, table_net);
+}
+
+int condition_test(Condition *c, char **env) {
+        static const condition_test_func_t table[_CONDITION_TYPE_MAX] = {
                 [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,
@@ -1382,28 +1418,15 @@ int condition_test(Condition *c, char **env) {
                 [CONDITION_KERNEL_MODULE_LOADED]     = condition_test_kernel_module_loaded,
         };
 
-        int r, b;
-
-        assert(c);
-        assert(c->type >= 0);
-        assert(c->type < _CONDITION_TYPE_MAX);
-
-        r = condition_tests[c->type](c, env);
-        if (r < 0) {
-                c->result = CONDITION_ERROR;
-                return r;
-        }
-
-        b = (r > 0) == !c->negate;
-        c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED;
-        return b;
+        return condition_test_impl(c, env, table);
 }
 
-bool condition_test_list(
+static bool condition_test_list_impl(
                 Condition *first,
                 char **env,
                 condition_to_string_t to_string,
                 condition_test_logger_t logger,
+                condition_test_func_t tester,
                 void *userdata) {
 
         int triggered = -1;
@@ -1418,7 +1441,7 @@ bool condition_test_list(
         LIST_FOREACH(conditions, c, first) {
                 int r;
 
-                r = condition_test(c, env);
+                r = tester(c, env);
 
                 if (logger) {
                         if (r < 0)
@@ -1448,6 +1471,26 @@ bool condition_test_list(
         return triggered != 0;
 }
 
+bool condition_test_list_net(
+                Condition *first,
+                char **env,
+                condition_to_string_t to_string,
+                condition_test_logger_t logger,
+                void *userdata) {
+
+        return condition_test_list_impl(first, env, to_string, logger, condition_test_net, userdata);
+}
+
+bool condition_test_list(
+                Condition *first,
+                char **env,
+                condition_to_string_t to_string,
+                condition_test_logger_t logger,
+                void *userdata) {
+
+        return condition_test_list_impl(first, env, to_string, logger, condition_test, userdata);
+}
+
 void condition_dump(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string) {
         assert(c);
         assert(f);
index 1f5c33284c3fe92bcb7d4999f12765a5b6d617d8..e518ee608b78aa0c7b3ae28cea2073e4c6857618 100644 (file)
@@ -85,6 +85,7 @@ 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) _const_;
+bool condition_test_list_net(Condition *first, char **env, condition_to_string_t to_string, 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);
 
 void condition_dump(Condition *c, FILE *f, const char *prefix, condition_to_string_t to_string);
index 306686845e916beb4f5430307ee4393ceff9f37a..9d2cb3730e2e8f7d208770063250efdf39fee83d 100644 (file)
@@ -320,7 +320,7 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
                 return 0;
         }
 
-        if (!condition_test_list(config->conditions, environ, NULL, NULL, NULL)) {
+        if (!condition_test_list_net(config->conditions, environ, NULL, NULL, NULL)) {
                 log_debug("%s: Conditions do not match the system environment, skipping.", filename);
                 return 0;
         }
index 341e00d1186c07cd359fa5e923b462d4a0cfc8ea..62a3cdd64f09b3029c1990670d9fa871a11690c3 100644 (file)
@@ -102,8 +102,6 @@ static int run(int argc, char *argv[]) {
         char **args = NULL;
         int r;
 
-        LIBAPPARMOR_NOTE(recommended);
-        LIBAUDIT_NOTE(recommended);
         LIBSELINUX_NOTE(recommended);
 
         if (invoked_as(argv, "udevd"))