diff options
-rwxr-xr-x | test/udev-test.pl | 49 | ||||
-rw-r--r-- | udev_rules.c | 37 | ||||
-rw-r--r-- | udev_rules_parse.c | 51 |
3 files changed, 106 insertions, 31 deletions
diff --git a/test/udev-test.pl b/test/udev-test.pl index b44bd18af5..33da68a386 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -387,7 +387,7 @@ EOF devpath => "/block/sda/sda3", exp_name => "Major:8-minor:3-kernelnumber:3-id:0:0:0:0", rules => <<EOF -BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id" +BUS=="scsi", ID=="0:0:0:0", DEVPATH=="*/sda/*", NAME="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id" EOF }, { @@ -396,7 +396,7 @@ EOF devpath => "/block/sda/sda3", exp_name => "830:0:0:03" , rules => <<EOF -BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="%M%m%b%n" +BUS=="scsi", ID=="0:0:0:0", DEVPATH=="*/sda/*", NAME="%M%m%b%n" EOF }, { @@ -405,7 +405,7 @@ EOF devpath => "/block/sda/sda3", exp_name => "833" , rules => <<EOF -BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="\$major\$minor\$number" +BUS=="scsi", ID=="0:0:0:0", DEVPATH=="*/sda/*", NAME="\$major\$minor\$number" EOF }, { @@ -414,7 +414,7 @@ EOF devpath => "/block/sda/sda3", exp_name => "8330:0:0:0" , rules => <<EOF -BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="\$major%m%n\$id" +BUS=="scsi", ID=="0:0:0:0", DEVPATH=="*/sda/*", NAME="\$major%m%n\$id" EOF }, { @@ -1291,8 +1291,8 @@ EOF devpath => "/block/sda/sda1", exp_name => "part", rules => <<EOF -SUBSYSTEM=="block", KERNEL="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false" -SUBSYSTEM=="block", KERNEL="*[!0-9]", ENV{PARTITION}="false", ENV{MAINDEVICE}="true" +SUBSYSTEM=="block", KERNEL=="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false" +SUBSYSTEM=="block", KERNEL=="*[!0-9]", ENV{PARTITION}="false", ENV{MAINDEVICE}="true" ENV{MAINDEVICE}=="true", NAME="disk" ENV{PARTITION}=="true", NAME="part" NAME="bad" @@ -1530,6 +1530,43 @@ KERNEL=="sda1", NAME="right", LABEL="TEST" KERNEL=="sda1", NAME="wrong2" EOF }, + { + desc => "NAME compare test", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "link", + exp_target => "node", + not_exp_name => "wronglink", + rules => <<EOF +KERNEL=="sda1", NAME="node" +KERNEL=="sda2", NAME="wrong" +KERNEL=="sda1", NAME=="wrong*", SYMLINK+="wronglink" +KERNEL=="sda1", NAME=="?*", SYMLINK+="link" +KERNEL=="sda1", NAME=="node*", SYMLINK+="link2" +EOF + }, + { + desc => "NAME compare test 2", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "link2", + exp_target => "sda1", + not_exp_name => "link", + rules => <<EOF +KERNEL=="sda1", NAME=="?*", SYMLINK+="link" +KERNEL=="sda1", NAME!="?*", SYMLINK+="link2" +EOF + }, + { + desc => "invalid key operation", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "yes", + rules => <<EOF +KERNEL="sda1", NAME=="no" +KERNEL=="sda1", NAME="yes" +EOF + }, ); # set env diff --git a/udev_rules.c b/udev_rules.c index 5b1e6889ec..596bcd188b 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -680,7 +680,8 @@ static int match_key(const char *key_name, struct udev_rule *rule, struct key *k char *key_value; char *pos; - if (key->operation == KEY_OP_UNSET) + if (key->operation != KEY_OP_MATCH && + key->operation != KEY_OP_NOMATCH) return 0; strlcpy(value, rule->buf + key->val_off, sizeof(value)); @@ -726,6 +727,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath)) goto nomatch; + /* compare NAME against a previously assigned value */ + if (match_key("NAME", rule, &rule->name, udev->name)) + goto nomatch; + if (rule->modalias.operation != KEY_OP_UNSET) { const char *value; static int warn = 1; @@ -748,7 +753,8 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) struct key_pair *pair = &rule->env.keys[i]; /* we only check for matches, assignments will be handled later */ - if (pair->key.operation != KEY_OP_ASSIGN) { + if (pair->key.operation == KEY_OP_MATCH || + pair->key.operation == KEY_OP_NOMATCH) { const char *key_name = key_pair_name(rule, pair); const char *value = getenv(key_name); @@ -775,22 +781,16 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) udev->dev_parent = udev->dev; while (1) { /* check for matching driver */ - if (rule->driver.operation != KEY_OP_UNSET) { - if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver)) - goto try_parent; - } + if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver)) + goto try_parent; /* check for matching subsystem/bus value */ - if (rule->bus.operation != KEY_OP_UNSET) { - if (match_key("BUS", rule, &rule->bus, udev->dev_parent->subsystem)) - goto try_parent; - } + if (match_key("BUS", rule, &rule->bus, udev->dev_parent->subsystem)) + goto try_parent; /* check for matching bus id (device name) */ - if (rule->id.operation != KEY_OP_UNSET) { - if (match_key("ID", rule, &rule->id, udev->dev_parent->kernel_name)) - goto try_parent; - } + if (match_key("ID", rule, &rule->id, udev->dev_parent->kernel_name)) + goto try_parent; /* check for matching sysfs pairs */ if (rule->sysfs.count) { @@ -934,7 +934,10 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) if (rule == NULL) break; - if (name_set && rule->name.operation != KEY_OP_UNSET) { + if (name_set && + (rule->name.operation == KEY_OP_ASSIGN || + rule->name.operation == KEY_OP_ASSIGN_FINAL || + rule->name.operation == KEY_OP_ADD)) { dbg("node name already set, rule ignored"); continue; } @@ -1020,7 +1023,9 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) } /* set name, later rules with name set will be ignored */ - if (rule->name.operation != KEY_OP_UNSET) { + if (rule->name.operation == KEY_OP_ASSIGN || + rule->name.operation == KEY_OP_ASSIGN_FINAL || + rule->name.operation == KEY_OP_ADD) { int count; name_set = 1; diff --git a/udev_rules_parse.c b/udev_rules_parse.c index 6bb83ae12b..442ec65390 100644 --- a/udev_rules_parse.c +++ b/udev_rules_parse.c @@ -235,7 +235,7 @@ static int add_rule_key_pair(struct udev_rule *rule, struct key_pairs *pairs, return 0; } -static int add_to_rules(struct udev_rules *rules, char *line) +static int add_to_rules(struct udev_rules *rules, char *line, const char *filename, unsigned int lineno) { struct udev_rule *rule; size_t rule_size; @@ -276,36 +276,66 @@ static int add_to_rules(struct udev_rules *rules, char *line) } if (strcasecmp(key, "KERNEL") == 0) { + if (operation != KEY_OP_MATCH && + operation != KEY_OP_NOMATCH) { + err("invalid KERNEL operation"); + goto invalid; + } add_rule_key(rule, &rule->kernel_name, operation, value); valid = 1; continue; } if (strcasecmp(key, "SUBSYSTEM") == 0) { + if (operation != KEY_OP_MATCH && + operation != KEY_OP_NOMATCH) { + err("invalid SUBSYSTEM operation"); + goto invalid; + } add_rule_key(rule, &rule->subsystem, operation, value); valid = 1; continue; } if (strcasecmp(key, "ACTION") == 0) { + if (operation != KEY_OP_MATCH && + operation != KEY_OP_NOMATCH) { + err("invalid ACTION operation"); + goto invalid; + } add_rule_key(rule, &rule->action, operation, value); valid = 1; continue; } if (strcasecmp(key, "DEVPATH") == 0) { + if (operation != KEY_OP_MATCH && + operation != KEY_OP_NOMATCH) { + err("invalid DEVPATH operation"); + goto invalid; + } add_rule_key(rule, &rule->devpath, operation, value); valid = 1; continue; } if (strcasecmp(key, "BUS") == 0) { + if (operation != KEY_OP_MATCH && + operation != KEY_OP_NOMATCH) { + err("invalid BUS operation"); + goto invalid; + } add_rule_key(rule, &rule->bus, operation, value); valid = 1; continue; } if (strcasecmp(key, "ID") == 0) { + if (operation != KEY_OP_MATCH && + operation != KEY_OP_NOMATCH) { + err("invalid ID operation"); + goto invalid; + } add_rule_key(rule, &rule->id, operation, value); valid = 1; continue; @@ -504,14 +534,12 @@ static int add_to_rules(struct udev_rules *rules, char *line) continue; } - err("unknown key '%s', in '%s'", key, line); + err("unknown key '%s'", key); } /* skip line if not any valid key was found */ - if (!valid) { - err("invalid rule '%s'", line); - goto exit; - } + if (!valid) + goto invalid; /* grow buffer and add rule */ rule_size = sizeof(struct udev_rule) + rule->bufsize; @@ -531,13 +559,18 @@ static int add_to_rules(struct udev_rules *rules, char *line) exit: free(rule); return 0; + +invalid: + free(rule); + err("invalid rule '%s:%u'", filename, lineno); + return -1; } static int parse_file(struct udev_rules *rules, const char *filename) { char line[LINE_SIZE]; char *bufline; - int lineno; + unsigned int lineno; char *buf; size_t bufsize; size_t cur; @@ -562,7 +595,7 @@ static int parse_file(struct udev_rules *rules, const char *filename) lineno++; if (count >= sizeof(line)) { - info("line too long, rule skipped %s, line %d", filename, lineno); + err("line too long, rule skipped '%s:%u'", filename, lineno); continue; } @@ -588,7 +621,7 @@ static int parse_file(struct udev_rules *rules, const char *filename) line[j] = '\0'; dbg("read '%s'", line); - add_to_rules(rules, line); + add_to_rules(rules, line, filename, lineno); } file_unmap(buf, bufsize); |