]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-rules: add another check for conflicting expressions
authorDmitry V. Levin <ldv@strace.io>
Mon, 20 Mar 2023 08:00:00 +0000 (08:00 +0000)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 21 Mar 2023 00:34:50 +0000 (09:34 +0900)
Log an error when a rule line contains the following kind of conflicting
match expressions:

  KEY=="foo", KEY=="bar"

src/udev/udev-rules.c
test/units/testsuite-17.11.sh

index f708f79c9af254fb5e338513f2336dc4887abd95..4859a142da4ac2085027cf10a145eb53f19c3928 100644 (file)
@@ -1409,6 +1409,28 @@ static bool tokens_eq(const UdevRuleToken *a, const UdevRuleToken *b) {
                token_type_and_data_eq(a, b);
 }
 
+static bool nulstr_tokens_conflict(const UdevRuleToken *a, const UdevRuleToken *b) {
+        assert(a);
+        assert(b);
+
+        if (!(a->type == b->type &&
+              type_has_nulstr_value(a->type) &&
+              a->op == b->op &&
+              a->op == OP_MATCH &&
+              a->match_type == b->match_type &&
+              a->match_type == MATCH_TYPE_PLAIN &&
+              a->attr_subst_type == b->attr_subst_type &&
+              a->attr_match_remove_trailing_whitespace == b->attr_match_remove_trailing_whitespace &&
+              token_type_and_data_eq(a, b)))
+                return false;
+
+        NULSTR_FOREACH(i, a->value)
+                if (nulstr_contains(b->value, i))
+                        return false;
+
+        return true;
+}
+
 static void udev_check_unused_labels(UdevRuleLine *line) {
         assert(line);
 
@@ -1424,14 +1446,24 @@ static void udev_check_conflicts_duplicates(UdevRuleLine *line) {
 
         LIST_FOREACH(tokens, token, line->tokens)
                 LIST_FOREACH(tokens, i, token->tokens_next) {
-                        if (!tokens_eq(token, i))
+                        bool new_conflicts = false, new_duplicates = false;
+
+                        if (tokens_eq(token, i)) {
+                                if (!duplicates && token->op == i->op)
+                                        new_duplicates = true;
+                                if (!conflicts && conflicting_op(token->op, i->op))
+                                        new_conflicts = true;
+                        } else if (!conflicts && nulstr_tokens_conflict(token, i))
+                                new_conflicts = true;
+                        else
                                 continue;
-                        if (!duplicates && token->op == i->op) {
-                                duplicates = true;
+
+                        if (new_duplicates) {
+                                duplicates = new_duplicates;
                                 log_line_warning(line, "duplicate expressions");
                         }
-                        if (!conflicts && conflicting_op(token->op, i->op)) {
-                                conflicts = true;
+                        if (new_conflicts) {
+                                conflicts = new_conflicts;
                                 log_line_error(line, "conflicting match expressions, the line takes no effect");
                         }
                         if (conflicts && duplicates)
index 5f067f02b299afda5a1608b2f10c6e15b2f7a1c8..88172acde6d3686ea181e17ce6b25dea5ae66295 100755 (executable)
@@ -278,6 +278,7 @@ test_syntax_error 'a="b"' "Invalid key 'a'"
 test_syntax_error 'KERNEL=="", KERNEL=="?*", NAME="a"' 'conflicting match expressions, the line takes no effect'
 test_syntax_error 'KERNEL=="abc", KERNEL!="abc", NAME="b"' 'conflicting match expressions, the line takes no effect'
 test_syntax_error 'KERNEL=="|a|b", KERNEL!="b|a|", NAME="c"' 'conflicting match expressions, the line takes no effect'
+test_syntax_error 'KERNEL=="a|b", KERNEL=="c|d|e", NAME="f"' 'conflicting match expressions, the line takes no effect'
 # shellcheck disable=SC2016
 test_syntax_error 'ENV{DISKSEQ}=="?*", ENV{DEVTYPE}!="partition", ENV{DISKSEQ}!="?*" ENV{ID_IGNORE_DISKSEQ}!="1", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}"' \
                   'conflicting match expressions, the line takes no effect'
@@ -290,6 +291,8 @@ test_syntax_error 'ENV{DISKSEQ}=="?*", ENV{DEVTYPE}!="partition", ENV{DISKSEQ}==
 cat >"${rules}" <<'EOF'
 KERNEL=="a|b", KERNEL=="a|c", NAME="d"
 KERNEL=="a|b", KERNEL!="a|c", NAME="d"
+KERNEL!="a", KERNEL!="b", NAME="c"
+KERNEL=="|a", KERNEL=="|b", NAME="c"
 EOF
 assert_0 "${rules}"