Browse Source

systemd add missing patches

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 4 years ago
parent
commit
8edc77b6ac
  1. 37
      SOURCES/0748-return-error-value-on-failure.patch
  2. 29
      SOURCES/0749-revert-local-changes-made-during-backport-of-the-tes.patch
  3. 73
      SOURCES/0757-core-timer-Prevent-timer-looping-when-unit-cannot-st.patch
  4. 57
      SOURCES/0758-service-relax-PID-file-symlink-chain-checks-a-bit-81.patch
  5. 24
      SOURCES/0759-udev-rules-Add-rule-for-dev-kfd.patch
  6. 39
      SOURCES/0760-core-exclude-.slice-units-from-systemctl-isolate.patch
  7. 30
      SOURCES/0761-udev-scsi_id-fix-incorrect-page-length-when-get-devi.patch
  8. 164
      SOURCES/0762-core-when-determining-whether-a-process-exit-status-.patch
  9. 31
      SOURCES/0763-units-add-Wants-initrd-cleanup.service-to-initrd-swi.patch
  10. 37
      SOURCES/0764-units-make-sure-initrd-cleanup.service-terminates-be.patch
  11. 37
      SOURCES/0765-core-tiny-tweak-for-cgroup-trimming-during-manager_f.patch
  12. 35
      SOURCES/0766-process-an-empty-environment-block-should-be-returne.patch
  13. 59
      SOURCES/0767-core-make-sure-initrd-switch-root-command-survives-P.patch
  14. 34
      SOURCES/0768-systemctl-always-avoid-being-killed-when-doing-switc.patch
  15. 27
      SOURCES/0769-units-drop-KillMode-from-initrd-switch-root.service.patch
  16. 41
      SOURCES/0770-systemctl-ignore-SIGTERM-after-switch-root.patch
  17. 37
      SOURCES/0771-units-restore-Before-dependencies-for-systemd-vconso.patch
  18. 405
      SOURCES/0772-core-reduce-the-number-of-stalled-PIDs-from-the-watc.patch
  19. 78
      SOURCES/0773-timedate-use-gmtime_r-and-localtime_r.patch
  20. 30
      SOURCES/0774-sd-bus-stop-using-the-result-of-an-assignment-as-an-.patch
  21. 65
      SOURCES/0775-journal-upload-add-asserts-that-snprintf-does-not-re.patch
  22. 35
      SOURCES/0776-analyze-actually-select-longest-activated-time-of-se.patch
  23. 30
      SOURCES/0777-pid1-remove-unnecessary-error-reassignment.patch
  24. 28
      SOURCES/0778-core-drop-unnecessary-condition.patch
  25. 26
      SOURCES/0779-import-drop-unnecessary-condition.patch
  26. 31
      SOURCES/0780-journal-verify-add-comment-and-silence-LGTM-warning.patch
  27. 25
      SOURCES/0781-journal-drop-redundant-condition.patch
  28. 28
      SOURCES/0782-lldp-set-correct-state-for-processing.patch
  29. 25
      SOURCES/0783-sd-bus-fix-implicit-downcast-of-bitfield-reported-by.patch
  30. 28
      SOURCES/0784-tree-wide-use-signed-int-instead-of-int-for-bit-fiel.patch
  31. 25
      SOURCES/0785-machinectl-check-correct-FD-for-a-return-value.patch
  32. 37
      SOURCES/0786-shared-install-avoid-overwriting-r-counter-with-a-pa.patch
  33. 30
      SOURCES/0787-systemctl-set_put-can-t-return-EEXIST.patch
  34. 38
      SOURCES/0788-systemctl-remove-dead-check.patch
  35. 75
      SOURCES/0789-journal-gateway-explicitly-declare-local-variables.patch
  36. 36
      SOURCES/0790-journal-gateway-use-localStorage-cursor-only-when-it.patch
  37. 25
      SOURCES/0791-lgtm-ignore-files-dropped-in-upstream.patch
  38. 42
      SOURCES/0792-lgtm-suppress-several-constant-comparisons.patch
  39. 121
      SOURCES/0793-core-add-a-new-unit_needs_console-call.patch
  40. 171
      SOURCES/0794-core-rework-how-we-count-the-n_on_console-counter.patch
  41. 71
      SOURCES/0795-service-introduce-protocol-error-type.patch
  42. 76
      SOURCES/0796-service-fix-main-processes-exit-behavior-for-type-no.patch
  43. 111
      SOURCES/0797-service-go-through-stop_post-on-failure-4770.patch
  44. 44
      SOURCES/0798-Call-getgroups-to-know-size-of-supplementary-groups-.patch
  45. 190
      SOURCES/0799-udev-introduce-CONST-key-name.patch

37
SOURCES/0748-return-error-value-on-failure.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
From e4a25c5d867e6ed832a077c32f3555bcd49ef8a6 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Thu, 4 Jul 2019 15:57:23 +0200
Subject: [PATCH] return error value on failure

Regression from commit c0f32feb77768aa76d8c813471b3484c93bc2651 .

Resolves: #1726785
---
src/core/service.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/core/service.c b/src/core/service.c
index 93e4759171..957c6f37cc 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -750,9 +750,9 @@ static int service_load_pid_file(Service *s, bool may_warn) {
fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL);
if (fd == -EPERM)
- return log_unit_full(UNIT(s)->id, prio, "Permission denied while opening PID file or unsafe symlink chain: %s", s->pid_file);
+ return log_unit_full_errno(UNIT(s)->id, prio, fd, "Permission denied while opening PID file or unsafe symlink chain: %s", s->pid_file);
if (fd < 0)
- return log_unit_full(UNIT(s)->id, prio, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
+ return log_unit_full_errno(UNIT(s)->id, prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
/* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd chase_symlinks() returned us into a proper fd first. */
xsprintf(procfs, "/proc/self/fd/%i", fd);
@@ -762,7 +762,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
r = parse_pid(k, &pid);
if (r < 0)
- return log_unit_full(UNIT(s)->id, prio, "Failed to parse PID from file %s: %m", s->pid_file);
+ return log_unit_full_errno(UNIT(s)->id, prio, r, "Failed to parse PID from file %s: %m", s->pid_file);
if (s->main_pid_known && pid == s->main_pid)
return 0;

29
SOURCES/0749-revert-local-changes-made-during-backport-of-the-tes.patch

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
From 225a458ec4c1bee97d0cee13895977614fd8cc16 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 10 Jul 2019 09:48:51 +0200
Subject: [PATCH] revert local changes made during backport of the test

Related: #1726785
---
test/TEST-20-MAINPIDGAMES/testsuite.sh | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/test/TEST-20-MAINPIDGAMES/testsuite.sh b/test/TEST-20-MAINPIDGAMES/testsuite.sh
index d4ad63865c..8b0b664652 100755
--- a/test/TEST-20-MAINPIDGAMES/testsuite.sh
+++ b/test/TEST-20-MAINPIDGAMES/testsuite.sh
@@ -175,12 +175,10 @@ ExecStart=/dev/shm/mainpid3.sh
EOF
systemctl daemon-reload
-systemctl start mainpidsh3.service
+! systemctl start mainpidsh3.service
# Test that this failed due to timeout, and not some other error
-# test `systemctl_show_value -p Result mainpidsh3.service` = timeout
-# Just check that there is no MainPID => the pid file was ignored
-test `systemctl_show_value -p MainPID mainpidsh3.service` -eq 0
+test `systemctl_show_value -p Result mainpidsh3.service` = timeout
systemd-analyze set-log-level info

73
SOURCES/0757-core-timer-Prevent-timer-looping-when-unit-cannot-st.patch

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
From fe81f6f734ee46a4877df6dda6e31cdc24c00a3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkoutny@suse.com>
Date: Tue, 16 Jan 2018 19:22:46 +0100
Subject: [PATCH] core/timer: Prevent timer looping when unit cannot start

When a unit job finishes early (e.g. when fork(2) fails) triggered unit goes
through states
stopped->failed (or failed->failed),
in case a ExecStart= command fails unit passes through
stopped->starting->failed.

The former transition doesn't result in unit active/inactive timestamp being
updated and timer (OnUnitActiveSec= or OnUnitInactiveSec=) would use an expired
timestamp triggering immediately again (repeatedly).

This patch exploits timer's last trigger timestamp to ensure the timer isn't
triggered more frequently than OnUnitActiveSec=/OnUnitInactiveSec= period.

Steps to reproduce:

0) Create sample units:

cat >~/.config/systemd/user/looper.service <<EOD
[Service]
ExecStart=/usr/bin/sleep 2
EOD

cat >~/.config/systemd/user/looper.timer <<EOD
[Timer]
AccuracySec=5
OnUnitActiveSec=5
EOD

1) systemctl --user daemon-reload

2) systemctl --user start looper.timer
# to have first activation timestamp/sentinel
systemctl --user start looper.service

o Observe the service is being regularly triggered.

3) systemctl set-property user@$UID.service TasksMax=2

o Observe the tight looping as long as the looper.service cannot be started.

Ref: #5969
(cherry picked from commit 204d140c4def364c47d36226e4514a7e077fa196)

Resolves: #1710302
---
src/core/timer.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/src/core/timer.c b/src/core/timer.c
index d32b007c7c..1d4868643a 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -416,6 +416,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
if (base <= 0)
continue;
+ base = MAX(base, t->last_trigger.monotonic);
break;
@@ -428,6 +429,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
if (base <= 0)
continue;
+ base = MAX(base, t->last_trigger.monotonic);
break;

57
SOURCES/0758-service-relax-PID-file-symlink-chain-checks-a-bit-81.patch

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
From ce87ed7b47c61e649a0f9da39d272631b9524740 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 9 Feb 2018 17:05:17 +0100
Subject: [PATCH] service: relax PID file symlink chain checks a bit (#8133)

Let's read the PID file after all if there's a potentially unsafe
symlink chain in place. But if we do, then refuse taking the PID if its
outside of the cgroup.

Fixes: #8085
(cherry picked from commit 73969ab61c39357e6892747e43307fbf07cafbed)

Resolves: #1724420
---
src/core/service.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/core/service.c b/src/core/service.c
index eaa588863f..6b61ccac18 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -736,6 +736,7 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) {
static int service_load_pid_file(Service *s, bool may_warn) {
char procfs[sizeof("/proc/self/fd/") - 1 + DECIMAL_STR_MAX(int)];
+ bool questionable_pid_file = false;
_cleanup_free_ char *k = NULL;
_cleanup_close_ int fd = -1;
int r, prio;
@@ -749,8 +750,13 @@ static int service_load_pid_file(Service *s, bool may_warn) {
prio = may_warn ? LOG_INFO : LOG_DEBUG;
fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL);
- if (fd == -EPERM)
- return log_unit_full_errno(UNIT(s)->id, prio, fd, "Permission denied while opening PID file or unsafe symlink chain: %s", s->pid_file);
+ if (fd == -EPERM) {
+ log_unit_full(UNIT(s)->id, LOG_DEBUG, "Permission denied while opening PID file or potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file);
+
+ questionable_pid_file = true;
+
+ fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN, NULL);
+ }
if (fd < 0)
return log_unit_full_errno(UNIT(s)->id, prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
@@ -773,6 +779,11 @@ static int service_load_pid_file(Service *s, bool may_warn) {
if (r == 0) {
struct stat st;
+ if (questionable_pid_file) {
+ log_unit_error(UNIT(s)->id, "Refusing to accept PID outside of service control group, acquired through unsafe symlink chain: %s", s->pid_file);
+ return -EPERM;
+ }
+
/* Hmm, it's not clear if the new main PID is safe. Let's allow this if the PID file is owned by root */
if (fstat(fd, &st) < 0)

24
SOURCES/0759-udev-rules-Add-rule-for-dev-kfd.patch

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
From 302a74feba2dd946a2f046857b5e9b6a874a2c8b Mon Sep 17 00:00:00 2001
From: Tom Stellard <tstellar@redhat.com>
Date: Tue, 31 Oct 2017 08:56:19 -0700
Subject: [PATCH] udev-rules: Add rule for /dev/kfd

(cherry picked from commit f301622d840ae414e7f56c364fe9b035f3041539)

Resolves: #1659516
---
rules/50-udev-default.rules | 1 +
1 file changed, 1 insertion(+)

diff --git a/rules/50-udev-default.rules b/rules/50-udev-default.rules
index 2bf9c1ec7e..27681c8a8b 100644
--- a/rules/50-udev-default.rules
+++ b/rules/50-udev-default.rules
@@ -31,6 +31,7 @@ SUBSYSTEM=="misc", KERNEL=="agpgart", GROUP="video"
SUBSYSTEM=="graphics", GROUP="video"
SUBSYSTEM=="drm", GROUP="video"
SUBSYSTEM=="dvb", GROUP="video"
+SUBSYSTEM=="kfd", GROUP="video"
SUBSYSTEM=="sound", GROUP="audio", \
OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer"

39
SOURCES/0760-core-exclude-.slice-units-from-systemctl-isolate.patch

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
From 0e6f66ae4853b0e7c99f415b14ecfefb752d51ca Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 18 Feb 2016 22:51:23 +0100
Subject: [PATCH] core: exclude .slice units from "systemctl isolate"

Fixes: #1969
(cherry picked from commit 1b4cd0cf11feb7d41f2eff17f86fa55b31bb6841)

Resolves: #1745199
---
src/core/slice.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/src/core/slice.c b/src/core/slice.c
index 0985a65286..b0769205f6 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -36,6 +36,13 @@ static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = {
[SLICE_ACTIVE] = UNIT_ACTIVE
};
+static void slice_init(Unit *u) {
+ assert(u);
+ assert(u->load_state == UNIT_STUB);
+
+ u->ignore_on_isolate = true;
+}
+
static void slice_set_state(Slice *t, SliceState state) {
SliceState old_state;
assert(t);
@@ -274,6 +281,7 @@ const UnitVTable slice_vtable = {
.no_instances = true,
.can_transient = true,
+ .init = slice_init,
.load = slice_load,
.coldplug = slice_coldplug,

30
SOURCES/0761-udev-scsi_id-fix-incorrect-page-length-when-get-devi.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From 0c25ad023d3864bf55ae7334cbc3da25b9227d18 Mon Sep 17 00:00:00 2001
From: Zhang Xianwei <zhang.xianwei8@zte.com.cn>
Date: Mon, 13 May 2019 18:41:55 +0800
Subject: [PATCH] udev/scsi_id: fix incorrect page length when get device
identification VPD page

The length of device identification VPD page is filled with two bytes,
but scsi_id only gets the low byte. Fix it.

Signed-off-by: Zhang Xianwei <zhang.xianwei8@zte.com.cn>
(cherry picked from commit 1f7b6872dbe8ccae1f3bda9aa6aeb87c9b42e01e)

Resolves: #1635945
---
src/udev/scsi_id/scsi_serial.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/udev/scsi_id/scsi_serial.c b/src/udev/scsi_id/scsi_serial.c
index dcfff1d4ea..06fb4815b6 100644
--- a/src/udev/scsi_id/scsi_serial.c
+++ b/src/udev/scsi_id/scsi_serial.c
@@ -677,7 +677,7 @@ static int do_scsi_page83_inquiry(struct udev *udev,
* Examine each descriptor returned. There is normally only
* one or a small number of descriptors.
*/
- for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) {
+ for (j = 4; j <= ((unsigned)page_83[2] << 8) + (unsigned)page_83[3] + 3; j += page_83[j + 3] + 4) {
retval = check_fill_0x83_id(udev,
dev_scsi, &page_83[j],
&id_search_list[id_ind],

164
SOURCES/0762-core-when-determining-whether-a-process-exit-status-.patch

@ -0,0 +1,164 @@ @@ -0,0 +1,164 @@
From 8c9d6639a22d32734d950db37bfb852a1464c621 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 10 Oct 2016 22:07:30 +0200
Subject: [PATCH] core: when determining whether a process exit status is
clean, consider whether it is a command or a daemon

SIGTERM should be considered a clean exit code for daemons (i.e. long-running
processes, as a daemon without SIGTERM handler may be shut down without issues
via SIGTERM still) while it should not be considered a clean exit code for
commands (i.e. short-running processes).

Let's add two different clean checking modes for this, and use the right one at
the appropriate places.

Fixes: #4275
(cherry picked from commit 1f0958f640b87175cd547c1e69084cfe54a22e9d)

Resolves: #1560417
---
src/core/busname.c | 2 +-
src/core/mount.c | 2 +-
src/core/service.c | 2 +-
src/core/socket.c | 2 +-
src/core/swap.c | 2 +-
src/remount-fs/remount-fs.c | 2 +-
src/shared/exit-status.c | 13 ++++---------
src/shared/exit-status.h | 7 ++++++-
8 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/core/busname.c b/src/core/busname.c
index 97886f1e05..f5553e5418 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -849,7 +849,7 @@ static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) {
n->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = BUSNAME_SUCCESS;
else if (code == CLD_EXITED)
f = BUSNAME_FAILURE_EXIT_CODE;
diff --git a/src/core/mount.c b/src/core/mount.c
index 8a25ebd163..bfbfc10731 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1203,7 +1203,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
m->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = MOUNT_SUCCESS;
else if (code == CLD_EXITED)
f = MOUNT_FAILURE_EXIT_CODE;
diff --git a/src/core/service.c b/src/core/service.c
index 6b61ccac18..f7b859d076 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2632,7 +2632,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
assert(s);
assert(pid >= 0);
- if (UNIT(s)->fragment_path ? is_clean_exit(code, status, &s->success_status) :
+ if (UNIT(s)->fragment_path ? is_clean_exit(code, status, s->type == SERVICE_ONESHOT ? EXIT_CLEAN_COMMAND : EXIT_CLEAN_DAEMON, &s->success_status) :
is_clean_exit_lsb(code, status, &s->success_status))
f = SERVICE_SUCCESS;
else if (code == CLD_EXITED)
diff --git a/src/core/socket.c b/src/core/socket.c
index 8489575de6..1e8ae0a6e5 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2344,7 +2344,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = SOCKET_SUCCESS;
else if (code == CLD_EXITED)
f = SOCKET_FAILURE_EXIT_CODE;
diff --git a/src/core/swap.c b/src/core/swap.c
index 1f69736aa3..757a8d45c5 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -972,7 +972,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = SWAP_SUCCESS;
else if (code == CLD_EXITED)
f = SWAP_FAILURE_EXIT_CODE;
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
index 57b47021e4..db9ae391b8 100644
--- a/src/remount-fs/remount-fs.c
+++ b/src/remount-fs/remount-fs.c
@@ -142,7 +142,7 @@ int main(int argc, char *argv[]) {
s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
if (s) {
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
+ if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) {
if (si.si_code == CLD_EXITED)
log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status);
else
diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c
index 90c83a47a8..ab09550d7a 100644
--- a/src/shared/exit-status.c
+++ b/src/shared/exit-status.c
@@ -180,22 +180,17 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
return NULL;
}
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
if (code == CLD_EXITED)
return status == 0 ||
(success_status &&
set_contains(success_status->status, INT_TO_PTR(status)));
- /* If a daemon does not implement handlers for some of the
- * signals that's not considered an unclean shutdown */
+ /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
if (code == CLD_KILLED)
return
- status == SIGHUP ||
- status == SIGINT ||
- status == SIGTERM ||
- status == SIGPIPE ||
+ (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
(success_status &&
set_contains(success_status->signal, INT_TO_PTR(status)));
@@ -204,7 +199,7 @@ bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
- if (is_clean_exit(code, status, success_status))
+ if (is_clean_exit(code, status, EXIT_CLEAN_DAEMON, success_status))
return true;
return
diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h
index 1d774f25dc..f7953aecb1 100644
--- a/src/shared/exit-status.h
+++ b/src/shared/exit-status.h
@@ -95,7 +95,12 @@ typedef struct ExitStatusSet {
const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) _const_;
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status);
+typedef enum ExitClean {
+ EXIT_CLEAN_DAEMON,
+ EXIT_CLEAN_COMMAND,
+} ExitClean;
+
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status);
bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status);
void exit_status_set_free(ExitStatusSet *x);

31
SOURCES/0763-units-add-Wants-initrd-cleanup.service-to-initrd-swi.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
From 592fde970f4493b202ed0fc035e3f6785a850a55 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 11 Oct 2016 21:36:14 +0900
Subject: [PATCH] units: add Wants=initrd-cleanup.service to
initrd-switch-root.target (#4345)

`systemctl isolate initrd-switch-root.target` called by initrd-cleanup.service
kills initrd-cleanup.service itself. Then, initrd-cleanup.service failed and
system goes to emergency shell.
To prevent this problem, this commit adds `Wants=initrd-cleanup.service` to
initrd-switch-root.target.

fixes: #4343.
(cherry picked from commit a8cb1dc3e0fa81affd01c8ed3df35e4c4520a24e)

Related: #1560417
---
units/initrd-switch-root.target | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/units/initrd-switch-root.target b/units/initrd-switch-root.target
index f34768790b..934d82f667 100644
--- a/units/initrd-switch-root.target
+++ b/units/initrd-switch-root.target
@@ -12,5 +12,5 @@ DefaultDependencies=no
Requires=initrd-switch-root.service
Before=initrd-switch-root.service
AllowIsolate=yes
-Wants=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target systemd-journald.service
+Wants=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target systemd-journald.service initrd-cleanup.service
After=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target emergency.service emergency.target

37
SOURCES/0764-units-make-sure-initrd-cleanup.service-terminates-be.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
From d6f32f9063f5e7bb7864fb6be014a52e6036b111 Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Mon, 28 Jan 2019 12:07:37 +0100
Subject: [PATCH] units: make sure initrd-cleanup.service terminates before
switching to rootfs

A follow-up for commit a8cb1dc3e0fa81aff.

Commit a8cb1dc3e0fa81aff made sure that initrd-cleanup.service won't be stopped
when initrd-switch-root.target is isolated.

However even with this change, it might happen that initrd-cleanup.service
survives the switch to rootfs (since it has no ordering constraints against
initrd-switch-root.target) and is stopped right after when default.target is
isolated. This led to initrd-cleanup.service entering in failed state as it
happens when oneshot services are stopped.

This patch along with a8cb1dc3e0fa81aff should fix issue #4343.

Fixes: #4343
(cherry picked from commit e2c7c94ea35fe7e669afb51bfc2251158b522ea5)

Related: #1560417
---
units/initrd-switch-root.target | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/units/initrd-switch-root.target b/units/initrd-switch-root.target
index 934d82f667..ada5b9e7fd 100644
--- a/units/initrd-switch-root.target
+++ b/units/initrd-switch-root.target
@@ -13,4 +13,4 @@ Requires=initrd-switch-root.service
Before=initrd-switch-root.service
AllowIsolate=yes
Wants=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target systemd-journald.service initrd-cleanup.service
-After=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target emergency.service emergency.target
+After=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target emergency.service emergency.target initrd-cleanup.service

37
SOURCES/0765-core-tiny-tweak-for-cgroup-trimming-during-manager_f.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
From 83c66e1d0c1bc6e7522719250e77fad40a147870 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 9 Oct 2018 15:56:27 +0200
Subject: [PATCH] core: tiny tweak for cgroup trimming during manager_free()

Instead of blacklisting when not to trim the cgroup tree, let's instead
whitelist when to do it, as an excercise of being careful when being
destructive.

This should not change behaviour with exception that during switch roots
we now won't attempt to trim the cgroup tree anymore. Which is more
correct behaviour after all we serialize/deserialize during the
transition and should be needlessly destructive.

(cherry picked from commit 86036b26a1da4d90ca274d37e77c56980ab689fd)

Resolves: #1630378
---
src/core/manager.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/core/manager.c b/src/core/manager.c
index fdbb3c0fd9..afa4d2b8fa 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -998,9 +998,8 @@ Manager* manager_free(Manager *m) {
if (unit_vtable[c]->shutdown)
unit_vtable[c]->shutdown(m);
- /* If we reexecute ourselves, we keep the root cgroup
- * around */
- manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
+ /* Keep the cgroup hierarchy in place except when we know we are going down for good */
+ manager_shutdown_cgroup(m, IN_SET(m->exit_code, MANAGER_EXIT, MANAGER_REBOOT, MANAGER_POWEROFF, MANAGER_HALT, MANAGER_KEXEC));
manager_undo_generators(m);

35
SOURCES/0766-process-an-empty-environment-block-should-be-returne.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
From c145af2a34a47f357711a2ae97c3d71db8df905f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 23 Jul 2015 23:47:54 +0200
Subject: [PATCH] process: an empty environment block should be returned as
such

An empty env block is completely valid, hence return it as such, and
don't turn it into an error.

(cherry picked from commit 03c55bc0b980e2a6aaf6f166a9271ed8ecce2222)

Resolves: #1685648
---
src/shared/util.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/shared/util.c b/src/shared/util.c
index 07de902aaf..82c8e433dd 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -954,7 +954,13 @@ int get_process_environ(pid_t pid, char **env) {
sz += cescape_char(c, outcome + sz);
}
- outcome[sz] = '\0';
+ if (!outcome) {
+ outcome = strdup("");
+ if (!outcome)
+ return -ENOMEM;
+ } else
+ outcome[sz] = '\0';
+
*env = outcome;
outcome = NULL;

59
SOURCES/0767-core-make-sure-initrd-switch-root-command-survives-P.patch

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
From 5e68640c5b25b3b682ca8ce92a4a573e8dfba6ae Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Thu, 24 Nov 2016 18:52:04 +0100
Subject: [PATCH] core: make sure initrd-switch-root command survives PID1's
killing spree (#4730)

This is a different way to implement the fix proposed by commit
a4021390fef27f4136497328f suggested by Lennart Poettering.

In this patch we instruct PID1 to not kill "systemctl switch-root" command
started by initrd-switch-root service using the "argv[0][0]='@'" trick.

See: https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/ for
more details.

We had to backup argv[0] because argv is modified by dispatch_verb().

(cherry picked from commit acc28e2e3037d689d6481e4664925cf31d4d087b)

Related: #1754053
---
src/systemctl/systemctl.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index f31137787a..f84b92ccbe 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -128,6 +128,7 @@ static const char *arg_kill_who = NULL;
static int arg_signal = SIGTERM;
static const char *arg_root = NULL;
static usec_t arg_when = 0;
+static char *argv_cmdline = NULL;
static enum action {
_ACTION_INVALID,
ACTION_SYSTEMCTL,
@@ -5060,6 +5061,13 @@ static int switch_root(sd_bus *bus, char **args) {
init = NULL;
}
+ /* Instruct PID1 to exclude us from its killing spree applied during
+ * the transition from the initrd to the main system otherwise we would
+ * exit with a failure status even though the switch to the new root
+ * has succeed. */
+ if (in_initrd())
+ argv_cmdline[0] = '@';
+
log_debug("Switching root - root: %s; init: %s", root, strna(init));
r = sd_bus_call_method(
@@ -7626,6 +7634,8 @@ int main(int argc, char*argv[]) {
_cleanup_bus_close_unref_ sd_bus *bus = NULL;
int r;
+ argv_cmdline = argv[0];
+
setlocale(LC_ALL, "");
log_parse_environment();
log_open();

34
SOURCES/0768-systemctl-always-avoid-being-killed-when-doing-switc.patch

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
From 1be885f0e0f7023d1adc09fb0b247935c1a0b3bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sat, 28 Jan 2017 21:18:31 -0500
Subject: [PATCH] systemctl: always avoid being killed when doing switch-root

The same logic as described in acc28e2e3037d689d6481e applies to any time we are
switching root, to just set the flag unconditionally.

(cherry picked from commit b3ad0ff48c154ed056a6bded2adac609395a9439)

Related: #1754053
---
src/systemctl/systemctl.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index f84b92ccbe..0928e2972a 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5062,11 +5062,9 @@ static int switch_root(sd_bus *bus, char **args) {
}
/* Instruct PID1 to exclude us from its killing spree applied during
- * the transition from the initrd to the main system otherwise we would
- * exit with a failure status even though the switch to the new root
- * has succeed. */
- if (in_initrd())
- argv_cmdline[0] = '@';
+ * the transition. Otherwise we would exit with a failure status even
+ * though the switch to the new root has succeed. */
+ argv_cmdline[0] = '@';
log_debug("Switching root - root: %s; init: %s", root, strna(init));

27
SOURCES/0769-units-drop-KillMode-from-initrd-switch-root.service.patch

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
From 7872e75d4be31e6ba295c8360e801fd133ee6d76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sun, 29 Jan 2017 12:45:51 -0500
Subject: [PATCH] units: drop KillMode= from initrd-switch-root.service

The service already has DefaultDeps disabled, so systemd should not try to stop
it. And if it *does* get stopped, we don't want the zombie process around.
KillMode=none does not change anything in the killall() phase, and we already
use argv[0][0] = '@' to protect against that anyway. KillMode=none should not
be useful in normal operation, so let's leave it out.

(cherry picked from commit 0af9a194ca0243fcb206499116e28612f571bd91)

Related: #1754053
---
units/initrd-switch-root.service.in | 1 -
1 file changed, 1 deletion(-)

diff --git a/units/initrd-switch-root.service.in b/units/initrd-switch-root.service.in
index 82893dafb1..d8e35c79fe 100644
--- a/units/initrd-switch-root.service.in
+++ b/units/initrd-switch-root.service.in
@@ -17,4 +17,3 @@ AllowIsolate=yes
Type=oneshot
# we have to use "--force" here, otherwise systemd would umount /run
ExecStart=@rootbindir@/systemctl --no-block --force switch-root /sysroot
-KillMode=none

41
SOURCES/0770-systemctl-ignore-SIGTERM-after-switch-root.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
From 928f72e2070685886c0266891a74ca266587755a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 30 Jan 2017 13:06:10 -0500
Subject: [PATCH] systemctl: ignore SIGTERM after switch root

https://bugzilla.redhat.com/show_bug.cgi?id=1414904#c14 and #c15.
(cherry picked from commit 8a7a9ceab204fb02fd5d93a765b36b31efeb9beb)

Resolves: #1754053
---
src/systemctl/systemctl.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 0928e2972a..398727cc7d 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5066,6 +5066,14 @@ static int switch_root(sd_bus *bus, char **args) {
* though the switch to the new root has succeed. */
argv_cmdline[0] = '@';
+ /* If we are slow to exit after the root switch, the new systemd instance
+ * will send us a signal to terminate. Just ignore it and exit normally.
+ * This way the unit does not end up as failed.
+ */
+ r = ignore_signals(SIGTERM, -1);
+ if (r < 0)
+ log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m");
+
log_debug("Switching root - root: %s; init: %s", root, strna(init));
r = sd_bus_call_method(
@@ -5078,6 +5086,8 @@ static int switch_root(sd_bus *bus, char **args) {
NULL,
"ss", root, init);
if (r < 0) {
+ (void) default_signals(SIGTERM, -1);
+
log_error("Failed to switch root: %s", bus_error_message(&error, r));
return r;
}

37
SOURCES/0771-units-restore-Before-dependencies-for-systemd-vconso.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
From 9335b508002f0d10c64011a90d81b515b53f0ac3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 31 Jan 2017 00:34:33 -0500
Subject: [PATCH] units: restore Before dependencies for
systemd-vconsole-setup.service

When the service is run in the initramfs, it is possible for it to get started
and not be fast enough to exit before the root switch happens. It is started
multiple times (depending on the consoles being detected), and runs
asynchronously, so this is quite likely. It'll then get killed by killall(),
and systemd will consider the service failed. To avoid all this, just wait
for the service to terminate on it's own.

Before=initrd-switch-root.target should be good for the initramfs, and
Before=shutdown.tuarget should be good for the real system, although it's
unlikely to make any difference there.

(cherry picked from commit 750e550eba362096d56a35104c6a32631aa67b8e)

Related: #1754053
---
units/systemd-vconsole-setup.service.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in
index 18faa63f28..8aba67b393 100644
--- a/units/systemd-vconsole-setup.service.in
+++ b/units/systemd-vconsole-setup.service.in
@@ -11,7 +11,7 @@ Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service
-Before=sysinit.target shutdown.target
+Before=sysinit.target initrd-switch-root.target shutdown.target
ConditionPathExists=/dev/tty0
[Service]

405
SOURCES/0772-core-reduce-the-number-of-stalled-PIDs-from-the-watc.patch

@ -0,0 +1,405 @@ @@ -0,0 +1,405 @@
From 7aff4320eab8b12b19a8800a13f6573c0cdda946 Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Mon, 18 Mar 2019 20:59:36 +0100
Subject: [PATCH] core: reduce the number of stalled PIDs from the watched
processes list when possible

Some PIDs can remain in the watched list even though their processes have
exited since a long time. It can easily happen if the main process of a forking
service manages to spawn a child before the control process exits for example.

However when a pid is about to be mapped to a unit by calling unit_watch_pid(),
the caller usually knows if the pid should belong to this unit exclusively: if
we just forked() off a child, then we can be sure that its PID is otherwise
unused. In this case we take this opportunity to remove any stalled PIDs from
the watched process list.

If we learnt about a PID in any other form (for example via PID file, via
searching, MAINPID= and so on), then we can't assume anything.

(cherry picked from commit f75f613d259e9332be8e9657fa37e73f7aabcb8a)

Resolves: #1501796
---
src/core/busname.c | 4 ++--
src/core/cgroup.c | 8 +++-----
src/core/dbus-scope.c | 2 +-
src/core/mount.c | 4 ++--
src/core/service.c | 24 ++++++++++--------------
src/core/socket.c | 6 +++---
src/core/swap.c | 4 ++--
src/core/unit.c | 25 ++++++++++++++++++++++---
src/core/unit.h | 2 +-
src/shared/util.c | 14 ++++++++++++++
src/shared/util.h | 1 +
11 files changed, 61 insertions(+), 33 deletions(-)

diff --git a/src/core/busname.c b/src/core/busname.c
index f5553e5418..8d149aae4e 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -350,7 +350,7 @@ static int busname_coldplug(Unit *u, Hashmap *deferred_work) {
if (n->control_pid <= 0)
return -EBADMSG;
- r = unit_watch_pid(UNIT(n), n->control_pid);
+ r = unit_watch_pid(UNIT(n), n->control_pid, false);
if (r < 0)
return r;
@@ -413,7 +413,7 @@ static int busname_make_starter(BusName *n, pid_t *_pid) {
_exit(ret);
}
- r = unit_watch_pid(UNIT(n), pid);
+ r = unit_watch_pid(UNIT(n), pid, true);
if (r < 0)
goto fail;
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 0779fa5552..0ce265dbf4 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -26,6 +26,7 @@
#include "special.h"
#include "cgroup-util.h"
#include "cgroup.h"
+#include "util.h"
#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
@@ -881,7 +882,7 @@ void unit_destroy_cgroup_if_empty(Unit *u) {
pid_t unit_search_main_pid(Unit *u) {
_cleanup_fclose_ FILE *f = NULL;
- pid_t pid = 0, npid, mypid;
+ pid_t pid = 0, npid;
assert(u);
@@ -891,15 +892,12 @@ pid_t unit_search_main_pid(Unit *u) {
if (cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f) < 0)
return 0;
- mypid = getpid();
while (cg_read_pid(f, &npid) > 0) {
- pid_t ppid;
-
if (npid == pid)
continue;
/* Ignore processes that aren't our kids */
- if (get_parent_of_pid(npid, &ppid) >= 0 && ppid != mypid)
+ if (pid_is_my_child(npid) == 0)
continue;
if (pid != 0) {
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index 60215a1935..f31360ad56 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -93,7 +93,7 @@ static int bus_scope_set_transient_property(
return -EINVAL;
if (mode != UNIT_CHECK) {
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, false);
if (r < 0 && r != -EEXIST)
return r;
}
diff --git a/src/core/mount.c b/src/core/mount.c
index bfbfc10731..3167bd6bb1 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -659,7 +659,7 @@ static int mount_coldplug(Unit *u, Hashmap *deferred_work) {
if (m->control_pid <= 0)
return -EBADMSG;
- r = unit_watch_pid(UNIT(m), m->control_pid);
+ r = unit_watch_pid(UNIT(m), m->control_pid, false);
if (r < 0)
return r;
@@ -751,7 +751,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
if (r < 0)
goto fail;
- r = unit_watch_pid(UNIT(m), pid);
+ r = unit_watch_pid(UNIT(m), pid, true);
if (r < 0)
/* FIXME: we need to do something here */
goto fail;
diff --git a/src/core/service.c b/src/core/service.c
index f7b859d076..1ad154e41f 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -145,8 +145,6 @@ static void service_unwatch_pid_file(Service *s) {
}
static int service_set_main_pid(Service *s, pid_t pid) {
- pid_t ppid;
-
assert(s);
if (pid <= 1)
@@ -165,12 +163,10 @@ static int service_set_main_pid(Service *s, pid_t pid) {
s->main_pid = pid;
s->main_pid_known = true;
+ s->main_pid_alien = pid_is_my_child(pid) == 0;
- if (get_parent_of_pid(pid, &ppid) >= 0 && ppid != getpid()) {
+ if (s->main_pid_alien)
log_unit_warning(UNIT(s)->id, "%s: Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", UNIT(s)->id, pid);
- s->main_pid_alien = true;
- } else
- s->main_pid_alien = false;
return 0;
}
@@ -809,7 +805,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
if (r < 0)
return r;
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, false);
if (r < 0) {
/* FIXME: we need to do something here */
log_unit_warning(UNIT(s)->id, "Failed to watch PID "PID_FMT" from service %s", pid, UNIT(s)->id);
@@ -844,7 +840,7 @@ static int service_search_main_pid(Service *s) {
if (r < 0)
return r;
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, false);
if (r < 0) {
/* FIXME: we need to do something here */
log_unit_warning(UNIT(s)->id, "Failed to watch PID "PID_FMT" from service %s", pid, UNIT(s)->id);
@@ -989,7 +985,7 @@ static int service_coldplug(Unit *u, Hashmap *deferred_work) {
SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
SERVICE_STOP_SIGABRT, SERVICE_STOP_POST,
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
- r = unit_watch_pid(UNIT(s), s->main_pid);
+ r = unit_watch_pid(UNIT(s), s->main_pid, false);
if (r < 0)
return r;
}
@@ -1001,7 +997,7 @@ static int service_coldplug(Unit *u, Hashmap *deferred_work) {
SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
SERVICE_STOP_SIGABRT, SERVICE_STOP_POST,
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
- r = unit_watch_pid(UNIT(s), s->control_pid);
+ r = unit_watch_pid(UNIT(s), s->control_pid, false);
if (r < 0)
return r;
}
@@ -1271,7 +1267,7 @@ static int service_spawn(
if (r < 0)
goto fail;
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, true);
if (r < 0)
/* FIXME: we need to do something here */
goto fail;
@@ -2325,7 +2321,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
log_unit_debug(u->id, "Failed to parse main-pid value %s", value);
else {
service_set_main_pid(s, pid);
- unit_watch_pid(UNIT(s), pid);
+ unit_watch_pid(UNIT(s), pid, false);
}
} else if (streq(key, "main-pid-known")) {
int b;
@@ -3085,7 +3081,7 @@ static void service_notify_message(
}
if (r > 0) {
service_set_main_pid(s, new_main_pid);
- unit_watch_pid(UNIT(s), new_main_pid);
+ unit_watch_pid(UNIT(s), new_main_pid, false);
notify_dbus = true;
}
}
@@ -3265,7 +3261,7 @@ static void service_bus_name_owner_change(
log_unit_debug(u->id, "%s's D-Bus name %s is now owned by process %u", u->id, name, (unsigned) pid);
service_set_main_pid(s, pid);
- unit_watch_pid(UNIT(s), pid);
+ unit_watch_pid(UNIT(s), pid, false);
}
}
}
diff --git a/src/core/socket.c b/src/core/socket.c
index 1e8ae0a6e5..a5f610cd77 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -1350,7 +1350,7 @@ static int socket_coldplug(Unit *u, Hashmap *deferred_work) {
if (s->control_pid <= 0)
return -EBADMSG;
- r = unit_watch_pid(UNIT(s), s->control_pid);
+ r = unit_watch_pid(UNIT(s), s->control_pid, false);
if (r < 0)
return r;
@@ -1427,7 +1427,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
if (r < 0)
goto fail;
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, true);
if (r < 0)
/* FIXME: we need to do something here */
goto fail;
@@ -1512,7 +1512,7 @@ static int socket_chown(Socket *s, pid_t *_pid) {
_exit(ret);
}
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, true);
if (r < 0)
goto fail;
diff --git a/src/core/swap.c b/src/core/swap.c
index 757a8d45c5..4a5e882332 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -548,7 +548,7 @@ static int swap_coldplug(Unit *u, Hashmap *deferred_work) {
if (s->control_pid <= 0)
return -EBADMSG;
- r = unit_watch_pid(UNIT(s), s->control_pid);
+ r = unit_watch_pid(UNIT(s), s->control_pid, false);
if (r < 0)
return r;
@@ -645,7 +645,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
if (r < 0)
goto fail;
- r = unit_watch_pid(UNIT(s), pid);
+ r = unit_watch_pid(UNIT(s), pid, true);
if (r < 0)
/* FIXME: we need to do something here */
goto fail;
diff --git a/src/core/unit.c b/src/core/unit.c
index def36a0930..cdac192eb6 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -52,6 +52,7 @@
#include "execute.h"
#include "virt.h"
#include "dropin.h"
+#include "util.h"
const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
[UNIT_SERVICE] = &service_vtable,
@@ -1961,7 +1962,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
unit_add_to_gc_queue(u);
}
-int unit_watch_pid(Unit *u, pid_t pid) {
+int unit_watch_pid(Unit *u, pid_t pid, bool exclusive) {
int q, r;
assert(u);
@@ -1970,6 +1971,15 @@ int unit_watch_pid(Unit *u, pid_t pid) {
/* Watch a specific PID. We only support one or two units
* watching each PID for now, not more. */
+ /* Caller might be sure that this PID belongs to this unit only. Let's take this
+ * opportunity to remove any stalled references to this PID as they can be created
+ * easily (when watching a process which is not our direct child). */
+ if (exclusive) {
+ log_unit_debug(u->id, "Cleaning "PID_FMT" from watches.", pid);
+ hashmap_remove2(u->manager->watch_pids1, LONG_TO_PTR(pid), NULL);
+ hashmap_remove2(u->manager->watch_pids2, LONG_TO_PTR(pid), NULL);
+ }
+
r = set_ensure_allocated(&u->pids, NULL);
if (r < 0)
return r;
@@ -1985,7 +1995,12 @@ int unit_watch_pid(Unit *u, pid_t pid) {
return r;
r = hashmap_put(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
- }
+ if (r >= 0)
+ log_unit_debug(u->id, "Watching "PID_FMT" through watch_pids2.", pid);
+ else if (r == -EEXIST)
+ log_unit_warning(u->id, "Cannot watch "PID_FMT", PID is already watched twice.", pid);
+ } else if (r >= 0)
+ log_unit_debug(u->id, "Watching "PID_FMT" through watch_pids1.", pid);
q = set_put(u->pids, LONG_TO_PTR(pid));
if (q < 0)
@@ -1998,6 +2013,8 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
assert(u);
assert(pid >= 1);
+ log_unit_debug(u->id, "Unwatching "PID_FMT".", pid);
+
hashmap_remove_value(u->manager->watch_pids1, LONG_TO_PTR(pid), u);
hashmap_remove_value(u->manager->watch_pids2, LONG_TO_PTR(pid), u);
set_remove(u->pids, LONG_TO_PTR(pid));
@@ -2028,7 +2045,9 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) {
pid_t pid;
while ((r = cg_read_pid(f, &pid)) > 0) {
- r = unit_watch_pid(u, pid);
+ if (pid_is_my_child(pid) == 0)
+ log_unit_debug(u->id, "Watching non detached "PID_FMT".", pid);
+ r = unit_watch_pid(u, pid, false);
if (r < 0 && ret >= 0)
ret = r;
}
diff --git a/src/core/unit.h b/src/core/unit.h
index a6e21d60ce..4a8bd79052 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -537,7 +537,7 @@ int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t cont
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
-int unit_watch_pid(Unit *u, pid_t pid);
+int unit_watch_pid(Unit *u, pid_t pid, bool exclusive);
void unit_unwatch_pid(Unit *u, pid_t pid);
int unit_watch_all_pids(Unit *u);
void unit_unwatch_all_pids(Unit *u);
diff --git a/src/shared/util.c b/src/shared/util.c
index 82c8e433dd..127a64c3c6 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -641,6 +641,20 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
return 0;
}
+int pid_is_my_child(pid_t pid) {
+ pid_t ppid;
+ int r;
+
+ if (pid <= 1)
+ return false;
+
+ r = get_parent_of_pid(pid, &ppid);
+ if (r < 0)
+ return r;
+
+ return ppid == getpid();
+}
+
int fchmod_umask(int fd, mode_t m) {
mode_t u;
int r;
diff --git a/src/shared/util.h b/src/shared/util.h
index 538ca4be2d..6b885d7533 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -279,6 +279,7 @@ const char* split(const char **state, size_t *l, const char *separator, bool quo
for ((state) = (s), (word) = split(&(state), &(length), (separator), (quoted)); (word); (word) = split(&(state), &(length), (separator), (quoted)))
pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
+int pid_is_my_child(pid_t pid);
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);

78
SOURCES/0773-timedate-use-gmtime_r-and-localtime_r.patch

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
From 52df8972d4005b23f7c2e52b0cf7210b8c594876 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 25 Jun 2018 14:29:25 +0200
Subject: [PATCH] timedate: use gmtime_r() and localtime_r()

gmtime() and localtime() operate on a static buffer. let's avoid this,
as we never know whether some library might use these calls in some
backrgound thread.

Discovered by lgtm:

https://lgtm.com/projects/g/systemd/systemd/
(cherry picked from commit e46acb7950a9f07ac60d772309de842c444ad2bd)

Resolves: #1694605
---
src/timedate/timedated.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c
index 09d0dbabcd..afd54a8936 100644
--- a/src/timedate/timedated.c
+++ b/src/timedate/timedated.c
@@ -542,9 +542,9 @@ static int method_set_local_rtc(sd_bus *bus, sd_bus_message *m, void *userdata,
* initialize the timezone fields of
* struct tm. */
if (c->local_rtc)
- tm = *localtime(&ts.tv_sec);
+ localtime_r(&ts.tv_sec, &tm);
else
- tm = *gmtime(&ts.tv_sec);
+ gmtime_r(&ts.tv_sec, &tm);
/* Override the main fields of
* struct tm, but not the timezone
@@ -562,15 +562,15 @@ static int method_set_local_rtc(sd_bus *bus, sd_bus_message *m, void *userdata,
}
} else {
- struct tm *tm;
+ struct tm tm;
/* Sync RTC from system clock */
if (c->local_rtc)
- tm = localtime(&ts.tv_sec);
+ localtime_r(&ts.tv_sec, &tm);
else
- tm = gmtime(&ts.tv_sec);
+ gmtime_r(&ts.tv_sec, &tm);
- clock_set_hwclock(tm);
+ clock_set_hwclock(&tm);
}
log_info("RTC configured to %s time.", c->local_rtc ? "local" : "UTC");
@@ -585,7 +585,7 @@ static int method_set_time(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bu
Context *c = userdata;
int64_t utc;
struct timespec ts;
- struct tm* tm;
+ struct tm tm;
int r;
assert(bus);
@@ -633,10 +633,10 @@ static int method_set_time(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bu
/* Sync down to RTC */
if (c->local_rtc)
- tm = localtime(&ts.tv_sec);
+ localtime_r(&ts.tv_sec, &tm);
else
- tm = gmtime(&ts.tv_sec);
- clock_set_hwclock(tm);
+ gmtime_r(&ts.tv_sec, &tm);
+ clock_set_hwclock(&tm);
log_struct(LOG_INFO,
LOG_MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),

30
SOURCES/0774-sd-bus-stop-using-the-result-of-an-assignment-as-an-.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From b6f311503a6d8cbca75d1579045ec4bff2d2459a Mon Sep 17 00:00:00 2001
From: Evegeny Vereshchagin <evvers@ya.ru>
Date: Tue, 26 Jun 2018 02:32:44 +0000
Subject: [PATCH] sd-bus: stop using the result of an assignment as an operand
of &&

This makes OBJECT_PATH_FOREACH_PREFIX consistent with PATH_FOREACH_PREFIX
and also fixes 7 alerts reported by LGTM at
https://lgtm.com/projects/g/systemd/systemd/snapshot/ac0a08700344a5690803df8dd80e8bb5013184a5/files/src/libsystemd/sd-bus/bus-objects.c?sort=name&dir=ASC&mode=heatmap&showExcluded=true#V1383

(cherry picked from commit 283c2653877f2b958045ad99493869fe1a88be95)

Resolves: #1694605
---
src/libsystemd/sd-bus/bus-internal.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 1c5fbeac2a..33a5569146 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -378,7 +378,7 @@ char *bus_address_escape(const char *v);
#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \
for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \
- _slash && !(_slash[(_slash) == (prefix)] = 0); \
+ _slash && ((_slash[(_slash) == (prefix)] = 0), true); \
_slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/'))
/* If we are invoking callbacks of a bus object, ensure unreffing the

65
SOURCES/0775-journal-upload-add-asserts-that-snprintf-does-not-re.patch

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
From c394463688c332199a8fcabe6f84818b57c730b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 2 Oct 2018 12:46:31 +0200
Subject: [PATCH] journal-upload: add asserts that snprintf does not return an
error

LGMT complains:
> The size argument of this snprintf call is derived from its return value,
> which may exceed the size of the buffer and overflow.

Let's make sure that r is non-negative. (This shouldn't occur unless the format
string is borked, so let's just add an assert.)
Then, let's reorder the comparison to avoid the potential overflow.

(cherry picked from commit 91db8ed5b2e67abf738381a6ed6a05a8271498cd)

Resolves: #1694605
---
src/journal-remote/journal-upload-journal.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c
index 5fd639a76a..c244a76932 100644
--- a/src/journal-remote/journal-upload-journal.c
+++ b/src/journal-remote/journal-upload-journal.c
@@ -30,7 +30,8 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
r = snprintf(buf + pos, size - pos,
"__CURSOR=%s\n", u->current_cursor);
- if (pos + r > size)
+ assert(r >= 0);
+ if ((size_t) r > size - pos)
/* not enough space */
return pos;
@@ -54,7 +55,8 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
r = snprintf(buf + pos, size - pos,
"__REALTIME_TIMESTAMP="USEC_FMT"\n", realtime);
- if (r + pos > size)
+ assert(r >= 0);
+ if ((size_t) r > size - pos)
/* not enough space */
return pos;
@@ -79,7 +81,8 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
r = snprintf(buf + pos, size - pos,
"__MONOTONIC_TIMESTAMP="USEC_FMT"\n", monotonic);
- if (r + pos > size)
+ assert(r >= 0);
+ if ((size_t) r > size - pos)
/* not enough space */
return pos;
@@ -104,7 +107,8 @@ static ssize_t write_entry(char *buf, size_t size, Uploader *u) {
r = snprintf(buf + pos, size - pos,
"_BOOT_ID=%s\n", sd_id128_to_string(boot_id, sid));
- if (r + pos > size)
+ assert(r >= 0);
+ if ((size_t) r > size - pos)
/* not enough space */
return pos;

35
SOURCES/0776-analyze-actually-select-longest-activated-time-of-se.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
From 91b866591a2fb05a087a040a49a792a3d40a2a06 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 27 Jun 2018 13:32:05 +0900
Subject: [PATCH] analyze: actually select longest activated-time of services

Discovered by LGTM.

(cherry picked from commit e68131526b7a2cfdb8e59bd2ed7a284dba095ac5)

Resolves: #1694605
---
src/analyze/analyze.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 7116aaa88d..e9ca9ba818 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -788,14 +788,11 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned int lev
if (times
&& times->activated
&& times->activated <= boot->finish_time
- && (times->activated >= service_longest
- || service_longest == 0)) {
+ && times->activated >= service_longest)
service_longest = times->activated;
- break;
- }
}
- if (service_longest == 0 )
+ if (service_longest == 0)
return r;
STRV_FOREACH(c, deps) {

30
SOURCES/0777-pid1-remove-unnecessary-error-reassignment.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From f1851da2600d24191d90cfa2474574821c240969 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Wed, 27 Feb 2019 18:11:44 +0100
Subject: [PATCH] pid1: remove unnecessary error reassignment

r is always >= 0 so let's drop the unnecessary condition
to make LGTM happy

Based on commit 7c3733d5defb5428ddfeefae6d80fcbcc253e7ef

Resolves: #1694605
---
src/core/manager.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/core/manager.c b/src/core/manager.c
index afa4d2b8fa..88d156e8fb 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -2805,9 +2805,7 @@ int manager_reload(Manager *m) {
lookup_paths_free(&m->lookup_paths);
/* Find new unit paths */
- q = manager_run_generators(m);
- if (q < 0 && r >= 0)
- r = q;
+ r = manager_run_generators(m);
q = lookup_paths_init(
&m->lookup_paths, m->running_as, true,

28
SOURCES/0778-core-drop-unnecessary-condition.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
From 443a7bc554b65f9b859db60474439c03b19c79c1 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Wed, 27 Feb 2019 18:35:15 +0100
Subject: [PATCH] core: drop unnecessary condition

In this case ret is always >= 0 as it still contains the initialization
value (i.e. 0). Let's drop the unnecessary condition to make LGTM happy.

Relevant commit: efdb02375beb0a940c3320865572913780b4d7de

Resolves: #1694605
---
src/core/unit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/unit.c b/src/core/unit.c
index cdac192eb6..4069a6f4c4 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2054,7 +2054,7 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) {
if (r < 0 && ret >= 0)
ret = r;
- } else if (ret >= 0)
+ } else
ret = r;
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);

26
SOURCES/0779-import-drop-unnecessary-condition.patch

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
From 8606f4b13ba677efad8bb6aae2d61c98e23a75f2 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Wed, 27 Feb 2019 18:53:19 +0100
Subject: [PATCH] import: drop unnecessary condition

Relevant commit: d61b34f1b22d1d7a641a1652ff23113d3e87ace7

Resolves: #1694605
---
src/import/import-common.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/import/import-common.c b/src/import/import-common.c
index 243e657c56..713a218c67 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -455,8 +455,7 @@ int import_verify(
}
finish:
- if (sig_file >= 0)
- unlink(sig_file_path);
+ (void) unlink(sig_file_path);
if (gpg_home_created)
rm_rf_dangerous(gpg_home, false, true, false);

31
SOURCES/0780-journal-verify-add-comment-and-silence-LGTM-warning.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
From d58e871a424fedf286747816e9525fc2287bb72d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 2 Oct 2018 12:26:23 +0200
Subject: [PATCH] journal-verify: add comment and silence LGTM warning

(cherry picked from commit 0a587335d2a16a48479b10969491a7353d78c25b)

Resolves: #1694605
---
src/journal/journal-verify.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 250d4c7586..7c6d8ab780 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -70,10 +70,11 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
}
static uint64_t scale_progress(uint64_t scale, uint64_t p, uint64_t m) {
+ /* Calculates scale * p / m, but handles m == 0 safely, and saturates.
+ * Currently all callers use m >= 1, but we keep the check to be defensive.
+ */
- /* Calculates scale * p / m, but handles m == 0 safely, and saturates */
-
- if (p >= m || m == 0)
+ if (p >= m || m == 0) // lgtm[cpp/constant-comparison]
return scale;
return scale * p / m;

25
SOURCES/0781-journal-drop-redundant-condition.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
From 5f71ed0c948653fd9037d751f48182cb0c5dfb99 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Wed, 27 Feb 2019 19:01:20 +0100
Subject: [PATCH] journal: drop redundant condition

Relevant commit: 29bfb683a8c9d03f10db58b4e61351fd9048f270

Resolves: #1694605
---
src/journal/journald-server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 2e1e07eb0e..aaabb2f7ab 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -345,7 +345,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
if (r >= 0) {
server_fix_perms(s, s->system_journal, 0);
available_space(s, true);
- } else if (r < 0) {
+ } else {
if (r != -ENOENT && r != -EROFS)
log_warning_errno(r, "Failed to open system journal: %m");

28
SOURCES/0782-lldp-set-correct-state-for-processing.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
From 9562c6da55b17beb54de3a4f2c3a0ef0592dc53f Mon Sep 17 00:00:00 2001
From: Susant Sahani <susant@redhat.com>
Date: Thu, 2 Jul 2015 09:00:02 +0530
Subject: [PATCH] lldp: set correct state for processing

ldp_receive_frame after correct processing of the packet the state
should be LLDP_AGENT_RX_WAIT_FOR_FRAME not LLDP_AGENT_RX_UPDATE_INFO.

(cherry picked from commit 9bb1bffe3018aef5e70c411f68863eafdc92fddf)

Resolves: #1694605
---
src/libsystemd-network/sd-lldp.c | 2 --
1 file changed, 2 deletions(-)

diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index 19ef2ccdbd..d2f21fd10f 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -136,8 +136,6 @@ static int lldp_receive_frame(sd_lldp *lldp, tlv_packet *tlv) {
lldp->statistics.stats_frames_in_total ++;
- return 0;
-
out:
if (r < 0)
log_lldp("Receive frame failed: %s", strerror(-r));

25
SOURCES/0783-sd-bus-fix-implicit-downcast-of-bitfield-reported-by.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
From c8389c4a0b1e2587247824782230d4c132a639ee Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 27 Jun 2018 13:28:28 +0900
Subject: [PATCH] sd-bus: fix implicit downcast of bitfield reported by LGTM

(cherry picked from commit affaed1e55685e8e248db1afd50b3e0f466ce5cc)

Resolves: #1694605
---
src/libsystemd/sd-bus/bus-introspect.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c
index d528ab2a04..f77e6abec7 100644
--- a/src/libsystemd/sd-bus/bus-introspect.c
+++ b/src/libsystemd/sd-bus/bus-introspect.c
@@ -74,7 +74,7 @@ int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefi
return 0;
}
-static void introspect_write_flags(struct introspect *i, int type, int flags) {
+static void introspect_write_flags(struct introspect *i, int type, uint64_t flags) {
if (flags & SD_BUS_VTABLE_DEPRECATED)
fputs(" <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);

28
SOURCES/0784-tree-wide-use-signed-int-instead-of-int-for-bit-fiel.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
From 16c52e0a0efcdddc7809eca7fa6543f47e91ec9b Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Wed, 27 Feb 2019 19:45:59 +0100
Subject: [PATCH] tree-wide: use 'signed int' instead of 'int' for bit field
variables

Suggested by LGTM: https://lgtm.com/rules/1506024027114/

(cherry picked from commit 845d247a3dbca437fd8a118a118328acb322e2c1)

Resolves: #1694605
---
src/libsystemd/sd-event/sd-event.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 9d48e5a490..1cd2dfac84 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -68,7 +68,7 @@ struct sd_event_source {
char *description;
EventSourceType type:5;
- int enabled:3;
+ signed int enabled:3;
bool pending:1;
bool dispatching:1;
bool floating:1;

25
SOURCES/0785-machinectl-check-correct-FD-for-a-return-value.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
From 2d1a6a5665492cc0a71554045b2293e1193c889b Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Wed, 27 Feb 2019 19:51:48 +0100
Subject: [PATCH] machinectl: check correct FD for a return value

Found by LGTM.

Resolves: #1694605
---
src/machine/machinectl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 1a58aeaf11..66b64e1feb 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1086,7 +1086,7 @@ static int copy_files(int argc, char *argv[], void *userdata) {
return r;
hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
- if (r < 0)
+ if (hostfd < 0)
return log_error_errno(errno, "Failed to open source directory: %m");
child = fork();

37
SOURCES/0786-shared-install-avoid-overwriting-r-counter-with-a-pa.patch

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
From 3d359367291484097c0b496f6d83726e4070d036 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Thu, 28 Feb 2019 11:09:24 +0100
Subject: [PATCH] shared/install: avoid overwriting 'r' counter with a partial
result

We want to store either the first error or the total number of changes in 'r'.
Instead, we were overwriting this with the return value from
install_info_traverse().

LGTM complained later in the loop that:
> Comparison is always true because r >= 0.

Relevant commit: 459500a32cf74edca93ec79ee4cdd9dfcd20eee0

Resolves: #1694605
---
src/shared/install.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/shared/install.c b/src/shared/install.c
index ea01e4dcc2..f2f968e329 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1482,9 +1482,9 @@ static int install_context_apply(
if (q < 0)
return q;
- r = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL);
- if (r < 0)
- return r;
+ q = install_info_traverse(scope, c, root_dir, paths, i, flags, NULL);
+ if (q < 0)
+ return q;
if (i->type != UNIT_FILE_TYPE_REGULAR)
continue;

30
SOURCES/0787-systemctl-set_put-can-t-return-EEXIST.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From 732efbce6725db08a527e14d34f4e10e51fae965 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Thu, 28 Feb 2019 11:35:53 +0100
Subject: [PATCH] systemctl: set_put() can't return (-)EEXIST

set_put() returns 0 if the key already exists, 1 if the entry
was inserted successfully, and -ENOMEM otherwise.

See: set_put(), hashmap_base_put_boldly()

Found by LGTM.

Resolves: #1694605
---
src/systemctl/systemctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 398727cc7d..83c418f0b7 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4310,7 +4310,7 @@ static int show_one(
return log_oom();
r = set_put(found_properties, name);
- if (r < 0 && r != EEXIST)
+ if (r < 0)
return log_oom();
r = print_property(name, reply, contents);

38
SOURCES/0788-systemctl-remove-dead-check.patch

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
From 9e1bc4f2d8c24ad1b257e3452212d945e1078a8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Sat, 7 Mar 2015 15:00:22 -0500
Subject: [PATCH] systemctl: remove dead check

r could never be less than zero.

CID #1271350.

(cherry picked from commit 2558691285b2f7b3078b43b26736fcadf3c6d194)

Resolves: #1694605
---
src/systemctl/systemctl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 83c418f0b7..a55340f0a4 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4652,7 +4652,7 @@ static int cat(sd_bus *bus, char **args) {
_cleanup_strv_free_ char **names = NULL;
char **name;
bool first = true, avoid_bus_cache;
- int r = 0;
+ int r;
assert(args);
@@ -4702,7 +4702,7 @@ static int cat(sd_bus *bus, char **args) {
}
}
- return r < 0 ? r : 0;
+ return 0;
}
static int set_property(sd_bus *bus, char **args) {

75
SOURCES/0789-journal-gateway-explicitly-declare-local-variables.patch

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
From c101d92274043d6d219b97fb356f8827407c3eeb Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 27 Jun 2018 14:22:24 +0900
Subject: [PATCH] journal-gateway: explicitly declare local variables

Suggested by LGTM.

(cherry picked from commit c497e449f41774a36e01ae2cc2abade6133dffe1)

Resolves: #1694605
---
src/journal-remote/browse.html | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/journal-remote/browse.html b/src/journal-remote/browse.html
index 3594f70c87..30615795b3 100644
--- a/src/journal-remote/browse.html
+++ b/src/journal-remote/browse.html
@@ -304,7 +304,6 @@
var buf = '';
for (i in l) {
-
if (l[i] == '')
continue;
@@ -322,6 +321,7 @@
else
priority = 6;
+ var clazz;
if (priority <= 3)
clazz = "message-error";
else if (priority <= 5)
@@ -388,7 +388,7 @@
var d = JSON.parse(event.currentTarget.responseText);
document.getElementById("diventry").style.display = "block";
- entry = document.getElementById("tableentry");
+ var entry = document.getElementById("tableentry");
var buf = "";
for (var key in d){
@@ -455,7 +455,7 @@
(event.currentTarget.status != 200 && event.currentTarget.status != 0))
return;
- f = document.getElementById("filter");
+ var f = document.getElementById("filter");
var l = event.currentTarget.responseText.split('\n');
var buf = '<option>No filter</option>';
@@ -511,11 +511,12 @@
}
function initFilter() {
- f = document.getElementById("filter");
+ var f = document.getElementById("filter");
var buf = '<option>No filter</option>';
var filter = localStorage["filter"];
+ var j;
if (filter != null && filter != "") {
buf += '<option value="' + escape(filter) + '">' + escapeHTML(filter) + '</option>';
j = 1;
@@ -529,7 +530,7 @@
function installHandlers() {
document.onkeyup = onKeyUp;
- logs = document.getElementById("divlogs");
+ var logs = document.getElementById("divlogs");
logs.addEventListener("mousewheel", onMouseWheel, false);
logs.addEventListener("DOMMouseScroll", onMouseWheel, false);
}

36
SOURCES/0790-journal-gateway-use-localStorage-cursor-only-when-it.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
From 0b53945e8b1db6255bf25017a7569b2545c8ed15 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 27 Jun 2018 14:50:19 +0900
Subject: [PATCH] journal-gateway: use localStorage["cursor"] only when it has
valid value

Discovered by LGTM.

(cherry picked from commit 944072feddb73333023d0a98bf87fd2a17f894d3)

Resolves: #1694605
---
src/journal-remote/browse.html | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/journal-remote/browse.html b/src/journal-remote/browse.html
index 30615795b3..be1ec5f235 100644
--- a/src/journal-remote/browse.html
+++ b/src/journal-remote/browse.html
@@ -236,10 +236,12 @@
function entriesLoad(range) {
- if (range == null)
- range = localStorage["cursor"] + ":0";
- if (range == null)
- range = "";
+ if (range == null) {
+ if (localStorage["cursor"] != null && localStorage["cursor"] != "")
+ range = localStorage["cursor"] + ":0";
+ else
+ range = "";
+ }
var url = "/entries";

25
SOURCES/0791-lgtm-ignore-files-dropped-in-upstream.patch

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
From a9c3cc27f21e3ec11ba47f6f5a2cf719098d366c Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Thu, 28 Feb 2019 14:20:31 +0100
Subject: [PATCH] lgtm: ignore files dropped in upstream

Resolves: #1694605
---
.lgtm.yml | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/.lgtm.yml b/.lgtm.yml
index 0c8304d689..070a13cd63 100644
--- a/.lgtm.yml
+++ b/.lgtm.yml
@@ -7,3 +7,10 @@ extraction:
--disable-gtk-doc --disable-manpages --disable-gtk-doc-html
--enable-compat-libs --disable-sysusers --disable-ldconfig
--enable-lz4 --disable-microhttpd
+path_classifiers:
+ # Any files which have a tag attached are filtered out from results & stats
+ ignored:
+ # Skip files dropped in upstream
+ - src/bootchart/
+ - src/gudev/
+ - src/libsystemd/sd-bus/bus-bloom.c

42
SOURCES/0792-lgtm-suppress-several-constant-comparisons.patch

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
From 1499ff8f8ddd699a950729f5f3985975ef929c0a Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Thu, 28 Feb 2019 14:27:44 +0100
Subject: [PATCH] lgtm: suppress several constant comparisons

Even though LGTM is right is these cases, fixing it would require
substantial refactoring in some cases, so it's better to leave them
here (at least for RHEL 7).

Resolves: #1694605
rhel-only
---
src/sysv-generator/sysv-generator.c | 2 +-
src/tty-ask-password-agent/tty-ask-password-agent.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c
index fe6fae1510..232436a258 100644
--- a/src/sysv-generator/sysv-generator.c
+++ b/src/sysv-generator/sysv-generator.c
@@ -568,7 +568,7 @@ static int load_sysv(SysvStub *s) {
}
}
- if (r < 0)
+ if (r < 0) // lgtm[cpp/constant-comparison]
log_unit_error(s->name,
"[%s:%u] Failed to add dependency on %s, ignoring: %s",
s->path, line, m, strerror(-r));
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 47093b850d..1b7bbfa075 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -150,7 +150,7 @@ static int ask_password_plymouth(
p += k;
- if (p < 1)
+ if (p < 1) // lgtm[cpp/constant-comparison]
continue;
if (buffer[0] == 5) {

121
SOURCES/0793-core-add-a-new-unit_needs_console-call.patch

@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
From 94355e0146245c14012ac177461110d0a0c65f10 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 24 Jan 2018 19:54:26 +0100
Subject: [PATCH] core: add a new unit_needs_console() call

This call determines whether a specific unit currently needs access to
the console. It's a fancy wrapper around
exec_context_may_touch_console() ultimately, however for service units
we'll explicitly exclude the SERVICE_EXITED state from when we report
true.

(cherry picked from commit bb2c7685454842549bc1fe47adc35cbca2a84190)

Related: #1524359
---
src/core/service.c | 27 +++++++++++++++++++++++++++
src/core/unit.c | 22 ++++++++++++++++++++++
src/core/unit.h | 5 +++++
3 files changed, 54 insertions(+)

diff --git a/src/core/service.c b/src/core/service.c
index 1ad154e41f..8a8f4be149 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3368,6 +3368,32 @@ static int service_control_pid(Unit *u) {
return s->control_pid;
}
+static bool service_needs_console(Unit *u) {
+ Service *s = SERVICE(u);
+
+ assert(s);
+
+ /* We provide our own implementation of this here, instead of relying of the generic implementation
+ * unit_needs_console() provides, since we want to return false if we are in SERVICE_EXITED state. */
+
+ if (!exec_context_may_touch_console(&s->exec_context))
+ return false;
+
+ return IN_SET(s->state,
+ SERVICE_START_PRE,
+ SERVICE_START,
+ SERVICE_START_POST,
+ SERVICE_RUNNING,
+ SERVICE_RELOAD,
+ SERVICE_STOP,
+ SERVICE_STOP_SIGABRT,
+ SERVICE_STOP_SIGTERM,
+ SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM,
+ SERVICE_FINAL_SIGKILL);
+}
+
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
[SERVICE_RESTART_NO] = "no",
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
@@ -3489,6 +3515,7 @@ const UnitVTable service_vtable = {
.bus_commit_properties = bus_service_commit_properties,
.get_timeout = service_get_timeout,
+ .needs_console = service_needs_console,
.can_transient = true,
.status_message_formats = {
diff --git a/src/core/unit.c b/src/core/unit.c
index 4069a6f4c4..48358bc026 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -3699,6 +3699,28 @@ pid_t unit_main_pid(Unit *u) {
return 0;
}
+bool unit_needs_console(Unit *u) {
+ ExecContext *ec;
+ UnitActiveState state;
+
+ assert(u);
+
+ state = unit_active_state(u);
+
+ if (UNIT_IS_INACTIVE_OR_FAILED(state))
+ return false;
+
+ if (UNIT_VTABLE(u)->needs_console)
+ return UNIT_VTABLE(u)->needs_console(u);
+
+ /* If this unit type doesn't implement this call, let's use a generic fallback implementation: */
+ ec = unit_get_exec_context(u);
+ if (!ec)
+ return false;
+
+ return exec_context_may_touch_console(ec);
+}
+
static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
[UNIT_ACTIVE] = "active",
[UNIT_RELOADING] = "reloading",
diff --git a/src/core/unit.h b/src/core/unit.h
index 4a8bd79052..fa7de11645 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -408,6 +408,9 @@ struct UnitVTable {
/* Returns the main PID if there is any defined, or 0. */
pid_t (*control_pid)(Unit *u);
+ /* Returns true if the unit currently needs access to the console */
+ bool (*needs_console)(Unit *u);
+
/* This is called for each unit type and should be used to
* enumerate existing devices and load them. However,
* everything that is loaded here should still stay in
@@ -627,6 +630,8 @@ pid_t unit_main_pid(Unit *u);
const char *unit_active_state_to_string(UnitActiveState i) _const_;
UnitActiveState unit_active_state_from_string(const char *s) _pure_;
+bool unit_needs_console(Unit *u);
+
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full_errno(unit, level, error, ...) log_object_internal(level, error, __FILE__, __LINE__, __func__, getpid() == 1 ? "UNIT=" : "USER_UNIT=", unit, __VA_ARGS__)

171
SOURCES/0794-core-rework-how-we-count-the-n_on_console-counter.patch

@ -0,0 +1,171 @@ @@ -0,0 +1,171 @@
From 1ac6c613ef11a9ee9c36b25133cc302c4be1a858 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 24 Jan 2018 19:59:55 +0100
Subject: [PATCH] core: rework how we count the n_on_console counter

Let's add a per-unit boolean that tells us whether our unit is currently
counted or not. This way it's unlikely we get out of sync again and
things are generally more robust.

This also allows us to remove the counting logic specific to service
units (which was in fact mostly a copy from the generic implementation),
in favour of fully generic code.

Replaces: #7824
(cherry picked from commit adefcf2821a386184991054ed2bb6dacc90d7419)

Resolves: #1524359
---
src/core/manager.c | 15 +++++++++++++++
src/core/manager.h | 3 +++
src/core/service.c | 20 --------------------
src/core/unit.c | 39 +++++++++++++++++++++------------------
src/core/unit.h | 1 +
5 files changed, 40 insertions(+), 38 deletions(-)

diff --git a/src/core/manager.c b/src/core/manager.c
index 88d156e8fb..4c87ad8a2f 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -3379,6 +3379,21 @@ ManagerState manager_state(Manager *m) {
return MANAGER_RUNNING;
}
+void manager_ref_console(Manager *m) {
+ assert(m);
+
+ m->n_on_console++;
+}
+
+void manager_unref_console(Manager *m) {
+
+ assert(m->n_on_console > 0);
+ m->n_on_console--;
+
+ if (m->n_on_console == 0)
+ m->no_console_output = false; /* unset no_console_output flag, since the console is definitely free now */
+}
+
static const char *const manager_state_table[_MANAGER_STATE_MAX] = {
[MANAGER_INITIALIZING] = "initializing",
[MANAGER_STARTING] = "starting",
diff --git a/src/core/manager.h b/src/core/manager.h
index b0e4cad1fc..cfc564dfb6 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -379,5 +379,8 @@ const char *manager_get_runtime_prefix(Manager *m);
ManagerState manager_state(Manager *m);
+void manager_ref_console(Manager *m);
+void manager_unref_console(Manager *m);
+
const char *manager_state_to_string(ManagerState m) _const_;
ManagerState manager_state_from_string(const char *s) _pure_;
diff --git a/src/core/service.c b/src/core/service.c
index 8a8f4be149..ea71c9e237 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -914,26 +914,6 @@ static void service_set_state(Service *s, ServiceState state) {
if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0)
unit_destroy_cgroup_if_empty(UNIT(s));
- /* For remain_after_exit services, let's see if we can "release" the
- * hold on the console, since unit_notify() only does that in case of
- * change of state */
- if (state == SERVICE_EXITED &&
- s->remain_after_exit &&
- UNIT(s)->manager->n_on_console > 0) {
-
- ExecContext *ec;
-
- ec = unit_get_exec_context(UNIT(s));
- if (ec && exec_context_may_touch_console(ec)) {
- Manager *m = UNIT(s)->manager;
-
- m->n_on_console --;
- if (m->n_on_console == 0)
- /* unset no_console_output flag, since the console is free */
- m->no_console_output = false;
- }
- }
-
if (old_state != state)
log_unit_debug(UNIT(s)->id, "%s changed %s -> %s", UNIT(s)->id, service_state_to_string(old_state), service_state_to_string(state));
diff --git a/src/core/unit.c b/src/core/unit.c
index 48358bc026..294c9eb70f 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -544,6 +544,9 @@ void unit_free(Unit *u) {
u->manager->n_in_gc_queue--;
}
+ if (u->on_console)
+ manager_unref_console(u->manager);
+
condition_free_list(u->conditions);
condition_free_list(u->asserts);
@@ -1741,6 +1744,23 @@ void unit_trigger_notify(Unit *u) {
UNIT_VTABLE(other)->trigger_notify(other, u);
}
+static void unit_update_on_console(Unit *u) {
+ bool b;
+
+ assert(u);
+
+ b = unit_needs_console(u);
+ if (u->on_console == b)
+ return;
+
+ u->on_console = b;
+ if (b)
+ manager_ref_console(u->manager);
+ else
+ manager_unref_console(u->manager);
+
+}
+
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
Manager *m;
bool unexpected;
@@ -1784,24 +1804,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
if (UNIT_IS_INACTIVE_OR_FAILED(ns))
unit_destroy_cgroup_if_empty(u);
- /* Note that this doesn't apply to RemainAfterExit services exiting
- * successfully, since there's no change of state in that case. Which is
- * why it is handled in service_set_state() */
- if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
- ExecContext *ec;
-
- ec = unit_get_exec_context(u);
- if (ec && exec_context_may_touch_console(ec)) {
- if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
- m->n_on_console --;
-
- if (m->n_on_console == 0)
- /* unset no_console_output flag, since the console is free */
- m->no_console_output = false;
- } else
- m->n_on_console ++;
- }
- }
+ unit_update_on_console(u);
if (u->job) {
unexpected = false;
diff --git a/src/core/unit.h b/src/core/unit.h
index fa7de11645..719fc95260 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -238,6 +238,7 @@ struct Unit {
bool no_gc:1;
bool in_audit:1;
+ bool on_console:1;
bool cgroup_realized:1;
bool cgroup_members_mask_valid:1;

71
SOURCES/0795-service-introduce-protocol-error-type.patch

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
From c460203ad5165dfb095fcfaa6646708e39d2080e Mon Sep 17 00:00:00 2001
From: Jouke Witteveen <j.witteveen@gmail.com>
Date: Tue, 22 Nov 2016 17:39:56 +0100
Subject: [PATCH] service: introduce protocol error type

Introduce a SERVICE_FAILURE_PROTOCOL error type for when a service does
not follow the protocol.
This error type is used when a pid file is expected, but not delivered.

(cherry picked from commit c35755fb878af58b80ac62a501a75f79c90a3763)

Related: #1733998
---
src/core/service.c | 9 +++++----
src/core/service.h | 1 +
2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/core/service.c b/src/core/service.c
index ea71c9e237..84a5aeb072 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2568,9 +2568,9 @@ static void service_notify_cgroup_empty_event(Unit *u) {
service_unwatch_pid_file(s);
if (s->state == SERVICE_START)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
else
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
+ service_enter_stop(s, SERVICE_FAILURE_PROTOCOL);
}
break;
@@ -2804,7 +2804,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (!has_start_post && r < 0) {
r = service_demand_pid_file(s);
if (r < 0 || !cgroup_good(s))
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
} else
@@ -2826,7 +2826,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (r < 0) {
r = service_demand_pid_file(s);
if (r < 0 || !cgroup_good(s))
- service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
+ service_enter_stop(s, SERVICE_FAILURE_PROTOCOL);
break;
}
} else
@@ -3428,6 +3428,7 @@ DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState);
static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
[SERVICE_SUCCESS] = "success",
[SERVICE_FAILURE_RESOURCES] = "resources",
+ [SERVICE_FAILURE_PROTOCOL] = "protocol",
[SERVICE_FAILURE_TIMEOUT] = "timeout",
[SERVICE_FAILURE_EXIT_CODE] = "exit-code",
[SERVICE_FAILURE_SIGNAL] = "signal",
diff --git a/src/core/service.h b/src/core/service.h
index e0547a464e..82938a1fc4 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -108,6 +108,7 @@ typedef enum NotifyState {
typedef enum ServiceResult {
SERVICE_SUCCESS,
SERVICE_FAILURE_RESOURCES,
+ SERVICE_FAILURE_PROTOCOL,
SERVICE_FAILURE_TIMEOUT,
SERVICE_FAILURE_EXIT_CODE,
SERVICE_FAILURE_SIGNAL,

76
SOURCES/0796-service-fix-main-processes-exit-behavior-for-type-no.patch

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
From 273d69011bf2a8abfcef71e33e6b6ae3323dfc34 Mon Sep 17 00:00:00 2001
From: Jouke Witteveen <j.witteveen@gmail.com>
Date: Sat, 1 Oct 2016 14:06:48 +0200
Subject: [PATCH] service: fix main processes exit behavior for type notify
services

Before this commit, when the main process of a Type=notify service exits the
service would enter a running state without passing through the startup post
state. This meant ExecStartPost= from being executed and allowed follow-up
units to start too early (before the ready notification).
Additionally, when RemainAfterExit=yes is used on a Type=notify service, the
exit status of the main process would be disregarded.

After this commit, an unsuccessful exit of the main process of a Type=notify
service puts the unit in a failed state. A successful exit is inconsequential
in case RemainAfterExit=yes. Otherwise, when no ready notification has been
received, the unit is put in a failed state because it has never been active.
When all processes in the cgroup of a Type=notify service are gone and no ready
notification has been received yet, the unit is also put in a failed state.

(cherry picked from commit 3d474ef7a687e2052aa303e0f95893b2fc610475)

Related: #1733998
---
src/core/service.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/core/service.c b/src/core/service.c
index 84a5aeb072..b6f302ec33 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1531,7 +1531,9 @@ static void service_enter_running(Service *s, ServiceResult f) {
else
service_set_state(s, SERVICE_RUNNING);
- } else if (s->remain_after_exit)
+ } else if (f != SERVICE_SUCCESS)
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ else if (s->remain_after_exit)
service_set_state(s, SERVICE_EXITED);
else
service_enter_stop(s, SERVICE_SUCCESS);
@@ -2561,10 +2563,12 @@ static void service_notify_cgroup_empty_event(Unit *u) {
case SERVICE_START:
case SERVICE_START_POST:
- /* If we were hoping for the daemon to write its PID file,
- * we can give up now. */
- if (s->pid_file_pathspec) {
- log_unit_warning(u->id, "%s never wrote its PID file. Failing.", UNIT(s)->id);
+ if (s->type == SERVICE_NOTIFY)
+ /* No chance of getting a ready notification anymore */
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ else if (s->pid_file_pathspec) {
+ /* Give up hoping for the daemon to write its PID file */
+ log_unit_warning(u->id, "Daemon never wrote its PID file. Failing.");
service_unwatch_pid_file(s);
if (s->state == SERVICE_START)
@@ -2699,6 +2703,16 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
else
service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
break;
+ } else if (s->type == SERVICE_NOTIFY) {
+ /* Only enter running through a notification, so that the
+ * SERVICE_START state signifies that no ready notification
+ * has been received */
+ if (f != SERVICE_SUCCESS)
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ else if (!s->remain_after_exit)
+ /* The service has never been active */
+ service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ break;
}
/* Fall through */

111
SOURCES/0797-service-go-through-stop_post-on-failure-4770.patch

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
From 5f0bb278dfe913bd2c7dcbc9f457892f5e8aca9d Mon Sep 17 00:00:00 2001
From: Jouke Witteveen <j.witteveen@gmail.com>
Date: Tue, 6 Dec 2016 13:30:28 +0100
Subject: [PATCH] service: go through stop_post on failure (#4770)

(cherry picked from commit c3fda31da36706b045f5de800d6a77e65e7a8ec9)

Resolves: #1733998
---
src/core/service.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/src/core/service.c b/src/core/service.c
index b6f302ec33..e538280bad 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1532,7 +1532,7 @@ static void service_enter_running(Service *s, ServiceResult f) {
service_set_state(s, SERVICE_RUNNING);
} else if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
else if (s->remain_after_exit)
service_set_state(s, SERVICE_EXITED);
else
@@ -1671,7 +1671,7 @@ static void service_enter_start(Service *s) {
fail:
log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run 'start' task: %m", UNIT(s)->id);
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
static void service_enter_start_pre(Service *s) {
@@ -1823,9 +1823,7 @@ static void service_run_next_control(Service *s) {
fail:
log_unit_warning_errno(UNIT(s)->id, r, "%s failed to run next control task: %m", UNIT(s)->id);
- if (s->state == SERVICE_START_PRE)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
- else if (s->state == SERVICE_STOP)
+ if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_STOP))
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
@@ -2572,7 +2570,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
service_unwatch_pid_file(s);
if (s->state == SERVICE_START)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL);
else
service_enter_stop(s, SERVICE_FAILURE_PROTOCOL);
}
@@ -2701,17 +2699,17 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (f == SERVICE_SUCCESS)
service_enter_start_post(s);
else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
} else if (s->type == SERVICE_NOTIFY) {
/* Only enter running through a notification, so that the
* SERVICE_START state signifies that no ready notification
* has been received */
if (f != SERVICE_SUCCESS)
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
else if (!s->remain_after_exit)
/* The service has never been active */
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
@@ -2792,7 +2790,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (f == SERVICE_SUCCESS)
service_enter_start(s);
else
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
case SERVICE_START:
@@ -2801,7 +2799,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
break;
if (f != SERVICE_SUCCESS) {
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, f);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
break;
}
@@ -2818,7 +2816,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
if (!has_start_post && r < 0) {
r = service_demand_pid_file(s);
if (r < 0 || !cgroup_good(s))
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
} else
@@ -2914,7 +2912,7 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
case SERVICE_START_PRE:
case SERVICE_START:
log_unit_warning(UNIT(s)->id, "%s %s operation timed out. Terminating.", UNIT(s)->id, s->state == SERVICE_START ? "start" : "start-pre");
- service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_START_POST:

44
SOURCES/0798-Call-getgroups-to-know-size-of-supplementary-groups-.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
From 0d0ba7ee44d652c23e6027fe3b1c1ee8e2f65a25 Mon Sep 17 00:00:00 2001
From: systemd team <systemd-maint@redhat.com>
Date: Mon, 19 Aug 2019 13:51:48 +0200
Subject: [PATCH] Call getgroups() to know size of supplementary groups array
to allocate

Resolves RHBZ #1743230 - journalctl dumps core when stack limit is reduced to 256 KB
---
src/shared/util.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/shared/util.c b/src/shared/util.c
index 127a64c3c6..ce6678eb38 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5097,7 +5097,7 @@ int get_group_creds(const char **groupname, gid_t *gid) {
int in_gid(gid_t gid) {
gid_t *gids;
- int ngroups_max, r, i;
+ int ngroups, r, i;
if (getgid() == gid)
return 1;
@@ -5105,12 +5105,15 @@ int in_gid(gid_t gid) {
if (getegid() == gid)
return 1;
- ngroups_max = sysconf(_SC_NGROUPS_MAX);
- assert(ngroups_max > 0);
+ ngroups = getgroups(0, NULL);
+ if (ngroups < 0)
+ return -errno;
+ if (ngroups == 0)
+ return 0;
- gids = alloca(sizeof(gid_t) * ngroups_max);
+ gids = alloca(sizeof(gid_t) * ngroups);
- r = getgroups(ngroups_max, gids);
+ r = getgroups(ngroups, gids);
if (r < 0)
return -errno;

190
SOURCES/0799-udev-introduce-CONST-key-name.patch

@ -0,0 +1,190 @@ @@ -0,0 +1,190 @@
From be88b819ecec075187ac313b8ab15d8ed8004b54 Mon Sep 17 00:00:00 2001
From: Jan Synacek <jsynacek@redhat.com>
Date: Wed, 11 Sep 2019 12:35:18 +0200
Subject: [PATCH] udev: introduce CONST key name

Currently, there is no way to match against system-wide constants, such
as architecture or virtualization type, without forking helper binaries.
That potentially results in a huge number of spawned processes which
output always the same answer.

This patch introduces a special CONST keyword which takes a hard-coded
string as its key and returns a value assigned to that key. Currently
implemented are CONST{arch} and CONST{virt}, which can be used to match
against the system's architecture and virtualization type.

(based on commit 4801d8afe2ff1c1c075c9f0bc5631612172e0bb7)

Resolves: #1748051
---
man/udev.xml | 26 ++++++++++++++++++++++++++
rules/40-redhat.rules | 4 ++--
src/udev/udev-rules.c | 39 +++++++++++++++++++++++++++++++++++++++
test/rule-syntax-check.py | 2 +-
4 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/man/udev.xml b/man/udev.xml
index a948ea79a9..fc02edd214 100644
--- a/man/udev.xml
+++ b/man/udev.xml
@@ -240,6 +240,32 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>CONST{<replaceable>key</replaceable>}</varname></term>
+ <listitem>
+ <para>Match against a system-wide constant. Supported keys are:</para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>arch</literal></term>
+ <listitem>
+ <para>System's architecture. See <option>ConditionArchitecture=</option> in
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for possible values.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>virt</literal></term>
+ <listitem>
+ <para>System's virtualization environment. See
+ <citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ for possible values.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ <para>Unknown keys will never match.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>TAG</varname></term>
<listitem>
diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules
index 2c690e522e..83d823e172 100644
--- a/rules/40-redhat.rules
+++ b/rules/40-redhat.rules
@@ -6,10 +6,10 @@ SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}
# Memory hotadd request
SUBSYSTEM!="memory", GOTO="memory_hotplug_end"
ACTION!="add", GOTO="memory_hotplug_end"
-PROGRAM="/bin/uname -p", RESULT=="s390*", GOTO="memory_hotplug_end"
+CONST{arch}=="s390*", GOTO="memory_hotplug_end"
ENV{.state}="online"
-PROGRAM="/bin/systemd-detect-virt", RESULT=="none", ENV{.state}="online_movable"
+CONST{virt}=="none", ENV{.state}="online_movable"
ATTR{state}=="offline", ATTR{state}="$env{.state}"
LABEL="memory_hotplug_end"
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index c9a0197534..9211f563b1 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -29,12 +29,14 @@
#include <fnmatch.h>
#include <time.h>
+#include "architecture.h"
#include "udev.h"
#include "path-util.h"
#include "conf-files.h"
#include "strbuf.h"
#include "strv.h"
#include "util.h"
+#include "virt.h"
#define PREALLOC_TOKEN 2048
@@ -123,6 +125,7 @@ enum token_type {
TK_M_DEVLINK, /* val */
TK_M_NAME, /* val */
TK_M_ENV, /* val, attr */
+ TK_M_CONST, /* val, attr */
TK_M_TAG, /* val */
TK_M_SUBSYSTEM, /* val */
TK_M_DRIVER, /* val */
@@ -257,6 +260,7 @@ static const char *token_str(enum token_type type) {
[TK_M_DEVLINK] = "M DEVLINK",
[TK_M_NAME] = "M NAME",
[TK_M_ENV] = "M ENV",
+ [TK_M_CONST] = "M CONST",
[TK_M_TAG] = "M TAG",
[TK_M_SUBSYSTEM] = "M SUBSYSTEM",
[TK_M_DRIVER] = "M DRIVER",
@@ -365,6 +369,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) {
case TK_M_ATTR:
case TK_M_ATTRS:
case TK_M_ENV:
+ case TK_M_CONST:
case TK_A_ATTR:
case TK_A_ENV:
log_debug("%s %s '%s' '%s'(%s)",
@@ -905,6 +910,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type,
token->key.builtin_cmd = *(enum udev_builtin_cmd *)data;
break;
case TK_M_ENV:
+ case TK_M_CONST:
case TK_M_ATTR:
case TK_M_ATTRS:
case TK_A_ATTR:
@@ -1264,6 +1270,22 @@ static int add_rule(struct udev_rules *rules, char *line,
continue;
}
+ if (startswith(key, "CONST{")) {
+ attr = get_key_attribute(rules->udev, key + STRLEN("CONST"));
+ if (attr == NULL || !STR_IN_SET(attr, "arch", "virt")) {
+ log_error("error parsing CONST attribute");
+ goto invalid;
+ }
+ if (op == OP_REMOVE) {
+ log_error("invalid CONST operation");
+ goto invalid;
+ }
+ if (op < OP_MATCH_MAX) {
+ if (rule_add_key(&rule_tmp, TK_M_CONST, op, value, attr) != 0)
+ goto invalid;
+ }
+ continue;
+ }
if (streq(key, "TAG")) {
if (op < OP_MATCH_MAX)
rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL);
@@ -1959,6 +1981,23 @@ int udev_rules_apply_to_event(struct udev_rules *rules,
goto nomatch;
break;
}
+ case TK_M_CONST: {
+ const char *key_name = rules_str(rules, cur->key.attr_off);
+ const char *value = NULL;
+ int q;
+
+ if (streq(key_name, "arch")) {
+ q = uname_architecture();
+ value = architecture_to_string(q);
+ } else if (streq(key_name, "virt")) {
+ q = detect_virtualization(&value);
+ } else
+ assert_not_reached("Invalid CONST key");
+
+ if (match_key(rules, cur, value))
+ goto nomatch;
+ break;
+ }
case TK_M_TAG: {
struct udev_list_entry *list_entry;
bool match = false;
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py
index 80bbe65bea..c6d003b167 100644
--- a/test/rule-syntax-check.py
+++ b/test/rule-syntax-check.py
@@ -34,7 +34,7 @@ else:
rules_files = glob(os.path.join(rules_dir, '*.rules'))
no_args_tests = re.compile('(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST)\s*(?:=|!)=\s*"([^"]*)"$')
-args_tests = re.compile('(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$')
+args_tests = re.compile('(ATTRS?|ENV|CONST|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$')
no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$')
args_assign = re.compile('(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*"([^"]*)"$')
Loading…
Cancel
Save