From 6b6e471a325bf149839c5c822b4ae3e66cb1d9a3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 16 Dec 2021 07:47:24 +0900 Subject: [PATCH] udev: do not import property value from truncated line of program result --- src/udev/test-udev-event.c | 2 +- src/udev/udev-event.c | 27 +++++++++++++++++---------- src/udev/udev-event.h | 3 ++- src/udev/udev-rules.c | 16 ++++++++++++++-- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/udev/test-udev-event.c b/src/udev/test-udev-event.c index b1a631dea2f..2e89fa8f0d4 100644 --- a/src/udev/test-udev-event.c +++ b/src/udev/test-udev-event.c @@ -17,7 +17,7 @@ static void test_event_spawn_core(bool with_pidfd, const char *cmd, char result_ assert_se(sd_device_new_from_syspath(&dev, "/sys/class/net/lo") >= 0); assert_se(event = udev_event_new(dev, 0, NULL, LOG_DEBUG)); - assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, BUF_SIZE) == 0); + assert_se(udev_event_spawn(event, 5 * USEC_PER_SEC, SIGKILL, false, cmd, result_buf, BUF_SIZE, NULL) == 0); assert_se(unsetenv("SYSTEMD_PIDFD") >= 0); } diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index eb576508dea..aa7d229816b 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -50,6 +50,7 @@ typedef struct Spawn { char *result; size_t result_size; size_t result_len; + bool truncated; } Spawn; UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl, int log_level) { @@ -569,7 +570,6 @@ int udev_check_format(const char *value, size_t *offset, const char **hint) { static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) { Spawn *spawn = userdata; char buf[4096], *p; - bool full = false; size_t size; ssize_t l; int r; @@ -601,7 +601,7 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd log_device_warning(spawn->device, "Truncating stdout of '%s' up to %zu byte.", spawn->cmd, spawn->result_size); l--; - full = true; + spawn->truncated = true; } p[l] = '\0'; @@ -624,7 +624,7 @@ static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userd fd == spawn->fd_stdout ? "out" : "err", *q); } - if (l == 0 || full) + if (l == 0 || spawn->truncated) return 0; reenable: @@ -763,12 +763,16 @@ static int spawn_wait(Spawn *spawn) { return sd_event_loop(e); } -int udev_event_spawn(UdevEvent *event, - usec_t timeout_usec, - int timeout_signal, - bool accept_failure, - const char *cmd, - char *result, size_t ressize) { +int udev_event_spawn( + UdevEvent *event, + usec_t timeout_usec, + int timeout_signal, + bool accept_failure, + const char *cmd, + char *result, + size_t ressize, + bool *ret_truncated) { + _cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1}; _cleanup_strv_free_ char **argv = NULL; char **envp = NULL; @@ -859,6 +863,9 @@ int udev_event_spawn(UdevEvent *event, if (result) result[spawn.result_len] = '\0'; + if (ret_truncated) + *ret_truncated = spawn.truncated; + return r; /* 0 for success, and positive if the program failed */ } @@ -1133,7 +1140,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s log_device_debug(event->dev, "Running command \"%s\"", command); - r = udev_event_spawn(event, timeout_usec, timeout_signal, false, command, NULL, 0); + r = udev_event_spawn(event, timeout_usec, timeout_signal, false, command, NULL, 0, NULL); if (r < 0) log_device_warning_errno(event->dev, r, "Failed to execute '%s', ignoring: %m", command); else if (r > 0) /* returned value is positive when program fails */ diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h index 823055ddb23..d201fb580a5 100644 --- a/src/udev/udev-event.h +++ b/src/udev/udev-event.h @@ -66,7 +66,8 @@ int udev_event_spawn( bool accept_failure, const char *cmd, char *result, - size_t ressize); + size_t ressize, + bool *ret_truncated); int udev_event_execute_rules( UdevEvent *event, int inotify_fd, diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index b353b5b8106..a610dea0d97 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1740,7 +1740,7 @@ static int udev_rule_apply_token_to_event( log_rule_debug(dev, rules, "Running PROGRAM '%s'", buf); - r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof(result)); + r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof(result), NULL); if (r != 0) { if (r < 0) log_rule_warning_errno(dev, rules, r, "Failed to execute \"%s\": %m", buf); @@ -1826,7 +1826,7 @@ 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, timeout_signal, true, buf, result, sizeof result); + r = udev_event_spawn(event, timeout_usec, timeout_signal, true, buf, result, sizeof result, &truncated); if (r != 0) { if (r < 0) log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf); @@ -1835,6 +1835,18 @@ static int udev_rule_apply_token_to_event( return token->op == OP_NOMATCH; } + if (truncated) { + bool found = false; + + /* Drop the last line. */ + for (char *p = buf + strlen(buf) - 1; p >= buf; p--) + if (strchr(NEWLINE, *p)) { + *p = '\0'; + found = true; + } else if (found) + break; + } + r = strv_split_newlines_full(&lines, result, EXTRACT_RETAIN_ESCAPE); if (r < 0) log_rule_warning_errno(dev, rules, r,