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.
This commit is contained in:
Lennart Poettering
2017-12-26 17:39:44 +01:00
parent 95f7f85d39
commit 5022f08a23
19 changed files with 129 additions and 18 deletions
+11
View File
@@ -172,6 +172,17 @@
for details.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>KernelVersion=</varname></term>
<listitem>
<para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
expression (or if prefixed with the exclamation mark does not match it). See
<literal>ConditionKernelVersion=</literal> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Architecture=</varname></term>
<listitem>
+10
View File
@@ -232,6 +232,16 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>KernelVersion=</varname></term>
<listitem>
<para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
expression (or if prefixed with the exclamation mark does not match it). See
<literal>ConditionKernelVersion=</literal> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Architecture=</varname></term>
<listitem>
+11
View File
@@ -193,6 +193,17 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>KernelVersion=</varname></term>
<listitem>
<para>Checks whether the kernel version (as reported by <command>uname -r</command>) matches a certain
expression (or if prefixed with the exclamation mark does not match it). See
<literal>ConditionKernelVersion=</literal> in
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Architecture=</varname></term>
<listitem>
+6
View File
@@ -923,6 +923,7 @@
<term><varname>ConditionVirtualization=</varname></term>
<term><varname>ConditionHost=</varname></term>
<term><varname>ConditionKernelCommandLine=</varname></term>
<term><varname>ConditionKernelVersion=</varname></term>
<term><varname>ConditionSecurity=</varname></term>
<term><varname>ConditionCapability=</varname></term>
<term><varname>ConditionACPower=</varname></term>
@@ -1050,6 +1051,10 @@
the exact assignment is looked for with right and left hand
side matching.</para>
<para><varname>ConditionKernelVersion=</varname> may be used to check whether the kernel version (as reported
by <command>uname -r</command>) 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.</para>
<para><varname>ConditionSecurity=</varname> may be used to
check whether the given security module is enabled on the
system. Currently, the recognized values are
@@ -1201,6 +1206,7 @@
<term><varname>AssertVirtualization=</varname></term>
<term><varname>AssertHost=</varname></term>
<term><varname>AssertKernelCommandLine=</varname></term>
<term><varname>AssertKernelVersion=</varname></term>
<term><varname>AssertSecurity=</varname></term>
<term><varname>AssertCapability=</varname></term>
<term><varname>AssertACPower=</varname></term>
+2
View File
@@ -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)
+6 -2
View File
@@ -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)
+2 -1
View File
@@ -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,
+2 -1
View File
@@ -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)
+4 -2
View File
@@ -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;
+2 -1
View File
@@ -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;
+2 -1
View File
@@ -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)
+4 -3
View File
@@ -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) {
+2 -1
View File
@@ -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;
+16
View File
@@ -26,6 +26,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <time.h>
#include <unistd.h>
@@ -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",
+1
View File
@@ -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,
+40 -2
View File
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#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();
+2 -1
View File
@@ -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)
+4 -2
View File
@@ -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)),
+2 -1
View File
@@ -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;