From: Lennart Poettering Date: Wed, 13 Dec 2017 19:34:13 +0000 (+0100) Subject: core,udev,networkd: add ConditionKernelVersion= X-Git-Tag: v237~171^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5022f08a23c0b64973b74cd71be9f5122ec655a6;p=thirdparty%2Fsystemd.git core,udev,networkd: add ConditionKernelVersion= This adds a simple condition/assert/match to the service manager, to udev's .link handling and to networkd, for matching the kernel version string. In this version we only do fnmatch() based globbing, but we might want to extend that to version comparisons later on, if we like, by slightly extending the syntax with ">=", "<=", ">", "<" and "==" expressions. --- diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 162674f7698..fb091b883ce 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -172,6 +172,17 @@ for details. + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression (or if prefixed with the exclamation mark does not match it). See + ConditionKernelVersion= in + systemd.unit5 for + details. + + + Architecture= diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 4e5d47f585a..b9647a2f7a5 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -232,6 +232,16 @@ + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression (or if prefixed with the exclamation mark does not match it). See + ConditionKernelVersion= in + systemd.unit5 for details. + + + Architecture= diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 3466f3a3cf7..f78beaa7dc7 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -193,6 +193,17 @@ + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression (or if prefixed with the exclamation mark does not match it). See + ConditionKernelVersion= in + systemd.unit5 for + details. + + + Architecture= diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 005fdea73cd..0d35d619e01 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -923,6 +923,7 @@ ConditionVirtualization= ConditionHost= ConditionKernelCommandLine= + ConditionKernelVersion= ConditionSecurity= ConditionCapability= ConditionACPower= @@ -1050,6 +1051,10 @@ the exact assignment is looked for with right and left hand side matching. + ConditionKernelVersion= may be used to check whether the kernel version (as reported + by uname -r) matches a certain expression (or if prefixed with the exclamation mark does not + match it). The argument must be a single string, optionally containing shell-style globs. + ConditionSecurity= may be used to check whether the given security module is enabled on the system. Currently, the recognized values are @@ -1201,6 +1206,7 @@ AssertVirtualization= AssertHost= AssertKernelCommandLine= + AssertKernelVersion= AssertSecurity= AssertCapability= AssertACPower= diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 5604312bc5e..549c7eb4d6f 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -241,6 +241,7 @@ Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_F Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions) Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions) Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) +Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions) Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions) Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions) @@ -263,6 +264,7 @@ Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_F Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts) Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts) Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) +Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts) Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts) Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts) diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index e48b7d22ddc..c20e9fca353 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -116,7 +116,8 @@ bool net_match_config(const struct ether_addr *match_mac, char * const *match_names, Condition *match_host, Condition *match_virt, - Condition *match_kernel, + Condition *match_kernel_cmdline, + Condition *match_kernel_version, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, @@ -131,7 +132,10 @@ bool net_match_config(const struct ether_addr *match_mac, if (match_virt && condition_test(match_virt) <= 0) return false; - if (match_kernel && condition_test(match_kernel) <= 0) + if (match_kernel_cmdline && condition_test(match_kernel_cmdline) <= 0) + return false; + + if (match_kernel_version && condition_test(match_kernel_version) <= 0) return false; if (match_arch && condition_test(match_arch) <= 0) diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index a54adac602a..4e69f1a5988 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -37,7 +37,8 @@ bool net_match_config(const struct ether_addr *match_mac, char * const *match_name, Condition *match_host, Condition *match_virt, - Condition *match_kernel, + Condition *match_kernel_cmdline, + Condition *match_kernel_version, Condition *match_arch, const struct ether_addr *dev_mac, const char *dev_path, diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf index 3aeba06ee01..03b86619574 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -33,7 +33,8 @@ struct ConfigPerfItem; %% Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel_cmdline) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(NetDev, match_kernel_version) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, match_arch) NetDev.Description, config_parse_string, 0, offsetof(NetDev, description) NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 7afe30f7fba..7cf110672f2 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -149,7 +149,8 @@ static void netdev_free(NetDev *netdev) { condition_free_list(netdev->match_host); condition_free_list(netdev->match_virt); - condition_free_list(netdev->match_kernel); + condition_free_list(netdev->match_kernel_cmdline); + condition_free_list(netdev->match_kernel_version); condition_free_list(netdev->match_arch); if (NETDEV_VTABLE(netdev) && @@ -642,7 +643,8 @@ static int netdev_load_one(Manager *manager, const char *filename) { /* skip out early if configuration does not match the environment */ if (net_match_config(NULL, NULL, NULL, NULL, NULL, netdev_raw->match_host, netdev_raw->match_virt, - netdev_raw->match_kernel, netdev_raw->match_arch, + netdev_raw->match_kernel_cmdline, netdev_raw->match_kernel_version, + netdev_raw->match_arch, NULL, NULL, NULL, NULL, NULL, NULL) <= 0) return 0; diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 24915b2b04b..507b86a078f 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -93,7 +93,8 @@ typedef struct NetDev { Condition *match_host; Condition *match_virt; - Condition *match_kernel; + Condition *match_kernel_cmdline; + Condition *match_kernel_version; Condition *match_arch; NetDevState state; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 57a96aff941..cb0c01fbe74 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -27,7 +27,8 @@ Match.Type, config_parse_strv, Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name) Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel_cmdline) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, match_kernel_version) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 8e37a0a229f..b037fc67e37 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -431,7 +431,8 @@ void network_free(Network *network) { condition_free_list(network->match_host); condition_free_list(network->match_virt); - condition_free_list(network->match_kernel); + condition_free_list(network->match_kernel_cmdline); + condition_free_list(network->match_kernel_version); condition_free_list(network->match_arch); free(network->dhcp_server_timezone); @@ -485,8 +486,8 @@ int network_get(Manager *manager, struct udev_device *device, if (net_match_config(network->match_mac, network->match_path, network->match_driver, network->match_type, network->match_name, network->match_host, - network->match_virt, network->match_kernel, - network->match_arch, + network->match_virt, network->match_kernel_cmdline, + network->match_kernel_version, network->match_arch, address, path, parent_driver, driver, devtype, ifname)) { if (network->match_name && device) { diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 49c62654b6b..702aa7692a4 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -112,7 +112,8 @@ struct Network { Condition *match_host; Condition *match_virt; - Condition *match_kernel; + Condition *match_kernel_cmdline; + Condition *match_kernel_version; Condition *match_arch; char *description; diff --git a/src/shared/condition.c b/src/shared/condition.c index d4bbaf3c65d..887c9a75886 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -143,6 +144,18 @@ static int condition_test_kernel_command_line(Condition *c) { return false; } +static int condition_test_kernel_version(Condition *c) { + struct utsname u; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_KERNEL_VERSION); + + assert_se(uname(&u) >= 0); + + return fnmatch(c->parameter, u.release, 0) == 0; +} + static int condition_test_user(Condition *c) { uid_t id; int r; @@ -552,6 +565,7 @@ int condition_test(Condition *c) { [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty, [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable, [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line, + [CONDITION_KERNEL_VERSION] = condition_test_kernel_version, [CONDITION_VIRTUALIZATION] = condition_test_virtualization, [CONDITION_SECURITY] = condition_test_security, [CONDITION_CAPABILITY] = condition_test_capability, @@ -612,6 +626,7 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", [CONDITION_HOST] = "ConditionHost", [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", + [CONDITION_KERNEL_VERSION] = "ConditionKernelVersion", [CONDITION_SECURITY] = "ConditionSecurity", [CONDITION_CAPABILITY] = "ConditionCapability", [CONDITION_AC_POWER] = "ConditionACPower", @@ -639,6 +654,7 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { [CONDITION_VIRTUALIZATION] = "AssertVirtualization", [CONDITION_HOST] = "AssertHost", [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine", + [CONDITION_KERNEL_VERSION] = "AssertKernelVersion", [CONDITION_SECURITY] = "AssertSecurity", [CONDITION_CAPABILITY] = "AssertCapability", [CONDITION_AC_POWER] = "AssertACPower", diff --git a/src/shared/condition.h b/src/shared/condition.h index 715866be704..98af2daaeee 100644 --- a/src/shared/condition.h +++ b/src/shared/condition.h @@ -31,6 +31,7 @@ typedef enum ConditionType { CONDITION_VIRTUALIZATION, CONDITION_HOST, CONDITION_KERNEL_COMMAND_LINE, + CONDITION_KERNEL_VERSION, CONDITION_SECURITY, CONDITION_CAPABILITY, CONDITION_AC_POWER, diff --git a/src/test/test-condition.c b/src/test/test-condition.c index bf455aac891..8fb2ad5d18c 100644 --- a/src/test/test-condition.c +++ b/src/test/test-condition.c @@ -20,6 +20,7 @@ #include #include +#include #include #include "sd-id128.h" @@ -38,10 +39,11 @@ #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 "user-util.h" +#include "util.h" +#include "virt.h" static void test_condition_test_path(void) { Condition *condition; @@ -298,6 +300,41 @@ static void test_condition_test_kernel_command_line(void) { condition_free(condition); } +static void test_condition_test_kernel_version(void) { + Condition *condition; + struct utsname u; + + 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); +} + static void test_condition_test_null(void) { Condition *condition; @@ -556,6 +593,7 @@ int main(int argc, char *argv[]) { 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(); test_condition_test_virtualization(); diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf index 85f0a0625b2..5cb126d870b 100644 --- a/src/udev/net/link-config-gperf.gperf +++ b/src/udev/net/link-config-gperf.gperf @@ -26,7 +26,8 @@ Match.Driver, config_parse_strv, 0, Match.Type, config_parse_strv, 0, offsetof(link_config, match_type) Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, match_host) Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, match_kernel_cmdline) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, match_kernel_version) Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, match_arch) Link.Description, config_parse_string, 0, offsetof(link_config, description) Link.MACAddressPolicy, config_parse_mac_policy, 0, offsetof(link_config, mac_policy) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 92d41a6e95b..a4368f088d1 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -77,7 +77,8 @@ static void link_config_free(link_config *link) { free(link->match_name); free(link->match_host); free(link->match_virt); - free(link->match_kernel); + free(link->match_kernel_cmdline); + free(link->match_kernel_version); free(link->match_arch); free(link->description); @@ -248,7 +249,8 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device, if (net_match_config(link->match_mac, link->match_path, link->match_driver, link->match_type, link->match_name, link->match_host, - link->match_virt, link->match_kernel, link->match_arch, + link->match_virt, link->match_kernel_cmdline, + link->match_kernel_version, link->match_arch, attr_value ? ether_aton(attr_value) : NULL, udev_device_get_property_value(device, "ID_PATH"), udev_device_get_driver(udev_device_get_parent(device)), diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h index a413251bd06..dabc3eff8f9 100644 --- a/src/udev/net/link-config.h +++ b/src/udev/net/link-config.h @@ -58,7 +58,8 @@ struct link_config { char **match_name; Condition *match_host; Condition *match_virt; - Condition *match_kernel; + Condition *match_kernel_cmdline; + Condition *match_kernel_version; Condition *match_arch; char *description;