From 337f1a319514d501ba1964c701c5f2fb933d073b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 9 Jul 2026 12:47:04 +0900 Subject: [PATCH] condition: split condition_test_list() to minimize dlopen dependencies 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 | 2 +- src/network/networkd-network.c | 2 +- src/network/networkd.c | 5 --- src/shared/condition.c | 81 ++++++++++++++++++++++++++-------- src/shared/condition.h | 1 + src/udev/net/link-config.c | 2 +- src/udev/udevadm.c | 2 - 7 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index bde8d2db05f..658eb1808f1 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -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) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 1e3fd33bcaa..087a6ba121f 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -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); diff --git a/src/network/networkd.c b/src/network/networkd.c index 9415c090257..cbdf3896b2a 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -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(); diff --git a/src/shared/condition.c b/src/shared/condition.c index 2b4a29ed5c6..fc77d9f06eb 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -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); diff --git a/src/shared/condition.h b/src/shared/condition.h index 1f5c33284c3..e518ee608b7 100644 --- a/src/shared/condition.h +++ b/src/shared/condition.h @@ -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); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 306686845e9..9d2cb3730e2 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -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; } diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c index 341e00d1186..62a3cdd64f0 100644 --- a/src/udev/udevadm.c +++ b/src/udev/udevadm.c @@ -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")) -- 2.47.3