Brian Stinson 2593d8
From d6210c3d053d70175d72ed1d1719497eed76000b Mon Sep 17 00:00:00 2001
Brian Stinson 2593d8
From: Jan Synacek <jsynacek@redhat.com>
Brian Stinson 2593d8
Date: Thu, 17 Oct 2019 09:37:35 +0200
Brian Stinson 2593d8
Subject: [PATCH] udev: introduce CONST key name
Brian Stinson 2593d8
Brian Stinson 2593d8
Currently, there is no way to match against system-wide constants, such
Brian Stinson 2593d8
as architecture or virtualization type, without forking helper binaries.
Brian Stinson 2593d8
That potentially results in a huge number of spawned processes which
Brian Stinson 2593d8
output always the same answer.
Brian Stinson 2593d8
Brian Stinson 2593d8
This patch introduces a special CONST keyword which takes a hard-coded
Brian Stinson 2593d8
string as its key and returns a value assigned to that key. Currently
Brian Stinson 2593d8
implemented are CONST{arch} and CONST{virt}, which can be used to match
Brian Stinson 2593d8
against the system's architecture and virtualization type.
Brian Stinson 2593d8
Brian Stinson 2593d8
(based on commit 4801d8afe2ff1c1c075c9f0bc5631612172e0bb7)
Brian Stinson 2593d8
Brian Stinson 2593d8
Resolves: #1762679
Brian Stinson 2593d8
---
Brian Stinson 2593d8
 man/udev.xml              | 26 ++++++++++++++++++++++++++
Brian Stinson 2593d8
 rules/40-redhat.rules     |  6 +++---
Brian Stinson 2593d8
 src/udev/udev-rules.c     | 32 ++++++++++++++++++++++++++++++++
Brian Stinson 2593d8
 test/rule-syntax-check.py |  2 +-
Brian Stinson 2593d8
 4 files changed, 62 insertions(+), 4 deletions(-)
Brian Stinson 2593d8
Brian Stinson 2593d8
diff --git a/man/udev.xml b/man/udev.xml
Brian Stinson 2593d8
index bdf901a8f0..8c1eb41787 100644
Brian Stinson 2593d8
--- a/man/udev.xml
Brian Stinson 2593d8
+++ b/man/udev.xml
Brian Stinson 2593d8
@@ -236,6 +236,32 @@
Brian Stinson 2593d8
           </listitem>
Brian Stinson 2593d8
         </varlistentry>
Brian Stinson 2593d8
 
Brian Stinson 2593d8
+        <varlistentry>
Brian Stinson 2593d8
+          <term><varname>CONST{<replaceable>key</replaceable>}</varname></term>
Brian Stinson 2593d8
+          <listitem>
Brian Stinson 2593d8
+            <para>Match against a system-wide constant. Supported keys are:</para>
Brian Stinson 2593d8
+            <variablelist>
Brian Stinson 2593d8
+              <varlistentry>
Brian Stinson 2593d8
+                <term><literal>arch</literal></term>
Brian Stinson 2593d8
+                <listitem>
Brian Stinson 2593d8
+                  <para>System's architecture. See <option>ConditionArchitecture=</option> in
Brian Stinson 2593d8
+                  <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
Brian Stinson 2593d8
+                  for possible values.</para>
Brian Stinson 2593d8
+                </listitem>
Brian Stinson 2593d8
+              </varlistentry>
Brian Stinson 2593d8
+              <varlistentry>
Brian Stinson 2593d8
+                <term><literal>virt</literal></term>
Brian Stinson 2593d8
+                <listitem>
Brian Stinson 2593d8
+                  <para>System's virtualization environment. See
Brian Stinson 2593d8
+                  <citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry>
Brian Stinson 2593d8
+                  for possible values.</para>
Brian Stinson 2593d8
+                </listitem>
Brian Stinson 2593d8
+              </varlistentry>
Brian Stinson 2593d8
+            </variablelist>
Brian Stinson 2593d8
+            <para>Unknown keys will never match.</para>
Brian Stinson 2593d8
+          </listitem>
Brian Stinson 2593d8
+        </varlistentry>
Brian Stinson 2593d8
+
Brian Stinson 2593d8
         <varlistentry>
Brian Stinson 2593d8
           <term><varname>TAG</varname></term>
Brian Stinson 2593d8
           <listitem>
Brian Stinson 2593d8
diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules
Brian Stinson 2593d8
index fadc6e59f1..3c95cd2df0 100644
Brian Stinson 2593d8
--- a/rules/40-redhat.rules
Brian Stinson 2593d8
+++ b/rules/40-redhat.rules
Brian Stinson 2593d8
@@ -6,11 +6,11 @@ SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}
Brian Stinson 2593d8
 # Memory hotadd request
Brian Stinson 2593d8
 SUBSYSTEM!="memory", GOTO="memory_hotplug_end"
Brian Stinson 2593d8
 ACTION!="add", GOTO="memory_hotplug_end"
Brian Stinson 2593d8
-PROGRAM="/bin/uname -p", RESULT=="s390*", GOTO="memory_hotplug_end"
Brian Stinson 2593d8
-PROGRAM="/bin/uname -p", RESULT=="ppc64*", GOTO="memory_hotplug_end"
Brian Stinson 2593d8
+CONST{arch}=="s390*", GOTO="memory_hotplug_end"
Brian Stinson 2593d8
+CONST{arch}=="ppc64*", GOTO="memory_hotplug_end"
Brian Stinson 2593d8
 
Brian Stinson 2593d8
 ENV{.state}="online"
Brian Stinson 2593d8
-PROGRAM="/bin/systemd-detect-virt", RESULT=="none", ENV{.state}="online_movable"
Brian Stinson 2593d8
+CONST{virt}=="none", ENV{.state}="online_movable"
Brian Stinson 2593d8
 ATTR{state}=="offline", ATTR{state}="$env{.state}"
Brian Stinson 2593d8
 
Brian Stinson 2593d8
 LABEL="memory_hotplug_end"
Brian Stinson 2593d8
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
Brian Stinson 2593d8
index 58af863f3d..a246cbe67e 100644
Brian Stinson 2593d8
--- a/src/udev/udev-rules.c
Brian Stinson 2593d8
+++ b/src/udev/udev-rules.c
Brian Stinson 2593d8
@@ -17,6 +17,7 @@
Brian Stinson 2593d8
 #include <unistd.h>
Brian Stinson 2593d8
 
Brian Stinson 2593d8
 #include "alloc-util.h"
Brian Stinson 2593d8
+#include "architecture.h"
Brian Stinson 2593d8
 #include "conf-files.h"
Brian Stinson 2593d8
 #include "dirent-util.h"
Brian Stinson 2593d8
 #include "escape.h"
Brian Stinson 2593d8
@@ -34,6 +35,7 @@
Brian Stinson 2593d8
 #include "udev.h"
Brian Stinson 2593d8
 #include "user-util.h"
Brian Stinson 2593d8
 #include "util.h"
Brian Stinson 2593d8
+#include "virt.h"
Brian Stinson 2593d8
 
Brian Stinson 2593d8
 #define PREALLOC_TOKEN          2048
Brian Stinson 2593d8
 
Brian Stinson 2593d8
@@ -123,6 +125,7 @@ enum token_type {
Brian Stinson 2593d8
         TK_M_DEVLINK,                   /* val */
Brian Stinson 2593d8
         TK_M_NAME,                      /* val */
Brian Stinson 2593d8
         TK_M_ENV,                       /* val, attr */
Brian Stinson 2593d8
+        TK_M_CONST,                     /* val, attr */
Brian Stinson 2593d8
         TK_M_TAG,                       /* val */
Brian Stinson 2593d8
         TK_M_SUBSYSTEM,                 /* val */
Brian Stinson 2593d8
         TK_M_DRIVER,                    /* val */
Brian Stinson 2593d8
@@ -259,6 +262,7 @@ static const char *token_str(enum token_type type) {
Brian Stinson 2593d8
                 [TK_M_DEVLINK] =                "M DEVLINK",
Brian Stinson 2593d8
                 [TK_M_NAME] =                   "M NAME",
Brian Stinson 2593d8
                 [TK_M_ENV] =                    "M ENV",
Brian Stinson 2593d8
+                [TK_M_CONST] =                  "M CONST",
Brian Stinson 2593d8
                 [TK_M_TAG] =                    "M TAG",
Brian Stinson 2593d8
                 [TK_M_SUBSYSTEM] =              "M SUBSYSTEM",
Brian Stinson 2593d8
                 [TK_M_DRIVER] =                 "M DRIVER",
Brian Stinson 2593d8
@@ -370,6 +374,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) {
Brian Stinson 2593d8
         case TK_M_SYSCTL:
Brian Stinson 2593d8
         case TK_M_ATTRS:
Brian Stinson 2593d8
         case TK_M_ENV:
Brian Stinson 2593d8
+        case TK_M_CONST:
Brian Stinson 2593d8
         case TK_A_ATTR:
Brian Stinson 2593d8
         case TK_A_SYSCTL:
Brian Stinson 2593d8
         case TK_A_ENV:
Brian Stinson 2593d8
@@ -903,6 +908,7 @@ static void rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
Brian Stinson 2593d8
                 token->key.builtin_cmd = *(enum udev_builtin_cmd *)data;
Brian Stinson 2593d8
                 break;
Brian Stinson 2593d8
         case TK_M_ENV:
Brian Stinson 2593d8
+        case TK_M_CONST:
Brian Stinson 2593d8
         case TK_M_ATTR:
Brian Stinson 2593d8
         case TK_M_SYSCTL:
Brian Stinson 2593d8
         case TK_M_ATTRS:
Brian Stinson 2593d8
@@ -1226,6 +1232,17 @@ static void add_rule(struct udev_rules *rules, char *line,
Brian Stinson 2593d8
                                 rule_add_key(&rule_tmp, TK_A_ENV, op, value, attr);
Brian Stinson 2593d8
                         }
Brian Stinson 2593d8
 
Brian Stinson 2593d8
+                } else if (startswith(key, "CONST{")) {
Brian Stinson 2593d8
+                        attr = get_key_attribute(rules->udev, key + STRLEN("CONST"));
Brian Stinson 2593d8
+                        if (attr == NULL || !STR_IN_SET(attr, "arch", "virt"))
Brian Stinson 2593d8
+                                LOG_AND_RETURN("error parsing %s attribute", "CONST");
Brian Stinson 2593d8
+
Brian Stinson 2593d8
+                        if (op == OP_REMOVE)
Brian Stinson 2593d8
+                                LOG_AND_RETURN("invalid %s operation", "CONST");
Brian Stinson 2593d8
+
Brian Stinson 2593d8
+                        if (op < OP_MATCH_MAX)
Brian Stinson 2593d8
+                                rule_add_key(&rule_tmp, TK_M_CONST, op, value, attr);
Brian Stinson 2593d8
+
Brian Stinson 2593d8
                 } else if (streq(key, "TAG")) {
Brian Stinson 2593d8
                         if (op < OP_MATCH_MAX)
Brian Stinson 2593d8
                                 rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
Brian Stinson 2593d8
@@ -1855,6 +1872,21 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
Brian Stinson 2593d8
                                 goto nomatch;
Brian Stinson 2593d8
                         break;
Brian Stinson 2593d8
                 }
Brian Stinson 2593d8
+                case TK_M_CONST: {
Brian Stinson 2593d8
+                        const char *key_name = rules_str(rules, cur->key.attr_off);
Brian Stinson 2593d8
+                        const char *value = NULL;
Brian Stinson 2593d8
+
Brian Stinson 2593d8
+                        if (streq(key_name, "arch")) {
Brian Stinson 2593d8
+                                value = architecture_to_string(uname_architecture());
Brian Stinson 2593d8
+                        } else if (streq(key_name, "virt")) {
Brian Stinson 2593d8
+                                value = virtualization_to_string(detect_virtualization());
Brian Stinson 2593d8
+                        } else
Brian Stinson 2593d8
+                                assert_not_reached("Invalid CONST key");
Brian Stinson 2593d8
+
Brian Stinson 2593d8
+                        if (match_key(rules, cur, value))
Brian Stinson 2593d8
+                                goto nomatch;
Brian Stinson 2593d8
+                        break;
Brian Stinson 2593d8
+                }
Brian Stinson 2593d8
                 case TK_M_TAG: {
Brian Stinson 2593d8
                         struct udev_list_entry *list_entry;
Brian Stinson 2593d8
                         bool match = false;
Brian Stinson 2593d8
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py
Brian Stinson 2593d8
index c7c0a1a656..6e59f421f5 100755
Brian Stinson 2593d8
--- a/test/rule-syntax-check.py
Brian Stinson 2593d8
+++ b/test/rule-syntax-check.py
Brian Stinson 2593d8
@@ -19,7 +19,7 @@ quoted_string_re = r'"(?:[^\\"]|\\.)*"'
Brian Stinson 2593d8
 no_args_tests = re.compile(r'(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|PROGRAM|RESULT|TEST)\s*(?:=|!)=\s*' + quoted_string_re + '$')
Brian Stinson 2593d8
 # PROGRAM can also be specified as an assignment.
Brian Stinson 2593d8
 program_assign = re.compile(r'PROGRAM\s*=\s*' + quoted_string_re + '$')
Brian Stinson 2593d8
-args_tests = re.compile(r'(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*' + quoted_string_re + '$')
Brian Stinson 2593d8
+args_tests = re.compile(r'(ATTRS?|ENV|CONST|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*' + quoted_string_re + '$')
Brian Stinson 2593d8
 no_args_assign = re.compile(r'(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*' + quoted_string_re + '$')
Brian Stinson 2593d8
 args_assign = re.compile(r'(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*' + quoted_string_re + '$')
Brian Stinson 2593d8
 # Find comma-separated groups, but allow commas that are inside quoted strings.