HomeFreeBSD

Udev rules: use match (==) rather than assign (=) for PROGRAM

Description

Udev rules: use match (==) rather than assign (=) for PROGRAM

Assignment syntax (=) can be used for the PROGRAM key. But the PROGRAM
key is really a match key, not an assign key. The internal logic used by
udev to decide whether a PROGRAM key "matched" or not (which determines
whether the remainder of the rule is evaluated) depends on whether the
operator was OP_MATCH (==) or OP_NOMATCH (!=). [1]

The man page claims that '"=", ":=", and "+=" have the same effect as
"=="' for PROGRAM keys. And, after a brief perusal, the udev source code
does seem to confirm that operators other than OP_MATCH (==) or
OP_NOMATCH (!=) are implicitly converted to OP_MATCH (==). [2] But it's
not entirely clear that this is definitely the case: anecdotal testing
seems to indicate that when OP_ASSIGN (=) is used, the program's exit
status is disregarded and the remainder of the rule is processed
regardless of whether it was, in fact, a successful exit.

The bottom line here is that, if zvol_id hits some snag and returns a
nonzero exit status, then we almost certainly do NOT want to continue on
with the rule and use whatever the stdout contents may have been to
mindlessly create /dev/zvol/* symlinks. Therefore, let's be extra-sure
and use the match (==) operator explicitly, to eliminate any possibility
that udev might do the wrong thing, and ensure that a nonzero exit
status will definitely short-circuit the rest of the rule, bypassing the
SYMLINK+= assignments.

[1]
udev,
file src/udev/udev-rules.c,

func udev_rule_apply_token_to_event,
 switch case TK_M_PROGRAM if r != 0 (nonzero exit status):
    return token->op == OP_NOMATCH;
 switch case TK_M_PROGRAM if r == 0 (zero exit status):
    return token->op == OP_MATCH;
 func retval 0 => key is considered to have matched
 func retval 1 => key is considered to have NOT matched

[2]
udev,
file src/udev/udev-rules.c,

func parse_token,
 at func start:
    bool is_match = IN_SET(op, OP_MATCH, OP_NOMATCH);
 in else-if case streq(key, "PROGRAM"):
    if (!is_match) op = OP_MATCH;

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com>
Signed-off-by: Justin Gottula <justin@jgottula.com>
Closes #12302

Details

Provenance
Justin Gottula <justin@jgottula.com>Authored on Jun 30 2021, 1:54 AM
Brian Behlendorf <behlendorf1@llnl.gov>Committed on Jul 2 2021, 8:09 PM
Parents
rG17c794e7b072: Udev rules: replace deprecated $tempnode with $devnode
Branches
Unknown
Tags
Unknown

Event Timeline

Brian Behlendorf <behlendorf1@llnl.gov> committed rGf1aef8d4df83: Udev rules: use match (==) rather than assign (=) for PROGRAM (authored by Justin Gottula <justin@jgottula.com>).Jul 2 2021, 8:09 PM