udev-rules: update log messages
This also adds trace logs about token result, and skipping assignment caused by final value already assigned.
This commit is contained in:
+248
-185
@@ -298,6 +298,37 @@ static bool token_is_for_parents(UdevRuleToken *token) {
|
||||
#define log_event_trace(event, ...) \
|
||||
_log_event_trace(event, UNIQ_T(e, UNIQ), __VA_ARGS__)
|
||||
|
||||
#define _log_event_result(event, token, result, result_u) \
|
||||
({ \
|
||||
bool result_u = (result); \
|
||||
\
|
||||
log_event_trace(event, token, "%s", \
|
||||
result_u ? "PASS" : "FAIL"); \
|
||||
result_u; \
|
||||
})
|
||||
|
||||
#define log_event_result(event, token, result) \
|
||||
_log_event_result(event, token, result, UNIQ_T(r, UNIQ))
|
||||
|
||||
#define log_event_done(event, token) \
|
||||
({ \
|
||||
log_event_trace(event, token, "DONE"); \
|
||||
true; \
|
||||
})
|
||||
|
||||
#define _log_event_final_set(event, token, token_u) \
|
||||
({ \
|
||||
UdevRuleToken *token_u = ASSERT_PTR(token); \
|
||||
\
|
||||
log_event_trace(event, token_u, \
|
||||
"Already assigned final value, ignoring further %s.", \
|
||||
token_u->op == OP_REMOVE ? "modification" : "assignment"); \
|
||||
true; \
|
||||
})
|
||||
|
||||
#define log_event_final_set(event, token) \
|
||||
_log_event_final_set(event, token, UNIQ_T(t, UNIQ))
|
||||
|
||||
#define _log_event_truncated(event, token, token_u, what, format) \
|
||||
({ \
|
||||
UdevRuleToken *token_u = ASSERT_PTR(token); \
|
||||
@@ -359,16 +390,6 @@ static bool token_is_for_parents(UdevRuleToken *token) {
|
||||
"Invalid value \"%s\" for %s (char %zu: %s), ignoring.", \
|
||||
value, key, offset, hint)
|
||||
|
||||
static void log_unknown_owner(sd_device *dev, UdevRuleLine *line, int error, const char *entity, const char *name) {
|
||||
assert(line);
|
||||
ASSERT_NON_ZERO(error);
|
||||
|
||||
if (IN_SET(abs(error), ENOENT, ESRCH))
|
||||
log_udev_rule_line_full(dev, line, LOG_ERR, error, "Unknown %s '%s', ignoring.", entity, name);
|
||||
else
|
||||
log_udev_rule_line_full(dev, line, LOG_ERR, error, "Failed to resolve %s '%s', ignoring: %m", entity, name);
|
||||
}
|
||||
|
||||
/*** Other functions ***/
|
||||
|
||||
static UdevRuleToken* udev_rule_token_free(UdevRuleToken *token) {
|
||||
@@ -453,7 +474,11 @@ static int rule_resolve_user(UdevRuleLine *rule_line, const char *name, uid_t *r
|
||||
|
||||
r = get_user_creds(&name, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
|
||||
if (r < 0) {
|
||||
log_unknown_owner(NULL, rule_line, r, "user", name);
|
||||
if (IN_SET(r, -ENOENT, -ESRCH))
|
||||
log_line_error_errno(rule_line, r, "Unknown user '%s', ignoring.", name);
|
||||
else
|
||||
log_line_error_errno(rule_line, r, "Failed to resolve user '%s', ignoring: %m", name);
|
||||
|
||||
*ret = UID_INVALID;
|
||||
return 0;
|
||||
}
|
||||
@@ -489,7 +514,11 @@ static int rule_resolve_group(UdevRuleLine *rule_line, const char *name, gid_t *
|
||||
|
||||
r = get_group_creds(&name, &gid, USER_CREDS_ALLOW_MISSING);
|
||||
if (r < 0) {
|
||||
log_unknown_owner(NULL, rule_line, r, "group", name);
|
||||
if (IN_SET(r, -ENOENT, -ESRCH))
|
||||
log_line_error_errno(rule_line, r, "Unknown group '%s', ignoring.", name);
|
||||
else
|
||||
log_line_error_errno(rule_line, r, "Failed to resolve group '%s', ignoring: %m", name);
|
||||
|
||||
*ret = GID_INVALID;
|
||||
return 0;
|
||||
}
|
||||
@@ -2012,30 +2041,6 @@ static int get_property_from_string(char *line, char **ret_key, char **ret_value
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int import_parent_into_properties(sd_device *dev, const char *filter) {
|
||||
sd_device *parent;
|
||||
int r;
|
||||
|
||||
assert(dev);
|
||||
assert(filter);
|
||||
|
||||
r = sd_device_get_parent(dev, &parent);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
FOREACH_DEVICE_PROPERTY(parent, key, val) {
|
||||
if (fnmatch(filter, key, 0) != 0)
|
||||
continue;
|
||||
r = device_add_property(dev, key, val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int attr_subst_subdir(char attr[static UDEV_PATH_SIZE]) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
char buf[UDEV_PATH_SIZE], *p;
|
||||
@@ -2173,8 +2178,8 @@ static int udev_rule_apply_token_to_event(
|
||||
case TK_M_DEVLINK:
|
||||
FOREACH_DEVICE_DEVLINK(dev, val)
|
||||
if (token_match_string(event, token, strempty(startswith(val, "/dev/")), /* log_result = */ false) == (token->op == OP_MATCH))
|
||||
return token->op == OP_MATCH;
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
|
||||
case TK_M_NAME:
|
||||
return token_match_string(event, token, event->name, /* log_result = */ true);
|
||||
@@ -2203,8 +2208,8 @@ static int udev_rule_apply_token_to_event(
|
||||
case TK_M_PARENTS_TAG:
|
||||
FOREACH_DEVICE_CURRENT_TAG(dev, val)
|
||||
if (token_match_string(event, token, val, /* log_result = */ false) == (token->op == OP_MATCH))
|
||||
return token->op == OP_MATCH;
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
|
||||
case TK_M_SUBSYSTEM:
|
||||
case TK_M_PARENTS_SUBSYSTEM: {
|
||||
@@ -2243,7 +2248,7 @@ static int udev_rule_apply_token_to_event(
|
||||
|
||||
r = sysctl_read(sysctl_normalize(buf), &value);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_event_error_errno(event, token, r, "Failed to read sysctl '%s': %m", buf);
|
||||
return log_event_error_errno(event, token, r, "Failed to read sysctl \"%s\": %m", buf);
|
||||
|
||||
return token_match_string(event, token, strstrip(value), /* log_result = */ true);
|
||||
}
|
||||
@@ -2270,23 +2275,26 @@ static int udev_rule_apply_token_to_event(
|
||||
assert(!truncated);
|
||||
strscpyl_full(buf, sizeof(buf), &truncated, val, "/", tmp, NULL);
|
||||
if (truncated)
|
||||
return false;
|
||||
return log_event_result(event, token, false);
|
||||
}
|
||||
|
||||
r = attr_subst_subdir(buf);
|
||||
if (r == -ENOENT)
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to test for the existence of '%s': %m", buf);
|
||||
return log_event_error_errno(event, token, r, "Failed to test for the existence of \"%s\": %m", buf);
|
||||
|
||||
if (stat(buf, &statbuf) < 0)
|
||||
return token->op == OP_NOMATCH;
|
||||
if (stat(buf, &statbuf) < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_event_warning_errno(event, token, errno, "Failed to stat \"%s\", ignoring: %m", buf);
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
}
|
||||
|
||||
if (mode == MODE_INVALID)
|
||||
return token->op == OP_MATCH;
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
|
||||
match = (statbuf.st_mode & mode) > 0;
|
||||
return token->op == (match ? OP_MATCH : OP_NOMATCH);
|
||||
return log_event_result(event, token, token->op == (match ? OP_MATCH : OP_NOMATCH));
|
||||
}
|
||||
case TK_M_PROGRAM: {
|
||||
char buf[UDEV_LINE_SIZE], result[UDEV_LINE_SIZE];
|
||||
@@ -2296,7 +2304,7 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "command"))
|
||||
return false;
|
||||
|
||||
log_event_debug(event, token, "Running PROGRAM=\"%s\"", buf);
|
||||
log_event_debug(event, token, "Running command \"%s\"", buf);
|
||||
|
||||
r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof(result), NULL);
|
||||
if (r != 0) {
|
||||
@@ -2304,14 +2312,14 @@ static int udev_rule_apply_token_to_event(
|
||||
log_event_warning_errno(event, token, r, "Failed to execute \"%s\": %m", buf);
|
||||
else /* returned value is positive when program fails */
|
||||
log_event_debug(event, token, "Command \"%s\" returned %d (error)", buf, r);
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
}
|
||||
|
||||
delete_trailing_chars(result, "\n");
|
||||
udev_replace_chars_and_log(event, token, result, UDEV_ALLOWED_CHARS_INPUT, "command output");
|
||||
|
||||
event->program_result = strdup(result);
|
||||
return token->op == OP_MATCH;
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
}
|
||||
case TK_M_IMPORT_FILE: {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
@@ -2320,13 +2328,13 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "file name to be imported"))
|
||||
return false;
|
||||
|
||||
log_event_debug(event, token, "Importing properties from '%s'", buf);
|
||||
log_event_debug(event, token, "Importing properties from \"%s\"", buf);
|
||||
|
||||
f = fopen(buf, "re");
|
||||
if (!f) {
|
||||
if (errno != ENOENT)
|
||||
return log_event_error_errno(event, token, errno, "Failed to open '%s': %m", buf);
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_error_errno(event, token, errno, "Failed to open \"%s\": %m", buf);
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -2335,16 +2343,16 @@ static int udev_rule_apply_token_to_event(
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0) {
|
||||
log_event_debug_errno(event, token, r, "Failed to read '%s', ignoring: %m", buf);
|
||||
return token->op == OP_NOMATCH;
|
||||
log_event_debug_errno(event, token, r, "Failed to read \"%s\", ignoring: %m", buf);
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
|
||||
r = get_property_from_string(line, &key, &value);
|
||||
if (r < 0) {
|
||||
log_event_debug_errno(event, token, r,
|
||||
"Failed to parse key and value from '%s', ignoring: %m",
|
||||
"Failed to parse key and value from \"%s\", ignoring: %m",
|
||||
line);
|
||||
continue;
|
||||
}
|
||||
@@ -2356,9 +2364,10 @@ static int udev_rule_apply_token_to_event(
|
||||
return log_event_error_errno(event, token, r,
|
||||
"Failed to add property %s=%s: %m",
|
||||
key, value);
|
||||
log_event_trace(event, token, "Imported property \"%s=%s\".", key, value);
|
||||
}
|
||||
|
||||
return token->op == OP_MATCH;
|
||||
assert_not_reached();
|
||||
}
|
||||
case TK_M_IMPORT_PROGRAM: {
|
||||
_cleanup_strv_free_ char **lines = NULL;
|
||||
@@ -2368,15 +2377,15 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "command"))
|
||||
return false;
|
||||
|
||||
log_event_debug(event, token, "Importing properties from results of '%s'", buf);
|
||||
log_event_debug(event, token, "Importing properties from results of \"%s\"", buf);
|
||||
|
||||
r = udev_event_spawn(event, /* accept_failure = */ true, buf, result, sizeof result, &truncated);
|
||||
if (r != 0) {
|
||||
if (r < 0)
|
||||
log_event_warning_errno(event, token, r, "Failed to execute '%s', ignoring: %m", buf);
|
||||
log_event_warning_errno(event, token, r, "Failed to execute \"%s\", ignoring: %m", buf);
|
||||
else /* returned value is positive when program fails */
|
||||
log_event_debug(event, token, "Command \"%s\" returned %d (error), ignoring", buf, r);
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
}
|
||||
|
||||
if (truncated) {
|
||||
@@ -2400,7 +2409,7 @@ static int udev_rule_apply_token_to_event(
|
||||
if (r < 0) {
|
||||
log_event_warning_errno(event, token, r,
|
||||
"Failed to extract lines from result of command \"%s\", ignoring: %m", buf);
|
||||
return false;
|
||||
return log_event_result(event, token, false);
|
||||
}
|
||||
|
||||
STRV_FOREACH(line, lines) {
|
||||
@@ -2409,7 +2418,7 @@ static int udev_rule_apply_token_to_event(
|
||||
r = get_property_from_string(*line, &key, &value);
|
||||
if (r < 0) {
|
||||
log_event_debug_errno(event, token, r,
|
||||
"Failed to parse key and value from '%s', ignoring: %m",
|
||||
"Failed to parse key and value from \"%s\", ignoring: %m",
|
||||
*line);
|
||||
continue;
|
||||
}
|
||||
@@ -2421,9 +2430,10 @@ static int udev_rule_apply_token_to_event(
|
||||
return log_event_error_errno(event, token, r,
|
||||
"Failed to add property %s=%s: %m",
|
||||
key, value);
|
||||
log_event_trace(event, token, "Imported property \"%s=%s\".", key, value);
|
||||
}
|
||||
|
||||
return token->op == OP_MATCH;
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
}
|
||||
case TK_M_IMPORT_BUILTIN: {
|
||||
UdevBuiltinCommand cmd = PTR_TO_UDEV_BUILTIN_CMD(token->data);
|
||||
@@ -2434,10 +2444,10 @@ static int udev_rule_apply_token_to_event(
|
||||
if (udev_builtin_run_once(cmd)) {
|
||||
/* check if we ran already */
|
||||
if (event->builtin_run & mask) {
|
||||
log_event_debug(event, token, "Skipping builtin '%s' in IMPORT key",
|
||||
log_event_debug(event, token, "Builtin command \"%s\" has already run, skipping.",
|
||||
udev_builtin_name(cmd));
|
||||
/* return the result from earlier run */
|
||||
return token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH);
|
||||
return log_event_result(event, token, token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH));
|
||||
}
|
||||
/* mark as ran */
|
||||
event->builtin_run |= mask;
|
||||
@@ -2446,34 +2456,36 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "builtin command"))
|
||||
return false;
|
||||
|
||||
log_event_debug(event, token, "Importing properties from results of builtin command '%s'", buf);
|
||||
log_event_debug(event, token, "Importing properties from results of builtin command \"%s\".", buf);
|
||||
|
||||
r = udev_builtin_run(event, cmd, buf);
|
||||
if (r < 0) {
|
||||
/* remember failure */
|
||||
log_event_debug_errno(event, token, r, "Failed to run builtin '%s': %m", buf);
|
||||
log_event_debug_errno(event, token, r, "Failed to run builtin \"%s\": %m", buf);
|
||||
event->builtin_ret |= mask;
|
||||
}
|
||||
return token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH);
|
||||
return log_event_result(event, token, token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH));
|
||||
}
|
||||
case TK_M_IMPORT_DB: {
|
||||
const char *val;
|
||||
|
||||
if (!event->dev_db_clone)
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
r = sd_device_get_property_value(event->dev_db_clone, token->value, &val);
|
||||
if (r == -ENOENT)
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r,
|
||||
"Failed to get property '%s' from database: %m",
|
||||
"Failed to get property \"%s\" from database: %m",
|
||||
token->value);
|
||||
|
||||
r = device_add_property(dev, token->value, val);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m",
|
||||
return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m",
|
||||
token->value, val);
|
||||
return token->op == OP_MATCH;
|
||||
log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val);
|
||||
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
}
|
||||
case TK_M_IMPORT_CMDLINE: {
|
||||
_cleanup_free_ char *value = NULL;
|
||||
@@ -2481,16 +2493,19 @@ static int udev_rule_apply_token_to_event(
|
||||
r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL|PROC_CMDLINE_IGNORE_EFI_OPTIONS, &value);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r,
|
||||
"Failed to read '%s' option from /proc/cmdline: %m",
|
||||
"Failed to read \"%s\" option from /proc/cmdline: %m",
|
||||
token->value);
|
||||
if (r == 0)
|
||||
return token->op == OP_NOMATCH;
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
|
||||
r = device_add_property(dev, token->value, value ?: "1");
|
||||
const char *val = value ?: "1";
|
||||
r = device_add_property(dev, token->value, val);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m",
|
||||
token->value, value ?: "1");
|
||||
return token->op == OP_MATCH;
|
||||
return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m",
|
||||
token->value, val);
|
||||
log_event_trace(event, token, "Imported property \"%s=%s\".", token->value, val);
|
||||
|
||||
return log_event_result(event, token, token->op == OP_MATCH);
|
||||
}
|
||||
case TK_M_IMPORT_PARENT: {
|
||||
char buf[UDEV_PATH_SIZE];
|
||||
@@ -2498,35 +2513,56 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "property name"))
|
||||
return false;
|
||||
|
||||
r = import_parent_into_properties(dev, buf);
|
||||
sd_device *parent;
|
||||
r = sd_device_get_parent(dev, &parent);
|
||||
if (ERRNO_IS_NEG_DEVICE_ABSENT(r))
|
||||
return log_event_result(event, token, token->op == OP_NOMATCH);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r,
|
||||
"Failed to import properties '%s' from parent: %m",
|
||||
buf);
|
||||
return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH);
|
||||
return log_event_error_errno(event, token, r, "Failed to get parent device: %m");
|
||||
|
||||
bool have = false;
|
||||
FOREACH_DEVICE_PROPERTY(parent, key, val) {
|
||||
if (fnmatch(buf, key, 0) != 0)
|
||||
continue;
|
||||
|
||||
r = device_add_property(dev, key, val);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to add property \"%s=%s\": %m", key, val);
|
||||
log_event_trace(event, token, "Imported property \"%s=%s\".", key, val);
|
||||
have = true;
|
||||
}
|
||||
|
||||
return log_event_result(event, token, token->op == (have ? OP_MATCH : OP_NOMATCH));
|
||||
}
|
||||
case TK_M_RESULT:
|
||||
return token_match_string(event, token, event->program_result, /* log_result = */ true);
|
||||
|
||||
case TK_A_OPTIONS_STRING_ESCAPE_NONE:
|
||||
event->esc = ESCAPE_NONE;
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
|
||||
case TK_A_OPTIONS_STRING_ESCAPE_REPLACE:
|
||||
event->esc = ESCAPE_REPLACE;
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
|
||||
case TK_A_OPTIONS_DB_PERSIST:
|
||||
device_set_db_persist(dev);
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
|
||||
case TK_A_OPTIONS_INOTIFY_WATCH:
|
||||
if (event->inotify_watch_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->inotify_watch_final = true;
|
||||
|
||||
event->inotify_watch = token->data;
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
|
||||
case TK_A_OPTIONS_DEVLINK_PRIORITY:
|
||||
device_set_devlink_priority(dev, PTR_TO_INT(token->data));
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
|
||||
case TK_A_OPTIONS_LOG_LEVEL: {
|
||||
int level = PTR_TO_INT(token->data);
|
||||
|
||||
@@ -2548,14 +2584,15 @@ static int udev_rule_apply_token_to_event(
|
||||
event->log_level_was_debug = true;
|
||||
}
|
||||
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
}
|
||||
case TK_A_OWNER: {
|
||||
char owner[UDEV_NAME_SIZE];
|
||||
const char *ow = owner;
|
||||
|
||||
if (event->owner_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->owner_final = true;
|
||||
|
||||
@@ -2563,18 +2600,21 @@ static int udev_rule_apply_token_to_event(
|
||||
return true;
|
||||
|
||||
r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
|
||||
if (r < 0)
|
||||
log_unknown_owner(dev, token->rule_line, r, "user", owner);
|
||||
if (IN_SET(r, -ENOENT, -ESRCH))
|
||||
log_event_error_errno(event, token, r, "Unknown user \"%s\", ignoring.", owner);
|
||||
else if (r < 0)
|
||||
log_event_error_errno(event, token, r, "Failed to resolve user \"%s\", ignoring: %m", owner);
|
||||
else
|
||||
log_event_debug(event, token, "OWNER %s(%u)", owner, event->uid);
|
||||
break;
|
||||
log_event_debug(event, token, "Set owner: %s(%u)", owner, event->uid);
|
||||
return true;
|
||||
}
|
||||
case TK_A_GROUP: {
|
||||
char group[UDEV_NAME_SIZE];
|
||||
const char *gr = group;
|
||||
|
||||
if (event->group_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->group_final = true;
|
||||
|
||||
@@ -2582,17 +2622,20 @@ static int udev_rule_apply_token_to_event(
|
||||
return true;
|
||||
|
||||
r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING);
|
||||
if (r < 0)
|
||||
log_unknown_owner(dev, token->rule_line, r, "group", group);
|
||||
if (IN_SET(r, -ENOENT, -ESRCH))
|
||||
log_event_error_errno(event, token, r, "Unknown group \"%s\", ignoring.", group);
|
||||
else if (r < 0)
|
||||
log_event_error_errno(event, token, r, "Failed to resolve group \"%s\", ignoring: %m", group);
|
||||
else
|
||||
log_event_debug(event, token, "GROUP %s(%u)", group, event->gid);
|
||||
break;
|
||||
log_event_debug(event, token, "Set group: %s(%u)", group, event->gid);
|
||||
return true;
|
||||
}
|
||||
case TK_A_MODE: {
|
||||
char mode_str[UDEV_NAME_SIZE];
|
||||
|
||||
if (event->mode_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->mode_final = true;
|
||||
|
||||
@@ -2601,41 +2644,44 @@ static int udev_rule_apply_token_to_event(
|
||||
|
||||
r = parse_mode(mode_str, &event->mode);
|
||||
if (r < 0)
|
||||
log_event_error_errno(event, token, r, "Failed to parse mode '%s', ignoring: %m", mode_str);
|
||||
log_event_error_errno(event, token, r, "Failed to parse mode \"%s\", ignoring: %m", mode_str);
|
||||
else
|
||||
log_event_debug(event, token, "MODE %#o", event->mode);
|
||||
break;
|
||||
log_event_debug(event, token, "Set mode: %#o", event->mode);
|
||||
return true;
|
||||
}
|
||||
case TK_A_OWNER_ID:
|
||||
if (event->owner_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->owner_final = true;
|
||||
if (!token->data)
|
||||
break;
|
||||
event->uid = PTR_TO_UID(token->data);
|
||||
log_event_debug(event, token, "OWNER %u", event->uid);
|
||||
break;
|
||||
|
||||
event->uid = PTR_TO_UID(ASSERT_PTR(token->data));
|
||||
log_event_debug(event, token, "Set owner ID: %u", event->uid);
|
||||
return true;
|
||||
|
||||
case TK_A_GROUP_ID:
|
||||
if (event->group_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->group_final = true;
|
||||
if (!token->data)
|
||||
break;
|
||||
event->gid = PTR_TO_GID(token->data);
|
||||
log_event_debug(event, token, "GROUP %u", event->gid);
|
||||
break;
|
||||
|
||||
event->gid = PTR_TO_GID(ASSERT_PTR(token->data));
|
||||
log_event_debug(event, token, "Set group ID: %u", event->gid);
|
||||
return true;
|
||||
|
||||
case TK_A_MODE_ID:
|
||||
if (event->mode_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->mode_final = true;
|
||||
if (!token->data)
|
||||
break;
|
||||
event->mode = PTR_TO_MODE(token->data);
|
||||
log_event_debug(event, token, "MODE %#o", event->mode);
|
||||
break;
|
||||
|
||||
event->mode = PTR_TO_MODE(ASSERT_PTR(token->data));
|
||||
log_event_debug(event, token, "Set mode: %#o", event->mode);
|
||||
return true;
|
||||
|
||||
case TK_A_SECLABEL: {
|
||||
_cleanup_free_ char *name = NULL, *label = NULL;
|
||||
char label_str[UDEV_LINE_SIZE] = {};
|
||||
@@ -2661,13 +2707,13 @@ static int udev_rule_apply_token_to_event(
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to store SECLABEL{%s}='%s': %m", name, label);
|
||||
return log_event_error_errno(event, token, r, "Failed to store security label \"%s=%s\": %m", name, label);
|
||||
|
||||
log_event_debug(event, token, "SECLABEL{%s}='%s'", name, label);
|
||||
log_event_debug(event, token, "Set security label: %s=%s", name, label);
|
||||
|
||||
TAKE_PTR(name);
|
||||
TAKE_PTR(label);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case TK_A_ENV: {
|
||||
const char *val, *name = token->data;
|
||||
@@ -2676,11 +2722,13 @@ static int udev_rule_apply_token_to_event(
|
||||
|
||||
if (isempty(token->value)) {
|
||||
if (token->op == OP_ADD)
|
||||
break;
|
||||
return log_event_done(event, token);
|
||||
|
||||
r = device_add_property(dev, name, NULL);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to remove property '%s': %m", name);
|
||||
break;
|
||||
return log_event_error_errno(event, token, r, "Failed to remove property \"%s\": %m", name);
|
||||
log_event_trace(event, token, "Removed property \"%s\".", name);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token->op == OP_ADD &&
|
||||
@@ -2689,9 +2737,9 @@ static int udev_rule_apply_token_to_event(
|
||||
l = strpcpyl_full(&p, l, &truncated, val, " ", NULL);
|
||||
if (truncated) {
|
||||
log_event_warning(event, token,
|
||||
"The buffer for the property '%s' is full, "
|
||||
"refusing to append the new value '%s'.", name, token->value);
|
||||
break;
|
||||
"The buffer for the property is full, refusing to append new property \"%s=%s\".",
|
||||
name, token->value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2703,8 +2751,9 @@ static int udev_rule_apply_token_to_event(
|
||||
|
||||
r = device_add_property(dev, name, value_new);
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to add property '%s=%s': %m", name, value_new);
|
||||
break;
|
||||
return log_event_error_errno(event, token, r, "Failed to set property \"%s=%s\": %m", name, value_new);
|
||||
log_event_trace(event, token, "Set property \"%s=%s\".", name, value_new);
|
||||
return true;
|
||||
}
|
||||
case TK_A_TAG: {
|
||||
char buf[UDEV_PATH_SIZE];
|
||||
@@ -2712,33 +2761,39 @@ static int udev_rule_apply_token_to_event(
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "tag name"))
|
||||
return true;
|
||||
|
||||
if (token->op == OP_REMOVE) {
|
||||
device_remove_tag(dev, buf);
|
||||
log_event_trace(event, token, "Removed tag \"%s\".", buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(IN_SET(token->op, OP_ASSIGN, OP_ADD));
|
||||
|
||||
if (token->op == OP_ASSIGN)
|
||||
device_cleanup_tags(dev);
|
||||
|
||||
if (token->op == OP_REMOVE)
|
||||
device_remove_tag(dev, buf);
|
||||
else {
|
||||
r = device_add_tag(dev, buf, true);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_event_warning_errno(event, token, r, "Failed to add tag '%s', ignoring: %m", buf);
|
||||
}
|
||||
break;
|
||||
r = device_add_tag(dev, buf, /* both = */ true);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_event_warning_errno(event, token, r, "Failed to %s tag \"%s\", ignoring: %m",
|
||||
token->op == OP_ASSIGN ? "set" : "add", buf);
|
||||
else
|
||||
log_event_trace(event, token, "%s tag \"%s\".", token->op == OP_ASSIGN ? "Set" : "Added", buf);
|
||||
return true;
|
||||
}
|
||||
case TK_A_NAME: {
|
||||
char buf[UDEV_PATH_SIZE];
|
||||
|
||||
if (event->name_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->name_final = true;
|
||||
|
||||
if (sd_device_get_ifindex(dev, NULL) < 0) {
|
||||
log_event_error(event, token,
|
||||
"Only network interfaces can be renamed, ignoring NAME=\"%s\".",
|
||||
token->value);
|
||||
break;
|
||||
log_event_warning(event, token, "Only network interfaces can be renamed, ignoring.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!apply_format_value(event, token, buf, sizeof(buf), "network interface name"))
|
||||
@@ -2751,18 +2806,23 @@ static int udev_rule_apply_token_to_event(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_event_debug(event, token, "NAME '%s'", event->name);
|
||||
break;
|
||||
log_event_debug(event, token, "Set network interface name: %s", event->name);
|
||||
return true;
|
||||
}
|
||||
case TK_A_DEVLINK: {
|
||||
char buf[UDEV_PATH_SIZE];
|
||||
|
||||
if (event->devlink_final)
|
||||
break;
|
||||
if (sd_device_get_devnum(dev, NULL) < 0)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (sd_device_get_devnum(dev, NULL) < 0) {
|
||||
log_event_debug(event, token, "Device does not have device node, ignoring to manage device node symlink.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->devlink_final = true;
|
||||
|
||||
if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL))
|
||||
device_cleanup_devlinks(dev);
|
||||
|
||||
@@ -2784,31 +2844,31 @@ static int udev_rule_apply_token_to_event(
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to extract first path in SYMLINK=, ignoring: %m");
|
||||
break;
|
||||
log_warning_errno(r, "Failed to extract first path in device node symlinks, ignoring: %m");
|
||||
return true;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
return true;
|
||||
|
||||
if (token->op == OP_REMOVE) {
|
||||
r = device_remove_devlink(dev, path);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_event_warning_errno(event, token, r, "Failed to remove devlink '%s', ignoring: %m", path);
|
||||
log_event_warning_errno(event, token, r, "Failed to remove device node symlink \"%s\", ignoring: %m", path);
|
||||
else if (r > 0)
|
||||
log_event_debug(event, token, "Dropped SYMLINK '%s'", path);
|
||||
log_event_debug(event, token, "Removed device node symlink \"%s\"", path);
|
||||
} else {
|
||||
r = device_add_devlink(dev, path);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
log_event_warning_errno(event, token, r, "Failed to add devlink '%s', ignoring: %m", path);
|
||||
log_event_warning_errno(event, token, r, "Failed to add device node symlink \"%s\", ignoring: %m", path);
|
||||
else if (r > 0)
|
||||
log_event_debug(event, token, "Added SYMLINK '%s'", path);
|
||||
log_event_debug(event, token, "Added device node symlink \"%s\".", path);
|
||||
}
|
||||
}
|
||||
break;
|
||||
assert_not_reached();
|
||||
}
|
||||
case TK_A_ATTR: {
|
||||
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
|
||||
@@ -2820,34 +2880,36 @@ static int udev_rule_apply_token_to_event(
|
||||
strscpyl_full(buf, sizeof(buf), &truncated, val, "/", key_name, NULL);
|
||||
if (truncated) {
|
||||
log_event_warning(event, token,
|
||||
"The path to the attribute '%s/%s' is too long, refusing to set the attribute.",
|
||||
"The path to the attribute \"%s/%s\" is too long, refusing to set the attribute.",
|
||||
val, key_name);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
r = attr_subst_subdir(buf);
|
||||
if (r < 0) {
|
||||
log_event_error_errno(event, token, r, "Could not find file matches '%s', ignoring: %m", buf);
|
||||
break;
|
||||
log_event_error_errno(event, token, r, "Could not find file matches \"%s\", ignoring: %m", buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!apply_format_value(event, token, value, sizeof(value), "attribute value"))
|
||||
return true;
|
||||
|
||||
if (EVENT_MODE_DESTRUCTIVE(event)) {
|
||||
log_event_debug(event, token, "Writing ATTR{'%s'}=\"%s\".", buf, value);
|
||||
log_event_debug(event, token, "Writing \"%s\" to sysfs attribute \"%s\".", value, buf);
|
||||
r = write_string_file(buf, value,
|
||||
WRITE_STRING_FILE_VERIFY_ON_FAILURE |
|
||||
WRITE_STRING_FILE_DISABLE_BUFFER |
|
||||
WRITE_STRING_FILE_AVOID_NEWLINE |
|
||||
WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE);
|
||||
if (r < 0)
|
||||
log_event_error_errno(event, token, r, "Failed to write ATTR{%s}=\"%s\", ignoring: %m", buf, value);
|
||||
log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysfs attribute \"%s\", ignoring: %m", value, buf);
|
||||
else
|
||||
log_event_done(event, token);
|
||||
} else
|
||||
log_event_debug(event, token, "Running in test mode, skipping writing ATTR{%s}=\"%s\".", buf, value);
|
||||
log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysfs attribute \"%s\".", value, buf);
|
||||
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case TK_A_SYSCTL: {
|
||||
char buf[UDEV_PATH_SIZE], value[UDEV_NAME_SIZE];
|
||||
@@ -2861,14 +2923,16 @@ static int udev_rule_apply_token_to_event(
|
||||
sysctl_normalize(buf);
|
||||
|
||||
if (EVENT_MODE_DESTRUCTIVE(event)) {
|
||||
log_event_debug(event, token, "Writing SYSCTL{%s}=\"%s\".", buf, value);
|
||||
log_event_debug(event, token, "Writing \"%s\" to sysctl entry \"%s\".", value, buf);
|
||||
r = sysctl_write(buf, value);
|
||||
if (r < 0)
|
||||
log_event_error_errno(event, token, r, "Failed to write SYSCTL{%s}=\"%s\", ignoring: %m", buf, value);
|
||||
log_event_error_errno(event, token, r, "Failed to write \"%s\" to sysctl entry \"%s\", ignoring: %m", value, buf);
|
||||
else
|
||||
log_event_done(event, token);
|
||||
} else
|
||||
log_event_debug(event, token, "Running in test mode, skipping writing SYSCTL{%s}=\"%s\".", buf, value);
|
||||
log_event_debug(event, token, "Running in test mode, skipping writing \"%s\" to sysctl entry \"%s\".", value, buf);
|
||||
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case TK_A_RUN_BUILTIN:
|
||||
case TK_A_RUN_PROGRAM: {
|
||||
@@ -2876,7 +2940,8 @@ static int udev_rule_apply_token_to_event(
|
||||
char buf[UDEV_LINE_SIZE];
|
||||
|
||||
if (event->run_final)
|
||||
break;
|
||||
return log_event_final_set(event, token);
|
||||
|
||||
if (token->op == OP_ASSIGN_FINAL)
|
||||
event->run_final = true;
|
||||
|
||||
@@ -2891,24 +2956,22 @@ static int udev_rule_apply_token_to_event(
|
||||
return log_oom();
|
||||
|
||||
r = ordered_hashmap_ensure_put(&event->run_list, NULL, cmd, token->data);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0)
|
||||
return log_event_error_errno(event, token, r, "Failed to store command '%s': %m", cmd);
|
||||
return log_event_error_errno(event, token, r, "Failed to store command \"%s\": %m", cmd);
|
||||
|
||||
log_event_debug(event, token, "Set command: %s", cmd);
|
||||
TAKE_PTR(cmd);
|
||||
|
||||
log_event_debug(event, token, "RUN '%s'", token->value);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case TK_A_OPTIONS_STATIC_NODE:
|
||||
/* do nothing for events. */
|
||||
break;
|
||||
return true;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return true;
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
static int udev_rule_apply_parent_token_to_event(UdevRuleToken *head_token, UdevEvent *event) {
|
||||
|
||||
Reference in New Issue
Block a user