]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/udev/udev-rules.c
Merge pull request #15561 from poettering/udev-memdup-fix
[thirdparty/systemd.git] / src / udev / udev-rules.c
index ab54067b3f16232c030b906d6e19a01d71737e92..4c955b0c079c3ee0a67db3a3001d681800ba871f 100644 (file)
@@ -78,7 +78,7 @@ typedef enum {
         TK_M_ATTR,                          /* string, takes filename through attribute, sd_device_get_sysattr_value(), util_resolve_subsys_kernel(), etc. */
         TK_M_SYSCTL,                        /* string, takes kernel parameter through attribute */
 
-        /* matches parent paramters */
+        /* matches parent parameters */
         TK_M_PARENTS_KERNEL,                /* string */
         TK_M_PARENTS_SUBSYSTEM,             /* string */
         TK_M_PARENTS_DRIVER,                /* string */
@@ -751,10 +751,7 @@ static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOp
                 if (op == OP_REMOVE)
                         return log_token_invalid_op(rules, key);
                 if (!is_match) {
-                        if (op == OP_ASSIGN)
-                                log_token_debug(rules, "Operator '=' is specified to %s key, assuming '=='.", key);
-                        else
-                                log_token_warning(rules, "%s key takes '==' or '!=' operator, assuming '==', but please fix it.", key);
+                        log_token_debug(rules, "%s key takes '==' or '!=' operator, assuming '=='.", key);
                         op = OP_MATCH;
                 }
 
@@ -766,10 +763,7 @@ static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOp
                 if (op == OP_REMOVE)
                         return log_token_invalid_op(rules, key);
                 if (!is_match) {
-                        if (op == OP_ASSIGN)
-                                log_token_debug(rules, "Operator '=' is specified to %s key, assuming '=='.", key);
-                        else
-                                log_token_warning(rules, "%s key takes '==' or '!=' operator, assuming '==', but please fix it.", key);
+                        log_token_debug(rules, "%s key takes '==' or '!=' operator, assuming '=='.", key);
                         op = OP_MATCH;
                 }
 
@@ -927,7 +921,7 @@ static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOp
                         op = OP_ASSIGN;
                 }
 
-                r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, NULL);
+                r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, attr);
         } else if (streq(key, "RUN")) {
                 if (is_match || op == OP_REMOVE)
                         return log_token_invalid_op(rules, key);
@@ -1098,7 +1092,9 @@ static int rule_add_line(UdevRules *rules, const char *line_str, unsigned line_n
         if (isempty(line_str))
                 return 0;
 
-        line = strdup(line_str);
+        /* We use memdup_suffix0() here, since we want to add a second NUL byte to the end, since possibly
+         * some parsers might turn this into a "nulstr", which requires an extra NUL at the end. */
+        line = memdup_suffix0(line_str, strlen(line_str) + 1);
         if (!line)
                 return log_oom();
 
@@ -1334,11 +1330,7 @@ static bool token_match_string(UdevRuleToken *token, const char *str) {
                 match = isempty(str);
                 break;
         case MATCH_TYPE_SUBSYSTEM:
-                NULSTR_FOREACH(i, "subsystem\0class\0bus\0")
-                        if (streq(i, str)) {
-                                match = true;
-                                break;
-                        }
+                match = STR_IN_SET(str, "subsystem", "class", "bus");
                 break;
         case MATCH_TYPE_PLAIN_WITH_EMPTY:
                 if (isempty(str)) {
@@ -1660,7 +1652,7 @@ static int udev_rule_apply_token_to_event(
                 if (mode == MODE_INVALID)
                         return token->op == OP_MATCH;
 
-                match = (((statbuf.st_mode ^ mode) & 07777) == 0);
+                match = (statbuf.st_mode & mode) > 0;
                 return token->op == (match ? OP_MATCH : OP_NOMATCH);
         }
         case TK_M_PROGRAM: {
@@ -1671,10 +1663,13 @@ static int udev_rule_apply_token_to_event(
                 log_rule_debug(dev, rules, "Running PROGRAM '%s'", buf);
 
                 r = udev_event_spawn(event, timeout_usec, true, buf, result, sizeof(result));
-                if (r < 0)
-                        return log_rule_error_errno(dev, rules, r, "Failed to execute '%s': %m", buf);
-                if (r > 0)
+                if (r != 0) {
+                        if (r < 0)
+                                log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf);
+                        else /* returned value is positive when program fails */
+                                log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r);
                         return token->op == OP_NOMATCH;
+                }
 
                 delete_trailing_chars(result, "\n");
                 count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT);
@@ -1738,10 +1733,11 @@ static int udev_rule_apply_token_to_event(
                 log_rule_debug(dev, rules, "Importing properties from results of '%s'", buf);
 
                 r = udev_event_spawn(event, timeout_usec, true, buf, result, sizeof result);
-                if (r < 0)
-                        return log_rule_error_errno(dev, rules, r, "Failed to execute '%s': %m", buf);
-                if (r > 0) {
-                        log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r);
+                if (r != 0) {
+                        if (r < 0)
+                                log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf);
+                        else /* returned value is positive when program fails */
+                                log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r);
                         return token->op == OP_NOMATCH;
                 }
 
@@ -2102,7 +2098,7 @@ static int udev_rule_apply_token_to_event(
                 (void) udev_event_apply_format(event, token->value, value, sizeof(value), false);
 
                 log_rule_debug(dev, rules, "ATTR '%s' writing '%s'", buf, value);
-                r = write_string_file(buf, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
+                r = write_string_file(buf, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_AVOID_NEWLINE);
                 if (r < 0)
                         log_rule_error_errno(dev, rules, r, "Failed to write ATTR{%s}, ignoring: %m", buf);
                 break;
@@ -2333,9 +2329,10 @@ static int apply_static_dev_perms(const char *devnode, uid_t uid, gid_t gid, mod
                 gid = 0;
 
         r = chmod_and_chown(device_node, mode, uid, gid);
+        if (r == -ENOENT)
+                return 0;
         if (r < 0)
-                return log_error_errno(errno, "Failed to chown '%s' %u %u: %m",
-                                               device_node, uid, gid);
+                return log_error_errno(r, "Failed to chown '%s' %u %u: %m", device_node, uid, gid);
         else
                 log_debug("chown '%s' %u:%u with mode %#o", device_node, uid, gid, mode);