import systemd-252-8.el9

i9c-beta changed/i9c-beta/systemd-252-8.el9
MSVSphere Packaging Team 2 years ago
commit 8186801bfd

1
.gitignore vendored

@ -0,0 +1 @@
SOURCES/systemd-252.tar.gz

@ -0,0 +1 @@
7c961dc6e8bb950825b85129f59dc80f4536cabb SOURCES/systemd-252.tar.gz

@ -0,0 +1,78 @@
From 87bf366c97be1c811c4bfdf80b48d6c3e35da76a Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Tue, 25 Oct 2022 19:55:08 +0200
Subject: [PATCH] macro: Simply case macros for IN_SET
The CASE param would normally provide the operation for the compiler to
do in this macro magic. But in this case CASE_F_1 was hardcoding the
operation, making the parameter moot.
This just removes the somewhat pointless parameter instead of fixing
the one case. These macros are used for IN_SET case labels only and
not named generically anyways.
(cherry picked from commit 790f4dda74d7ecdb4e57101a37cc9f2f9236bef6)
Related #2138081
---
src/fundamental/macro-fundamental.h | 43 ++++++++++++++---------------
1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h
index 2536c741c6..63f4c49e78 100644
--- a/src/fundamental/macro-fundamental.h
+++ b/src/fundamental/macro-fundamental.h
@@ -251,33 +251,32 @@
(UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \
})
-#define CASE_F(X) case X:
-#define CASE_F_1(CASE, X) CASE_F(X)
-#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
-#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
-#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
-#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
-#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
-#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
-#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
-#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
-#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
-#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
-#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
-#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
-#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
-#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
-#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
-#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
-#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
-#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
-#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
+#define CASE_F_1(X) case X:
+#define CASE_F_2(X, ...) case X: CASE_F_1( __VA_ARGS__)
+#define CASE_F_3(X, ...) case X: CASE_F_2( __VA_ARGS__)
+#define CASE_F_4(X, ...) case X: CASE_F_3( __VA_ARGS__)
+#define CASE_F_5(X, ...) case X: CASE_F_4( __VA_ARGS__)
+#define CASE_F_6(X, ...) case X: CASE_F_5( __VA_ARGS__)
+#define CASE_F_7(X, ...) case X: CASE_F_6( __VA_ARGS__)
+#define CASE_F_8(X, ...) case X: CASE_F_7( __VA_ARGS__)
+#define CASE_F_9(X, ...) case X: CASE_F_8( __VA_ARGS__)
+#define CASE_F_10(X, ...) case X: CASE_F_9( __VA_ARGS__)
+#define CASE_F_11(X, ...) case X: CASE_F_10( __VA_ARGS__)
+#define CASE_F_12(X, ...) case X: CASE_F_11( __VA_ARGS__)
+#define CASE_F_13(X, ...) case X: CASE_F_12( __VA_ARGS__)
+#define CASE_F_14(X, ...) case X: CASE_F_13( __VA_ARGS__)
+#define CASE_F_15(X, ...) case X: CASE_F_14( __VA_ARGS__)
+#define CASE_F_16(X, ...) case X: CASE_F_15( __VA_ARGS__)
+#define CASE_F_17(X, ...) case X: CASE_F_16( __VA_ARGS__)
+#define CASE_F_18(X, ...) case X: CASE_F_17( __VA_ARGS__)
+#define CASE_F_19(X, ...) case X: CASE_F_18( __VA_ARGS__)
+#define CASE_F_20(X, ...) case X: CASE_F_19( __VA_ARGS__)
#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
#define FOR_EACH_MAKE_CASE(...) \
GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
- (CASE_F,__VA_ARGS__)
+ (__VA_ARGS__)
#define IN_SET(x, ...) \
({ \

@ -0,0 +1,25 @@
From 0c372e24bb30c25beccd76c071baca22258e71c9 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 26 Oct 2022 03:28:08 +0900
Subject: [PATCH] macro: fix indentation
(cherry picked from commit e967926b092d8635b3da28fc4ca492009e32228f)
Related #2138081
---
src/fundamental/macro-fundamental.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h
index 63f4c49e78..faab16ab31 100644
--- a/src/fundamental/macro-fundamental.h
+++ b/src/fundamental/macro-fundamental.h
@@ -290,7 +290,7 @@
switch (x) { \
FOR_EACH_MAKE_CASE(__VA_ARGS__) \
_found = true; \
- break; \
+ break; \
default: \
break; \
} \

@ -0,0 +1,61 @@
From 5ac8c56f111f2875467422c851a05891c0ec7d1b Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 31 Oct 2022 12:11:59 +0100
Subject: [PATCH] test: add a couple of sanity tests for journalctl
(cherry picked from commit ca46781c5ffa3aaa7a8fb6f09976357d003c4aae)
Related #2138081
---
test/units/testsuite-04.sh | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/test/units/testsuite-04.sh b/test/units/testsuite-04.sh
index b5468cbea4..fdc3273fea 100755
--- a/test/units/testsuite-04.sh
+++ b/test/units/testsuite-04.sh
@@ -119,6 +119,44 @@ systemctl start silent-success
journalctl --sync
[[ -z "$(journalctl -b -q -u silent-success.service)" ]]
+# Exercise the matching machinery
+SYSTEMD_LOG_LEVEL=debug journalctl -b -n 1 /dev/null /dev/zero /dev/null /dev/null /dev/null
+journalctl -b -n 1 /bin/true /bin/false
+journalctl -b -n 1 /bin/true + /bin/false
+journalctl -b -n 1 -r --unit "systemd*"
+
+systemd-run --user -M "testuser@.host" /bin/echo hello
+journalctl --sync
+journalctl -b -n 1 -r --user-unit "*"
+
+(! journalctl -b /dev/lets-hope-this-doesnt-exist)
+(! journalctl -b /dev/null /dev/zero /dev/this-also-shouldnt-exist)
+(! journalctl -b --unit "this-unit-should-not-exist*")
+
+# Facilities & priorities
+journalctl --facility help
+journalctl --facility kern -n 1
+journalctl --facility syslog --priority 0..3 -n 1
+journalctl --facility syslog --priority 3..0 -n 1
+journalctl --facility user --priority 0..0 -n 1
+journalctl --facility daemon --priority warning -n 1
+journalctl --facility daemon --priority warning..info -n 1
+journalctl --facility daemon --priority notice..crit -n 1
+journalctl --facility daemon --priority 5..crit -n 1
+
+(! journalctl --facility hopefully-an-unknown-facility)
+(! journalctl --priority hello-world)
+(! journalctl --priority 0..128)
+(! journalctl --priority 0..systemd)
+
+# Other options
+journalctl --disk-usage
+journalctl --dmesg -n 1
+journalctl --fields
+journalctl --list-boots
+journalctl --update-catalog
+journalctl --list-catalog
+
# Add new tests before here, the journald restarts below
# may make tests flappy.

@ -0,0 +1,25 @@
From b1a2687cf5b419d6928d024f26aabe1de8ff7727 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Mon, 31 Oct 2022 21:17:47 +0000
Subject: [PATCH] man: fix typo found by Lintian
(cherry picked from commit 84033dd40588dbf4f57a746c141fe7d111247a93)
Related #2138081
---
man/loader.conf.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/loader.conf.xml b/man/loader.conf.xml
index 3ee42cdb73..7f173aec61 100644
--- a/man/loader.conf.xml
+++ b/man/loader.conf.xml
@@ -236,7 +236,7 @@
<para>The different sets of variables can be set up under <filename>/loader/keys/<replaceable>NAME</replaceable></filename>
where <replaceable>NAME</replaceable> is the name that is going to be used as the name of the entry.
- This allows to ship multiple sets of Secure Boot variables and choose which one to enroll at runtime.</para>
+ This allows one to ship multiple sets of Secure Boot variables and choose which one to enroll at runtime.</para>
<para>Supported secure boot variables are one database for authorized images, one key exchange key (KEK)
and one platform key (PK). For more information, refer to the <ulink url="https://uefi.org/specifications">UEFI specification</ulink>,

@ -0,0 +1,19 @@
From 3d2fc0517d43ff2c5c6fc03ebb68ef9429be5fd4 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Mon, 31 Oct 2022 21:18:53 +0000
Subject: [PATCH] test: add +x to assert.sh
The script has a shebang and .sh extension, so make it executable
W: systemd-tests: script-not-executable [usr/lib/systemd/tests/testdata/units/assert.sh]
(cherry picked from commit fb4f7271d9f75a44756b110706cdb53b82f407ce)
Related #2138081
---
test/units/assert.sh | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100644 => 100755 test/units/assert.sh
diff --git a/test/units/assert.sh b/test/units/assert.sh
old mode 100644
new mode 100755

@ -0,0 +1,25 @@
From a2cb8467652ca36bd5420dc685d5e6b76014c3e1 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 1 Nov 2022 13:10:20 +0900
Subject: [PATCH] parse_hwdb: allow negative value for EVDEV_ABS_ properties
(cherry picked from commit f0b75cda5a3eac3fe953fd1a429a39e077387997)
Related #2138081
---
hwdb.d/parse_hwdb.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hwdb.d/parse_hwdb.py b/hwdb.d/parse_hwdb.py
index c0dde75650..5a1ae5a6a0 100755
--- a/hwdb.d/parse_hwdb.py
+++ b/hwdb.d/parse_hwdb.py
@@ -202,7 +202,7 @@ def property_grammar():
]
abs_props = [Regex(r'EVDEV_ABS_[0-9a-f]{2}')('NAME')
- Suppress('=') -
- Word(nums + ':')('VALUE')
+ Word('-' + nums + ':')('VALUE')
]
grammar = Or(fixed_props + kbd_props + abs_props) + EOL

@ -0,0 +1,24 @@
From 07aa3fcbb7b4e4cca7b2e9be6e038ab92bfc5fdc Mon Sep 17 00:00:00 2001
From: Youfu Zhang <1315097+zhangyoufu@users.noreply.github.com>
Date: Tue, 1 Nov 2022 13:18:25 +0800
Subject: [PATCH] resolved: fix typo in feature level table
(cherry picked from commit 2ab0042854934827e61076c6e42c7381fdf78fdf)
Related #2138081
---
src/resolve/resolved-dns-server.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 9b74a8d6d8..04a4f53ed0 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -1087,6 +1087,6 @@ static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVE
[DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0",
[DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN] = "TLS+EDNS0",
[DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO",
- [DNS_SERVER_FEATURE_LEVEL_TLS_DO] = "TLS+EDNS0+D0",
+ [DNS_SERVER_FEATURE_LEVEL_TLS_DO] = "TLS+EDNS0+DO",
};
DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);

@ -0,0 +1,28 @@
From a1f18876d5f7122c9f94af9a84f1324f50dba0ed Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Tue, 1 Nov 2022 09:43:32 +0100
Subject: [PATCH] coverage: Mark _coverage__exit as noreturn
../src/basic/coverage.h:15:48: warning: function '_coverage__exit' could
be declared with attribute 'noreturn' [-Wmissing-noreturn]
(cherry picked from commit 0bab5534b334677652bb69fe15eaa54ce84cbe7d)
Related #2138081
---
src/basic/coverage.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/basic/coverage.h b/src/basic/coverage.h
index 3ef02cf70e..640bddc485 100644
--- a/src/basic/coverage.h
+++ b/src/basic/coverage.h
@@ -12,7 +12,7 @@
extern void _exit(int);
extern void __gcov_dump(void);
-static inline void _coverage__exit(int status) {
+static inline _Noreturn void _coverage__exit(int status) {
__gcov_dump();
_exit(status);
}

@ -0,0 +1,154 @@
From 6ab61ac93e534aec1ea4d16e77c1c355c8286e64 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Thu, 27 Oct 2022 13:14:12 +0200
Subject: [PATCH] namespace: Add hidepid/subset support check
Using fsopen()/fsconfig(), we can check if hidepid/subset are supported to
avoid the noisy logs from the kernel if they aren't supported. This works
on centos/redhat 8 as well since they've backported fsopen()/fsconfig().
(cherry picked from commit 1c265fcd5963603d338233840129ecad8d9c1420)
Related #2138081
---
meson.build | 2 ++
src/basic/missing_syscall.h | 40 +++++++++++++++++++++++++++++++
src/core/namespace.c | 47 ++++++++++++++++++++++++++++++++-----
3 files changed, 83 insertions(+), 6 deletions(-)
diff --git a/meson.build b/meson.build
index 76ad51d3fb..7750534466 100644
--- a/meson.build
+++ b/meson.build
@@ -606,6 +606,8 @@ foreach ident : [
['mount_setattr', '''#include <sys/mount.h>'''],
['move_mount', '''#include <sys/mount.h>'''],
['open_tree', '''#include <sys/mount.h>'''],
+ ['fsopen', '''#include <sys/mount.h>'''],
+ ['fsconfig', '''#include <sys/mount.h>'''],
['getdents64', '''#include <dirent.h>'''],
]
diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h
index 793d111c55..d54e59fdf9 100644
--- a/src/basic/missing_syscall.h
+++ b/src/basic/missing_syscall.h
@@ -593,6 +593,46 @@ static inline int missing_move_mount(
/* ======================================================================= */
+#if !HAVE_FSOPEN
+
+#ifndef FSOPEN_CLOEXEC
+#define FSOPEN_CLOEXEC 0x00000001
+#endif
+
+static inline int missing_fsopen(const char *fsname, unsigned flags) {
+# if defined __NR_fsopen && __NR_fsopen >= 0
+ return syscall(__NR_fsopen, fsname, flags);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+# define fsopen missing_fsopen
+#endif
+
+/* ======================================================================= */
+
+#if !HAVE_FSCONFIG
+
+#ifndef FSCONFIG_SET_STRING
+#define FSCONFIG_SET_STRING 1 /* Set parameter, supplying a string value */
+#endif
+
+static inline int missing_fsconfig(int fd, unsigned cmd, const char *key, const void *value, int aux) {
+# if defined __NR_fsconfig && __NR_fsconfig >= 0
+ return syscall(__NR_fsconfig, fd, cmd, key, value, aux);
+# else
+ errno = ENOSYS;
+ return -1;
+# endif
+}
+
+# define fsconfig missing_fsconfig
+#endif
+
+/* ======================================================================= */
+
#if !HAVE_GETDENTS64
static inline ssize_t missing_getdents64(int fd, void *buffer, size_t length) {
diff --git a/src/core/namespace.c b/src/core/namespace.c
index c3cced7410..852be3bdde 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -26,6 +26,7 @@
#include "list.h"
#include "loop-util.h"
#include "loopback-setup.h"
+#include "missing_syscall.h"
#include "mkdir-label.h"
#include "mount-util.h"
#include "mountpoint-util.h"
@@ -1073,6 +1074,27 @@ static int mount_sysfs(const MountEntry *m) {
return 1;
}
+static bool mount_option_supported(const char *fstype, const char *key, const char *value) {
+ _cleanup_close_ int fd = -1;
+ int r;
+
+ /* This function assumes support by default. Only if the fsconfig() call fails with -EINVAL/-EOPNOTSUPP
+ * will it report that the option/value is not supported. */
+
+ fd = fsopen(fstype, FSOPEN_CLOEXEC);
+ if (fd < 0) {
+ if (errno != ENOSYS)
+ log_debug_errno(errno, "Failed to open superblock context for '%s': %m", fstype);
+ return true; /* If fsopen() fails for whatever reason, assume the value is supported. */
+ }
+
+ r = fsconfig(fd, FSCONFIG_SET_STRING, key, value, 0);
+ if (r < 0 && !IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS))
+ log_debug_errno(errno, "Failed to set '%s=%s' on '%s' superblock context: %m", key, value, fstype);
+
+ return r >= 0 || !IN_SET(errno, EINVAL, EOPNOTSUPP);
+}
+
static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {
_cleanup_free_ char *opts = NULL;
const char *entry_path;
@@ -1090,12 +1112,25 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {
* per-instance, we'll exclusively use the textual value for hidepid=, since support was
* added in the same commit: if it's supported it is thus also per-instance. */
- opts = strjoin("hidepid=",
- ns_info->protect_proc == PROTECT_PROC_DEFAULT ? "off" :
- protect_proc_to_string(ns_info->protect_proc),
- ns_info->proc_subset == PROC_SUBSET_PID ? ",subset=pid" : "");
- if (!opts)
- return -ENOMEM;
+ const char *hpv = ns_info->protect_proc == PROTECT_PROC_DEFAULT ?
+ "off" :
+ protect_proc_to_string(ns_info->protect_proc);
+
+ /* hidepid= support was added in 5.8, so we can use fsconfig()/fsopen() (which were added in
+ * 5.2) to check if hidepid= is supported. This avoids a noisy dmesg log by the kernel when
+ * trying to use hidepid= on systems where it isn't supported. The same applies for subset=.
+ * fsopen()/fsconfig() was also backported on some distros which allows us to detect
+ * hidepid=/subset= support in even more scenarios. */
+
+ if (mount_option_supported("proc", "hidepid", hpv)) {
+ opts = strjoin("hidepid=", hpv);
+ if (!opts)
+ return -ENOMEM;
+ }
+
+ if (ns_info->proc_subset == PROC_SUBSET_PID && mount_option_supported("proc", "subset", "pid"))
+ if (!strextend_with_separator(&opts, ",", "subset=pid"))
+ return -ENOMEM;
}
entry_path = mount_entry_path(m);

@ -0,0 +1,75 @@
From 07f188e9ca17345af904e6549c03b1c57d34405a Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 1 Nov 2022 09:17:58 +0100
Subject: [PATCH] test: add a couple of sanity tests for loginctl
(cherry picked from commit 70e9066bc2eaf159e9cde7d95bbee99e44f3045a)
Related #2138081
---
test/units/testsuite-35.sh | 45 ++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/test/units/testsuite-35.sh b/test/units/testsuite-35.sh
index 4ef0f0c11c..85925f2471 100755
--- a/test/units/testsuite-35.sh
+++ b/test/units/testsuite-35.sh
@@ -338,6 +338,50 @@ EOF
assert_eq "$(loginctl --no-legend | awk '$3=="logind-test-user" { print $5 }')" "tty2"
}
+test_sanity_check() {
+ # Exercise basic loginctl options
+
+ if [[ ! -c /dev/tty2 ]]; then
+ echo "/dev/tty2 does not exist, skipping test ${FUNCNAME[0]}."
+ return
+ fi
+
+ trap cleanup_session RETURN
+ create_session
+
+ # Run most of the loginctl commands from a user session to make
+ # the seat/session autodetection work-ish
+ systemd-run --user --pipe --wait -M "logind-test-user@.host" bash -eux <<\EOF
+ loginctl list-sessions
+ loginctl session-status
+ loginctl show-session
+ loginctl show-session -P DelayInhibited
+
+ # We're not in the same session scope, so in this case we need to specify
+ # the session ID explicitly
+ session=$(loginctl --no-legend | awk '$3 == "logind-test-user" { print $1; exit; }')
+ loginctl kill-session --signal=SIGCONT "$session"
+ # FIXME(?)
+ #loginctl kill-session --signal=SIGCONT --kill-who=leader "$session"
+
+ loginctl list-users
+ loginctl user-status
+ loginctl show-user -a
+ loginctl show-user -P IdleAction
+ loginctl kill-user --signal=SIGCONT ""
+
+ loginctl list-seats
+ loginctl seat-status
+ loginctl show-seat
+ loginctl show-seat -P IdleActionUSec
+EOF
+
+ # Requires root privileges
+ loginctl lock-sessions
+ loginctl unlock-sessions
+ loginctl flush-devices
+}
+
test_session() {
local dev
@@ -537,6 +581,7 @@ test_properties
test_started
test_suspend_on_lid
test_shutdown
+test_sanity_check
test_session
test_lock_idle_action
test_session_properties

@ -0,0 +1,48 @@
From 66a9a36c3bcd5709c30ac1f2be998eea034a9f6d Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 1 Nov 2022 17:53:42 +0100
Subject: [PATCH] test: rename TEST-26-SETENV to TEST-26-SYSTEMCTL
(cherry picked from commit c5c258ae0a4a0cfc829ed07ff96c7fab79b6ca71)
Related #2138081
---
test/{TEST-26-SETENV => TEST-26-SYSTEMCTL}/Makefile | 0
test/{TEST-26-SETENV => TEST-26-SYSTEMCTL}/test.sh | 2 +-
test/units/testsuite-26.service | 2 +-
3 files changed, 2 insertions(+), 2 deletions(-)
rename test/{TEST-26-SETENV => TEST-26-SYSTEMCTL}/Makefile (100%)
rename test/{TEST-26-SETENV => TEST-26-SYSTEMCTL}/test.sh (79%)
diff --git a/test/TEST-26-SETENV/Makefile b/test/TEST-26-SYSTEMCTL/Makefile
similarity index 100%
rename from test/TEST-26-SETENV/Makefile
rename to test/TEST-26-SYSTEMCTL/Makefile
diff --git a/test/TEST-26-SETENV/test.sh b/test/TEST-26-SYSTEMCTL/test.sh
similarity index 79%
rename from test/TEST-26-SETENV/test.sh
rename to test/TEST-26-SYSTEMCTL/test.sh
index b38e37bfce..64accf850f 100755
--- a/test/TEST-26-SETENV/test.sh
+++ b/test/TEST-26-SYSTEMCTL/test.sh
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
-TEST_DESCRIPTION="test setenv"
+TEST_DESCRIPTION="systemctl-related tests"
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
diff --git a/test/units/testsuite-26.service b/test/units/testsuite-26.service
index aa553b61a6..d8fdaffb06 100644
--- a/test/units/testsuite-26.service
+++ b/test/units/testsuite-26.service
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
-Description=TEST-26-SETENV
+Description=TEST-26-SYSTEMCTL
[Service]
ExecStartPre=rm -f /failed /testok

@ -0,0 +1,251 @@
From 680d2b33d3b2a0bed17c2c1594690155bdb910bb Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 1 Nov 2022 20:47:37 +0100
Subject: [PATCH] test: add a couple of sanity tests for systemctl
(cherry picked from commit d16684fe13e1d56e55df19b57b6c01b9a9303086)
Related #2138081
---
test/units/testsuite-26.sh | 209 +++++++++++++++++++++++++++++++++++--
1 file changed, 202 insertions(+), 7 deletions(-)
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index ad08415317..b83f85917b 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -3,32 +3,227 @@
set -eux
set -o pipefail
+at_exit() {
+ if [[ -v UNIT_NAME && -e "/usr/lib/systemd/system/$UNIT_NAME" ]]; then
+ rm -fv "/usr/lib/systemd/system/$UNIT_NAME"
+ fi
+}
+
+trap at_exit EXIT
+
+# Create a simple unit file for testing
+# Note: the service file is created under /usr on purpose to test
+# the 'revert' verb as well
+UNIT_NAME="systemctl-test-$RANDOM.service"
+cat >"/usr/lib/systemd/system/$UNIT_NAME" <<\EOF
+[Unit]
+Description=systemctl test
+
+[Service]
+ExecStart=sleep infinity
+ExecReload=true
+
+# For systemctl clean
+CacheDirectory=%n
+ConfigurationDirectory=%n
+LogsDirectory=%n
+RuntimeDirectory=%n
+StateDirectory=%n
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+# Configure the preset setting for the unit file
+mkdir /run/systemd/system-preset/
+echo "disable $UNIT_NAME" >/run/systemd/system-preset/99-systemd-test.preset
+
+systemctl daemon-reload
+
+# Argument help
+systemctl --state help
+systemctl --signal help
+systemctl --type help
+
+# list-dependencies
+systemctl list-dependencies systemd-journald
+systemctl list-dependencies --after systemd-journald
+systemctl list-dependencies --before systemd-journald
+systemctl list-dependencies --after --reverse systemd-journald
+systemctl list-dependencies --before --reverse systemd-journald
+systemctl list-dependencies --plain systemd-journald
+
+# list-* verbs
+systemctl list-units
+systemctl list-units --recursive
+systemctl list-units --type=socket
+systemctl list-units --type=service,timer
+systemctl list-units --legend=yes -a "systemd-*"
+systemctl list-units --state=active
+systemctl list-units --with-dependencies systemd-journald.service
+systemctl list-units --with-dependencies --after systemd-journald.service
+systemctl list-units --with-dependencies --before --reverse systemd-journald.service
+systemctl list-sockets
+systemctl list-sockets --legend=no -a "*journal*"
+systemctl list-sockets --show-types
+systemctl list-sockets --state=listening
+systemctl list-timers -a -l
+systemctl list-unit-files
+systemctl list-unit-files "*journal*"
+systemctl list-jobs
+systemctl list-jobs --after
+systemctl list-jobs --before
+systemctl list-jobs --after --before
+systemctl list-jobs "*"
+
+# Basic service management
+systemctl start --show-transaction "$UNIT_NAME"
+systemctl status -n 5 "$UNIT_NAME"
+systemctl is-active "$UNIT_NAME"
+systemctl reload -T "$UNIT_NAME"
+systemctl restart -T "$UNIT_NAME"
+systemctl try-restart --show-transaction "$UNIT_NAME"
+systemctl try-reload-or-restart --show-transaction "$UNIT_NAME"
+systemctl kill "$UNIT_NAME"
+(! systemctl is-active "$UNIT_NAME")
+systemctl restart "$UNIT_NAME"
+systemctl is-active "$UNIT_NAME"
+systemctl restart "$UNIT_NAME"
+systemctl stop "$UNIT_NAME"
+(! systemctl is-active "$UNIT_NAME")
+
+# enable/disable/preset
+(! systemctl is-enabled "$UNIT_NAME")
+systemctl enable "$UNIT_NAME"
+systemctl is-enabled -l "$UNIT_NAME"
+# We created a preset file for this unit above with a "disable" policy
+systemctl preset "$UNIT_NAME"
+(! systemctl is-enabled "$UNIT_NAME")
+systemctl reenable "$UNIT_NAME"
+systemctl is-enabled "$UNIT_NAME"
+systemctl preset --preset-mode=enable-only "$UNIT_NAME"
+systemctl is-enabled "$UNIT_NAME"
+systemctl preset --preset-mode=disable-only "$UNIT_NAME"
+(! systemctl is-enabled "$UNIT_NAME")
+systemctl enable --runtime "$UNIT_NAME"
+[[ -e "/run/systemd/system/multi-user.target.wants/$UNIT_NAME" ]]
+systemctl is-enabled "$UNIT_NAME"
+systemctl disable "$UNIT_NAME"
+# The unit should be still enabled, as we didn't use the --runtime switch
+systemctl is-enabled "$UNIT_NAME"
+systemctl disable --runtime "$UNIT_NAME"
+(! systemctl is-enabled "$UNIT_NAME")
+
+# mask/unmask/revert
+systemctl disable "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
+systemctl mask "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked ]]
+systemctl unmask "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
+systemctl mask "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked ]]
+systemctl revert "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
+systemctl mask --runtime "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked-runtime ]]
+# This should be a no-op without the --runtime switch
+systemctl unmask "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked-runtime ]]
+systemctl unmask --runtime "$UNIT_NAME"
+[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
+
+# add-wants/add-requires
+(! systemctl show -P Wants "$UNIT_NAME" | grep "systemd-journald.service")
+systemctl add-wants "$UNIT_NAME" "systemd-journald.service"
+systemctl show -P Wants "$UNIT_NAME" | grep "systemd-journald.service"
+(! systemctl show -P Requires "$UNIT_NAME" | grep "systemd-journald.service")
+systemctl add-requires "$UNIT_NAME" "systemd-journald.service"
+systemctl show -P Requires "$UNIT_NAME" | grep "systemd-journald.service"
+
+# set-property
+systemctl set-property "$UNIT_NAME" IPAccounting=yes MemoryMax=1234567
+systemctl cat "$UNIT_NAME"
+# These properties should be saved to a persistent storage
+grep -r "IPAccounting=yes" "/etc/systemd/system.control/${UNIT_NAME}.d/"
+grep -r "MemoryMax=1234567" "/etc/systemd/system.control/${UNIT_NAME}.d"
+systemctl revert "$UNIT_NAME"
+(! grep -r "IPAccounting=" "/etc/systemd/system.control/${UNIT_NAME}.d/")
+(! grep -r "MemoryMax=" "/etc/systemd/system.control/${UNIT_NAME}.d/")
+# Same stuff, but with --runtime, which should use /run
+systemctl set-property --runtime "$UNIT_NAME" CPUAccounting=no CPUQuota=10%
+systemctl cat "$UNIT_NAME"
+grep -r "CPUAccounting=no" "/run/systemd/system.control/${UNIT_NAME}.d/"
+grep -r "CPUQuota=10%" "/run/systemd/system.control/${UNIT_NAME}.d/"
+systemctl revert "$UNIT_NAME"
+(! grep -r "CPUAccounting=" "/run/systemd/system.control/${UNIT_NAME}.d/")
+(! grep -r "CPUQuota=" "/run/systemd/system.control/${UNIT_NAME}.d/")
+
+# Failed-unit related tests
+systemd-run --unit "failed.service" /bin/false
+systemctl is-failed failed.service
+systemctl --state=failed | grep failed.service
+systemctl --failed | grep failed.service
+systemctl reset-failed "fail*.service"
+(! systemctl is-failed failed.service)
+
+# clean
+systemctl restart "$UNIT_NAME"
+systemctl stop "$UNIT_NAME"
+# Check if the directories from *Directory= directives exist
+# (except RuntimeDirectory= in /run, which is removed when the unit is stopped)
+for path in /var/lib /var/cache /var/log /etc; do
+ [[ -e "$path/$UNIT_NAME" ]]
+done
+# Run the cleanup
+for what in "" configuration state cache logs runtime all; do
+ systemctl clean ${what:+--what="$what"} "$UNIT_NAME"
+done
+# All respective directories should be removed
+for path in /run /var/lib /var/cache /var/log /etc; do
+ [[ ! -e "$path/$UNIT_NAME" ]]
+done
+
+# --timestamp
+for value in pretty us µs utc us+utc µs+utc; do
+ systemctl show -P KernelTimestamp --timestamp="$value"
+done
+
+# Aux verbs & assorted checks
+systemctl is-active "*-journald.service"
+systemctl cat "*journal*"
+systemctl cat "$UNIT_NAME"
+systemctl help "$UNIT_NAME"
+
+# show/set-environment
# Make sure PATH is set
systemctl show-environment | grep -q '^PATH='
-
# Let's add an entry and override a built-in one
systemctl set-environment PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/testaddition FOO=BAR
-
# Check that both are set
systemctl show-environment | grep -q '^PATH=.*testaddition$'
systemctl show-environment | grep -q '^FOO=BAR$'
-
systemctl daemon-reload
-
# Check again after the reload
systemctl show-environment | grep -q '^PATH=.*testaddition$'
systemctl show-environment | grep -q '^FOO=BAR$'
-
# Check that JSON output is supported
systemctl show-environment --output=json | grep -q '^{.*"FOO":"BAR".*}$'
-
# Drop both
systemctl unset-environment FOO PATH
-
# Check that one is gone and the other reverted to the built-in
systemctl show-environment | grep '^FOO=$' && exit 1
systemctl show-environment | grep '^PATH=.*testaddition$' && exit 1
systemctl show-environment | grep -q '^PATH='
+# Check import-environment
+export IMPORT_THIS=hello
+export IMPORT_THIS_TOO=world
+systemctl import-environment IMPORT_THIS IMPORT_THIS_TOO
+systemctl show-environment | grep "^IMPORT_THIS=$IMPORT_THIS"
+systemctl show-environment | grep "^IMPORT_THIS_TOO=$IMPORT_THIS_TOO"
+systemctl unset-environment IMPORT_THIS IMPORT_THIS_TOO
+(! systemctl show-environment | grep "^IMPORT_THIS=")
+(! systemctl show-environment | grep "^IMPORT_THIS_TOO=")
echo OK >/testok

@ -0,0 +1,49 @@
From a9424191821c8c967edd7dd92a19d02ff5bbca87 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 2 Nov 2022 07:06:46 +0900
Subject: [PATCH] core: fix memleak in GetUnitFileLinks method
(cherry picked from commit a12ba535fa677e642c7ba19e81062ed6e9365ceb)
Related #2138081
---
src/core/dbus-manager.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 919aa58cde..88f098ec86 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -2647,21 +2647,27 @@ static int method_get_unit_file_links(sd_bus_message *message, void *userdata, s
(runtime ? UNIT_FILE_RUNTIME : 0);
r = unit_file_disable(LOOKUP_SCOPE_SYSTEM, flags, NULL, p, &changes, &n_changes);
- if (r < 0)
- return log_error_errno(r, "Failed to get file links for %s: %m", name);
+ if (r < 0) {
+ log_error_errno(r, "Failed to get file links for %s: %m", name);
+ goto finish;
+ }
for (i = 0; i < n_changes; i++)
if (changes[i].type == INSTALL_CHANGE_UNLINK) {
r = sd_bus_message_append(reply, "s", changes[i].path);
if (r < 0)
- return r;
+ goto finish;
}
r = sd_bus_message_close_container(reply);
if (r < 0)
- return r;
+ goto finish;
- return sd_bus_send(NULL, reply, NULL);
+ r = sd_bus_send(NULL, reply, NULL);
+
+finish:
+ install_changes_free(changes, n_changes);
+ return r;
}
static int method_get_job_waiting(sd_bus_message *message, void *userdata, sd_bus_error *error) {

@ -0,0 +1,42 @@
From ada95dd4f4c0014815a2c3162de6297107569b05 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 2 Nov 2022 11:48:23 +0100
Subject: [PATCH] man: use the correct 'Markers' property name for marking
units
Follow-up to c9615f7352 and 70666e28a1.
(cherry picked from commit 1ca1bb03dec9ae3e8d734bd40eeb60210ffd7a0a)
Related #2138081
---
man/org.freedesktop.systemd1.xml | 2 +-
man/systemctl.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index cbd552bd99..5e08b35234 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -1250,7 +1250,7 @@ node /org/freedesktop/systemd1 {
"ReloadOrRestart" flavors attempt a reload if the unit supports it and use a restart otherwise.</para>
<para><function>EnqueueMarkedJobs()</function> creates reload/restart jobs for units which have been
- appropriately marked, see <varname>Marks</varname> property above. This is equivalent to calling
+ appropriately marked, see <varname>Markers</varname> property above. This is equivalent to calling
<function>TryRestartUnit()</function> or <function>ReloadOrTryRestartUnit()</function> for the marked
units.</para>
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 4d4f6c3992..997925892d 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -2386,7 +2386,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<listitem><para>Only allowed with <command>reload-or-restart</command>. Enqueues restart jobs for all
units that have the <literal>needs-restart</literal> mark, and reload jobs for units that have the
<literal>needs-reload</literal> mark. When a unit marked for reload does not support reload, restart
- will be queued. Those properties can be set using <command>set-property Marks</command>.</para>
+ will be queued. Those properties can be set using <command>set-property Markers=…</command>.</para>
<para>Unless <option>--no-block</option> is used, <command>systemctl</command> will wait for the
queued jobs to finish.</para></listitem>

@ -0,0 +1,115 @@
From cce2e337e37524df5ff81e758dbcfa91bf8b696a Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 2 Nov 2022 11:44:00 +0100
Subject: [PATCH] test: further extend systemctl's sanity coverage
Also, fix a race condition introduced by d16684fe13:
```
[ 16.904218] H testsuite-26.sh[394]: + systemd-run --unit failed.service /bin/false
[ 16.964783] H systemd[845]: failed.service: Executing: /bin/false
[ 16.965062] H systemd[1]: Started failed.service.
[ 16.965462] H testsuite-26.sh[844]: Running as unit: failed.service
[ 16.966390] H testsuite-26.sh[394]: + systemctl is-failed failed.service
[ 16.977970] H testsuite-26.sh[846]: active
[ 16.978403] H systemd[1]: failed.service: Main process exited, code=exited, status=1/FAILURE
[ 16.978478] H systemd[1]: failed.service: Failed with result 'exit-code'.
```
(cherry picked from commit 23f3a6f5ff864fd26063c6c35fdaa6d85de566c7)
Related #2138081
---
test/units/testsuite-26.sh | 61 +++++++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index b83f85917b..7c7a12b1ae 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -58,6 +58,9 @@ systemctl list-units
systemctl list-units --recursive
systemctl list-units --type=socket
systemctl list-units --type=service,timer
+# Compat: --type= allows load states for compatibility reasons
+systemctl list-units --type=loaded
+systemctl list-units --type=loaded,socket
systemctl list-units --legend=yes -a "systemd-*"
systemctl list-units --state=active
systemctl list-units --with-dependencies systemd-journald.service
@@ -160,7 +163,7 @@ systemctl revert "$UNIT_NAME"
(! grep -r "CPUQuota=" "/run/systemd/system.control/${UNIT_NAME}.d/")
# Failed-unit related tests
-systemd-run --unit "failed.service" /bin/false
+(! systemd-run --wait --unit "failed.service" /bin/false)
systemctl is-failed failed.service
systemctl --state=failed | grep failed.service
systemctl --failed | grep failed.service
@@ -189,11 +192,67 @@ for value in pretty us µs utc us+utc µs+utc; do
systemctl show -P KernelTimestamp --timestamp="$value"
done
+# set-default/get-default
+target="$(systemctl get-default)"
+systemctl set-default emergency.target
+[[ "$(systemctl get-default)" == emergency.target ]]
+systemctl set-default "$target"
+[[ "$(systemctl get-default)" == "$target" ]]
+
+# show/status
+systemctl show --property ""
+# Pick a heavily sandboxed unit for the best effect on coverage
+systemctl show systemd-logind.service
+systemctl status
+# Ignore the exit code in this case, as it might try to load non-existing units
+systemctl status -a >/dev/null || :
+systemctl status -a --state active,running,plugged >/dev/null
+systemctl status "systemd-*.timer"
+systemctl status "systemd-journald*.socket"
+systemctl status "sys-devices-*-ttyS0.device"
+systemctl status -- -.mount
+
+# --marked
+systemctl restart "$UNIT_NAME"
+systemctl set-property "$UNIT_NAME" Markers=needs-restart
+systemctl show -P Markers "$UNIT_NAME" | grep needs-restart
+systemctl reload-or-restart --marked
+(! systemctl show -P Markers "$UNIT_NAME" | grep needs-restart)
+
+# --dry-run with destructive verbs
+# kexec is skipped intentionally, as it requires a bit more involved setup
+VERBS=(
+ default
+ emergency
+ exit
+ halt
+ hibernate
+ hybrid-sleep
+ poweroff
+ reboot
+ rescue
+ suspend
+ suspend-then-hibernate
+)
+
+for verb in "${VERBS[@]}"; do
+ systemctl --dry-run "$verb"
+
+ if [[ "$verb" =~ (halt|poweroff|reboot) ]]; then
+ systemctl --dry-run --message "Hello world" "$verb"
+ systemctl --dry-run --no-wall "$verb"
+ systemctl --dry-run -f "$verb"
+ systemctl --dry-run -ff "$verb"
+ fi
+done
+
# Aux verbs & assorted checks
systemctl is-active "*-journald.service"
systemctl cat "*journal*"
systemctl cat "$UNIT_NAME"
systemctl help "$UNIT_NAME"
+systemctl service-watchdogs
+systemctl service-watchdogs "$(systemctl service-watchdogs)"
# show/set-environment
# Make sure PATH is set

@ -0,0 +1,131 @@
From d68d785ba0e3ecd59a2678fe00fbd7b1bde90622 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 2 Nov 2022 17:51:51 +0100
Subject: [PATCH] test: add a sanity coverage for systemd-analyze verbs
(cherry picked from commit 6c83054c0133eb53245e479d71589dceff76cf74)
Related #2138081
---
test/units/testsuite-65.sh | 108 +++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh
index 64ce629f3b..ece6b8734e 100755
--- a/test/units/testsuite-65.sh
+++ b/test/units/testsuite-65.sh
@@ -9,6 +9,114 @@ set -eux
systemd-analyze log-level debug
export SYSTEMD_LOG_LEVEL=debug
+# Sanity checks
+#
+# We can't really test time, blame, critical-chain and plot verbs here, as
+# the testsuite service is a part of the boot transaction, so let's assume
+# they fail
+systemd-analyze || :
+systemd-analyze time || :
+systemd-analyze blame || :
+systemd-analyze critical-chain || :
+systemd-analyze plot >/dev/null || :
+# dot
+systemd-analyze dot >/dev/null
+systemd-analyze dot systemd-journald.service >/dev/null
+systemd-analyze dot systemd-journald.service systemd-logind.service >/dev/null
+systemd-analyze dot --from-pattern="*" --from-pattern="*.service" systemd-journald.service >/dev/null
+systemd-analyze dot --to-pattern="*" --to-pattern="*.service" systemd-journald.service >/dev/null
+systemd-analyze dot --from-pattern="*.service" --to-pattern="*.service" systemd-journald.service >/dev/null
+systemd-analyze dot --order systemd-journald.service systemd-logind.service >/dev/null
+systemd-analyze dot --require systemd-journald.service systemd-logind.service >/dev/null
+systemd-analyze dot "systemd-*.service" >/dev/null
+(! systemd-analyze dot systemd-journald.service systemd-logind.service "*" bbb ccc)
+# dump
+systemd-analyze dump >/dev/null
+systemd-analyze dump "*" >/dev/null
+systemd-analyze dump "*.socket" >/dev/null
+systemd-analyze dump systemd-journald.service >/dev/null
+(! systemd-analyze dump "")
+# unit-paths
+systemd-analyze unit-paths
+systemd-analyze unit-paths --user
+systemd-analyze unit-paths --global
+# exist-status
+systemd-analyze exit-status
+systemd-analyze exit-status STDOUT BPF
+systemd-analyze exit-status 0 1 {63..65}
+(! systemd-analyze exit-status STDOUT BPF "hello*")
+# capability
+systemd-analyze capability
+systemd-analyze capability cap_chown CAP_KILL
+systemd-analyze capability 0 1 {30..32}
+(! systemd-analyze capability cap_chown CAP_KILL "hello*")
+# condition
+mkdir -p /run/systemd/system
+UNIT_NAME="analyze-condition-$RANDOM.service"
+cat >"/run/systemd/system/$UNIT_NAME" <<EOF
+[Unit]
+AssertPathExists=/etc/os-release
+AssertEnvironment=!FOOBAR
+ConditionKernelVersion=>1.0
+ConditionPathExists=/etc/os-release
+
+[Service]
+ExecStart=/bin/true
+EOF
+systemctl daemon-reload
+systemd-analyze condition --unit="$UNIT_NAME"
+systemd-analyze condition 'ConditionKernelVersion = ! <4.0' \
+ 'ConditionKernelVersion = >=3.1' \
+ 'ConditionACPower=|false' \
+ 'ConditionArchitecture=|!arm' \
+ 'AssertPathExists=/etc/os-release'
+(! systemd-analyze condition 'ConditionArchitecture=|!arm' 'AssertXYZ=foo')
+(! systemd-analyze condition 'ConditionKernelVersion=<1.0')
+(! systemd-analyze condition 'AssertKernelVersion=<1.0')
+# syscall-filter
+systemd-analyze syscall-filter >/dev/null
+systemd-analyze syscall-filter @chown @sync
+systemd-analyze syscall-filter @sync @sync @sync
+(! systemd-analyze syscall-filter @chown @sync @foobar)
+# filesystems (requires libbpf support)
+if systemctl --version | grep "+BPF_FRAMEWORK"; then
+ systemd-analyze filesystems >/dev/null
+ systemd-analyze filesystems @basic-api
+ systemd-analyze filesystems @basic-api @basic-api @basic-api
+ (! systemd-analyze filesystems @basic-api @basic-api @foobar @basic-api)
+fi
+# calendar
+systemd-analyze calendar '*-2-29 0:0:0'
+systemd-analyze calendar --iterations=5 '*-2-29 0:0:0'
+systemd-analyze calendar '*-* *:*:*'
+systemd-analyze calendar --iterations=5 '*-* *:*:*'
+systemd-analyze calendar --iterations=50 '*-* *:*:*'
+systemd-analyze calendar --iterations=0 '*-* *:*:*'
+systemd-analyze calendar --base-time=yesterday --iterations=5 '*-* *:*:*'
+(! systemd-analyze calendar --iterations=0 '*-* 99:*:*')
+(! systemd-analyze calendar --base-time=never '*-* *:*:*')
+(! systemd-analyze calendar 1)
+(! systemd-analyze calendar "")
+# timestamp
+systemd-analyze timestamp now
+systemd-analyze timestamp -- -1
+systemd-analyze timestamp yesterday now tomorrow
+(! systemd-analyze timestamp yesterday never tomorrow)
+(! systemd-analyze timestamp 1)
+(! systemd-analyze timestamp "")
+# timespan
+systemd-analyze timespan 1
+systemd-analyze timespan 1s 300s '1year 0.000001s'
+(! systemd-analyze timespan 1s 300s aaaaaa '1year 0.000001s')
+(! systemd-analyze timespan -- -1)
+(! systemd-analyze timespan "")
+# cat-config
+systemd-analyze cat-config systemd/system.conf >/dev/null
+systemd-analyze cat-config /etc/systemd/system.conf >/dev/null
+systemd-analyze cat-config systemd/system.conf systemd/journald.conf >/dev/null
+systemd-analyze cat-config systemd/system.conf foo/bar systemd/journald.conf >/dev/null
+systemd-analyze cat-config foo/bar
+
mkdir -p /tmp/img/usr/lib/systemd/system/
mkdir -p /tmp/img/opt/

@ -0,0 +1,37 @@
From 080747ee6685b9c5877073c5120375e7a04d8216 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 3 Nov 2022 09:39:36 +0900
Subject: [PATCH] udev: first set properties based on usb subsystem
After 479da1107a0d4e2f7ef5cd938512b87a0e45f180, the usb_id builtin
command does not set ID_SERIAL if ID_BUS is already set.
Before the commit, all properties set based on pci bus were overwritten
by the usb_id, hence now it is sufficient setting them only when ID_BUS is
not set yet.
Fixes #25238.
(cherry picked from commit 01e704eba982fbc1517287cd261d229ff8e0a779)
Related #2138081
---
rules.d/60-serial.rules | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/rules.d/60-serial.rules b/rules.d/60-serial.rules
index f303e27fd5..c133f26109 100644
--- a/rules.d/60-serial.rules
+++ b/rules.d/60-serial.rules
@@ -3,9 +3,10 @@
ACTION=="remove", GOTO="serial_end"
SUBSYSTEM!="tty", GOTO="serial_end"
-SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}"
-SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
+SUBSYSTEMS=="pci", ENV{ID_BUS}=="", ENV{ID_BUS}="pci", \
+ ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}", \
+ IMPORT{builtin}="hwdb --subsystem=pci"
# /dev/serial/by-path/, /dev/serial/by-id/ for USB devices
KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end"

@ -0,0 +1,30 @@
From 35ec16bfef92d072edacad892fc138b3595ee69b Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 3 Nov 2022 09:43:14 +0900
Subject: [PATCH] udev: drop redundant call of usb_id and assignment of
ID_USB_INTERFACE_NUM
The usb_id builtin command is already called in the above, and the
command sets the ID_USB_INTERFACE_NUM property.
(cherry picked from commit b2e53f5a0f12db65c88404477fedee5c57d201ba)
Related #2138081
---
rules.d/60-serial.rules | 2 --
1 file changed, 2 deletions(-)
diff --git a/rules.d/60-serial.rules b/rules.d/60-serial.rules
index c133f26109..2c1488e930 100644
--- a/rules.d/60-serial.rules
+++ b/rules.d/60-serial.rules
@@ -17,9 +17,7 @@ IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}"
-IMPORT{builtin}="usb_id"
ENV{ID_SERIAL}=="", GOTO="serial_end"
-SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACE_NUM}="$attr{bInterfaceNumber}"
ENV{ID_USB_INTERFACE_NUM}=="", GOTO="serial_end"
ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}"
ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}-port$env{.ID_PORT}"

@ -0,0 +1,26 @@
From 03bb31bbb875e20da7ae37eb44e98d244823e0e7 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 3 Nov 2022 09:52:23 +0900
Subject: [PATCH] udev: add safe guard for setting by-id symlink
The ID_BUS property is necessary for creating by-id symlinks.
(cherry picked from commit 5286da064c97d2ac934cb301066aaa8605a3c8f9)
Related #2138081
---
rules.d/60-serial.rules | 1 +
1 file changed, 1 insertion(+)
diff --git a/rules.d/60-serial.rules b/rules.d/60-serial.rules
index 2c1488e930..a0e66323a9 100644
--- a/rules.d/60-serial.rules
+++ b/rules.d/60-serial.rules
@@ -17,6 +17,7 @@ IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}"
+ENV{ID_BUS}=="", GOTO="serial_end"
ENV{ID_SERIAL}=="", GOTO="serial_end"
ENV{ID_USB_INTERFACE_NUM}=="", GOTO="serial_end"
ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}"

@ -0,0 +1,45 @@
From 266baa71dbb336d9c2eb1e4e7db3983477cc6ce0 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 3 Nov 2022 10:59:38 +0100
Subject: [PATCH] test: cover legacy/deprecated systemd-analyze verbs
They're no longer documented since 26e1e97345 but still work.
(cherry picked from commit 926d95cd4c209b8c292829511542b11d7c43e662)
Related #2138081
---
test/units/testsuite-65.sh | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh
index ece6b8734e..89406a108e 100755
--- a/test/units/testsuite-65.sh
+++ b/test/units/testsuite-65.sh
@@ -6,7 +6,7 @@ set -eux
# shellcheck source=test/units/assert.sh
. "$(dirname "$0")"/assert.sh
-systemd-analyze log-level debug
+systemctl log-level debug
export SYSTEMD_LOG_LEVEL=debug
# Sanity checks
@@ -19,6 +19,17 @@ systemd-analyze time || :
systemd-analyze blame || :
systemd-analyze critical-chain || :
systemd-analyze plot >/dev/null || :
+# legacy/deprecated options (moved to systemctl, but still usable from analyze)
+systemd-analyze log-level
+systemd-analyze log-level "$(systemctl log-level)"
+systemd-analyze get-log-level
+systemd-analyze set-log-level "$(systemctl log-level)"
+systemd-analyze log-target
+systemd-analyze log-target "$(systemctl log-target)"
+systemd-analyze get-log-target
+systemd-analyze set-log-target "$(systemctl log-target)"
+systemd-analyze service-watchdogs
+systemd-analyze service-watchdogs "$(systemctl service-watchdogs)"
# dot
systemd-analyze dot >/dev/null
systemd-analyze dot systemd-journald.service >/dev/null

@ -0,0 +1,56 @@
From 37614533602981aa3757cd3e847f184fdae1432e Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 3 Nov 2022 11:33:13 +0100
Subject: [PATCH] test: cover a couple of previously missed analyze code paths
(cherry picked from commit 8b1879bcd0ed1168f5ad35a3dd0e213a31a2ee42)
Related #2138081
---
test/units/testsuite-65.sh | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh
index 89406a108e..1f34308b44 100755
--- a/test/units/testsuite-65.sh
+++ b/test/units/testsuite-65.sh
@@ -45,8 +45,16 @@ systemd-analyze dot "systemd-*.service" >/dev/null
systemd-analyze dump >/dev/null
systemd-analyze dump "*" >/dev/null
systemd-analyze dump "*.socket" >/dev/null
+systemd-analyze dump "*.socket" "*.service" aaaaaaa ... >/dev/null
systemd-analyze dump systemd-journald.service >/dev/null
(! systemd-analyze dump "")
+# unit-files
+systemd-analyze unit-files >/dev/null
+systemd-analyze unit-files systemd-journald.service >/dev/null
+systemd-analyze unit-files "*" >/dev/null
+systemd-analyze unit-files "*" aaaaaa "*.service" "*.target" >/dev/null
+systemd-analyze unit-files --user >/dev/null
+systemd-analyze unit-files --user "*" aaaaaa "*.service" "*.target" >/dev/null
# unit-paths
systemd-analyze unit-paths
systemd-analyze unit-paths --user
@@ -103,6 +111,7 @@ systemd-analyze calendar '*-* *:*:*'
systemd-analyze calendar --iterations=5 '*-* *:*:*'
systemd-analyze calendar --iterations=50 '*-* *:*:*'
systemd-analyze calendar --iterations=0 '*-* *:*:*'
+systemd-analyze calendar --iterations=5 '01-01-22 01:00:00'
systemd-analyze calendar --base-time=yesterday --iterations=5 '*-* *:*:*'
(! systemd-analyze calendar --iterations=0 '*-* 99:*:*')
(! systemd-analyze calendar --base-time=never '*-* *:*:*')
@@ -114,12 +123,14 @@ systemd-analyze timestamp -- -1
systemd-analyze timestamp yesterday now tomorrow
(! systemd-analyze timestamp yesterday never tomorrow)
(! systemd-analyze timestamp 1)
+(! systemd-analyze timestamp '*-2-29 0:0:0')
(! systemd-analyze timestamp "")
# timespan
systemd-analyze timespan 1
systemd-analyze timespan 1s 300s '1year 0.000001s'
(! systemd-analyze timespan 1s 300s aaaaaa '1year 0.000001s')
(! systemd-analyze timespan -- -1)
+(! systemd-analyze timespan '*-2-29 0:0:0')
(! systemd-analyze timespan "")
# cat-config
systemd-analyze cat-config systemd/system.conf >/dev/null

@ -0,0 +1,371 @@
From e0d51a65a8bbe8c86af4bb843a5f9ac7d590fa01 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 3 Nov 2022 13:13:03 +0100
Subject: [PATCH] test: introduce sanity coverage for auxiliary utils
(cherry picked from commit d1020334fd15e0cffe68cb4d7e862a36253cc481)
Related #2138081
---
test/TEST-74-AUX-UTILS/Makefile | 1 +
test/TEST-74-AUX-UTILS/test.sh | 10 ++
test/units/testsuite-74.cgls.sh | 26 +++++
test/units/testsuite-74.cgtop.sh | 32 ++++++
test/units/testsuite-74.delta.sh | 59 +++++++++++
test/units/testsuite-74.firstboot.sh | 145 +++++++++++++++++++++++++++
test/units/testsuite-74.service | 8 ++
test/units/testsuite-74.sh | 14 +++
8 files changed, 295 insertions(+)
create mode 120000 test/TEST-74-AUX-UTILS/Makefile
create mode 100755 test/TEST-74-AUX-UTILS/test.sh
create mode 100755 test/units/testsuite-74.cgls.sh
create mode 100755 test/units/testsuite-74.cgtop.sh
create mode 100755 test/units/testsuite-74.delta.sh
create mode 100755 test/units/testsuite-74.firstboot.sh
create mode 100644 test/units/testsuite-74.service
create mode 100755 test/units/testsuite-74.sh
diff --git a/test/TEST-74-AUX-UTILS/Makefile b/test/TEST-74-AUX-UTILS/Makefile
new file mode 120000
index 0000000000..e9f93b1104
--- /dev/null
+++ b/test/TEST-74-AUX-UTILS/Makefile
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-74-AUX-UTILS/test.sh b/test/TEST-74-AUX-UTILS/test.sh
new file mode 100755
index 0000000000..f422c89141
--- /dev/null
+++ b/test/TEST-74-AUX-UTILS/test.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -e
+
+TEST_DESCRIPTION="Tests for auxiliary utilities"
+
+# shellcheck source=test/test-functions
+. "${TEST_BASE_DIR:?}/test-functions"
+
+do_test "$@"
diff --git a/test/units/testsuite-74.cgls.sh b/test/units/testsuite-74.cgls.sh
new file mode 100755
index 0000000000..120570c9cc
--- /dev/null
+++ b/test/units/testsuite-74.cgls.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+systemd-cgls
+systemd-cgls --all --full
+systemd-cgls -k
+systemd-cgls --xattr=yes
+systemd-cgls --xattr=no
+systemd-cgls --cgroup-id=yes
+systemd-cgls --cgroup-id=no
+
+systemd-cgls /system.slice/systemd-journald.service
+systemd-cgls /system.slice/systemd-journald.service /init.scope
+systemd-cgls /sys/fs/cgroup/system.slice/systemd-journald.service /init.scope
+(cd /sys/fs/cgroup/init.scope && systemd-cgls)
+systemd-cgls --unit=systemd-journald.service
+# There's most likely no user session running, so we need to create one
+systemd-run --user --wait --pipe -M testuser@.host systemd-cgls --user-unit=app.slice
+
+(! systemd-cgls /foo/bar)
+(! systemd-cgls --unit=hello.world)
+(! systemd-cgls --user-unit=hello.world)
+(! systemd-cgls --xattr=foo)
+(! systemd-cgls --cgroup-id=foo)
diff --git a/test/units/testsuite-74.cgtop.sh b/test/units/testsuite-74.cgtop.sh
new file mode 100755
index 0000000000..8141ec1b1f
--- /dev/null
+++ b/test/units/testsuite-74.cgtop.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# Without tty attached cgtop should default to --iterations=1
+systemd-cgtop
+systemd-cgtop --iterations=1
+# Same as --iterations=1
+systemd-cgtop -1
+systemd-cgtop --delay=1ms
+systemd-cgtop --raw
+systemd-cgtop --batch
+systemd-cgtop --cpu=percentage
+systemd-cgtop --cpu=time
+systemd-cgtop -P
+systemd-cgtop -k
+# FIXME: https://github.com/systemd/systemd/issues/25248
+#systemd-cgtop --recursive=no
+systemd-cgtop --depth=0
+systemd-cgtop --depth=100
+
+for order in path tasks cpu memory io; do
+ systemd-cgtop --order="$order"
+done
+systemd-cgtop -p -t -c -m -i
+
+(! systemd-cgtop --cpu=foo)
+(! systemd-cgtop --order=foo)
+(! systemd-cgtop --depth=-1)
+(! systemd-cgtop --recursive=foo)
+(! systemd-cgtop --delay=1foo)
diff --git a/test/units/testsuite-74.delta.sh b/test/units/testsuite-74.delta.sh
new file mode 100755
index 0000000000..a0e1cb52dd
--- /dev/null
+++ b/test/units/testsuite-74.delta.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+at_exit() {
+ rm -rfv /{run,etc}/systemd/system/delta-test*
+}
+
+trap at_exit EXIT
+
+# Create a couple of supporting units with overrides
+#
+# Extended unit
+cat >"/run/systemd/system/delta-test-unit-extended.service" <<EOF
+[Service]
+ExecStart=/bin/true
+EOF
+mkdir -p "/run/systemd/system/delta-test-unit-extended.service.d"
+cat >"/run/systemd/system/delta-test-unit-extended.service.d/override.conf" <<EOF
+[Unit]
+Description=Foo Bar
+[Service]
+ExecStartPre=/bin/true
+EOF
+# Masked unit
+cp -fv /run/systemd/system/delta-test-unit-extended.service /run/systemd/system/delta-test-unit-masked.service
+systemctl mask delta-test-unit-masked.service
+# Overridden unit
+cp -fv /run/systemd/system/delta-test-unit-extended.service /run/systemd/system/delta-test-unit-overridden.service
+cp -fv /run/systemd/system/delta-test-unit-overridden.service /etc/systemd/system/delta-test-unit-overridden.service
+echo "ExecStartPost=/bin/true" >>/etc/systemd/system/delta-test-unit-overridden.service
+# Overridden but equivalent unit
+ln -srfv /run/systemd/system/delta-test-unit-extended.service /run/systemd/system/delta-test-unit-equivalent.service
+ln -sfv /run/systemd/system/delta-test-unit-extended.service /etc/systemd/system/delta-test-unit-equivalent.service
+# Redirected unit
+ln -srfv /run/systemd/system/delta-test-unit-extended.service /run/systemd/system/delta-test-unit-redirected.service
+ln -sfv /run/systemd/system/delta-test-unit-overidden.service /etc/systemd/system/delta-test-unit-extended.service
+
+systemctl daemon-reload
+
+systemd-delta
+systemd-delta /run
+systemd-delta systemd/system
+systemd-delta /run systemd/system /run
+systemd-delta /run foo/bar hello/world systemd/system /run
+systemd-delta foo/bar
+systemd-delta --diff=true
+systemd-delta --diff=false
+
+for type in masked equivalent redirected overridden extended unchanged; do
+ systemd-delta --type="$type"
+ systemd-delta --type="$type" /run
+done
+systemd-delta --type=equivalent,redirected
+
+(! systemd-delta --diff=foo)
+(! systemd-delta --type=foo)
+(! systemd-delta --type=equivalent,redirected,foo)
diff --git a/test/units/testsuite-74.firstboot.sh b/test/units/testsuite-74.firstboot.sh
new file mode 100755
index 0000000000..02f9f5cd7a
--- /dev/null
+++ b/test/units/testsuite-74.firstboot.sh
@@ -0,0 +1,145 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+if ! command -v systemd-firstboot >/dev/null; then
+ echo "systemd-firstboot not found, skipping the test"
+ exit 0
+fi
+
+at_exit() {
+ if [[ -v ROOT && -n "$ROOT" ]]; then
+ ls -lR "$ROOT"
+ rm -fr "$ROOT"
+ fi
+}
+
+trap at_exit EXIT
+
+# Generated via `mkpasswd -m sha-512 -S foobarsalt password1`
+# shellcheck disable=SC2016
+ROOT_HASHED_PASSWORD1='$6$foobarsalt$YbwdaATX6IsFxvWbY3QcZj2gB31R/LFRFrjlFrJtTTqFtSfn4dfOAg/km2k4Sl.a2g7LOYDo31wMTaEsCo9j41'
+# Generated via `mkpasswd -m sha-512 -S foobarsalt password2`
+# shellcheck disable=SC2016
+ROOT_HASHED_PASSWORD2='$6$foobarsalt$q.P2932zYMLbKnjFwIxPI8y3iuxeuJ2BgE372LcZMMnj3Gcg/9mJg2LPKUl.ha0TG/.fRNNnRQcLfzM0SNot3.'
+
+# Create a minimal root so we don't modify the testbed
+ROOT=test-root
+mkdir -p "$ROOT/bin"
+# Dummy shell for --root-shell=
+touch "$ROOT/bin/fooshell" "$ROOT/bin/barshell"
+
+systemd-firstboot --root="$ROOT" --locale=foo
+grep -q "LANG=foo" "$ROOT/etc/locale.conf"
+rm -fv "$ROOT/etc/locale.conf"
+# FIXME: https://github.com/systemd/systemd/issues/25249
+#systemd-firstboot --root="$ROOT" --locale-messages=foo
+#grep -q "LC_MESSAGES=foo" "$ROOT/etc/locale.conf"
+#rm -fv "$ROOT/etc/locale.conf"
+systemd-firstboot --root="$ROOT" --locale=foo --locale-messages=bar
+grep -q "LANG=foo" "$ROOT/etc/locale.conf"
+grep -q "LC_MESSAGES=bar" "$ROOT/etc/locale.conf"
+
+systemd-firstboot --root="$ROOT" --keymap=foo
+grep -q "KEYMAP=foo" "$ROOT/etc/vconsole.conf"
+
+systemd-firstboot --root="$ROOT" --timezone=Europe/Berlin
+readlink "$ROOT/etc/localtime" | grep -q "Europe/Berlin"
+
+systemd-firstboot --root="$ROOT" --hostname "foobar"
+grep -q "foobar" "$ROOT/etc/hostname"
+
+systemd-firstboot --root="$ROOT" --machine-id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+grep -q "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "$ROOT/etc/machine-id"
+
+rm -fv "$ROOT/etc/passwd" "$ROOT/etc/shadow"
+systemd-firstboot --root="$ROOT" --root-password=foo
+grep -q "^root:x:0:0:" "$ROOT/etc/passwd"
+grep -q "^root:" "$ROOT/etc/shadow"
+rm -fv "$ROOT/etc/passwd" "$ROOT/etc/shadow"
+echo "foo" >root.passwd
+systemd-firstboot --root="$ROOT" --root-password-file=root.passwd
+grep -q "^root:x:0:0:" "$ROOT/etc/passwd"
+grep -q "^root:" "$ROOT/etc/shadow"
+rm -fv "$ROOT/etc/passwd" "$ROOT/etc/shadow" root.passwd
+# Set the shell together with the password, as firstboot won't touch
+# /etc/passwd if it already exists
+systemd-firstboot --root="$ROOT" --root-password-hashed="$ROOT_HASHED_PASSWORD1" --root-shell=/bin/fooshell
+grep -q "^root:x:0:0:.*:/bin/fooshell$" "$ROOT/etc/passwd"
+grep -q "^root:$ROOT_HASHED_PASSWORD1:" "$ROOT/etc/shadow"
+
+systemd-firstboot --root="$ROOT" --kernel-command-line="foo.bar=42"
+grep -q "foo.bar=42" "$ROOT/etc/kernel/cmdline"
+
+# Configs should not get overwritten if they exist unless --force is used
+systemd-firstboot --root="$ROOT" \
+ --locale=locale-overwrite \
+ --locale-messages=messages-overwrite \
+ --keymap=keymap-overwrite \
+ --timezone=CET \
+ --hostname=hostname-overwrite \
+ --machine-id=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \
+ --root-password-hashed="$ROOT_HASHED_PASSWORD2" \
+ --root-shell=/bin/barshell \
+ --kernel-command-line="hello.world=0"
+grep -q "LANG=foo" "$ROOT/etc/locale.conf"
+grep -q "LC_MESSAGES=bar" "$ROOT/etc/locale.conf"
+grep -q "KEYMAP=foo" "$ROOT/etc/vconsole.conf"
+readlink "$ROOT/etc/localtime" | grep -q "Europe/Berlin$"
+grep -q "foobar" "$ROOT/etc/hostname"
+grep -q "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "$ROOT/etc/machine-id"
+grep -q "^root:x:0:0:.*:/bin/fooshell$" "$ROOT/etc/passwd"
+grep -q "^root:$ROOT_HASHED_PASSWORD1:" "$ROOT/etc/shadow"
+grep -q "foo.bar=42" "$ROOT/etc/kernel/cmdline"
+
+# The same thing, but now with --force
+systemd-firstboot --root="$ROOT" --force \
+ --locale=locale-overwrite \
+ --locale-messages=messages-overwrite \
+ --keymap=keymap-overwrite \
+ --timezone=CET \
+ --hostname=hostname-overwrite \
+ --machine-id=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \
+ --root-password-hashed="$ROOT_HASHED_PASSWORD2" \
+ --root-shell=/bin/barshell \
+ --kernel-command-line="hello.world=0"
+grep -q "LANG=locale-overwrite" "$ROOT/etc/locale.conf"
+grep -q "LC_MESSAGES=messages-overwrite" "$ROOT/etc/locale.conf"
+grep -q "KEYMAP=keymap-overwrite" "$ROOT/etc/vconsole.conf"
+readlink "$ROOT/etc/localtime" | grep -q "/CET$"
+grep -q "hostname-overwrite" "$ROOT/etc/hostname"
+grep -q "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" "$ROOT/etc/machine-id"
+grep -q "^root:x:0:0:.*:/bin/barshell$" "$ROOT/etc/passwd"
+grep -q "^root:$ROOT_HASHED_PASSWORD2:" "$ROOT/etc/shadow"
+grep -q "hello.world=0" "$ROOT/etc/kernel/cmdline"
+
+# --copy-* options
+rm -fr "$ROOT"
+mkdir "$ROOT"
+# Copy everything at once (--copy)
+systemd-firstboot --root="$ROOT" --copy
+diff /etc/locale.conf "$ROOT/etc/locale.conf"
+diff <(awk -F: '/^root/ { print $7; }' /etc/passwd) <(awk -F: '/^root/ { print $7; }' "$ROOT/etc/passwd")
+diff <(awk -F: '/^root/ { print $2; }' /etc/shadow) <(awk -F: '/^root/ { print $2; }' "$ROOT/etc/shadow")
+[[ -e /etc/vconsole.conf ]] && diff /etc/vconsole.conf "$ROOT/etc/vconsole.conf"
+[[ -e /etc/localtime ]] && diff <(readlink /etc/localtime) <(readlink "$ROOT/etc/localtime")
+rm -fr "$ROOT"
+mkdir "$ROOT"
+# Copy everything at once, but now by using separate switches
+systemd-firstboot --root="$ROOT" --copy-locale --copy-keymap --copy-timezone --copy-root-password --copy-root-shell
+diff /etc/locale.conf "$ROOT/etc/locale.conf"
+diff <(awk -F: '/^root/ { print $7; }' /etc/passwd) <(awk -F: '/^root/ { print $7; }' "$ROOT/etc/passwd")
+diff <(awk -F: '/^root/ { print $2; }' /etc/shadow) <(awk -F: '/^root/ { print $2; }' "$ROOT/etc/shadow")
+[[ -e /etc/vconsole.conf ]] && diff /etc/vconsole.conf "$ROOT/etc/vconsole.conf"
+[[ -e /etc/localtime ]] && diff <(readlink /etc/localtime) <(readlink "$ROOT/etc/localtime")
+
+# Assorted tests
+rm -fr "$ROOT"
+mkdir "$ROOT"
+
+systemd-firstboot --root="$ROOT" --setup-machine-id
+grep -E "[a-z0-9]{32}" "$ROOT/etc/machine-id"
+
+systemd-firstboot --root="$ROOT" --delete-root-password
+diff <(echo) <(awk -F: '/^root/ { print $2; }' "$ROOT/etc/shadow")
diff --git a/test/units/testsuite-74.service b/test/units/testsuite-74.service
new file mode 100644
index 0000000000..f782132a92
--- /dev/null
+++ b/test/units/testsuite-74.service
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Unit]
+Description=TEST-74-AUX-UTILS
+
+[Service]
+ExecStartPre=rm -f /failed /testok
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-74.sh b/test/units/testsuite-74.sh
new file mode 100755
index 0000000000..13c767e490
--- /dev/null
+++ b/test/units/testsuite-74.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+: >/failed
+
+for script in "${0%.sh}".*.sh; do
+ echo "Running $script"
+ "./$script"
+done
+
+touch /testok
+rm /failed

@ -0,0 +1,56 @@
From 1ef6ffdf0923095752665c7ff6062514dfa6c6bf Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Fri, 4 Nov 2022 00:01:16 +0000
Subject: [PATCH] firstboot: fix segfault when --locale-messages= is passed
without --locale=
\#0 __strcmp_evex () at ../sysdeps/x86_64/multiarch/strcmp-evex.S:295
No locals.
\#1 0x0000557444eb172b in process_locale () at ../src/firstboot/firstboot.c:342
etc_localeconf = 0x7ffd40217b80 "/root/root/etc/locale.conf"
locales = {0x0, 0x0, 0x0}
i = 0
r = <optimized out>
__PRETTY_FUNCTION__ = "process_locale"
__func__ = "process_locale"
\#2 0x0000557444eaff93 in run (argv=0x7ffd40217d98, argc=3) at ../src/firstboot/firstboot.c:1401
loop_device = 0x0
unlink_dir = 0x0
r = <optimized out>
loop_device = <optimized out>
unlink_dir = <optimized out>
r = <optimized out>
__func__ = <optimized out>
__PRETTY_FUNCTION__ = <optimized out>
enabled = <optimized out>
_error = <optimized out>
_level = <optimized out>
_e = <optimized out>
_level = <optimized out>
_e = <optimized out>
\#3 main (argc=3, argv=0x7ffd40217d98) at ../src/firstboot/firstboot.c:1432
r = <optimized out>
__PRETTY_FUNCTION__ = "main"
Fixes https://github.com/systemd/systemd/issues/25249
(cherry picked from commit 4c4a73ce068ef16cfe7ad07c7c3386ac1dbc58fe)
Related #2138081
---
src/firstboot/firstboot.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 065ee896cd..63db78b52d 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -339,7 +339,7 @@ static int process_locale(void) {
if (!isempty(arg_locale))
locales[i++] = strjoina("LANG=", arg_locale);
- if (!isempty(arg_locale_messages) && !streq(arg_locale_messages, arg_locale))
+ if (!isempty(arg_locale_messages) && !streq_ptr(arg_locale_messages, arg_locale))
locales[i++] = strjoina("LC_MESSAGES=", arg_locale_messages);
if (i == 0)

@ -0,0 +1,76 @@
From 1d41d2789bb67f5909d6974d2fd916e462a0a5cf Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Fri, 4 Nov 2022 12:24:10 +0100
Subject: [PATCH] tests: make test-execute pass on openSUSE
In my understanding user group "3" (aka "sys") is kept for historical reasons
but not really useful these days. That's probably explained why this group
isn't defined on openSUSE.
Hence let's drop reference to this user group, this shouldn't lessen the
revelance of the test since SupplementaryGroups= is still tested with 2 other
groups.
(cherry picked from commit d723b0467d7b8c5c772086d5352442f3fca4368d)
Related #2138081
---
test/test-execute/exec-dynamicuser-supplementarygroups.service | 3 +--
...plementarygroups-multiple-groups-default-group-user.service | 3 +--
.../exec-supplementarygroups-multiple-groups-withgid.service | 3 +--
.../exec-supplementarygroups-multiple-groups-withuid.service | 3 +--
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/test/test-execute/exec-dynamicuser-supplementarygroups.service b/test/test-execute/exec-dynamicuser-supplementarygroups.service
index fb0b57bc00..53ba0ec7cb 100644
--- a/test/test-execute/exec-dynamicuser-supplementarygroups.service
+++ b/test/test-execute/exec-dynamicuser-supplementarygroups.service
@@ -5,7 +5,6 @@ Description=Test DynamicUser with SupplementaryGroups=
[Service]
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
Type=oneshot
DynamicUser=yes
-SupplementaryGroups=1 2 3
+SupplementaryGroups=1 2
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
index 362e539287..4cb0326320 100644
--- a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
@@ -6,7 +6,6 @@ Description=Test for Supplementary Group with multiple groups without Group and
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "%G" && test "$$(id -u)" = "%U"'
Type=oneshot
-SupplementaryGroups=1 2 3
+SupplementaryGroups=1 2
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
index ff3fdc8142..e11743d754 100644
--- a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
@@ -5,8 +5,7 @@ Description=Test for Supplementary Group with multiple groups and Group=1
[Service]
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "%U"'
Type=oneshot
Group=1
-SupplementaryGroups=1 2 3
+SupplementaryGroups=1 2
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
index f35ff84765..3efbbfb0f9 100644
--- a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
@@ -5,7 +5,6 @@ Description=Test for Supplementary Group with multiple groups and Uid=1
[Service]
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1'
Type=oneshot
User=1
-SupplementaryGroups=1 2 3
+SupplementaryGroups=1 2

@ -0,0 +1,150 @@
From 5685a8b01abf34ec5da7c43a99ede6e3bb7394eb Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Fri, 4 Nov 2022 12:50:04 +0100
Subject: [PATCH] tests: minor simplification in test-execute
No functional change.
(cherry picked from commit 09415aef940f4a471da7cb899b9a66f1504d7c77)
Related #2138081
---
...xec-dynamicuser-fixeduser-one-supplementarygroup.service | 2 +-
test/test-execute/exec-dynamicuser-fixeduser.service | 2 +-
.../exec-dynamicuser-supplementarygroups.service | 4 ++--
...mentarygroups-multiple-groups-default-group-user.service | 6 +++---
...exec-supplementarygroups-multiple-groups-withgid.service | 4 ++--
...exec-supplementarygroups-multiple-groups-withuid.service | 4 ++--
.../exec-supplementarygroups-single-group-user.service | 2 +-
.../exec-supplementarygroups-single-group.service | 2 +-
test/test-execute/exec-supplementarygroups.service | 4 ++--
9 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service
index 0c2a218be0..bbb1af5fb3 100644
--- a/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service
+++ b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service
@@ -3,7 +3,7 @@
Description=Test DynamicUser with User= and SupplementaryGroups=
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"'
Type=oneshot
User=1
diff --git a/test/test-execute/exec-dynamicuser-fixeduser.service b/test/test-execute/exec-dynamicuser-fixeduser.service
index 061bbd2b93..c5828c2a93 100644
--- a/test/test-execute/exec-dynamicuser-fixeduser.service
+++ b/test/test-execute/exec-dynamicuser-fixeduser.service
@@ -3,7 +3,7 @@
Description=Test DynamicUser with User=
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"'
Type=oneshot
User=1
diff --git a/test/test-execute/exec-dynamicuser-supplementarygroups.service b/test/test-execute/exec-dynamicuser-supplementarygroups.service
index 53ba0ec7cb..d601af272e 100644
--- a/test/test-execute/exec-dynamicuser-supplementarygroups.service
+++ b/test/test-execute/exec-dynamicuser-supplementarygroups.service
@@ -3,8 +3,8 @@
Description=Test DynamicUser with SupplementaryGroups=
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "2" && exit 0; done; exit 1'
Type=oneshot
DynamicUser=yes
SupplementaryGroups=1 2
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
index 4cb0326320..0ecc34441c 100644
--- a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service
@@ -3,9 +3,9 @@
Description=Test for Supplementary Group with multiple groups without Group and User
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "%G" && exit 0; done; exit 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "2" && exit 0; done; exit 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "%G" && test "$$(id -u)" = "%U"'
Type=oneshot
SupplementaryGroups=1 2
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
index e11743d754..cd1021bbdf 100644
--- a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service
@@ -3,8 +3,8 @@
Description=Test for Supplementary Group with multiple groups and Group=1
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "2" && exit 0; done; exit 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "%U"'
Type=oneshot
Group=1
diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
index 3efbbfb0f9..7913a2c2ed 100644
--- a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
+++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service
@@ -3,8 +3,8 @@
Description=Test for Supplementary Group with multiple groups and Uid=1
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "2" && exit 0; done; exit 1'
Type=oneshot
User=1
SupplementaryGroups=1 2
diff --git a/test/test-execute/exec-supplementarygroups-single-group-user.service b/test/test-execute/exec-supplementarygroups-single-group-user.service
index aae71d0a30..ee4017e74e 100644
--- a/test/test-execute/exec-supplementarygroups-single-group-user.service
+++ b/test/test-execute/exec-supplementarygroups-single-group-user.service
@@ -3,7 +3,7 @@
Description=Test for Supplementary Group with only one group and uid 1
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"'
Type=oneshot
User=1
diff --git a/test/test-execute/exec-supplementarygroups-single-group.service b/test/test-execute/exec-supplementarygroups-single-group.service
index c870774382..62275201cc 100644
--- a/test/test-execute/exec-supplementarygroups-single-group.service
+++ b/test/test-execute/exec-supplementarygroups-single-group.service
@@ -3,7 +3,7 @@
Description=Test for Supplementary Group with only one group
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "0"'
Type=oneshot
Group=1
diff --git a/test/test-execute/exec-supplementarygroups.service b/test/test-execute/exec-supplementarygroups.service
index 75601eab57..03406c3ee8 100644
--- a/test/test-execute/exec-supplementarygroups.service
+++ b/test/test-execute/exec-supplementarygroups.service
@@ -3,7 +3,7 @@
Description=Test for Supplementary Group
[Service]
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1'
-ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "%G" && exit 0; done; exit 1'
+ExecStart=/bin/sh -x -c 'for g in $$(id -G); do test "$$g" = "1" && exit 0; done; exit 1'
Type=oneshot
SupplementaryGroups=1

@ -0,0 +1,29 @@
From 6d8f91ab2f7db862d95d0565bad3aaf4279c00bc Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Thu, 3 Nov 2022 20:10:57 +0000
Subject: [PATCH] tmpfiles.d: do not fail if provision.conf fails
On a read-only filesystem creating /root/.ssh might fail, but that's ok.
Do not fail the run, as this is only needed to add the credential, which
is a separate step.
(cherry picked from commit e0fc9be37e4d15e2c322eb8281692c2639dac023)
Related #2138081
---
tmpfiles.d/provision.conf | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tmpfiles.d/provision.conf b/tmpfiles.d/provision.conf
index 3c56f42d58..093104aaaf 100644
--- a/tmpfiles.d/provision.conf
+++ b/tmpfiles.d/provision.conf
@@ -17,6 +17,6 @@ f^ /etc/issue.d/50-provision.conf - - - - login.issue
f^ /etc/hosts - - - - network.hosts
# Provision SSH key for root
-d /root :0700 root :root -
-d /root/.ssh :0700 root :root -
+d- /root :0700 root :root -
+d- /root/.ssh :0700 root :root -
f^ /root/.ssh/authorized_keys :0600 root :root - ssh.authorized_keys.root

@ -0,0 +1,31 @@
From d3b559f5e561750e6c50449b2ca84b40abeb492d Mon Sep 17 00:00:00 2001
From: Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
Date: Fri, 4 Nov 2022 09:57:24 +0100
Subject: [PATCH] kernel-install/90-loaderentry: do not add multiple
systemd.machine_id options
Do not unconditionally add a new systemd.machine_id command line option, first
check if it already exists with the expected value.
Fixes #25203
(cherry picked from commit 981502c5cc9ce32c3f77ff74aad87cd6f0da3b16)
Related #2138081
---
src/kernel-install/90-loaderentry.install | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
index 743af33aa9..ea75e1b0d8 100755
--- a/src/kernel-install/90-loaderentry.install
+++ b/src/kernel-install/90-loaderentry.install
@@ -85,7 +85,7 @@ BOOT_OPTIONS="${BOOT_OPTIONS% }"
# command line with the machine ID we use, so that the machine ID remains
# stable, even during factory reset, in the initrd (where the system's machine
# ID is not directly accessible yet), and if the root file system is volatile.
-if [ "$ENTRY_TOKEN" = "$MACHINE_ID" ]; then
+if [ "$ENTRY_TOKEN" = "$MACHINE_ID" ] && ! echo "$BOOT_OPTIONS" | grep -q "systemd.machine_id=$MACHINE_ID"; then
BOOT_OPTIONS="$BOOT_OPTIONS systemd.machine_id=$MACHINE_ID"
fi

@ -0,0 +1,120 @@
From 1b7dfe48d6d66cad5d0368b8e8b387a4d9586ccd Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Thu, 27 Oct 2022 11:12:10 +0200
Subject: [PATCH] condition: Check that subsystem is enabled in
ConditionSecurity=tpm2
Instead of succeeding when either the firmware reports a TPM device
or we find a TPM device, let's check that the firmware reports a TPM
device and the TPM subsystem is enabled in the kernel.
To check whether the subsystem enabled, we check if the relevant
subdirectory in /sys exists at all.
(cherry picked from commit 300bba79c22e4be1effe2faad0e59ac725d396a1)
Related #2138081
---
man/systemd-creds.xml | 4 ++--
src/creds/creds.c | 6 ++++--
src/shared/condition.c | 9 ++++-----
src/shared/tpm2-util.c | 6 +++++-
src/shared/tpm2-util.h | 11 ++++++-----
5 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/man/systemd-creds.xml b/man/systemd-creds.xml
index 1e5632e63d..003fbcd463 100644
--- a/man/systemd-creds.xml
+++ b/man/systemd-creds.xml
@@ -175,8 +175,8 @@
by the OS kernel drivers and by userspace (i.e. systemd) this prints <literal>yes</literal> and exits
with exit status zero. If no such device is discovered/supported/used, prints
<literal>no</literal>. Otherwise prints <literal>partial</literal>. In either of these two cases
- exits with non-zero exit status. It also shows three lines indicating separately whether drivers,
- firmware and the system discovered/support/use TPM2.</para>
+ exits with non-zero exit status. It also shows four lines indicating separately whether firmware,
+ drivers, the system and the kernel discovered/support/use TPM2.</para>
<para>Combine with <option>--quiet</option> to suppress the output.</para></listitem>
</varlistentry>
diff --git a/src/creds/creds.c b/src/creds/creds.c
index 5586fd776a..a755a52c34 100644
--- a/src/creds/creds.c
+++ b/src/creds/creds.c
@@ -637,10 +637,12 @@ static int verb_has_tpm2(int argc, char **argv, void *userdata) {
printf("%sfirmware\n"
"%sdriver\n"
- "%ssystem\n",
+ "%ssystem\n"
+ "%ssubsystem\n",
plus_minus(s & TPM2_SUPPORT_FIRMWARE),
plus_minus(s & TPM2_SUPPORT_DRIVER),
- plus_minus(s & TPM2_SUPPORT_SYSTEM));
+ plus_minus(s & TPM2_SUPPORT_SYSTEM),
+ plus_minus(s & TPM2_SUPPORT_SUBSYSTEM));
}
/* Return inverted bit flags. So that TPM2_SUPPORT_FULL becomes EXIT_SUCCESS and the other values
diff --git a/src/shared/condition.c b/src/shared/condition.c
index 310ffcbdc6..a23d6a3e45 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -664,14 +664,13 @@ static int condition_test_ac_power(Condition *c, char **env) {
}
static int has_tpm2(void) {
- /* Checks whether the system has at least one TPM2 resource manager device, i.e. at least one "tpmrm"
- * class device. Alternatively, we are also happy if the firmware reports support (this is to cover
- * for cases where we simply haven't loaded the driver for it yet, i.e. during early boot where we
- * very likely want to use this condition check).
+ /* Checks whether the kernel has the TPM subsystem enabled and the firmware reports support. Note
+ * we don't check for actual TPM devices, since we might not have loaded the driver for it yet, i.e.
+ * during early boot where we very likely want to use this condition check).
*
* Note that we don't check if we ourselves are built with TPM2 support here! */
- return (tpm2_support() & (TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_FIRMWARE)) != 0;
+ return FLAGS_SET(tpm2_support(), TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_FIRMWARE);
}
static int condition_test_security(Condition *c, char **env) {
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 13e92c4144..65e8d48347 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -2189,7 +2189,11 @@ Tpm2Support tpm2_support(void) {
if (r != -ENOENT)
log_debug_errno(r, "Unable to test whether /sys/class/tpmrm/ exists and is populated, assuming it is not: %m");
} else if (r == 0) /* populated! */
- support |= TPM2_SUPPORT_DRIVER;
+ support |= TPM2_SUPPORT_SUBSYSTEM|TPM2_SUPPORT_DRIVER;
+ else
+ /* If the directory exists but is empty, we know the subsystem is enabled but no
+ * driver has been loaded yet. */
+ support |= TPM2_SUPPORT_SUBSYSTEM;
}
if (efi_has_tpm2())
diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h
index 048c28d6ca..c240335ae6 100644
--- a/src/shared/tpm2-util.h
+++ b/src/shared/tpm2-util.h
@@ -137,11 +137,12 @@ typedef struct {
typedef enum Tpm2Support {
/* NOTE! The systemd-creds tool returns these flags 1:1 as exit status. Hence these flags are pretty
* much ABI! Hence, be extra careful when changing/extending these definitions. */
- TPM2_SUPPORT_NONE = 0, /* no support */
- TPM2_SUPPORT_FIRMWARE = 1 << 0, /* firmware reports TPM2 was used */
- TPM2_SUPPORT_DRIVER = 1 << 1, /* the kernel has a driver loaded for it */
- TPM2_SUPPORT_SYSTEM = 1 << 2, /* we support it ourselves */
- TPM2_SUPPORT_FULL = TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_SYSTEM,
+ TPM2_SUPPORT_NONE = 0, /* no support */
+ TPM2_SUPPORT_FIRMWARE = 1 << 0, /* firmware reports TPM2 was used */
+ TPM2_SUPPORT_DRIVER = 1 << 1, /* the kernel has a driver loaded for it */
+ TPM2_SUPPORT_SYSTEM = 1 << 2, /* we support it ourselves */
+ TPM2_SUPPORT_SUBSYSTEM = 1 << 3, /* the kernel has the tpm subsystem enabled */
+ TPM2_SUPPORT_FULL = TPM2_SUPPORT_FIRMWARE|TPM2_SUPPORT_DRIVER|TPM2_SUPPORT_SYSTEM|TPM2_SUPPORT_SUBSYSTEM,
} Tpm2Support;
Tpm2Support tpm2_support(void);

@ -0,0 +1,52 @@
From f0839034c9910529f368e60262b5653afad58f63 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 7 Nov 2022 16:39:12 +0100
Subject: [PATCH] semaphore: remove the Semaphore repositories recursively
The list of disabled repositories was recently converted from a single
file into a directory with separate repository files, so let's adjust
the setup script accordingly.
```
$ ls -lR /etc/apt/sources.list.d/
/etc/apt/sources.list.d/:
total 36
-rw-r--r-- 1 root root 76 Nov 3 10:28 azure-cli.list
-rw-r--r-- 1 root root 72 Nov 3 10:22 bazel.list
drwxr-xr-x 2 root root 4096 Nov 3 10:31 disabled
-rw-r--r-- 1 root root 113 Nov 3 10:13 docker-source.list
-rw-r--r-- 1 root root 367 Nov 3 10:28 github_git-lfs.list
-rw-r--r-- 1 root root 111 Nov 3 10:25 google-chrome-source.list
-rw-r--r-- 1 root root 64 Nov 3 10:14 google-cloud-sdk.list
-rw-r--r-- 1 root root 54 Nov 3 10:23 helm-stable-debian.list
-rw-r--r-- 1 root root 89 Nov 3 10:29 yarn-source.list
/etc/apt/sources.list.d/disabled:
total 20
-rw-r--r-- 1 root root 100 Nov 3 10:23 devel_kubic_libcontainers_stable.list
-rw-r--r-- 1 root root 103 Nov 3 10:27 git.list
-rw-r--r-- 1 root root 105 Nov 3 10:22 gradle.list
-rw-r--r-- 1 root root 118 Nov 3 10:13 pypy.list
-rw-r--r-- 1 root root 104 Nov 3 10:13 python.list
```
(cherry picked from commit 610eb3f8260ecbb161db5186a5e27417f3110a68)
Related #2138081
---
.semaphore/semaphore-runner.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.semaphore/semaphore-runner.sh b/.semaphore/semaphore-runner.sh
index 98fd7b4411..b0d32bd136 100755
--- a/.semaphore/semaphore-runner.sh
+++ b/.semaphore/semaphore-runner.sh
@@ -55,7 +55,7 @@ for phase in "${PHASES[@]}"; do
case "$phase" in
SETUP)
# remove semaphore repos, some of them don't work and cause error messages
- sudo rm -f /etc/apt/sources.list.d/*
+ sudo rm -rf /etc/apt/sources.list.d/*
# enable backports for latest LXC
echo "deb http://archive.ubuntu.com/ubuntu $UBUNTU_RELEASE-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/backports.list

@ -0,0 +1,29 @@
From c440081c968c93d527d441f4d106e0acad9540eb Mon Sep 17 00:00:00 2001
From: Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
Date: Mon, 7 Nov 2022 15:25:25 +0100
Subject: [PATCH] kernel-install/90-loaderentry: do not override an existing
systemd.machine_id
If the systemd.machine_id command line option is already set, do not override
it.
(cherry picked from commit 802d9219aa19d759113dd6cd1e91b2bb661fe9ba)
Related #2138081
---
src/kernel-install/90-loaderentry.install | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install
index ea75e1b0d8..41a05534b9 100755
--- a/src/kernel-install/90-loaderentry.install
+++ b/src/kernel-install/90-loaderentry.install
@@ -85,7 +85,7 @@ BOOT_OPTIONS="${BOOT_OPTIONS% }"
# command line with the machine ID we use, so that the machine ID remains
# stable, even during factory reset, in the initrd (where the system's machine
# ID is not directly accessible yet), and if the root file system is volatile.
-if [ "$ENTRY_TOKEN" = "$MACHINE_ID" ] && ! echo "$BOOT_OPTIONS" | grep -q "systemd.machine_id=$MACHINE_ID"; then
+if [ "$ENTRY_TOKEN" = "$MACHINE_ID" ] && ! echo "$BOOT_OPTIONS" | grep -q "systemd.machine_id="; then
BOOT_OPTIONS="$BOOT_OPTIONS systemd.machine_id=$MACHINE_ID"
fi

@ -0,0 +1,28 @@
From d1abf107c5b4c661886001de996bf03587bb35c1 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Mon, 7 Nov 2022 16:28:33 +0000
Subject: [PATCH] kernel-install: skip 50-depmod if depmod is not available
Images might be built without any kernel module, and without
installing depmod as it is not needed. Skip it.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1023607
(cherry picked from commit cda4d00dfcbcd075cef95341f8a466f0c4ee8e1d)
Related #2138081
---
src/kernel-install/50-depmod.install | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/kernel-install/50-depmod.install b/src/kernel-install/50-depmod.install
index d4b991cfd6..43bd87c7ed 100755
--- a/src/kernel-install/50-depmod.install
+++ b/src/kernel-install/50-depmod.install
@@ -26,6 +26,7 @@ KERNEL_VERSION="${2:?}"
case "$COMMAND" in
add)
[ -d "/lib/modules/$KERNEL_VERSION/kernel" ] || exit 0
+ command -v depmod >/dev/null || exit 0
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "+depmod -a $KERNEL_VERSION"
exec depmod -a "$KERNEL_VERSION"
;;

@ -0,0 +1,38 @@
From 04cdbacc26c7e38d3bd684235b51c79ab64b6026 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 8 Nov 2022 11:07:02 +0100
Subject: [PATCH] man: add note that network-generator is not a generator
Also fix indentation.
(cherry picked from commit 2fa6574e835566c2aa5cbf4167ecee316f71bf98)
Related #2138081
---
man/systemd-network-generator.service.xml | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/man/systemd-network-generator.service.xml b/man/systemd-network-generator.service.xml
index 6b7e2564d4..2ddeadfc54 100644
--- a/man/systemd-network-generator.service.xml
+++ b/man/systemd-network-generator.service.xml
@@ -41,10 +41,17 @@
</para>
<para>Files are generated in <filename>/run/systemd/network/</filename>.</para>
+
+ <para>Note: despite the name, this generator executes as a normal systemd service and is
+ <emphasis>not</emphasis> an implementation of the
+ <citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ concept.</para>
</refsect1>
- <refsect1><title>Kernel command line options</title>
- <para>This tool understands the following options:</para>
+ <refsect1>
+ <title>Kernel command line options</title>
+
+ <para>This tool understands the following options:</para>
<variablelist class='kernel-commandline-options'>
<varlistentry>

@ -0,0 +1,64 @@
From 054da791c98fba7e11079e94c9b9fe0b1ca4e8d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 4 Nov 2022 15:48:50 +0100
Subject: [PATCH] test: fstab-generator: adjust PATH for fsck
fsck(8) is located in /usr/sib/ on Debian sid:
stdout:
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-01-dev-nfs.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-02-dhcp.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-03-dhcp6.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-04-nfs.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-05-nfs4.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-06-ipv4.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-07-ipv6.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-08-implicit-nfs.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-09-cifs.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-10-iscsi.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-11-live.input
*** Running /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-12-dev-sdx.input
--- /dev/fd/63 2022-11-04 15:39:13.131532174 +0100
+++ /dev/fd/62 2022-11-04 15:39:13.131532174 +0100
@@ -6,3 +6,4 @@
initrd-usr-fs.target.requires
initrd-usr-fs.target.requires/sysroot.mount
sysroot.mount
+systemd-fsck-root.service
**** Unexpected output for /home/christian/Coding/workspaces/systemd/test/testdata/test-fstab-generator/test-12-dev-sdx.input
stderr:
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on NFS was requested.
Skipping root directory handling, as root on CIFS was requested.
Skipping root directory handling, as root on iSCSI was requested.
Skipping root directory handling, as root on live image was requested.
Found entry what=/dev/sdx1 where=/sysroot type=n/a opts=ro
Checking was requested for /dev/sdx1, but the fsck command does not exist.
(cherry picked from commit a45efc9e4b574a85176610496f2ac7ae769364bb)
Related #2138081
---
test/test-fstab-generator.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/test/test-fstab-generator.sh b/test/test-fstab-generator.sh
index 0c977645e3..7c060dfac7 100755
--- a/test/test-fstab-generator.sh
+++ b/test/test-fstab-generator.sh
@@ -14,6 +14,9 @@ fi
src="$(dirname "$0")/testdata/test-fstab-generator"
+# fsck(8) is located in /usr/sbin on Debian
+PATH=$PATH:/usr/sbin
+
for f in "$src"/test-*.input; do
echo "*** Running $f"

@ -0,0 +1,30 @@
From ba5d26d85d0c4250b10a46a5c9cd3a3e1f0ce43b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 4 Nov 2022 19:36:31 +0100
Subject: [PATCH] loop-util: open lock fd read-only
flock(2) works with file descriptors opened with O_RDONLY.
This affects SELinux systems where access to block devices is quite
restricted to avoid bypasses on filesystem objects.
(cherry picked from commit 3e6b7d2626de9c0faf8b34b2629e8d6d8fa85a7d)
Related #2138081
---
src/shared/loop-util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c
index 731ce29112..fb7e80b1b5 100644
--- a/src/shared/loop-util.c
+++ b/src/shared/loop-util.c
@@ -77,7 +77,7 @@ static int open_lock_fd(int primary_fd, int operation) {
assert(primary_fd >= 0);
assert(IN_SET(operation & ~LOCK_NB, LOCK_SH, LOCK_EX));
- lock_fd = fd_reopen(primary_fd, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
+ lock_fd = fd_reopen(primary_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
if (lock_fd < 0)
return lock_fd;

@ -0,0 +1,30 @@
From ca92c2e035d5702f23f9a8d1cd705425b5605822 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 7 Nov 2022 11:55:29 +0100
Subject: [PATCH] test: don't ignore non-existent paths in inst_recursive()
The process substitution in the while loop hides errors raised by the
find utility, which might (and did), in turn, hide errors in test setup.
(cherry picked from commit eb5d7730e1b3b1bddecb80be37e5a4c938183f61)
Related #2138081
---
test/test-functions | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/test-functions b/test/test-functions
index 16d9da637b..80ce383e64 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -2773,6 +2773,10 @@ inst_recursive() {
local p item
for p in "$@"; do
+ # Make sure the source exists, as the process substitution below
+ # suppresses errors
+ stat "$p" >/dev/null || return 1
+
while read -r item; do
if [[ -d "$item" ]]; then
inst_dir "$item"

@ -0,0 +1,46 @@
From ea8b80cdc0dfd0ad92301a0e421df4d3110fe09c Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 7 Nov 2022 11:57:59 +0100
Subject: [PATCH] test: fix locale installation when locale-gen is used
locale-gen might merge all compiled locales into a simple archive, so we
need to install it as well if necessary.
(cherry picked from commit 0c416ea01bc14adff10f4fc5415a36bd2d48f604)
Related #2138081
---
test/test-functions | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/test/test-functions b/test/test-functions
index 80ce383e64..45ca472916 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -1988,14 +1988,19 @@ install_locales() {
inst /usr/share/i18n/SUPPORTED || :
inst_recursive /usr/share/i18n/charmaps
inst_recursive /usr/share/i18n/locales
- inst_recursive /usr/share/locale/en
- inst_recursive /usr/share/locale/en_*
+ inst_recursive /usr/share/locale/en*
+ inst_recursive /usr/share/locale/de*
+ image_install /usr/share/locale/locale.alias
+ # locale-gen might either generate each locale separately or merge them
+ # into a single archive
+ if ! (inst_recursive /usr/lib/locale/C.*8 /usr/lib/locale/en_*8 ||
+ image_install /usr/lib/locale/locale-archive); then
+ dfatal "Failed to install required locales"
+ exit 1
+ fi
+ else
+ inst_recursive /usr/lib/locale/C.*8 /usr/lib/locale/en_*8
fi
-
- inst_recursive /usr/lib/locale/C.utf8
- inst_recursive /usr/lib/locale/C.UTF-8
- inst_recursive /usr/lib/locale/en_*.utf8
- inst_recursive /usr/lib/locale/en_*.UTF-8
}
# shellcheck disable=SC2120

@ -0,0 +1,71 @@
From bec9d65390249d4e88f5095e751283645a2a4c08 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 7 Nov 2022 12:07:27 +0100
Subject: [PATCH] test: fix keymaps installation on Arch
Where the keymaps live under /usr/share/kbd/keymaps/.
(cherry picked from commit 1edad89399e7cbee230878589ac618103c157ec7)
Related #2138081
---
test/test-functions | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/test/test-functions b/test/test-functions
index 45ca472916..194cd682bb 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -2007,7 +2007,8 @@ install_locales() {
install_keymaps() {
local i p
local -a prefix=(
- "/usr"
+ "/usr/lib"
+ "/usr/share"
)
dinfo "Install console keymaps"
@@ -2016,7 +2017,7 @@ install_keymaps() {
&& [[ "$(meson configure "${BUILD_DIR:?}" | grep 'split-usr' | awk '{ print $2 }')" == "true" ]] \
|| [[ ! -L /lib ]]; then
prefix+=(
- ""
+ "/lib"
)
fi
@@ -2025,12 +2026,12 @@ install_keymaps() {
# The first three paths may be deprecated.
# It seems now the last three paths are used by many distributions.
for i in \
- "$p"/lib/kbd/keymaps/include/* \
- "$p"/lib/kbd/keymaps/i386/include/* \
- "$p"/lib/kbd/keymaps/i386/qwerty/us.* \
- "$p"/lib/kbd/keymaps/legacy/include/* \
- "$p"/lib/kbd/keymaps/legacy/i386/qwerty/us.* \
- "$p"/lib/kbd/keymaps/xkb/us*; do
+ "$p"/kbd/keymaps/include/* \
+ "$p"/kbd/keymaps/i386/include/* \
+ "$p"/kbd/keymaps/i386/qwerty/us.* \
+ "$p"/kbd/keymaps/legacy/include/* \
+ "$p"/kbd/keymaps/legacy/i386/qwerty/us.* \
+ "$p"/kbd/keymaps/xkb/us*; do
[[ -f "$i" ]] || continue
inst "$i"
done
@@ -2039,10 +2040,10 @@ install_keymaps() {
# When it takes any argument, then install more keymaps.
for p in "${prefix[@]}"; do
for i in \
- "$p"/lib/kbd/keymaps/include/* \
- "$p"/lib/kbd/keymaps/i386/*/* \
- "$p"/lib/kbd/keymaps/legacy/i386/*/* \
- "$p"/lib/kbd/keymaps/xkb/*; do
+ "$p"/kbd/keymaps/include/* \
+ "$p"/kbd/keymaps/i386/*/* \
+ "$p"/kbd/keymaps/legacy/i386/*/* \
+ "$p"/kbd/keymaps/xkb/*; do
[[ -f "$i" ]] || continue
inst "$i"
done

@ -0,0 +1,43 @@
From d63a1edb6bef959e8d6a481464a809badcc3a2eb Mon Sep 17 00:00:00 2001
From: Torsten Hilbrich <torsten.hilbrich@secunet.com>
Date: Mon, 7 Nov 2022 08:38:58 +0100
Subject: [PATCH] test: compile test-utmp.c only if UTMP is enabled
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When compiling with -D utmp=false the compilation fails with:
../../git/systemd/src/test/test-utmp.c: In function test_dump_run_utmp:
../../git/systemd/src/test/test-utmp.c:21:9: error: cleanup argument not a function
21 | _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
| ^~~~~~~~
../../git/systemd/src/test/test-utmp.c:23:17: error: implicit declaration of function utxent_start [-Werror=implicit-function-declaration]
23 | utmpx = utxent_start();
| ^~~~~~~~~~~~
any many other errors
Add a conditional to compile test-utmp.c only if ENABLE_UTMP is true.
(cherry picked from commit 41cac2a8b98fc5faebe942c697b17e109822342d)
Related: #2138081
---
src/test/meson.build | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/test/meson.build b/src/test/meson.build
index 86fc1d4fc0..2a4dfe26db 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -622,7 +622,8 @@ tests += [
[files('test-journal-importer.c')],
- [files('test-utmp.c')],
+ [files('test-utmp.c'),
+ [], [], [], 'ENABLE_UTMP'],
[files('test-udev.c'),
[libudevd_core,

@ -0,0 +1,19 @@
From d9328ee5e53d1901af9396ae3e0b2dd05f731781 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 14 Nov 2022 09:25:37 +0100
Subject: [PATCH] Create CNAME
Related: #2138081
---
docs/CNAME | 1 +
1 file changed, 1 insertion(+)
create mode 100644 docs/CNAME
diff --git a/docs/CNAME b/docs/CNAME
new file mode 100644
index 0000000000..cdcf4d9a52
--- /dev/null
+++ b/docs/CNAME
@@ -0,0 +1 @@
+systemd.io
\ No newline at end of file

@ -0,0 +1,46 @@
From 31f0c1b06bfd90d52009b59b9a4bf26c297790a7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 14 Nov 2022 17:26:49 +0100
Subject: [PATCH] tpm2-util: force default TCTI to be "device" with parameter
"/dev/tpmrm0"
Apparently some distros default to tss-abmrd. Let's bypass that and
always go to the kernel resource manager.
abmrd cannot really work for us, since we want to access the TPM already
in earliest boot i.e. in environments the abmrd service is not available
in.
Fixes: #25352
(cherry picked from commit 34906680afe60d724ea435b79b9b830a4bf2e7e9)
Related: #2138081
---
src/shared/tpm2-util.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 65e8d48347..9d73316146 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -152,8 +152,19 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
if (r < 0)
return log_error_errno(r, "TPM2 support not installed: %m");
- if (!device)
+ if (!device) {
device = secure_getenv("SYSTEMD_TPM2_DEVICE");
+ if (device)
+ /* Setting the env var to an empty string forces tpm2-tss' own device picking
+ * logic to be used. */
+ device = empty_to_null(device);
+ else
+ /* If nothing was specified explicitly, we'll use a hardcoded default: the "device" tcti
+ * driver and the "/dev/tpmrm0" device. We do this since on some distributions the tpm2-abrmd
+ * might be used and we really don't want that, since it is a system service and that creates
+ * various ordering issues/deadlocks during early boot. */
+ device = "device:/dev/tpmrm0";
+ }
if (device) {
const char *param, *driver, *fn;

@ -0,0 +1,52 @@
From 5b20ba25259da453a2aac5e65978a11bc2d048ed Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 15 Nov 2022 23:01:04 +0100
Subject: [PATCH] tpm2: add some extra validation of device string before using
it
Let's add some extra validation before constructing and using the .so
name to load. This isn't really security sensitive, given that we
used secure_getenv() to get the device string (and it thus should have
been come from a trusted source) but let's better be safe than sorry.
(cherry picked from commit 50a085143fa8f5dd6b6b3cef8a6ea2ec7c53ed0d)
Related: #2138081
---
src/shared/tpm2-util.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 9d73316146..4d0df944a9 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -174,15 +174,27 @@ int tpm2_context_init(const char *device, struct tpm2_context *ret) {
param = strchr(device, ':');
if (param) {
+ /* Syntax #1: Pair of driver string and arbitrary parameter */
driver = strndupa_safe(device, param - device);
+ if (isempty(driver))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name is empty, refusing.");
+
param++;
- } else {
+ } else if (path_is_absolute(device) && path_is_valid(device)) {
+ /* Syntax #2: TPM device node */
driver = "device";
param = device;
- }
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid TPM2 driver string, refusing.");
+
+ log_debug("Using TPM2 TCTI driver '%s' with device '%s'.", driver, param);
fn = strjoina("libtss2-tcti-", driver, ".so.0");
+ /* Better safe than sorry, let's refuse strings that cannot possibly be valid driver early, before going to disk. */
+ if (!filename_is_valid(fn))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 driver name '%s' not valid, refusing.", driver);
+
dl = dlopen(fn, RTLD_NOW);
if (!dl)
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to load %s: %s", fn, dlerror());

@ -0,0 +1,25 @@
From 2fdb15b3053d20282d7f3c20a7a4d2bd96d9a39b Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Sun, 13 Nov 2022 16:14:17 +0100
Subject: [PATCH] boot: Fix error message
(cherry picked from commit 6ee4aa22140dd8d51b1a18882eb4220629b8dd8f)
Related: #2138081
---
src/boot/efi/boot.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 4150b16ecf..84f4cc11a3 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -2678,7 +2678,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
err = device_path_to_str(loaded_image->FilePath, &loaded_image_path);
if (err != EFI_SUCCESS)
- return log_error_status_stall(err, L"Error getting loaded image path: %m");
+ return log_error_status_stall(err, L"Error getting loaded image path: %r", err);
export_variables(loaded_image, loaded_image_path, init_usec);

@ -0,0 +1,25 @@
From 58a3aaaad640bee3cca79a644422489e184b49c1 Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Mon, 14 Nov 2022 14:18:26 +0100
Subject: [PATCH] boot: Fix memory leak
(cherry picked from commit b7b327f856b3782f28be561d612d66ff406c7789)
Related: #2138081
---
src/boot/efi/boot.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 84f4cc11a3..17d4ec2d09 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -2650,7 +2650,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
_cleanup_(file_closep) EFI_FILE *root_dir = NULL;
_cleanup_(config_free) Config config = {};
- char16_t *loaded_image_path;
+ _cleanup_free_ char16_t *loaded_image_path = NULL;
EFI_STATUS err;
uint64_t init_usec;
bool menu = false;

@ -0,0 +1,88 @@
From 8cbb38625364640f390b2df2cda44ff3877fb16d Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Mon, 14 Nov 2022 14:37:13 +0100
Subject: [PATCH] boot: Do not require a loaded image path
If the device path to text protocol is not available (looking angrily at
Apple) we would fail to boot because we cannot get the loaded image
path. As this is only used for cosmetic purposes, we can just silently
continue.
Fixes: #25363
(cherry picked from commit af7ef648cddeb96da525de2410565d166f75cc96)
Related: #2138081
---
src/boot/efi/boot.c | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 17d4ec2d09..b490a1d972 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -471,7 +471,6 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
_cleanup_free_ char16_t *device_part_uuid = NULL;
assert(config);
- assert(loaded_image_path);
clear_screen(COLOR_NORMAL);
console_query_mode(&x_max, &y_max);
@@ -619,7 +618,6 @@ static bool menu_run(
assert(config);
assert(chosen_entry);
- assert(loaded_image_path);
EFI_STATUS err;
UINTN visible_max = 0;
@@ -1478,7 +1476,7 @@ static void config_entry_add_type1(
entry->loader = xstra_to_path(value);
/* do not add an entry for ourselves */
- if (loaded_image_path && strcaseeq16(entry->loader, loaded_image_path)) {
+ if (strcaseeq16(entry->loader, loaded_image_path)) {
entry->type = LOADER_UNDEFINED;
break;
}
@@ -1908,12 +1906,11 @@ static ConfigEntry *config_entry_add_loader_auto(
assert(root_dir);
assert(id);
assert(title);
- assert(loader || loaded_image_path);
if (!config->auto_entries)
return NULL;
- if (loaded_image_path) {
+ if (!loader) {
loader = L"\\EFI\\BOOT\\BOOT" EFI_MACHINE_TYPE_NAME ".efi";
/* We are trying to add the default EFI loader here,
@@ -2562,7 +2559,6 @@ static void export_variables(
char16_t uuid[37];
assert(loaded_image);
- assert(loaded_image_path);
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
@@ -2591,7 +2587,6 @@ static void config_load_all_entries(
assert(config);
assert(loaded_image);
- assert(loaded_image_path);
assert(root_dir);
config_load_defaults(config, root_dir);
@@ -2676,9 +2671,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
if (err != EFI_SUCCESS)
return log_error_status_stall(err, L"Error getting a LoadedImageProtocol handle: %r", err);
- err = device_path_to_str(loaded_image->FilePath, &loaded_image_path);
- if (err != EFI_SUCCESS)
- return log_error_status_stall(err, L"Error getting loaded image path: %r", err);
+ (void) device_path_to_str(loaded_image->FilePath, &loaded_image_path);
export_variables(loaded_image, loaded_image_path, init_usec);

@ -0,0 +1,75 @@
From 806165285b822436023df84ca0a3e5b28a3099d6 Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Mon, 14 Nov 2022 15:24:32 +0100
Subject: [PATCH] boot: Manually convert filepaths if needed
The conversion of a filepath device path to text is needed for the stub
loader to find credential files.
(cherry picked from commit 679007044fbbcf82c66cf20b99f2f5086b7df6b4)
Related: #2138081
---
src/boot/efi/util.c | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
index 5547d288de..57436dbf0c 100644
--- a/src/boot/efi/util.c
+++ b/src/boot/efi/util.c
@@ -772,19 +772,51 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text;
EFI_STATUS err;
+ _cleanup_free_ char16_t *str = NULL;
assert(dp);
assert(ret);
err = BS->LocateProtocol(&(EFI_GUID) EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, NULL, (void **) &dp_to_text);
- if (err != EFI_SUCCESS)
- return err;
+ if (err != EFI_SUCCESS) {
+ /* If the device path to text protocol is not available we can still do a best-effort attempt
+ * to convert it ourselves if we are given filepath-only device path. */
+
+ size_t size = 0;
+ for (const EFI_DEVICE_PATH *node = dp; !IsDevicePathEnd(node);
+ node = NextDevicePathNode(node)) {
+
+ if (DevicePathType(node) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType(node) != MEDIA_FILEPATH_DP)
+ return err;
+
+ size_t path_size = DevicePathNodeLength(node);
+ if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t))
+ return EFI_INVALID_PARAMETER;
+ path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName);
+
+ _cleanup_free_ char16_t *old = str;
+ str = xmalloc(size + path_size);
+ if (old) {
+ memcpy(str, old, size);
+ str[size / sizeof(char16_t) - 1] = '\\';
+ }
+
+ memcpy(str + (size / sizeof(char16_t)),
+ ((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName),
+ path_size);
+ size += path_size;
+ }
+
+ *ret = TAKE_PTR(str);
+ return EFI_SUCCESS;
+ }
- char16_t *str = dp_to_text->ConvertDevicePathToText(dp, false, false);
+ str = dp_to_text->ConvertDevicePathToText(dp, false, false);
if (!str)
return EFI_OUT_OF_RESOURCES;
- *ret = str;
+ *ret = TAKE_PTR(str);
return EFI_SUCCESS;
}

@ -0,0 +1,433 @@
From 519625977d19b7842d9b2ded8be12ed0aecbaefc Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Tue, 15 Nov 2022 18:22:38 +0100
Subject: [PATCH] boot: Rework security arch override
This simplifies the caller interface for security arch overrides by only
having to pass a validator and an optional context.
(cherry picked from commit 5489c13bae119dc5f6e65be8d7f241aa7d54c023)
Related: #2138081
---
src/boot/efi/linux.c | 61 ++++++++-------------
src/boot/efi/secure-boot.c | 105 +++++++++++++++++++++++++++++--------
src/boot/efi/secure-boot.h | 28 +++-------
src/boot/efi/shim.c | 104 +++++++++++-------------------------
4 files changed, 146 insertions(+), 152 deletions(-)
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
index 75b9507709..dd7eb48c8c 100644
--- a/src/boot/efi/linux.c
+++ b/src/boot/efi/linux.c
@@ -20,35 +20,26 @@
#define STUB_PAYLOAD_GUID \
{ 0x55c5d1f8, 0x04cd, 0x46b5, { 0x8a, 0x20, 0xe5, 0x6c, 0xbb, 0x30, 0x52, 0xd0 } }
-static EFIAPI EFI_STATUS security_hook(
- const SecurityOverride *this, uint32_t authentication_status, const EFI_DEVICE_PATH *file) {
+typedef struct {
+ const void *addr;
+ size_t len;
+ const EFI_DEVICE_PATH *device_path;
+} ValidationContext;
- assert(this);
- assert(this->hook == security_hook);
+static bool validate_payload(
+ const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
- if (file == this->payload_device_path)
- return EFI_SUCCESS;
+ const ValidationContext *payload = ASSERT_PTR(ctx);
- return this->original_security->FileAuthenticationState(
- this->original_security, authentication_status, file);
-}
-
-static EFIAPI EFI_STATUS security2_hook(
- const SecurityOverride *this,
- const EFI_DEVICE_PATH *device_path,
- void *file_buffer,
- size_t file_size,
- BOOLEAN boot_policy) {
-
- assert(this);
- assert(this->hook == security2_hook);
+ if (device_path != payload->device_path)
+ return false;
- if (file_buffer == this->payload && file_size == this->payload_len &&
- device_path == this->payload_device_path)
- return EFI_SUCCESS;
+ /* Security arch (1) protocol does not provide a file buffer. Instead we are supposed to fetch the payload
+ * ourselves, which is not needed as we already have everything in memory and the device paths match. */
+ if (file_buffer && (file_buffer != payload->addr || file_size != payload->len))
+ return false;
- return this->original_security2->FileAuthentication(
- this->original_security2, device_path, file_buffer, file_size, boot_policy);
+ return true;
}
static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len, EFI_HANDLE *ret_image) {
@@ -79,19 +70,13 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
/* We want to support unsigned kernel images as payload, which is safe to do under secure boot
* because it is embedded in this stub loader (and since it is already running it must be trusted). */
- SecurityOverride security_override = {
- .hook = security_hook,
- .payload = source,
- .payload_len = len,
- .payload_device_path = &payload_device_path.payload.Header,
- }, security2_override = {
- .hook = security2_hook,
- .payload = source,
- .payload_len = len,
- .payload_device_path = &payload_device_path.payload.Header,
- };
-
- install_security_override(&security_override, &security2_override);
+ install_security_override(
+ validate_payload,
+ &(ValidationContext) {
+ .addr = source,
+ .len = len,
+ .device_path = &payload_device_path.payload.Header,
+ });
EFI_STATUS ret = BS->LoadImage(
/*BootPolicy=*/false,
@@ -101,7 +86,7 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
len,
ret_image);
- uninstall_security_override(&security_override, &security2_override);
+ uninstall_security_override();
return ret;
}
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
index 171b2c96b3..0e615c55e0 100644
--- a/src/boot/efi/secure-boot.c
+++ b/src/boot/efi/secure-boot.c
@@ -127,10 +127,60 @@ out_deallocate:
return err;
}
-static EFI_STATUS install_security_override_one(EFI_GUID guid, SecurityOverride *override) {
+static struct SecurityOverride {
+ /* Our own security arch instances that we register onto original_handle, thereby replacing the
+ * firmware provided instances. */
+ EFI_SECURITY_ARCH_PROTOCOL override;
+ EFI_SECURITY2_ARCH_PROTOCOL override2;
+
+ /* These are saved so we can uninstall our own instance later. */
+ EFI_HANDLE original_handle, original_handle2;
+ EFI_SECURITY_ARCH_PROTOCOL *original_security;
+ EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
+
+ security_validator_t validator;
+ const void *validator_ctx;
+} security_override;
+
+static EFIAPI EFI_STATUS security_hook(
+ const EFI_SECURITY_ARCH_PROTOCOL *this,
+ uint32_t authentication_status,
+ const EFI_DEVICE_PATH *file) {
+
+ assert(security_override.validator);
+ assert(security_override.original_security);
+
+ if (security_override.validator(security_override.validator_ctx, file, NULL, 0))
+ return EFI_SUCCESS;
+
+ return security_override.original_security->FileAuthenticationState(
+ security_override.original_security, authentication_status, file);
+}
+
+static EFIAPI EFI_STATUS security2_hook(
+ const EFI_SECURITY2_ARCH_PROTOCOL *this,
+ const EFI_DEVICE_PATH *device_path,
+ void *file_buffer,
+ size_t file_size,
+ BOOLEAN boot_policy) {
+
+ assert(security_override.validator);
+ assert(security_override.original_security2);
+
+ if (security_override.validator(security_override.validator_ctx, device_path, file_buffer, file_size))
+ return EFI_SUCCESS;
+
+ return security_override.original_security2->FileAuthentication(
+ security_override.original_security2, device_path, file_buffer, file_size, boot_policy);
+}
+
+static EFI_STATUS install_security_override_one(
+ EFI_GUID guid, void *override, EFI_HANDLE *ret_original_handle, void **ret_original_security) {
EFI_STATUS err;
assert(override);
+ assert(ret_original_handle);
+ assert(ret_original_security);
_cleanup_free_ EFI_HANDLE *handles = NULL;
size_t n_handles = 0;
@@ -152,8 +202,8 @@ static EFI_STATUS install_security_override_one(EFI_GUID guid, SecurityOverride
if (err != EFI_SUCCESS)
return log_error_status_stall(err, u"Error overriding security arch protocol: %r", err);
- override->original = security;
- override->original_handle = handles[0];
+ *ret_original_security = security;
+ *ret_original_handle = handles[0];
return EFI_SUCCESS;
}
@@ -161,35 +211,46 @@ static EFI_STATUS install_security_override_one(EFI_GUID guid, SecurityOverride
* Specification) with the provided override instances. If not running in secure boot or the protocols are
* not available nothing happens. The override instances are provided with the necessary info to undo this
* in uninstall_security_override(). */
-void install_security_override(SecurityOverride *override, SecurityOverride *override2) {
- assert(override);
- assert(override2);
+void install_security_override(security_validator_t validator, const void *validator_ctx) {
+ assert(validator);
if (!secure_boot_enabled())
return;
- (void) install_security_override_one((EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, override);
- (void) install_security_override_one((EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, override2);
-}
+ security_override = (struct SecurityOverride) {
+ { .FileAuthenticationState = security_hook, },
+ { .FileAuthentication = security2_hook, },
+ .validator = validator,
+ .validator_ctx = validator_ctx,
+ };
-void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2) {
- assert(override);
- assert(override2);
+ (void) install_security_override_one(
+ (EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
+ &security_override.override,
+ &security_override.original_handle,
+ (void **) &security_override.original_security);
+ (void) install_security_override_one(
+ (EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
+ &security_override.override2,
+ &security_override.original_handle2,
+ (void **) &security_override.original_security2);
+}
+void uninstall_security_override(void) {
/* We use assert_se here to guarantee the system is not in a weird state in the unlikely case of an
* error restoring the original protocols. */
- if (override->original_handle)
+ if (security_override.original_handle)
assert_se(BS->ReinstallProtocolInterface(
- override->original_handle,
- &(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
- override,
- override->original) == EFI_SUCCESS);
+ security_override.original_handle,
+ &(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
+ &security_override.override,
+ security_override.original_security) == EFI_SUCCESS);
- if (override2->original_handle)
+ if (security_override.original_handle2)
assert_se(BS->ReinstallProtocolInterface(
- override2->original_handle,
- &(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
- override2,
- override2->original) == EFI_SUCCESS);
+ security_override.original_handle2,
+ &(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
+ &security_override.override2,
+ security_override.original_security2) == EFI_SUCCESS);
}
diff --git a/src/boot/efi/secure-boot.h b/src/boot/efi/secure-boot.h
index 91b6770edb..e98de81c2a 100644
--- a/src/boot/efi/secure-boot.h
+++ b/src/boot/efi/secure-boot.h
@@ -17,23 +17,11 @@ SecureBootMode secure_boot_mode(void);
EFI_STATUS secure_boot_enroll_at(EFI_FILE *root_dir, const char16_t *path);
-typedef struct {
- void *hook;
-
- /* End of EFI_SECURITY_ARCH(2)_PROTOCOL. The rest is our own protocol instance data. */
-
- EFI_HANDLE original_handle;
- union {
- void *original;
- EFI_SECURITY_ARCH_PROTOCOL *original_security;
- EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
- };
-
- /* Used by the stub to identify the embedded image. */
- const void *payload;
- size_t payload_len;
- const EFI_DEVICE_PATH *payload_device_path;
-} SecurityOverride;
-
-void install_security_override(SecurityOverride *override, SecurityOverride *override2);
-void uninstall_security_override(SecurityOverride *override, SecurityOverride *override2);
+typedef bool (*security_validator_t)(
+ const void *ctx,
+ const EFI_DEVICE_PATH *device_path,
+ const void *file_buffer,
+ size_t file_size);
+
+void install_security_override(security_validator_t validator, const void *validator_ctx);
+void uninstall_security_override(void);
diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c
index 3ae058cb84..ac224336bc 100644
--- a/src/boot/efi/shim.c
+++ b/src/boot/efi/shim.c
@@ -23,7 +23,7 @@
#endif
struct ShimLock {
- EFI_STATUS __sysv_abi__ (*shim_verify) (void *buffer, uint32_t size);
+ EFI_STATUS __sysv_abi__ (*shim_verify) (const void *buffer, uint32_t size);
/* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface
* see shim.c/shim.h and PeHeader.h in the github shim repo */
@@ -41,79 +41,45 @@ bool shim_loaded(void) {
return BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) == EFI_SUCCESS;
}
-static bool shim_validate(void *data, uint32_t size) {
- struct ShimLock *shim_lock;
-
- if (!data)
- return false;
-
- if (BS->LocateProtocol((EFI_GUID*) SHIM_LOCK_GUID, NULL, (void**) &shim_lock) != EFI_SUCCESS)
- return false;
-
- if (!shim_lock)
- return false;
-
- return shim_lock->shim_verify(data, size) == EFI_SUCCESS;
-}
-
-static EFIAPI EFI_STATUS security2_hook(
- const SecurityOverride *this,
- const EFI_DEVICE_PATH *device_path,
- void *file_buffer,
- UINTN file_size,
- BOOLEAN boot_policy) {
-
- assert(this);
- assert(this->hook == security2_hook);
-
- if (shim_validate(file_buffer, file_size))
- return EFI_SUCCESS;
-
- return this->original_security2->FileAuthentication(
- this->original_security2, device_path, file_buffer, file_size, boot_policy);
-}
-
-static EFIAPI EFI_STATUS security_hook(
- const SecurityOverride *this,
- uint32_t authentication_status,
- const EFI_DEVICE_PATH *device_path) {
+static bool shim_validate(
+ const void *ctx, const EFI_DEVICE_PATH *device_path, const void *file_buffer, size_t file_size) {
EFI_STATUS err;
+ _cleanup_free_ char *file_buffer_owned = NULL;
- assert(this);
- assert(this->hook == security_hook);
+ if (!file_buffer) {
+ if (!device_path)
+ return false;
- if (!device_path)
- return this->original_security->FileAuthenticationState(
- this->original_security, authentication_status, device_path);
+ EFI_HANDLE device_handle;
+ EFI_DEVICE_PATH *file_dp = (EFI_DEVICE_PATH *) device_path;
+ err = BS->LocateDevicePath(&FileSystemProtocol, &file_dp, &device_handle);
+ if (err != EFI_SUCCESS)
+ return false;
- EFI_HANDLE device_handle;
- EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *) device_path;
- err = BS->LocateDevicePath(&FileSystemProtocol, &dp, &device_handle);
- if (err != EFI_SUCCESS)
- return err;
+ _cleanup_(file_closep) EFI_FILE *root = NULL;
+ err = open_volume(device_handle, &root);
+ if (err != EFI_SUCCESS)
+ return false;
- _cleanup_(file_closep) EFI_FILE *root = NULL;
- err = open_volume(device_handle, &root);
- if (err != EFI_SUCCESS)
- return err;
+ _cleanup_free_ char16_t *dp_str = NULL;
+ err = device_path_to_str(file_dp, &dp_str);
+ if (err != EFI_SUCCESS)
+ return false;
- _cleanup_free_ char16_t *dp_str = NULL;
- err = device_path_to_str(dp, &dp_str);
- if (err != EFI_SUCCESS)
- return err;
+ err = file_read(root, dp_str, 0, 0, &file_buffer_owned, &file_size);
+ if (err != EFI_SUCCESS)
+ return false;
- char *file_buffer;
- size_t file_size;
- err = file_read(root, dp_str, 0, 0, &file_buffer, &file_size);
- if (err != EFI_SUCCESS)
- return err;
+ file_buffer = file_buffer_owned;
+ }
- if (shim_validate(file_buffer, file_size))
- return EFI_SUCCESS;
+ struct ShimLock *shim_lock;
+ err = BS->LocateProtocol((EFI_GUID *) SHIM_LOCK_GUID, NULL, (void **) &shim_lock);
+ if (err != EFI_SUCCESS)
+ return false;
- return this->original_security->FileAuthenticationState(
- this->original_security, authentication_status, device_path);
+ return shim_lock->shim_verify(file_buffer, file_size) == EFI_SUCCESS;
}
EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path, EFI_HANDLE *ret_image) {
@@ -122,20 +88,14 @@ EFI_STATUS shim_load_image(EFI_HANDLE parent, const EFI_DEVICE_PATH *device_path
bool have_shim = shim_loaded();
- SecurityOverride security_override = {
- .hook = security_hook,
- }, security2_override = {
- .hook = security2_hook,
- };
-
if (have_shim)
- install_security_override(&security_override, &security2_override);
+ install_security_override(shim_validate, NULL);
EFI_STATUS ret = BS->LoadImage(
/*BootPolicy=*/false, parent, (EFI_DEVICE_PATH *) device_path, NULL, 0, ret_image);
if (have_shim)
- uninstall_security_override(&security_override, &security2_override);
+ uninstall_security_override();
return ret;
}

@ -0,0 +1,185 @@
From 8d0b70887a09b9d4a8b669620579d3b6780f0755 Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Tue, 15 Nov 2022 18:53:02 +0100
Subject: [PATCH] boot: Replace firmware security hooks directly
For some firmware, replacing their own security arch instance with our
override using ReinstallProtocolInterface() is not enough as they will
not use it. This commit goes back to how this was done before by
directly modifying the security protocols.
Fixes: #25336
(cherry picked from commit 967a868563996e928f1fade5bcafc82a7219742b)
Related: #2138081
---
src/boot/efi/secure-boot.c | 119 +++++++++++++------------------------
1 file changed, 40 insertions(+), 79 deletions(-)
diff --git a/src/boot/efi/secure-boot.c b/src/boot/efi/secure-boot.c
index 0e615c55e0..65457bf423 100644
--- a/src/boot/efi/secure-boot.c
+++ b/src/boot/efi/secure-boot.c
@@ -128,15 +128,10 @@ out_deallocate:
}
static struct SecurityOverride {
- /* Our own security arch instances that we register onto original_handle, thereby replacing the
- * firmware provided instances. */
- EFI_SECURITY_ARCH_PROTOCOL override;
- EFI_SECURITY2_ARCH_PROTOCOL override2;
-
- /* These are saved so we can uninstall our own instance later. */
- EFI_HANDLE original_handle, original_handle2;
- EFI_SECURITY_ARCH_PROTOCOL *original_security;
- EFI_SECURITY2_ARCH_PROTOCOL *original_security2;
+ EFI_SECURITY_ARCH_PROTOCOL *security;
+ EFI_SECURITY2_ARCH_PROTOCOL *security2;
+ EFI_SECURITY_FILE_AUTHENTICATION_STATE original_hook;
+ EFI_SECURITY2_FILE_AUTHENTICATION original_hook2;
security_validator_t validator;
const void *validator_ctx;
@@ -148,13 +143,13 @@ static EFIAPI EFI_STATUS security_hook(
const EFI_DEVICE_PATH *file) {
assert(security_override.validator);
- assert(security_override.original_security);
+ assert(security_override.security);
+ assert(security_override.original_hook);
if (security_override.validator(security_override.validator_ctx, file, NULL, 0))
return EFI_SUCCESS;
- return security_override.original_security->FileAuthenticationState(
- security_override.original_security, authentication_status, file);
+ return security_override.original_hook(security_override.security, authentication_status, file);
}
static EFIAPI EFI_STATUS security2_hook(
@@ -165,92 +160,58 @@ static EFIAPI EFI_STATUS security2_hook(
BOOLEAN boot_policy) {
assert(security_override.validator);
- assert(security_override.original_security2);
+ assert(security_override.security2);
+ assert(security_override.original_hook2);
if (security_override.validator(security_override.validator_ctx, device_path, file_buffer, file_size))
return EFI_SUCCESS;
- return security_override.original_security2->FileAuthentication(
- security_override.original_security2, device_path, file_buffer, file_size, boot_policy);
+ return security_override.original_hook2(
+ security_override.security2, device_path, file_buffer, file_size, boot_policy);
}
-static EFI_STATUS install_security_override_one(
- EFI_GUID guid, void *override, EFI_HANDLE *ret_original_handle, void **ret_original_security) {
+/* This replaces the platform provided security arch protocols hooks (defined in the UEFI Platform
+ * Initialization Specification) with our own that uses the given validator to decide if a image is to be
+ * trusted. If not running in secure boot or the protocols are not available nothing happens. The override
+ * must be removed with uninstall_security_override() after LoadImage() has been called.
+ *
+ * This is a hack as we do not own the security protocol instances and modifying them is not an official part
+ * of their spec. But there is little else we can do to circumvent secure boot short of implementing our own
+ * PE loader. We could replace the firmware instances with our own instance using
+ * ReinstallProtocolInterface(), but some firmware will still use the old ones. */
+void install_security_override(security_validator_t validator, const void *validator_ctx) {
EFI_STATUS err;
- assert(override);
- assert(ret_original_handle);
- assert(ret_original_security);
-
- _cleanup_free_ EFI_HANDLE *handles = NULL;
- size_t n_handles = 0;
-
- err = BS->LocateHandleBuffer(ByProtocol, &guid, NULL, &n_handles, &handles);
- if (err != EFI_SUCCESS)
- /* No security arch protocol around? */
- return err;
-
- /* There should only ever be one security arch protocol instance, but let's be paranoid here. */
- assert(n_handles == 1);
-
- void *security = NULL;
- err = BS->LocateProtocol(&guid, NULL, &security);
- if (err != EFI_SUCCESS)
- return log_error_status_stall(err, u"Error getting security arch protocol: %r", err);
-
- err = BS->ReinstallProtocolInterface(handles[0], &guid, security, override);
- if (err != EFI_SUCCESS)
- return log_error_status_stall(err, u"Error overriding security arch protocol: %r", err);
-
- *ret_original_security = security;
- *ret_original_handle = handles[0];
- return EFI_SUCCESS;
-}
-
-/* This replaces the platform provided security arch protocols (defined in the UEFI Platform Initialization
- * Specification) with the provided override instances. If not running in secure boot or the protocols are
- * not available nothing happens. The override instances are provided with the necessary info to undo this
- * in uninstall_security_override(). */
-void install_security_override(security_validator_t validator, const void *validator_ctx) {
assert(validator);
if (!secure_boot_enabled())
return;
security_override = (struct SecurityOverride) {
- { .FileAuthenticationState = security_hook, },
- { .FileAuthentication = security2_hook, },
.validator = validator,
.validator_ctx = validator_ctx,
};
- (void) install_security_override_one(
- (EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
- &security_override.override,
- &security_override.original_handle,
- (void **) &security_override.original_security);
- (void) install_security_override_one(
- (EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
- &security_override.override2,
- &security_override.original_handle2,
- (void **) &security_override.original_security2);
+ EFI_SECURITY_ARCH_PROTOCOL *security = NULL;
+ err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID, NULL, (void **) &security);
+ if (err == EFI_SUCCESS) {
+ security_override.security = security;
+ security_override.original_hook = security->FileAuthenticationState;
+ security->FileAuthenticationState = security_hook;
+ }
+
+ EFI_SECURITY2_ARCH_PROTOCOL *security2 = NULL;
+ err = BS->LocateProtocol(&(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID, NULL, (void **) &security2);
+ if (err == EFI_SUCCESS) {
+ security_override.security2 = security2;
+ security_override.original_hook2 = security2->FileAuthentication;
+ security2->FileAuthentication = security2_hook;
+ }
}
void uninstall_security_override(void) {
- /* We use assert_se here to guarantee the system is not in a weird state in the unlikely case of an
- * error restoring the original protocols. */
-
- if (security_override.original_handle)
- assert_se(BS->ReinstallProtocolInterface(
- security_override.original_handle,
- &(EFI_GUID) EFI_SECURITY_ARCH_PROTOCOL_GUID,
- &security_override.override,
- security_override.original_security) == EFI_SUCCESS);
-
- if (security_override.original_handle2)
- assert_se(BS->ReinstallProtocolInterface(
- security_override.original_handle2,
- &(EFI_GUID) EFI_SECURITY2_ARCH_PROTOCOL_GUID,
- &security_override.override2,
- security_override.original_security2) == EFI_SUCCESS);
+ if (security_override.original_hook)
+ security_override.security->FileAuthenticationState = security_override.original_hook;
+ if (security_override.original_hook2)
+ security_override.security2->FileAuthentication = security_override.original_hook2;
}

@ -0,0 +1,31 @@
From a43bf9f897002744610a9ea5ce7bdc91c3e3dc83 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Tue, 8 Nov 2022 12:21:35 -0800
Subject: [PATCH] networkd-ipv4acd.c: Use net/if.h for getting IFF_LOOPBACK
definition
This helps in avoiding compiling errors on musl. Definition of
IFF_LOOPBACK is the reason for including linux/if_arp.h, this however
could be obtained from net/if.h glibc header equally and makes it
portable as well.
(cherry picked from commit 239e4a42a69c31e55e58618d800e0d68c68931d3)
Related: #2138081
---
src/network/networkd-ipv4acd.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/network/networkd-ipv4acd.c b/src/network/networkd-ipv4acd.c
index 4127657ebd..877dee00ec 100644
--- a/src/network/networkd-ipv4acd.c
+++ b/src/network/networkd-ipv4acd.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#include <linux/if_arp.h>
+#include <net/if.h> /* IFF_LOOPBACK */
+#include <net/if_arp.h> /* ARPHRD_ETHER */
#include "sd-dhcp-client.h"
#include "sd-ipv4acd.h"

@ -0,0 +1,111 @@
From 94f9a80db599dcc298f3058e5cf2bb60c4972228 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 24 Nov 2022 13:58:39 +0100
Subject: [PATCH] Revert "initrd: extend SYSTEMD_IN_INITRD to accept non-ramfs
rootfs"
This reverts commit 1f22621ba33f8089d2ae5fbcaf8b3970dd68aaf0.
This is a replacement for b1fd5cd4eda02a323db93d7daa97f5138f89677d. See that
commit for details.
Related: #2138081
---
docs/ENVIRONMENT.md | 10 +++-------
src/basic/util.c | 47 ++++++++-------------------------------------
2 files changed, 11 insertions(+), 46 deletions(-)
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
index a840dd0c90..ab3add6031 100644
--- a/docs/ENVIRONMENT.md
+++ b/docs/ENVIRONMENT.md
@@ -73,13 +73,9 @@ All tools:
(relevant in particular for the system manager and `systemd-hostnamed`).
Must be a valid hostname (either a single label or a FQDN).
-* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
- method. Defaults to `auto`. Behavior is defined as follows:
- `auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
- on `/`. If both conditions meet, then it's in initrd.
- `lenient`: Similar to `auto`, but the rootfs check is skipped.
- `0|1`: Simply overrides initrd detection. This is useful for debugging and
- testing initrd-only programs in the main system.
+* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection.
+ This is useful for debugging and testing initrd-only programs in the main
+ system.
* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call
completion. If no time unit is specified, assumes seconds. The usual other units
diff --git a/src/basic/util.c b/src/basic/util.c
index d7ef382737..981f917fab 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -52,13 +52,11 @@ int prot_from_flags(int flags) {
bool in_initrd(void) {
int r;
- const char *e;
- bool lenient = false;
if (saved_in_initrd >= 0)
return saved_in_initrd;
- /* We have two checks here:
+ /* We make two checks here:
*
* 1. the flag file /etc/initrd-release must exist
* 2. the root file system must be a memory file system
@@ -66,46 +64,17 @@ bool in_initrd(void) {
* The second check is extra paranoia, since misdetecting an
* initrd can have bad consequences due the initrd
* emptying when transititioning to the main systemd.
- *
- * If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
- * both checks are used. If it's set to "lenient", only check
- * 1 is used. If set to a boolean value, then the boolean
- * value is returned.
*/
- e = secure_getenv("SYSTEMD_IN_INITRD");
- if (e) {
- if (streq(e, "lenient"))
- lenient = true;
- else if (!streq(e, "auto")) {
- r = parse_boolean(e);
- if (r >= 0) {
- saved_in_initrd = r > 0;
- return saved_in_initrd;
- }
- log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
- }
- }
-
- if (!lenient) {
- r = path_is_temporary_fs("/");
- if (r < 0)
- log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
+ r = getenv_bool_secure("SYSTEMD_IN_INITRD");
+ if (r < 0 && r != -ENXIO)
+ log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
+ if (r >= 0)
saved_in_initrd = r > 0;
- }
-
- r = access("/etc/initrd-release", F_OK);
- if (r >= 0) {
- if (saved_in_initrd == 0)
- log_debug("/etc/initrd-release exists, but it's not an initrd.");
- else
- saved_in_initrd = 1;
- } else {
- if (errno != ENOENT)
- log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
- saved_in_initrd = 0;
- }
+ else
+ saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
+ path_is_temporary_fs("/") > 0;
return saved_in_initrd;
}

@ -0,0 +1,124 @@
From 7b6a09c47f1fee035c4b42840fabf65edce12aa8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 7 Nov 2022 12:40:20 +0100
Subject: [PATCH] pid1: skip cleanup if root is not tmpfs/ramfs
in_initrd() was really doing two things: checking if we're in the initrd, and
also verifying that the initrd is set up correctly. But this second check is
complicated, in particular it would return false for overlayfs, even with an
upper tmpfs layer. It also doesn't support the use case of having an initial
initrd with tmpfs, and then transitioning into an intermediate initrd that is
e.g. a DDI, i.e. a filesystem possibly with verity arranged as a disk image.
We don't need to check if we're in initrd in every program. Instead, concerns
are separated:
- in_initrd() just does a simple check for /etc/initrd-release.
- When doing cleanup, pid1 checks if it's on a tmpfs before starting to wipe
the old root. The only case where we want to remove the old root is when
we're on a plain tempory filesystem. With an overlay, we'd be creating
whiteout files, which is not very useful. (*)
This should resolve https://bugzilla.redhat.com/show_bug.cgi?id=2137631
which is caused by systemd refusing to treat the system as an initrd because
overlayfs is used.
(*) I think the idea of keeping the initrd fs around for shutdown is outdated.
We should just have a completely separate exitrd that is unpacked when we want
to shut down. This way, we don't waste memory at runtime, and we also don't
transition to a potentially older version of systemd. But we don't have support
for this yet.
This replaces 0fef5b0f0bd9ded1ae7bcb3e4e4b2893e36c51a6.
(cherry picked from commit a940f507fbe1c81d6787dc0b7ce232c39818eec9)
Related: #2138081
---
src/basic/util.c | 19 ++++++++-----------
src/shared/switch-root.c | 22 ++++++++++++----------
2 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/src/basic/util.c b/src/basic/util.c
index 981f917fab..e6aaa2dc9b 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -56,14 +56,8 @@ bool in_initrd(void) {
if (saved_in_initrd >= 0)
return saved_in_initrd;
- /* We make two checks here:
- *
- * 1. the flag file /etc/initrd-release must exist
- * 2. the root file system must be a memory file system
- *
- * The second check is extra paranoia, since misdetecting an
- * initrd can have bad consequences due the initrd
- * emptying when transititioning to the main systemd.
+ /* If /etc/initrd-release exists, we're in an initrd.
+ * This can be overridden by setting SYSTEMD_IN_INITRD=0|1.
*/
r = getenv_bool_secure("SYSTEMD_IN_INITRD");
@@ -72,9 +66,12 @@ bool in_initrd(void) {
if (r >= 0)
saved_in_initrd = r > 0;
- else
- saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
- path_is_temporary_fs("/") > 0;
+ else {
+ r = access("/etc/initrd-release", F_OK);
+ if (r < 0 && errno != ENOENT)
+ log_debug_errno(r, "Failed to check if /etc/initrd-release exists, assuming it does not: %m");
+ saved_in_initrd = r >= 0;
+ }
return saved_in_initrd;
}
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index 1a444841fa..4cad3551a6 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -32,7 +32,6 @@ int switch_root(const char *new_root,
_cleanup_free_ char *resolved_old_root_after = NULL;
_cleanup_close_ int old_root_fd = -1;
- bool old_root_remove;
int r;
assert(new_root);
@@ -42,12 +41,16 @@ int switch_root(const char *new_root,
return 0;
/* Check if we shall remove the contents of the old root */
- old_root_remove = in_initrd();
- if (old_root_remove) {
- old_root_fd = open("/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
- if (old_root_fd < 0)
- return log_error_errno(errno, "Failed to open root directory: %m");
- }
+ old_root_fd = open("/", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
+ if (old_root_fd < 0)
+ return log_error_errno(errno, "Failed to open root directory: %m");
+ r = fd_is_temporary_fs(old_root_fd);
+ if (r < 0)
+ return log_error_errno(r, "Failed to stat root directory: %m");
+ if (r > 0)
+ log_debug("Root directory is on tmpfs, will do cleanup later.");
+ else
+ old_root_fd = safe_close(old_root_fd);
/* Determine where we shall place the old root after the transition */
r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL);
@@ -117,9 +120,8 @@ int switch_root(const char *new_root,
struct stat rb;
if (fstat(old_root_fd, &rb) < 0)
- log_warning_errno(errno, "Failed to stat old root directory, leaving: %m");
- else
- (void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
+ return log_error_errno(errno, "Failed to stat old root directory: %m");
+ (void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */
}
return 0;

@ -0,0 +1,106 @@
From 2ac7d7a818788110342a99978680485fbe27cc25 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 11 Nov 2022 13:54:03 +0900
Subject: [PATCH] ac-power: check battery existence and status
If a battery is not present or its status is not discharging, then
the battery should not be used as a power source.
Let's count batteries currently discharging.
Fixes #25316.
(cherry picked from commit 1c03f7f4ba419aa65997e90accc0d935ae1cfbc5)
Related: #2138081
---
src/shared/udev-util.c | 58 ++++++++++++++++++++++++++++++++----------
1 file changed, 44 insertions(+), 14 deletions(-)
diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c
index aac02cd61b..7d95353452 100644
--- a/src/shared/udev-util.c
+++ b/src/shared/udev-util.c
@@ -642,9 +642,46 @@ static int device_is_power_sink(sd_device *device) {
return found_sink || !found_source;
}
+static bool battery_is_discharging(sd_device *d) {
+ const char *val;
+ int r;
+
+ assert(d);
+
+ r = sd_device_get_sysattr_value(d, "scope", &val);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
+ } else if (streq(val, "Device")) {
+ log_device_debug(d, "The power supply is a device battery, ignoring device.");
+ return false;
+ }
+
+ r = device_get_sysattr_bool(d, "present");
+ if (r < 0)
+ log_device_debug_errno(d, r, "Failed to read 'present' sysfs attribute, assuming the battery is present: %m");
+ else if (r == 0) {
+ log_device_debug(d, "The battery is not present, ignoring the power supply.");
+ return false;
+ }
+
+ /* Possible values: "Unknown", "Charging", "Discharging", "Not charging", "Full" */
+ r = sd_device_get_sysattr_value(d, "status", &val);
+ if (r < 0) {
+ log_device_debug_errno(d, r, "Failed to read 'status' sysfs attribute, assuming the battery is discharging: %m");
+ return true;
+ }
+ if (!streq(val, "Discharging")) {
+ log_device_debug(d, "The battery status is '%s', assuming the battery is not used as a power source of this machine.", val);
+ return false;
+ }
+
+ return true;
+}
+
int on_ac_power(void) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
- bool found_ac_online = false, found_battery = false;
+ bool found_ac_online = false, found_discharging_battery = false;
sd_device *d;
int r;
@@ -686,17 +723,10 @@ int on_ac_power(void) {
}
if (streq(val, "Battery")) {
- r = sd_device_get_sysattr_value(d, "scope", &val);
- if (r < 0) {
- if (r != -ENOENT)
- log_device_debug_errno(d, r, "Failed to read 'scope' sysfs attribute, ignoring: %m");
- } else if (streq(val, "Device")) {
- log_device_debug(d, "The power supply is a device battery, ignoring device.");
- continue;
+ if (battery_is_discharging(d)) {
+ found_discharging_battery = true;
+ log_device_debug(d, "The power supply is a battery and currently discharging.");
}
-
- found_battery = true;
- log_device_debug(d, "The power supply is battery.");
continue;
}
@@ -713,11 +743,11 @@ int on_ac_power(void) {
if (found_ac_online) {
log_debug("Found at least one online non-battery power supply, system is running on AC.");
return true;
- } else if (found_battery) {
- log_debug("Found battery and no online power sources, assuming system is running from battery.");
+ } else if (found_discharging_battery) {
+ log_debug("Found at least one discharging battery and no online power sources, assuming system is running from battery.");
return false;
} else {
- log_debug("No power supply reported online and no battery, assuming system is running on AC.");
+ log_debug("No power supply reported online and no discharging battery found, assuming system is running on AC.");
return true;
}
}

@ -0,0 +1,34 @@
From c2317e2a2be2dd39266b82712ec9569a86f7fde3 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 13 Nov 2022 21:10:56 +0900
Subject: [PATCH] systemctl: do not show unit properties with --all
Fixes a bug introduced by a6e334649d4bdff0c6f664e98666b2223aa21a8b.
Fixes #25343.
(cherry picked from commit 0b51a1c8c4c77f98a8c234cd2c7a7849329be027)
Related: #2138081
---
src/systemctl/systemctl-show.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/systemctl/systemctl-show.c b/src/systemctl/systemctl-show.c
index 8d3db98c0a..24c7d564b8 100644
--- a/src/systemctl/systemctl-show.c
+++ b/src/systemctl/systemctl-show.c
@@ -2207,9 +2207,10 @@ int verb_show(int argc, char *argv[], void *userdata) {
if (!arg_states && !arg_types) {
if (show_mode == SYSTEMCTL_SHOW_PROPERTIES)
- r = show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
- else
- r = show_system_status(bus);
+ /* systemctl show --all → show properties of the manager */
+ return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized);
+
+ r = show_system_status(bus);
if (r < 0)
return r;

@ -0,0 +1,46 @@
From abbfdf2aa3e17a84d0f4075f125e670defaf7296 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= <marcus.schaefer@gmail.com>
Date: Wed, 16 Nov 2022 00:17:19 +0100
Subject: [PATCH] Fix reading /etc/machine-id in kernel-install (#25388)
* Fix reading /etc/machine-id in kernel-install
The kernel-install script has code to read the contents of
/etc/machine-id into the MACHINE_ID variable. Depending
on the variable content kernel-install either logs the
value or creates a new machine id via 'systemd-id128 new'.
In that logic there is one issue. If the file /etc/machine-id
exists but is empty, the script tries to call read on an
empty file which return with an exit code != 0. As the
script code also uses 'set -e', kernel-install will exit at
this point which is unexpected.
The condition of an empty /etc/machine-id file exists for
example when building OS images, which should initialize the
system id on first boot but not staticly inside of the image.
afaik an empty /etc/machine-id is also a common approach
to make systemd indicate that it should create a new system
id. Because of this, the commit makes sure the reading of
/etc/machine-id does not fail in any case such that the
handling of the MACHINE_ID variable takes place.
(cherry picked from commit 883e7cbfc0dba6c81338e7924419b5cbb0cba0b2)
Related: #2138081
---
src/kernel-install/kernel-install.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in
index 22eb4d2be1..bba22f8a20 100755
--- a/src/kernel-install/kernel-install.in
+++ b/src/kernel-install/kernel-install.in
@@ -158,7 +158,7 @@ if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-info ]; then
[ -n "$MACHINE_ID" ] && \
log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-info"
fi
-if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-id ]; then
+if [ -z "$MACHINE_ID" ] && [ -s /etc/machine-id ]; then
read -r MACHINE_ID </etc/machine-id
[ -n "$MACHINE_ID" ] && \
log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-id"

@ -0,0 +1,83 @@
From 29c414e616f39e06d585ce6ecf25bb226963d0bc Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Mon, 14 Nov 2022 12:45:47 +0100
Subject: [PATCH] Revert "journal: Make sd_journal_previous/next() return 0 at
HEAD/TAIL"
This commit broke backwards compatibility so let's revert it until
we find a better solution.
This reverts commit 977ad21b5b8f6323515297bd8995dcaaca0905df.
(cherry picked from commit 1db6dbb1dcdacfd7d2b4c84562fc6e77bc8c43a5)
Related: #2138081
---
src/journal/test-journal-interleaving.c | 4 ----
src/libsystemd/sd-journal/sd-journal.c | 8 ++++----
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c
index 378bf162ca..b3ae4b8143 100644
--- a/src/journal/test-journal-interleaving.c
+++ b/src/journal/test-journal-interleaving.c
@@ -158,7 +158,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_head(j));
- assert_ret(sd_journal_previous(j) == 0);
assert_ret(sd_journal_next(j));
test_check_numbers_down(j, 4);
sd_journal_close(j);
@@ -167,7 +166,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_tail(j));
- assert_ret(sd_journal_next(j) == 0);
assert_ret(sd_journal_previous(j));
test_check_numbers_up(j, 4);
sd_journal_close(j);
@@ -176,7 +174,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_tail(j));
- assert_ret(sd_journal_next(j) == 0);
assert_ret(r = sd_journal_previous_skip(j, 4));
assert_se(r == 4);
test_check_numbers_down(j, 4);
@@ -186,7 +183,6 @@ static void test_skip_one(void (*setup)(void)) {
*/
assert_ret(sd_journal_open_directory(&j, t, 0));
assert_ret(sd_journal_seek_head(j));
- assert_ret(sd_journal_previous(j) == 0);
assert_ret(r = sd_journal_next_skip(j, 4));
assert_se(r == 4);
test_check_numbers_up(j, 4);
diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index 53c0b2a01e..1e4d128f05 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -606,9 +606,9 @@ static int find_location_for_match(
/* FIXME: missing: find by monotonic */
if (j->current_location.type == LOCATION_HEAD)
- return direction == DIRECTION_DOWN ? journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset) : 0;
+ return journal_file_next_entry_for_data(f, d, DIRECTION_DOWN, ret, offset);
if (j->current_location.type == LOCATION_TAIL)
- return direction == DIRECTION_UP ? journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset) : 0;
+ return journal_file_next_entry_for_data(f, d, DIRECTION_UP, ret, offset);
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum_for_data(f, d, j->current_location.seqnum, direction, ret, offset);
if (j->current_location.monotonic_set) {
@@ -701,9 +701,9 @@ static int find_location_with_matches(
/* No matches is simple */
if (j->current_location.type == LOCATION_HEAD)
- return direction == DIRECTION_DOWN ? journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset) : 0;
+ return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset);
if (j->current_location.type == LOCATION_TAIL)
- return direction == DIRECTION_UP ? journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset) : 0;
+ return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset);
if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id))
return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset);
if (j->current_location.monotonic_set) {

@ -0,0 +1,29 @@
From f740d67fd0ed36bc3318d724ccb1fdfca2f04125 Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Sun, 4 Sep 2022 00:22:23 +0200
Subject: [PATCH] boot: Correctly handle @saved default patterns
(cherry picked from commit 7941f11acb67c4f8ec857a791a51f3148af67b32)
Related: #2138081
---
src/shared/bootspec.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
index 6a34b10c04..d3cfb41a12 100644
--- a/src/shared/bootspec.c
+++ b/src/shared/bootspec.c
@@ -994,6 +994,12 @@ static int boot_config_find(const BootConfig *config, const char *id) {
if (!id)
return -1;
+ if (id[0] == '@') {
+ if (!strcaseeq(id, "@saved"))
+ return -1;
+ id = config->entry_selected;
+ }
+
for (size_t i = 0; i < config->n_entries; i++)
if (fnmatch(id, config->entries[i].id, FNM_CASEFOLD) == 0)
return i;

@ -0,0 +1,82 @@
From fda254c954d6a543e1977edc1d283c915ee43adc Mon Sep 17 00:00:00 2001
From: Vitaly Kuznetsov <vkuznets@redhat.com>
Date: Tue, 15 Nov 2022 14:57:23 +0100
Subject: [PATCH] shared/tpm2-util: Fix "Error: Esys invalid ESAPI handle
(40000001)" warning
systemd-cryptenroll complains (but succeeds!) upon binding to a signed PCR
policy:
$ systemd-cryptenroll --unlock-key-file=/tmp/passphrase --tpm2-device=auto
--tpm2-public-key=... --tpm2-signature=..." /tmp/tmp.img
ERROR:esys:src/tss2-esys/esys_iutil.c:394:iesys_handle_to_tpm_handle() Error: Esys invalid ESAPI handle (40000001).
WARNING:esys:src/tss2-esys/esys_iutil.c:415:iesys_is_platform_handle() Convert handle from TPM2_RH to ESYS_TR, got: 0x40000001
ERROR:esys:src/tss2-esys/esys_iutil.c:394:iesys_handle_to_tpm_handle() Error: Esys invalid ESAPI handle (40000001).
WARNING:esys:src/tss2-esys/esys_iutil.c:415:iesys_is_platform_handle() Convert handle from TPM2_RH to ESYS_TR, got: 0x4000000
New TPM2 token enrolled as key slot 1.
The problem seems to be that Esys_LoadExternal() function from tpm2-tss
expects a 'ESYS_TR_RH*' constant specifying the requested hierarchy and not
a 'TPM2_RH_*' one (see Esys_LoadExternal() -> Esys_LoadExternal_Async() ->
iesys_handle_to_tpm_handle() call chain).
It all works because Esys_LoadExternal_Async() falls back to using the
supplied values when iesys_handle_to_tpm_handle() fails:
r = iesys_handle_to_tpm_handle(hierarchy, &tpm_hierarchy);
if (r != TSS2_RC_SUCCESS) {
...
tpm_hierarchy = hierarchy;
}
Note, TPM2_RH_OWNER was used on purpose to support older tpm2-tss versions
(pre https://github.com/tpm2-software/tpm2-tss/pull/1531), use meson magic
to preserve compatibility.
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
(cherry picked from commit 155c51293d5bf37f54c65fd0a66ea29e6eedd580)
Related: #2138081
---
meson.build | 3 +++
src/shared/tpm2-util.c | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/meson.build b/meson.build
index 7750534466..015849af49 100644
--- a/meson.build
+++ b/meson.build
@@ -1474,11 +1474,14 @@ if want_tpm2 != 'false' and not skip_deps
tpm2 = dependency('tss2-esys tss2-rc tss2-mu',
required : want_tpm2 == 'true')
have = tpm2.found()
+ have_esys3 = tpm2.version().version_compare('>= 3.0.0')
else
have = false
+ have_esys3 = false
tpm2 = []
endif
conf.set10('HAVE_TPM2', have)
+conf.set10('HAVE_TSS2_ESYS3', have_esys3)
want_elfutils = get_option('elfutils')
if want_elfutils != 'false' and not skip_deps
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 4d0df944a9..8171b3e9e9 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -1117,7 +1117,13 @@ static int tpm2_make_policy_session(
ESYS_TR_NONE,
NULL,
&pubkey_tpm2,
+#if HAVE_TSS2_ESYS3
+ /* tpm2-tss >= 3.0.0 requires a ESYS_TR_RH_* constant specifying the requested
+ * hierarchy, older versions need TPM2_RH_* instead. */
+ ESYS_TR_RH_OWNER,
+#else
TPM2_RH_OWNER,
+#endif
&pubkey_handle);
if (rc != TSS2_RC_SUCCESS) {
r = log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),

@ -0,0 +1,31 @@
From 89adb54468aff192fccc9dce793e24d98b26d994 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= <marcus.schaefer@gmail.com>
Date: Wed, 16 Nov 2022 16:25:08 +0100
Subject: [PATCH] Handle MACHINE_ID=uninitialized
systemd supports /etc/machine-id to be set to: uninitialized
In this case the expectation is that systemd creates a new
machine ID and replaces the value 'uninitialized' with the
effective machine id. In the scope of kernel-install we
should also enforce the creation of a new machine id in this
condition
(cherry picked from commit 305dd91adfde332e7e5c1b2470edb32774f9a032)
Related: #2138081
---
src/kernel-install/kernel-install.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in
index bba22f8a20..fa2c0d5276 100755
--- a/src/kernel-install/kernel-install.in
+++ b/src/kernel-install/kernel-install.in
@@ -160,6 +160,7 @@ if [ -z "$MACHINE_ID" ] && [ -f /etc/machine-info ]; then
fi
if [ -z "$MACHINE_ID" ] && [ -s /etc/machine-id ]; then
read -r MACHINE_ID </etc/machine-id
+ [ "$MACHINE_ID" = "uninitialized" ] && unset MACHINE_ID
[ -n "$MACHINE_ID" ] && \
log_verbose "machine-id $MACHINE_ID acquired from /etc/machine-id"
fi

@ -0,0 +1,26 @@
From c64c705d9496faba81c8a2326a23f87470ffa692 Mon Sep 17 00:00:00 2001
From: Li kunyu <kunyu@nfschina.com>
Date: Fri, 18 Nov 2022 06:03:41 +0000
Subject: [PATCH] fuzz: fuzz-compress: fix copy-and-paste error: buf -> buf2
(#25431)
(cherry picked from commit f54f6d88b1235487eb7f0c634c488edc7813579a)
Related: #2138081
---
src/fuzz/fuzz-compress.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fuzz/fuzz-compress.c b/src/fuzz/fuzz-compress.c
index 712ab3ffa9..10956cc548 100644
--- a/src/fuzz/fuzz-compress.c
+++ b/src/fuzz/fuzz-compress.c
@@ -55,7 +55,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
size_t sw_alloc = MAX(h->sw_alloc, 1u);
buf2 = malloc(sw_alloc);
- if (!buf) {
+ if (!buf2) {
log_oom();
return 0;
}

@ -0,0 +1,25 @@
From 944fa2afca2bd6bd4d1d5aecd265fd4756ee44e2 Mon Sep 17 00:00:00 2001
From: Li kunyu <kunyu@nfschina.com>
Date: Fri, 18 Nov 2022 16:10:24 +0900
Subject: [PATCH] boot/measure: fix oom check
(cherry picked from commit fc0cc6db1ecbaa16513125d3fd1a7d11e391a8ee)
Related: #2138081
---
src/boot/measure.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/measure.c b/src/boot/measure.c
index 4f16acedf0..0bbd386449 100644
--- a/src/boot/measure.c
+++ b/src/boot/measure.c
@@ -897,7 +897,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) {
}
_cleanup_free_ void *sig = malloc(ss);
- if (!ss) {
+ if (!sig) {
r = log_oom();
goto finish;
}

@ -0,0 +1,57 @@
From b2d259a82329e37b0f369e9951f19a067cb8bfb4 Mon Sep 17 00:00:00 2001
From: Sam James <sam@gentoo.org>
Date: Fri, 18 Nov 2022 07:18:18 +0000
Subject: [PATCH] nspawn: allow sched_rr_get_interval_time64 through seccomp
filter
We only allow a selected subset of syscalls from nspawn containers
and don't list any time64 variants (needed for 32-bit arches when
built using TIME_BITS=64, which is relatively new).
We allow sched_rr_get_interval which cpython's test suite makes
use of, but we don't allow sched_rr_get_interval_time64.
The test failures when run in an arm32 nspawn container on an arm64 host
were as follows:
```
======================================================================
ERROR: test_sched_rr_get_interval (test.test_posix.PosixTester.test_sched_rr_get_interval)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/var/tmp/portage/dev-lang/python-3.11.0_p1/work/Python-3.11.0/Lib/test/test_posix.py", line 1180, in test_sched_rr_get_interval
interval = posix.sched_rr_get_interval(0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 1] Operation not permitted
```
Then strace showed:
```
sched_rr_get_interval_time64(0, 0xffbbd4a0) = -1 EPERM (Operation not permitted)
```
This appears to be the only time64 syscall that isn't already included one of
the sets listed in nspawn-seccomp.c that has a non-time64 variant. Checked
over each of the time64 syscalls known to systemd and verified that none
of the others had a non-time64-variant whitelisted in nspawn other than
sched_rr_get_interval.
Bug: https://bugs.gentoo.org/880131
(cherry picked from commit b9e7f22c2d80930cad36ae53e66e42a2996dca4a)
Related: #2138081
---
src/nspawn/nspawn-seccomp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c
index 77f4c2ac88..27044fadd2 100644
--- a/src/nspawn/nspawn-seccomp.c
+++ b/src/nspawn/nspawn-seccomp.c
@@ -88,6 +88,7 @@ static int add_syscall_filters(
{ 0, "sched_getparam" },
{ 0, "sched_getscheduler" },
{ 0, "sched_rr_get_interval" },
+ { 0, "sched_rr_get_interval_time64" },
{ 0, "sched_yield" },
{ 0, "seccomp" },
{ 0, "sendfile" },

@ -0,0 +1,26 @@
From 39974d2ee3b1e514e9d2cf25e4a11447d4dfee53 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 18 Nov 2022 16:52:01 +0100
Subject: [PATCH] resolved: use right conditionalization when setting unicast
ifindex on UDP sockets
(cherry picked from commit 5faaed5b62d5ed88d8df2802c5ab4d3ab2eb755a)
Related: #2138081
---
src/resolve/resolved-dns-scope.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 852829569d..4f744499aa 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -424,7 +424,7 @@ static int dns_scope_socket(
return r;
}
- if (s->link) {
+ if (ifindex != 0) {
r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
if (r < 0)
return r;

@ -0,0 +1,34 @@
From d8d96bce62e8597b8d35bed1d9e9cb103336fd6b Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 18 Nov 2022 16:52:06 +0100
Subject: [PATCH] resolved: when configuring 127.0.0.1 as per-interface DNS
server, contact it via "lo" always
ussually if you specify a DNS server on some interface then we'll use
that interface to talk to it. Let's override this for localhost
addresses, as they only really make sense on "lo".
Fixes: #25397
(cherry picked from commit 6e32414a66ff8dbcef233981a7066684d903ee9f)
Related: #2138081
---
src/resolve/resolved-dns-server.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 04a4f53ed0..8ff513fa33 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -648,6 +648,11 @@ int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeature
int dns_server_ifindex(const DnsServer *s) {
assert(s);
+ /* For loopback addresses, go via the loopback interface, regardless which interface this is linked
+ * to. */
+ if (in_addr_is_localhost(s->family, &s->address))
+ return LOOPBACK_IFINDEX;
+
/* The link ifindex always takes precedence */
if (s->link)
return s->link->ifindex;

@ -0,0 +1,50 @@
From bca4fe362cb2198f964d33c5a0fb27298d8e9ad8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 21 Nov 2022 20:03:08 +0100
Subject: [PATCH] manager: fix format strings for trigger metadata
Fixup for c8bc7519c888a99134f88f8c82353246d3c0cc5d.
(cherry picked from commit 6457ce15be84cf3c304d1ba47b89bacc2f60bf6e)
Related: #2138081
---
src/core/timer.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index 8bd430b931..b6810c8599 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -948,11 +948,11 @@ static int activation_details_timer_append_env(ActivationDetails *details, char
if (!dual_timestamp_is_set(&t->last_trigger))
return 0;
- r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=%" USEC_FMT, t->last_trigger.realtime);
+ r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=" USEC_FMT, t->last_trigger.realtime);
if (r < 0)
return r;
- r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=%" USEC_FMT, t->last_trigger.monotonic);
+ r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=" USEC_FMT, t->last_trigger.monotonic);
if (r < 0)
return r;
@@ -974,7 +974,7 @@ static int activation_details_timer_append_pair(ActivationDetails *details, char
if (r < 0)
return r;
- r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.realtime);
+ r = strv_extendf(strv, USEC_FMT, t->last_trigger.realtime);
if (r < 0)
return r;
@@ -982,7 +982,7 @@ static int activation_details_timer_append_pair(ActivationDetails *details, char
if (r < 0)
return r;
- r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.monotonic);
+ r = strv_extendf(strv, USEC_FMT, t->last_trigger.monotonic);
if (r < 0)
return r;

@ -0,0 +1,30 @@
From c103428e24f002e495412a5f9a0b919f4b92c2b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 21 Nov 2022 20:06:55 +0100
Subject: [PATCH] basic/strv: check printf arguments to strv_extendf()
The second argument to _printf_() specifies where the arguments start. We need to
use 0 in two cases: when the args in a va_list and can't be checked, and with journald
logging functions which accept multiple format strings with multiple argument sets,
which the _printf_ checker does not understand. But strv_extendf() can be checked.
(cherry picked from commit 400102ec91aa3404848a04f49a43d49e1a181708)
Related: #2138081
---
src/basic/strv.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/basic/strv.h b/src/basic/strv.h
index d6f5ac6ba5..6c9fa47943 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -45,7 +45,7 @@ static inline int strv_extend(char ***l, const char *value) {
return strv_extend_with_size(l, NULL, value);
}
-int strv_extendf(char ***l, const char *format, ...) _printf_(2,0);
+int strv_extendf(char ***l, const char *format, ...) _printf_(2,3);
int strv_extend_front(char ***l, const char *value);
int strv_push_with_size(char ***l, size_t *n, char *value);

@ -0,0 +1,139 @@
From 57bdd8a488d544282dcc71e6a23987ded71ac64d Mon Sep 17 00:00:00 2001
From: Benjamin Fogle <benfogle@gmail.com>
Date: Thu, 17 Nov 2022 09:52:50 -0500
Subject: [PATCH] resolved: Fix OpenSSL error messages
(cherry picked from commit f4a49d1c58578cb8d759dc6266a23d1acabdc38f)
Related: #2138081
---
src/resolve/resolved-dnstls-openssl.c | 65 +++++++++++----------------
1 file changed, 26 insertions(+), 39 deletions(-)
diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
index 4d3a88c8da..4a0132ad3d 100644
--- a/src/resolve/resolved-dnstls-openssl.c
+++ b/src/resolve/resolved-dnstls-openssl.c
@@ -14,6 +14,19 @@
#include "resolved-dnstls.h"
#include "resolved-manager.h"
+static char *dnstls_error_string(int ssl_error, char *buf, size_t count) {
+ assert(buf || count == 0);
+ if (ssl_error == SSL_ERROR_SSL)
+ ERR_error_string_n(ERR_get_error(), buf, count);
+ else
+ snprintf(buf, count, "SSL_get_error()=%d", ssl_error);
+ return buf;
+}
+
+#define DNSTLS_ERROR_BUFSIZE 256
+#define DNSTLS_ERROR_STRING(error) \
+ dnstls_error_string((error), (char[DNSTLS_ERROR_BUFSIZE]){}, DNSTLS_ERROR_BUFSIZE)
+
static int dnstls_flush_write_buffer(DnsStream *stream) {
ssize_t ss;
@@ -97,26 +110,18 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
if (server->server_name) {
r = SSL_set_tlsext_host_name(s, server->server_name);
- if (r <= 0) {
- char errbuf[256];
-
- error = ERR_get_error();
- ERR_error_string_n(error, errbuf, sizeof(errbuf));
- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", errbuf);
- }
+ if (r <= 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Failed to set server name: %s", DNSTLS_ERROR_STRING(SSL_ERROR_SSL));
}
ERR_clear_error();
stream->dnstls_data.handshake = SSL_do_handshake(s);
if (stream->dnstls_data.handshake <= 0) {
error = SSL_get_error(s, stream->dnstls_data.handshake);
- if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) {
- char errbuf[256];
-
- ERR_error_string_n(error, errbuf, sizeof(errbuf));
+ if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE))
return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
- "Failed to invoke SSL_do_handshake: %s", errbuf);
- }
+ "Failed to invoke SSL_do_handshake: %s", DNSTLS_ERROR_STRING(error));
}
stream->encrypted = true;
@@ -177,12 +182,8 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) {
} else if (error == SSL_ERROR_SYSCALL) {
if (errno > 0)
log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m");
- } else {
- char errbuf[256];
-
- ERR_error_string_n(error, errbuf, sizeof(errbuf));
- log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf);
- }
+ } else
+ log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(error));
}
stream->dnstls_events = 0;
@@ -206,14 +207,10 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) {
return r;
return -EAGAIN;
- } else {
- char errbuf[256];
-
- ERR_error_string_n(error, errbuf, sizeof(errbuf));
+ } else
return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
"Failed to invoke SSL_do_handshake: %s",
- errbuf);
- }
+ DNSTLS_ERROR_STRING(error));
}
stream->dnstls_events = 0;
@@ -275,12 +272,8 @@ int dnstls_stream_shutdown(DnsStream *stream, int error) {
} else if (ssl_error == SSL_ERROR_SYSCALL) {
if (errno > 0)
log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m");
- } else {
- char errbuf[256];
-
- ERR_error_string_n(ssl_error, errbuf, sizeof(errbuf));
- log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf);
- }
+ } else
+ log_debug("Failed to invoke SSL_shutdown, ignoring: %s", DNSTLS_ERROR_STRING(ssl_error));
}
stream->dnstls_events = 0;
@@ -307,10 +300,7 @@ static ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t co
stream->dnstls_events = 0;
ss = 0;
} else {
- char errbuf[256];
-
- ERR_error_string_n(error, errbuf, sizeof(errbuf));
- log_debug("Failed to invoke SSL_write: %s", errbuf);
+ log_debug("Failed to invoke SSL_write: %s", DNSTLS_ERROR_STRING(error));
stream->dnstls_events = 0;
ss = -EPIPE;
}
@@ -375,10 +365,7 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
stream->dnstls_events = 0;
ss = 0;
} else {
- char errbuf[256];
-
- ERR_error_string_n(error, errbuf, sizeof(errbuf));
- log_debug("Failed to invoke SSL_read: %s", errbuf);
+ log_debug("Failed to invoke SSL_read: %s", DNSTLS_ERROR_STRING(error));
stream->dnstls_events = 0;
ss = -EPIPE;
}

@ -0,0 +1,70 @@
From ff7e9a0e3bf9229b2ea55ac0e832358fe13b97b4 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 22 Nov 2022 14:24:32 +0900
Subject: [PATCH] network: wifi: try to reconfigure when connected
Sometimes, RTM_NEWLINK message with carrier is received earlier than
NL80211_CMD_CONNECT. To make SSID= or other WiFi related settings in
[Match] section work, let's try to reconfigure the interface.
Fixes a bug introduced by 96f5f9ef9a1ba5146d3357c1548fb675d3bd5b68.
Fixes #25384.
(cherry picked from commit 8a4ad01a72481a6a7c0309064dd2dbd814818c94)
Related: #2138081
---
src/network/networkd-link.c | 2 +-
src/network/networkd-link.h | 1 +
src/network/networkd-wifi.c | 12 ++++++++++++
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 00e4e451ef..788c7957d3 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1178,7 +1178,7 @@ static int link_get_network(Link *link, Network **ret) {
return -ENOENT;
}
-static int link_reconfigure_impl(Link *link, bool force) {
+int link_reconfigure_impl(Link *link, bool force) {
Network *network = NULL;
NetDev *netdev = NULL;
int r;
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 9f1cdca312..65b0164106 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -234,6 +234,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
+int link_reconfigure_impl(Link *link, bool force);
int link_reconfigure(Link *link, bool force);
int link_reconfigure_after_sleep(Link *link);
diff --git a/src/network/networkd-wifi.c b/src/network/networkd-wifi.c
index 4bf798a9eb..62cbca0cf9 100644
--- a/src/network/networkd-wifi.c
+++ b/src/network/networkd-wifi.c
@@ -269,6 +269,18 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
if (link->wlan_iftype == NL80211_IFTYPE_STATION && link->ssid)
log_link_info(link, "Connected WiFi access point: %s (%s)",
link->ssid, ETHER_ADDR_TO_STR(&link->bssid));
+
+ /* Sometimes, RTM_NEWLINK message with carrier is received earlier than NL80211_CMD_CONNECT.
+ * To make SSID= or other WiFi related settings in [Match] section work, let's try to
+ * reconfigure the interface. */
+ if (link->ssid && link_has_carrier(link)) {
+ r = link_reconfigure_impl(link, /* force = */ false);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
+ link_enter_failed(link);
+ return 0;
+ }
+ }
break;
}
case NL80211_CMD_DISCONNECT:

@ -0,0 +1,38 @@
From 6135d6239a40edb260dde80e5662d3e062dde0bd Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Tue, 22 Nov 2022 10:33:55 -0500
Subject: [PATCH] oomd: always allow root-owned cgroups to set
ManagedOOMPreference
Commit 652a4efb66a ("oomd: loosen the restriction on ManagedOOMPreference")
made the change to allow ManagedOOMPreference on a cgroup candidate when
the monitored cgroup and cgroup candidate are owned by the same user.
The commit assumed that this check was sufficient to continue allowing
ManagedOOMPreference on all cgroups owned by root. However, it caused a
regression for unprivileged LXD containers where e.g. /sys/fs/cgroup is
owned by nobody (uid=65534).
Fix this by explicitly allowing the ManagedOOMPreference if uid == 0 in
oomd_fetch_cgroup_oom_preference().
(cherry picked from commit 89186093485b52ca957d17842fc1f7c87958454a)
Related: #2138081
---
src/oom/oomd-util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c
index 1fc81d1843..70a1dc941e 100644
--- a/src/oom/oomd-util.c
+++ b/src/oom/oomd-util.c
@@ -164,7 +164,7 @@ int oomd_fetch_cgroup_oom_preference(OomdCGroupContext *ctx, const char *prefix)
if (r < 0)
return log_debug_errno(r, "Failed to get owner/group from %s: %m", ctx->path);
- if (uid == prefix_uid) {
+ if (uid == prefix_uid || uid == 0) {
/* Ignore most errors when reading the xattr since it is usually unset and cgroup xattrs are only used
* as an optional feature of systemd-oomd (and the system might not even support them). */
r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, ctx->path, "user.oomd_avoid");

@ -0,0 +1,36 @@
From 7706a5f2d35c6192a557fe7a72f76ea4e2591daf Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Tue, 22 Nov 2022 11:30:03 -0500
Subject: [PATCH] oomd: fix unreachable test case in test-oomd-util
This conditional with !empty_or_root(ctx->path) always returns false
because the most recent oomd_cgroup_context_acquire() call was with the
root cgroup. Make sure this test case can be reached by checking cgroup
instead of ctx->path.
While here, use an unused uid (61183) instead of the nobody uid so the
test case does not fail in unprivileged LXD containers.
(cherry picked from commit f05bcc18941eef5c2f93cfa06660eb06e0dc4c55)
Related: #2138081
---
src/oom/test-oomd-util.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/oom/test-oomd-util.c b/src/oom/test-oomd-util.c
index 176e3a8d69..faa75c5578 100644
--- a/src/oom/test-oomd-util.c
+++ b/src/oom/test-oomd-util.c
@@ -475,9 +475,9 @@ static void test_oomd_fetch_cgroup_oom_preference(void) {
/* Assert that avoid/omit are not set if the cgroup and prefix are not
* owned by the same user.*/
- if (test_xattrs && !empty_or_root(ctx->path)) {
+ if (test_xattrs && !empty_or_root(cgroup)) {
ctx = oomd_cgroup_context_free(ctx);
- assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 65534, 0) >= 0);
+ assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 61183, 0) >= 0);
assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
assert_se(oomd_fetch_cgroup_oom_preference(ctx, NULL) == 0);

@ -0,0 +1,48 @@
From e44e907f58d3c89e0de01e8ff4e25079f1ca505e Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Wed, 23 Nov 2022 16:06:48 +0000
Subject: [PATCH] portable: add a few more useful debug log messages
When attaching and /etc/systemd/system.attached can't be created or used
(eg: dead symlink) the logs are pretty much useless as even at debug
level there's no indication of what is going wrong.
Add some debug logs, and return a more specific error string over D-Bus.
(cherry picked from commit 80d95fcd6e1947a7887b96b22a32dbca115baac9)
Related: #2138081
---
src/portable/portable.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/portable/portable.c b/src/portable/portable.c
index be906f786c..fbc4497014 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -1131,7 +1131,7 @@ static int attach_unit_file(
(void) mkdir_parents(where, 0755);
if (mkdir(where, 0755) < 0) {
if (errno != EEXIST)
- return -errno;
+ return log_debug_errno(errno, "Failed to create attach directory %s: %m", where);
} else
(void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, where, NULL);
@@ -1145,7 +1145,7 @@ static int attach_unit_file(
if (mkdir(dropin_dir, 0755) < 0) {
if (errno != EEXIST)
- return -errno;
+ return log_debug_errno(errno, "Failed to create drop-in directory %s: %m", dropin_dir);
} else
(void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, dropin_dir, NULL);
@@ -1392,7 +1392,7 @@ int portable_attach(
r = attach_unit_file(&paths, image->path, image->type, extension_images,
item, profile, flags, changes, n_changes);
if (r < 0)
- return r;
+ return sd_bus_error_set_errnof(error, r, "Failed to attach unit '%s': %m", item->name);
}
/* We don't care too much for the image symlink, it's just a convenience thing, it's not necessary for proper

@ -0,0 +1,43 @@
From 44843b307d9acbe4f17b7af710cf66932667533a Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Tue, 22 Nov 2022 16:24:54 +0000
Subject: [PATCH] repart: respect --discard=no also for block devices
It's only used to avoid BLKDISCARD on individual partitions at the moment.
It can take a lot of time to run on very slow devices, so avoid it for
them too.
(cherry picked from commit 0dce448bbc97c861520c287b01d632b887442925)
Related: #2138081
---
src/partition/repart.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/partition/repart.c b/src/partition/repart.c
index 8e3cfece89..c4ca9840c8 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -4387,13 +4387,15 @@ static int context_write_partition_table(
log_info("Wiped block device.");
- r = context_discard_range(context, 0, context->total);
- if (r == -EOPNOTSUPP)
- log_info("Storage does not support discard, not discarding entire block device data.");
- else if (r < 0)
- return log_error_errno(r, "Failed to discard entire block device: %m");
- else if (r > 0)
- log_info("Discarded entire block device.");
+ if (arg_discard) {
+ r = context_discard_range(context, 0, context->total);
+ if (r == -EOPNOTSUPP)
+ log_info("Storage does not support discard, not discarding entire block device data.");
+ else if (r < 0)
+ return log_error_errno(r, "Failed to discard entire block device: %m");
+ else if (r > 0)
+ log_info("Discarded entire block device.");
+ }
}
r = fdisk_get_partitions(context->fdisk_context, &original_table);

@ -0,0 +1,92 @@
From e3dfedee10cb0c348d748bf438c76e5c3623ad69 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 21 Nov 2022 15:32:22 +0100
Subject: [PATCH] udev: make sure auto-root logic also works in UKIs booted
from XBOOTLDR
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If no root= switch is specified on the kernel command line we'll use the
root disk on which the partition the LoaderDevicePartUUID efi var is
located as long as that partition is an ESP. Let's slightly liberalize
that and also allow it if that partition is an XBOOTLDR partition. This
ensures that UKIs spawned directly from XBOOTLDR work the same as those
from the ESP.
(Note that this makes no difference if sd-boot is in the mix, as in that
case LoaderDevicePartUUID is always set to the ESP, as that's where
sd-boot is located, and sd-boot will set the var first, sd-stub will
only set it later if it#s not set yet.)
(cherry picked from commit e4cb147a2e230a4a0b804c3e70f2692a5e2fd698)
Related: #2138081
---
src/udev/udev-builtin-blkid.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index 92ea43eef0..9f5646ffdd 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -120,14 +120,14 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
#if defined(SD_GPT_ROOT_NATIVE) && ENABLE_EFI
_cleanup_free_ char *root_id = NULL, *root_label = NULL;
- bool found_esp = false;
+ bool found_esp_or_xbootldr = false;
int r;
assert(pr);
- /* Iterate through the partitions on this disk, and see if the
- * EFI ESP we booted from is on it. If so, find the first root
- * disk, and add a property indicating its partition UUID. */
+ /* Iterate through the partitions on this disk, and see if the UEFI ESP or XBOOTLDR partition we
+ * booted from is on it. If so, find the first root disk, and add a property indicating its partition
+ * UUID. */
errno = 0;
blkid_partlist pl = blkid_probe_get_partitions(pr);
@@ -157,21 +157,20 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
if (sd_id128_from_string(stype, &type) < 0)
continue;
- if (sd_id128_equal(type, SD_GPT_ESP)) {
- sd_id128_t id, esp;
+ if (sd_id128_in_set(type, SD_GPT_ESP, SD_GPT_XBOOTLDR)) {
+ sd_id128_t id, esp_or_xbootldr;
- /* We found an ESP, let's see if it matches
- * the ESP we booted from. */
+ /* We found an ESP or XBOOTLDR, let's see if it matches the ESP/XBOOTLDR we booted from. */
if (sd_id128_from_string(sid, &id) < 0)
continue;
- r = efi_loader_get_device_part_uuid(&esp);
+ r = efi_loader_get_device_part_uuid(&esp_or_xbootldr);
if (r < 0)
return r;
- if (sd_id128_equal(id, esp))
- found_esp = true;
+ if (sd_id128_equal(id, esp_or_xbootldr))
+ found_esp_or_xbootldr = true;
} else if (sd_id128_equal(type, SD_GPT_ROOT_NATIVE)) {
unsigned long long flags;
@@ -195,9 +194,9 @@ static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) {
}
}
- /* We found the ESP on this disk, and also found a root
- * partition, nice! Let's export its UUID */
- if (found_esp && root_id)
+ /* We found the ESP/XBOOTLDR on this disk, and also found a root partition, nice! Let's export its
+ * UUID */
+ if (found_esp_or_xbootldr && root_id)
udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id);
#endif

@ -0,0 +1,32 @@
From 812e979fe66e9c1a768fbcee3f568234fec2cded Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Tue, 15 Nov 2022 09:04:42 +0100
Subject: [PATCH] meson: install test-kernel-install only when
-Dkernel-install=true
This patch fixes the following build failure:
meson.build:3853:8: ERROR: Unknown variable "test_kernel_install_sh".
Fixes #25432.
(cherry picked from commit cc77a56532ddb59770e8312fc1b9954b0b135e72)
Related: #2138081
---
meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index 015849af49..35704947e3 100644
--- a/meson.build
+++ b/meson.build
@@ -3841,7 +3841,7 @@ exe = custom_target(
install_dir : bindir)
public_programs += exe
-if want_tests != 'false'
+if want_tests != 'false' and want_kernel_install
test('test-kernel-install',
test_kernel_install_sh,
args : [exe.full_path(), loaderentry_install])

@ -0,0 +1,55 @@
From 1dc423e2c194eec07a04b666533cd39e74eab6de Mon Sep 17 00:00:00 2001
From: Jan Janssen <medhefgo@web.de>
Date: Sat, 12 Nov 2022 16:24:53 +0100
Subject: [PATCH] boot: Silence driver reconnect errors
(cherry picked from commit 98ac5192d5feddae19f6f5ceb60aa3751a30676b)
Related: #2138081
---
src/boot/efi/drivers.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/src/boot/efi/drivers.c b/src/boot/efi/drivers.c
index 39b65e74a6..7f2057f5a1 100644
--- a/src/boot/efi/drivers.c
+++ b/src/boot/efi/drivers.c
@@ -51,25 +51,23 @@ static EFI_STATUS load_one_driver(
}
EFI_STATUS reconnect_all_drivers(void) {
- _cleanup_free_ EFI_HANDLE *handles = NULL;
- UINTN n_handles = 0;
- EFI_STATUS err;
+ _cleanup_free_ EFI_HANDLE *handles = NULL;
+ size_t n_handles = 0;
+ EFI_STATUS err;
- /* Reconnects all handles, so that any loaded drivers can take effect. */
+ /* Reconnects all handles, so that any loaded drivers can take effect. */
- err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
- if (err != EFI_SUCCESS)
- return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
+ err = BS->LocateHandleBuffer(AllHandles, NULL, NULL, &n_handles, &handles);
+ if (err != EFI_SUCCESS)
+ return log_error_status_stall(err, L"Failed to get list of handles: %r", err);
- for (UINTN i = 0; i < n_handles; i++) {
- err = BS->ConnectController(handles[i], NULL, NULL, true);
- if (err == EFI_NOT_FOUND) /* No drivers for this handle */
- continue;
- if (err != EFI_SUCCESS)
- log_error_status_stall(err, L"Failed to reconnect handle %" PRIuN L", ignoring: %r", i, err);
- }
+ for (size_t i = 0; i < n_handles; i++)
+ /* Some firmware gives us some bogus handles (or they might become bad due to
+ * reconnecting everything). Security policy may also prevent us from doing so too.
+ * There is nothing we can realistically do on errors anyways, so just ignore them. */
+ (void) BS->ConnectController(handles[i], NULL, NULL, true);
- return EFI_SUCCESS;
+ return EFI_SUCCESS;
}
EFI_STATUS load_drivers(

@ -0,0 +1,124 @@
From c67164cf2c6aed29f70a98ef9050503e56aba952 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 13 Nov 2022 19:25:02 +0900
Subject: [PATCH] dissect-image: do not try to close invalid fd
Fixes a bug introduced by f7725647bb41c3398a867f139efe526efe8aa1b3.
Hopefully fixes #25348.
(cherry picked from commit 088377e0920a3785e7926f2ed382810836480ae6)
Related: #2138081
---
src/shared/dissect-image.c | 58 +++++++++++++-------------------------
src/shared/dissect-image.h | 6 ++++
2 files changed, 26 insertions(+), 38 deletions(-)
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 2989d31d3c..6a991c877a 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -1010,19 +1010,13 @@ static int dissect_image(
log_debug("No root partition found of the native architecture, falling back to a root "
"partition of the secondary architecture.");
- m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY];
- zero(m->partitions[PARTITION_ROOT_SECONDARY]);
- m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY];
- zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
- m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG];
- zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
-
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
- zero(m->partitions[PARTITION_USR_SECONDARY]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
+ m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY]);
+ m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]);
+ m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]);
+
+ m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
+ m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
+ m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_ROOT_OTHER].found = false;
m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false;
@@ -1044,19 +1038,13 @@ static int dissect_image(
"falling back to a root partition of a non-native architecture (%s).",
architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
- m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_OTHER];
- zero(m->partitions[PARTITION_ROOT_OTHER]);
- m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_OTHER_VERITY];
- zero(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
- m->partitions[PARTITION_ROOT_VERITY_SIG] = m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG];
- zero(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
-
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
- zero(m->partitions[PARTITION_USR_OTHER]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
+ m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER]);
+ m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY]);
+ m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]);
+
+ m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
+ m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
+ m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
}
/* Hmm, we found a signature partition but no Verity data? Something is off. */
@@ -1083,12 +1071,9 @@ static int dissect_image(
"partition of the secondary architecture.");
/* Upgrade secondary arch to primary */
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_SECONDARY];
- zero(m->partitions[PARTITION_USR_SECONDARY]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_SECONDARY_VERITY];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
+ m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]);
+ m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]);
+ m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]);
m->partitions[PARTITION_USR_OTHER].found = false;
m->partitions[PARTITION_USR_OTHER_VERITY].found = false;
@@ -1105,12 +1090,9 @@ static int dissect_image(
architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture));
/* Upgrade other arch to primary */
- m->partitions[PARTITION_USR] = m->partitions[PARTITION_USR_OTHER];
- zero(m->partitions[PARTITION_USR_OTHER]);
- m->partitions[PARTITION_USR_VERITY] = m->partitions[PARTITION_USR_OTHER_VERITY];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY]);
- m->partitions[PARTITION_USR_VERITY_SIG] = m->partitions[PARTITION_USR_OTHER_VERITY_SIG];
- zero(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
+ m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]);
+ m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]);
+ m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]);
}
/* Hmm, we found a signature partition but no Verity data? Something is off. */
diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h
index 8007b544e7..f2278c4dfa 100644
--- a/src/shared/dissect-image.h
+++ b/src/shared/dissect-image.h
@@ -40,6 +40,12 @@ struct DissectedPartition {
.architecture = _ARCHITECTURE_INVALID, \
.mount_node_fd = -1, \
})
+#define TAKE_PARTITION(p) \
+ ({ \
+ DissectedPartition *_pp = &(p), _p = *_pp; \
+ *_pp = DISSECTED_PARTITION_NULL; \
+ _p; \
+ })
typedef enum PartitionDesignator {
PARTITION_ROOT,

@ -0,0 +1,33 @@
From 29180c67635d3a6e4d5fd340ff9251724c803a65 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 13 Nov 2022 14:36:01 +0900
Subject: [PATCH] bootctl: make boot entry id logged in hex
To make consistent with the printed boot id below and other tools e.g.
efibootmgr.
(cherry picked from commit a7dcb75c539dd5bb69b72e47c820fe79c794409a)
Related: #2138081
---
src/boot/bootctl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index b53df11764..64a4b74715 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -586,11 +586,11 @@ static int print_efi_option(uint16_t id, int *n_printed, bool in_order) {
r = efi_get_boot_option(id, &title, &partition, &path, &active);
if (r < 0)
- return log_error_errno(r, "Failed to read boot option %u: %m", id);
+ return log_error_errno(r, "Failed to read boot option 0x%04X: %m", id);
/* print only configured entries with partition information */
if (!path || sd_id128_is_null(partition)) {
- log_debug("Ignoring boot entry %u without partition information.", id);
+ log_debug("Ignoring boot entry 0x%04X without partition information.", id);
return 0;
}

@ -0,0 +1,28 @@
From 6164408188766a31e778ec670239482db886d9be Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 13 Nov 2022 14:41:08 +0900
Subject: [PATCH] bootctl: downgrade log message when firmware reports
non-existent or invalid boot entry
Fixes #25359.
(cherry picked from commit 78bfeeae508a554483de02b52aa2e5afdc341e1a)
Related: #2138081
---
src/boot/bootctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 64a4b74715..a5811adf20 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -586,7 +586,7 @@ static int print_efi_option(uint16_t id, int *n_printed, bool in_order) {
r = efi_get_boot_option(id, &title, &partition, &path, &active);
if (r < 0)
- return log_error_errno(r, "Failed to read boot option 0x%04X: %m", id);
+ return log_debug_errno(r, "Failed to read boot option 0x%04X: %m", id);
/* print only configured entries with partition information */
if (!path || sd_id128_is_null(partition)) {

@ -0,0 +1,37 @@
From 23ede492fbea1bd1440d84cef6dd68bb46d2e5fb Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 18 Nov 2022 18:05:53 +0100
Subject: [PATCH] bootctl: rework how we handle referenced but absent EFI boot
entries
Follow-up for #25368.
Let's consider ENOENT an expected error, and just debug log about it
(though, let's suffix it with `, ignoring.`). All other errors will log
loudly, as they are unexpected errors.
(cherry picked from commit af1bed8e83c3d380d1eb0b9147684b76d1ee4df0)
Related: #2138081
---
src/boot/bootctl.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index a5811adf20..7da48b4ca4 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -585,8 +585,12 @@ static int print_efi_option(uint16_t id, int *n_printed, bool in_order) {
assert(n_printed);
r = efi_get_boot_option(id, &title, &partition, &path, &active);
+ if (r == -ENOENT) {
+ log_debug_errno(r, "Boot option 0x%04X referenced but missing, ignoring: %m", id);
+ return 0;
+ }
if (r < 0)
- return log_debug_errno(r, "Failed to read boot option 0x%04X: %m", id);
+ return log_error_errno(r, "Failed to read boot option 0x%04X: %m", id);
/* print only configured entries with partition information */
if (!path || sd_id128_is_null(partition)) {

@ -0,0 +1,44 @@
From c59555a86d3fcd2b8d644885134e19fe864251e5 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Fri, 11 Nov 2022 11:26:54 +0100
Subject: [PATCH] strv: Make sure strv_make_nulstr() always returns a valid
nulstr
strv_make_nulstr() is documented to always return a valid nulstr,
but if the input is `NULL` we return a string terminated with only
a single NUL terminator, so let's fix that and always terminate the
resulting string with two NUL bytes.
(cherry picked from commit 5ea173a91b2093664a9ebb9add678edd6f5d1efd)
Related: #2138081
---
src/basic/strv.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/basic/strv.c b/src/basic/strv.c
index eea34ca68d..24fc56a1a5 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -721,7 +721,7 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
}
if (!m) {
- m = new0(char, 1);
+ m = new0(char, 2);
if (!m)
return -ENOMEM;
n = 1;
@@ -730,11 +730,9 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
m[n] = '\0';
assert(n > 0);
- *ret = m;
+ *ret = TAKE_PTR(m);
*ret_size = n - 1;
- m = NULL;
-
return 0;
}

@ -0,0 +1,28 @@
From 7da1d4780b1dae16369fa5191832ec26d24a2ace Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Fri, 11 Nov 2022 11:09:28 +0100
Subject: [PATCH] sd-bus: Use goto finish instead of return in
bus_add_match_full
Fixes #25340
(cherry picked from commit 0f3c342903d1a09577378912717539b530af1fcf)
Related: #2138081
---
src/libsystemd/sd-bus/sd-bus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 3803a2c4c4..bc716afabf 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -3529,7 +3529,7 @@ static int bus_add_match_full(
s);
if (r < 0)
- return r;
+ goto finish;
/* Make the slot of the match call floating now. We need the reference, but we don't
* want that this match pins the bus object, hence we first create it non-floating, but

@ -0,0 +1,56 @@
From 2edd56af85a0360df8bc49a6ee19e0f1051a2d68 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 11 Nov 2022 09:34:17 +0900
Subject: [PATCH] find-esp: downgrade and ignore error on retrieving
PART_ENTRY_SCHEME when searching
Fixes #25332.
(cherry picked from commit 01f234c6f5672926d6cfe4fbfcdb48326ce06250)
Related: #2138081
---
src/shared/find-esp.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c
index dfe0574aba..aa0b02cc2f 100644
--- a/src/shared/find-esp.c
+++ b/src/shared/find-esp.c
@@ -177,7 +177,9 @@ static int verify_esp_udev(
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_full_errno(searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
+ searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
+ "Failed to get device property: %m");
if (!streq(v, "gpt"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
@@ -572,10 +574,11 @@ static int verify_xbootldr_blkid(
else if (r != 0)
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "%s: Failed to probe file system: %m", node);
- errno = 0;
r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &type, NULL);
if (r != 0)
- return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "%s: Failed to probe PART_ENTRY_SCHEME: %m", node);
+ return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
+ searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(EIO),
+ "%s: Failed to probe PART_ENTRY_SCHEME: %m", node);
if (streq(type, "gpt")) {
errno = 0;
@@ -638,7 +641,10 @@ static int verify_xbootldr_udev(
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &type);
if (r < 0)
- return log_device_error_errno(d, r, "Failed to query ID_PART_ENTRY_SCHEME: %m");
+ return log_device_full_errno(d,
+ searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
+ searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
+ "Failed to query ID_PART_ENTRY_SCHEME: %m");
if (streq(type, "gpt")) {

@ -0,0 +1,114 @@
From 0f7bee592dfc80fd1a682a280399fdb493ea5e6d Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 13 Nov 2022 13:27:36 +0900
Subject: [PATCH] find-esp: include device sysname in the log message
(cherry picked from commit 388d14659d250545125f8e950e3abb6eb8682c61)
Related: #2138081
---
src/shared/find-esp.c | 52 +++++++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/src/shared/find-esp.c b/src/shared/find-esp.c
index aa0b02cc2f..fa234c8b5f 100644
--- a/src/shared/find-esp.c
+++ b/src/shared/find-esp.c
@@ -165,61 +165,65 @@ static int verify_esp_udev(
r = sd_device_get_devname(d, &node);
if (r < 0)
- return log_error_errno(r, "Failed to get device node: %m");
+ return log_device_error_errno(d, r, "Failed to get device node: %m");
r = sd_device_get_property_value(d, "ID_FS_TYPE", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_device_error_errno(d, r, "Failed to get device property: %m");
if (!streq(v, "vfat"))
- return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
- SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
- "File system \"%s\" is not FAT.", node );
+ return log_device_full_errno(d,
+ searching ? LOG_DEBUG : LOG_ERR,
+ SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+ "File system \"%s\" is not FAT.", node );
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &v);
if (r < 0)
- return log_full_errno(searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
- searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
- "Failed to get device property: %m");
+ return log_device_full_errno(d,
+ searching && r == -ENOENT ? LOG_DEBUG : LOG_ERR,
+ searching && r == -ENOENT ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : r,
+ "Failed to get device property: %m");
if (!streq(v, "gpt"))
- return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
- SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
- "File system \"%s\" is not on a GPT partition table.", node);
+ return log_device_full_errno(d,
+ searching ? LOG_DEBUG : LOG_ERR,
+ SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+ "File system \"%s\" is not on a GPT partition table.", node);
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_device_error_errno(d, r, "Failed to get device property: %m");
if (sd_id128_string_equal(v, SD_GPT_ESP) <= 0)
- return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
- SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
- "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
+ return log_device_full_errno(d,
+ searching ? LOG_DEBUG : LOG_ERR,
+ SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
+ "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
r = sd_device_get_property_value(d, "ID_PART_ENTRY_UUID", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_device_error_errno(d, r, "Failed to get device property: %m");
r = sd_id128_from_string(v, &uuid);
if (r < 0)
- return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v);
+ return log_device_error_errno(d, r, "Partition \"%s\" has invalid UUID \"%s\".", node, v);
r = sd_device_get_property_value(d, "ID_PART_ENTRY_NUMBER", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_device_error_errno(d, r, "Failed to get device property: %m");
r = safe_atou32(v, &part);
if (r < 0)
- return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.");
+ return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_NUMBER field.");
r = sd_device_get_property_value(d, "ID_PART_ENTRY_OFFSET", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_device_error_errno(d, r, "Failed to get device property: %m");
r = safe_atou64(v, &pstart);
if (r < 0)
- return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.");
+ return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_OFFSET field.");
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SIZE", &v);
if (r < 0)
- return log_error_errno(r, "Failed to get device property: %m");
+ return log_device_error_errno(d, r, "Failed to get device property: %m");
r = safe_atou64(v, &psize);
if (r < 0)
- return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.");
+ return log_device_error_errno(d, r, "Failed to parse PART_ENTRY_SIZE field.");
if (ret_part)
*ret_part = part;
@@ -637,7 +641,7 @@ static int verify_xbootldr_udev(
r = sd_device_get_devname(d, &node);
if (r < 0)
- return log_error_errno(r, "Failed to get device node: %m");
+ return log_device_error_errno(d, r, "Failed to get device node: %m");
r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &type);
if (r < 0)

@ -0,0 +1,191 @@
From 2f79547e8bbb5434a84c0b07c30fff63b351590c Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Thu, 10 Nov 2022 15:47:19 +0000
Subject: [PATCH] tmpfiles: log at info level when some allowed failures occur
In provision.conf we ship:
d- /root :0700 root :root -
d- /root/.ssh :0700 root :root -
These are allowed to fail, for example on a read-only filesystem. But they still
log at error level, which is annoying and gets flagged. Tune those specific errors
down to info.
There are likely more that could be tuned down, but the important thing is to cover
the tmpfiles.d that we ship right now.
Before:
$ echo -e "d- /root :0700 root :root - \nd- /root/.ssh :0700 root :root -" | SYSTEMD_LOG_LEVEL=err build/systemd-tmpfiles --root=/tmp/img --create -
Failed to create directory or subvolume "/tmp/img/root": Read-only file system
Failed to open path '/tmp/img/root': No such file or directory
$
After:
$ echo -e "d- /root :0700 root :root - \nd- /root/.ssh :0700 root :root -" | SYSTEMD_LOG_LEVEL=err build/systemd-tmpfiles --root=/tmp/img --create -
$
(cherry picked from commit 244c2a8344c01e94cd9bdf835de998b89bc53179)
Related: #2138081
---
src/tmpfiles/tmpfiles.c | 49 +++++++++++++++++++++++++++--------------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 784b895577..18bb75715b 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -961,22 +961,34 @@ shortcut:
return label_fix_full(fd, /* inode_path= */ NULL, /* label_path= */ path, 0);
}
-static int path_open_parent_safe(const char *path) {
+static int path_open_parent_safe(const char *path, bool allow_failure) {
_cleanup_free_ char *dn = NULL;
int r, fd;
if (!path_is_normalized(path))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to open parent of '%s': path not normalized.", path);
+ return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+ SYNTHETIC_ERRNO(EINVAL),
+ "Failed to open parent of '%s': path not normalized%s.",
+ path,
+ allow_failure ? ", ignoring" : "");
r = path_extract_directory(path, &dn);
if (r < 0)
- return log_error_errno(r, "Unable to determine parent directory of '%s': %m", path);
+ return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+ r,
+ "Unable to determine parent directory of '%s'%s: %m",
+ path,
+ allow_failure ? ", ignoring" : "");
- r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd);
+ r = chase_symlinks(dn, arg_root, allow_failure ? CHASE_SAFE : CHASE_SAFE|CHASE_WARN, NULL, &fd);
if (r == -ENOLINK) /* Unsafe symlink: already covered by CHASE_WARN */
return r;
if (r < 0)
- return log_error_errno(r, "Failed to open path '%s': %m", dn);
+ return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+ r,
+ "Failed to open path '%s'%s: %m",
+ dn,
+ allow_failure ? ", ignoring" : "");
return fd;
}
@@ -1431,7 +1443,7 @@ static int write_one_file(Item *i, const char *path, CreationMode creation) {
/* Validate the path and keep the fd on the directory for opening the file so we're sure that it
* can't be changed behind our back. */
- dir_fd = path_open_parent_safe(path);
+ dir_fd = path_open_parent_safe(path, i->allow_failure);
if (dir_fd < 0)
return dir_fd;
@@ -1481,7 +1493,7 @@ static int create_file(Item *i, const char *path) {
/* Validate the path and keep the fd on the directory for opening the file so we're sure that it
* can't be changed behind our back. */
- dir_fd = path_open_parent_safe(path);
+ dir_fd = path_open_parent_safe(path, i->allow_failure);
if (dir_fd < 0)
return dir_fd;
@@ -1549,7 +1561,7 @@ static int truncate_file(Item *i, const char *path) {
/* Validate the path and keep the fd on the directory for opening the file so we're sure that it
* can't be changed behind our back. */
- dir_fd = path_open_parent_safe(path);
+ dir_fd = path_open_parent_safe(path, i->allow_failure);
if (dir_fd < 0)
return dir_fd;
@@ -1628,7 +1640,7 @@ static int copy_files(Item *i) {
/* Validate the path and use the returned directory fd for copying the target so we're sure that the
* path can't be changed behind our back. */
- dfd = path_open_parent_safe(i->path);
+ dfd = path_open_parent_safe(i->path, i->allow_failure);
if (dfd < 0)
return dfd;
@@ -1664,6 +1676,7 @@ static int create_directory_or_subvolume(
const char *path,
mode_t mode,
bool subvol,
+ bool allow_failure,
struct stat *ret_st,
CreationMode *ret_creation) {
@@ -1679,7 +1692,7 @@ static int create_directory_or_subvolume(
if (r < 0)
return log_error_errno(r, "Failed to extract filename from path '%s': %m", path);
- pfd = path_open_parent_safe(path);
+ pfd = path_open_parent_safe(path, allow_failure);
if (pfd < 0)
return pfd;
@@ -1720,7 +1733,11 @@ static int create_directory_or_subvolume(
/* Then look at the original error */
if (r < 0)
- return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", path);
+ return log_full_errno(allow_failure ? LOG_INFO : LOG_ERR,
+ r,
+ "Failed to create directory or subvolume \"%s\"%s: %m",
+ path,
+ allow_failure ? ", ignoring" : "");
return log_error_errno(errno, "Failed to open directory/subvolume we just created '%s': %m", path);
}
@@ -1748,7 +1765,7 @@ static int create_directory(Item *i, const char *path) {
assert(i);
assert(IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY));
- fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, &st, &creation);
+ fd = create_directory_or_subvolume(path, i->mode, /* subvol= */ false, i->allow_failure, &st, &creation);
if (fd == -EEXIST)
return 0;
if (fd < 0)
@@ -1766,7 +1783,7 @@ static int create_subvolume(Item *i, const char *path) {
assert(i);
assert(IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA));
- fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, &st, &creation);
+ fd = create_directory_or_subvolume(path, i->mode, /* subvol = */ true, i->allow_failure, &st, &creation);
if (fd == -EEXIST)
return 0;
if (fd < 0)
@@ -1845,7 +1862,7 @@ static int create_device(Item *i, mode_t file_type) {
/* Validate the path and use the returned directory fd for copying the target so we're sure that the
* path can't be changed behind our back. */
- dfd = path_open_parent_safe(i->path);
+ dfd = path_open_parent_safe(i->path, i->allow_failure);
if (dfd < 0)
return dfd;
@@ -1947,7 +1964,7 @@ static int create_fifo(Item *i) {
if (r == O_DIRECTORY)
return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
- pfd = path_open_parent_safe(i->path);
+ pfd = path_open_parent_safe(i->path, i->allow_failure);
if (pfd < 0)
return pfd;
@@ -2032,7 +2049,7 @@ static int create_symlink(Item *i) {
if (r == O_DIRECTORY)
return log_error_errno(SYNTHETIC_ERRNO(EISDIR), "Cannot open path '%s' for creating FIFO, is a directory.", i->path);
- pfd = path_open_parent_safe(i->path);
+ pfd = path_open_parent_safe(i->path, i->allow_failure);
if (pfd < 0)
return pfd;

@ -0,0 +1,47 @@
From 60fa029fe83af62f27bf833dc86c0aeeb76b412b Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 4 Nov 2022 18:19:29 +0100
Subject: [PATCH] fd-util: make fd_in_set() (and thus close_all_fds()) handle
invalidated fds in the array
let's handle gracefully if fds in the specified array are already
invalidated (i.e. negative). This is handy when putting together arrays
on the fly.
(cherry picked from commit d11c14a9817f6561a30d96d8faea126a4c811af8)
Related: #2138081
---
src/basic/fd-util.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index cee20a9a81..6ed04449bf 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -177,9 +177,13 @@ int fd_cloexec(int fd, bool cloexec) {
_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
assert(n_fdset == 0 || fdset);
- for (size_t i = 0; i < n_fdset; i++)
+ for (size_t i = 0; i < n_fdset; i++) {
+ if (fdset[i] < 0)
+ continue;
+
if (fdset[i] == fd)
return true;
+ }
return false;
}
@@ -252,6 +256,10 @@ static int close_all_fds_special_case(const int except[], size_t n_except) {
if (!have_close_range)
return 0;
+ if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid,
+ * we got none */
+ n_except = 0;
+
switch (n_except) {
case 0:

@ -0,0 +1,55 @@
From b9223cd76c73fa5cf3ed19a2238980047bf13826 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 4 Nov 2022 18:20:19 +0100
Subject: [PATCH] fd-util: add new fd_cloexec_many() helper
(cherry picked from commit ed18c22c989495aab36512f03449222cfcf79aa7)
Related: #2138081
---
src/basic/fd-util.c | 19 +++++++++++++++++++
src/basic/fd-util.h | 1 +
2 files changed, 20 insertions(+)
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
index 6ed04449bf..66bb7569bb 100644
--- a/src/basic/fd-util.c
+++ b/src/basic/fd-util.c
@@ -174,6 +174,25 @@ int fd_cloexec(int fd, bool cloexec) {
return RET_NERRNO(fcntl(fd, F_SETFD, nflags));
}
+int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec) {
+ int ret = 0, r;
+
+ assert(n_fds == 0 || fds);
+
+ for (size_t i = 0; i < n_fds; i++) {
+ if (fds[i] < 0) /* Skip gracefully over already invalidated fds */
+ continue;
+
+ r = fd_cloexec(fds[i], cloexec);
+ if (r < 0 && ret >= 0) /* Continue going, but return first error */
+ ret = r;
+ else
+ ret = 1; /* report if we did anything */
+ }
+
+ return ret;
+}
+
_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
assert(n_fdset == 0 || fdset);
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
index d9896e27e8..29c7d86f27 100644
--- a/src/basic/fd-util.h
+++ b/src/basic/fd-util.h
@@ -56,6 +56,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
+int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec);
int get_max_fd(void);

@ -0,0 +1,49 @@
From 4fb6e9eddc7487a965b3e051115f9bb1d0413342 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 4 Nov 2022 18:20:47 +0100
Subject: [PATCH] process-util: add new FORK_CLOEXEC_OFF flag for disabling
O_CLOEXEC on remaining fds
Often the fds that shall stay around in the child shall be passed
to a process over execve(), hence add an option to explicitly disable
O_CLOEXEC on them in the child.
(cherry picked from commit 981cfbe046297a18f2cb115ef81202f3bd68d2a3)
Related: #2138081
---
src/basic/process-util.c | 8 ++++++++
src/basic/process-util.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index fb0b38fa49..0213f5913f 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -1372,6 +1372,14 @@ int safe_fork_full(
}
}
+ if (flags & FORK_CLOEXEC_OFF) {
+ r = fd_cloexec_many(except_fds, n_except_fds, false);
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to turn off O_CLOEXEC on file descriptors: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
/* When we were asked to reopen the logs, do so again now */
if (flags & FORK_REOPEN_LOG) {
log_open();
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index f8c374a310..ed2f73673e 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -150,6 +150,7 @@ typedef enum ForkFlags {
FORK_STDOUT_TO_STDERR = 1 << 11, /* Make stdout a copy of stderr */
FORK_FLUSH_STDIO = 1 << 12, /* fflush() stdout (and stderr) before forking */
FORK_NEW_USERNS = 1 << 13, /* Run child in its own user namespace */
+ FORK_CLOEXEC_OFF = 1 << 14, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);

@ -0,0 +1,71 @@
From 7f0f2caa082e7490c160b2c992a094116474a95f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 4 Nov 2022 18:26:42 +0100
Subject: [PATCH] dissect: fix fsck
Since f7725647bb41c3398a867f139efe526efe8aa1b3 when dissecting a disk
image we operate with fds to the device nodes in question wherever we
can. This includes when we fork off fsck, where we pass a /proc/self/fd/
path as argument. This only works if we keep that fd open however and
disable O_CLOEXEC on the fd. Hence do so, and fix fsck this way.
(Without this, all fsck will fail, since the fd path is invalid)
(cherry picked from commit f8ab781223bcb0330ee4499b879a62e84fee313e)
Related: #2138081
---
src/shared/dissect-image.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 6a991c877a..7676636723 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -1309,11 +1309,11 @@ static int is_loop_device(const char *path) {
return true;
}
-static int run_fsck(const char *node, const char *fstype) {
+static int run_fsck(int node_fd, const char *fstype) {
int r, exit_status;
pid_t pid;
- assert(node);
+ assert(node_fd >= 0);
assert(fstype);
r = fsck_exists_for_fstype(fstype);
@@ -1322,16 +1322,20 @@ static int run_fsck(const char *node, const char *fstype) {
return 0;
}
if (r == 0) {
- log_debug("Not checking partition %s, as fsck for %s does not exist.", node, fstype);
+ log_debug("Not checking partition %s, as fsck for %s does not exist.", FORMAT_PROC_FD_PATH(node_fd), fstype);
return 0;
}
- r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO, &pid);
+ r = safe_fork_full(
+ "(fsck)",
+ &node_fd, 1, /* Leave the node fd open */
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOEXEC_OFF,
+ &pid);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
if (r == 0) {
/* Child */
- execl("/sbin/fsck", "/sbin/fsck", "-aT", node, NULL);
+ execl("/sbin/fsck", "/sbin/fsck", "-aT", FORMAT_PROC_FD_PATH(node_fd), NULL);
log_open();
log_debug_errno(errno, "Failed to execl() fsck: %m");
_exit(FSCK_OPERATIONAL_ERROR);
@@ -1421,7 +1425,7 @@ static int mount_partition(
rw = m->rw && !(flags & DISSECT_IMAGE_MOUNT_READ_ONLY);
if (FLAGS_SET(flags, DISSECT_IMAGE_FSCK) && rw) {
- r = run_fsck(node, fstype);
+ r = run_fsck(m->mount_node_fd, fstype);
if (r < 0)
return r;
}

@ -0,0 +1,31 @@
From 0a191f8306b4439049fcac8eea206835c144215e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Fri, 4 Nov 2022 16:30:57 +0100
Subject: [PATCH] core: update audit messages
Pass getuid() instead of literal `0` as auid, since user session
managers also issue audit messages on SELinux denials.
(cherry picked from commit c826b7ef3272157167a5c9d493e9672f00d84b98)
Related: #2138081
---
src/core/selinux-access.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index c69baa8a1a..c1744cff92 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -113,9 +113,9 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
if (r >= 0) {
if (type == SELINUX_AVC)
- audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
+ audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, getuid());
else if (type == SELINUX_ERROR)
- audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, 0);
+ audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, getuid());
return 0;
}

@ -0,0 +1,53 @@
From 49fab9715ce09b86652e9855555e4ab4fc185220 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Wed, 1 Aug 2018 10:58:28 +0200
Subject: [PATCH] logind: set RemoveIPC to false by default
RHEL-only
Related: #2138081
---
man/logind.conf.xml | 2 +-
src/login/logind-core.c | 2 +-
src/login/logind.conf.in | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 9682add08c..1a87cf6baf 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -341,7 +341,7 @@
user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the
last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as
well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users
- are excluded from the effect of this setting. Defaults to <literal>yes</literal>.</para></listitem>
+ are excluded from the effect of this setting. Defaults to <literal>no</literal>.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 02adc81909..b5050c54c4 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -34,7 +34,7 @@ void manager_reset_config(Manager *m) {
m->n_autovts = 6;
m->reserve_vt = 6;
- m->remove_ipc = true;
+ m->remove_ipc = false;
m->inhibit_delay_max = 5 * USEC_PER_SEC;
m->user_stop_delay = 10 * USEC_PER_SEC;
diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in
index 0b10df6839..09c363817a 100644
--- a/src/login/logind.conf.in
+++ b/src/login/logind.conf.in
@@ -43,7 +43,7 @@
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RuntimeDirectoryInodesMax=
-#RemoveIPC=yes
+#RemoveIPC=no
#InhibitorsMax=8192
#SessionsMax=8192
#StopIdleSessionSec=infinity

@ -0,0 +1,43 @@
From efe2c6703e3132dafaa29c1a7d3e3db4a683ed15 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Thu, 5 Aug 2021 17:11:47 +0200
Subject: [PATCH] tmpfiles: don't create resolv.conf -> stub-resolv.conf
symlink
RHEL-only
Related: #2138081
---
tmpfiles.d/meson.build | 1 -
tmpfiles.d/systemd-resolve.conf | 10 ----------
2 files changed, 11 deletions(-)
delete mode 100644 tmpfiles.d/systemd-resolve.conf
diff --git a/tmpfiles.d/meson.build b/tmpfiles.d/meson.build
index ca1abbf3fe..179c71d375 100644
--- a/tmpfiles.d/meson.build
+++ b/tmpfiles.d/meson.build
@@ -10,7 +10,6 @@ files = [['README', ''],
['systemd-nologin.conf', 'HAVE_PAM'],
['systemd-nspawn.conf', 'ENABLE_MACHINED'],
['systemd-pstore.conf', 'ENABLE_PSTORE'],
- ['systemd-resolve.conf', 'ENABLE_RESOLVE'],
['systemd-tmp.conf', ''],
['tmp.conf', ''],
['x11.conf', ''],
diff --git a/tmpfiles.d/systemd-resolve.conf b/tmpfiles.d/systemd-resolve.conf
deleted file mode 100644
index cb1c56d6a6..0000000000
--- a/tmpfiles.d/systemd-resolve.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-# See tmpfiles.d(5) for details
-
-L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf

@ -0,0 +1,80 @@
From 6b5b5fefcb68cb53427747be4984531bdeddcf7e Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 2 Jul 2021 13:25:51 +0200
Subject: [PATCH] Copy 40-redhat.rules from RHEL-8
RHEL-only
Related: #2138081
---
rules.d/40-redhat.rules | 46 +++++++++++++++++++++++++++++++++++++++++
rules.d/meson.build | 3 ++-
2 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 rules.d/40-redhat.rules
diff --git a/rules.d/40-redhat.rules b/rules.d/40-redhat.rules
new file mode 100644
index 0000000000..3c95cd2df0
--- /dev/null
+++ b/rules.d/40-redhat.rules
@@ -0,0 +1,46 @@
+# do not edit this file, it will be overwritten on update
+
+# CPU hotadd request
+SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1"
+
+# Memory hotadd request
+SUBSYSTEM!="memory", GOTO="memory_hotplug_end"
+ACTION!="add", GOTO="memory_hotplug_end"
+CONST{arch}=="s390*", GOTO="memory_hotplug_end"
+CONST{arch}=="ppc64*", GOTO="memory_hotplug_end"
+
+ENV{.state}="online"
+CONST{virt}=="none", ENV{.state}="online_movable"
+ATTR{state}=="offline", ATTR{state}="$env{.state}"
+
+LABEL="memory_hotplug_end"
+
+# reload sysctl.conf / sysctl.conf.d settings when the bridge module is loaded
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/proc/sys/net/bridge"
+
+# load SCSI generic (sg) driver
+SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST!="[module/sg]", RUN+="/sbin/modprobe -bv sg"
+SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_target", TEST!="[module/sg]", RUN+="/sbin/modprobe -bv sg"
+
+# Rule for prandom character device node permissions
+KERNEL=="prandom", MODE="0644"
+
+# Rules for creating the ID_PATH for SCSI devices based on the CCW bus
+# using the form: ccw-<BUS_ID>-zfcp-<WWPN>:<LUN>
+#
+ACTION=="remove", GOTO="zfcp_scsi_device_end"
+
+#
+# Set environment variable "ID_ZFCP_BUS" to "1" if the devices
+# (both disk and partition) are SCSI devices based on FCP devices
+#
+KERNEL=="sd*", SUBSYSTEMS=="ccw", DRIVERS=="zfcp", ENV{.ID_ZFCP_BUS}="1"
+
+# For SCSI disks
+KERNEL=="sd*[!0-9]", SUBSYSTEMS=="scsi", ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}"
+
+
+# For partitions on a SCSI disk
+KERNEL=="sd*[0-9]", SUBSYSTEMS=="scsi", ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}-part%n"
+
+LABEL="zfcp_scsi_device_end"
diff --git a/rules.d/meson.build b/rules.d/meson.build
index 8d2878a36d..70f48e877b 100644
--- a/rules.d/meson.build
+++ b/rules.d/meson.build
@@ -5,7 +5,8 @@ install_data(
install_dir : udevrulesdir)
rules = [
- [files('60-autosuspend.rules',
+ [files('40-redhat.rules',
+ '60-autosuspend.rules',
'60-block.rules',
'60-cdrom_id.rules',
'60-drm.rules',

@ -0,0 +1,45 @@
From 711aca5f4820c2345489136cbbde7428d9f9da1b Mon Sep 17 00:00:00 2001
From: Jan Synacek <jsynacek@redhat.com>
Date: Tue, 15 May 2018 09:24:20 +0200
Subject: [PATCH] Avoid /tmp being mounted as tmpfs without the user's will
Ensure PrivateTmp doesn't require tmpfs through tmp.mount, but rather
adds an After relationship.
RHEL-only
Related: #2138081
---
src/core/unit.c | 7 +------
units/basic.target | 3 ++-
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index d08c73613b..1fad0b0ac8 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1301,12 +1301,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
}
if (c->private_tmp) {
-
- /* FIXME: for now we make a special case for /tmp and add a weak dependency on
- * tmp.mount so /tmp being masked is supported. However there's no reason to treat
- * /tmp specifically and masking other mount units should be handled more
- * gracefully too, see PR#16894. */
- r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, "tmp.mount", true, UNIT_DEPENDENCY_FILE);
+ r = unit_add_dependency_by_name(u, UNIT_AFTER, "tmp.mount", true, UNIT_DEPENDENCY_FILE);
if (r < 0)
return r;
diff --git a/units/basic.target b/units/basic.target
index d8cdd5ac14..9eae0782a2 100644
--- a/units/basic.target
+++ b/units/basic.target
@@ -19,4 +19,5 @@ After=sysinit.target sockets.target paths.target slices.target tmp.mount
# require /var and /var/tmp, but only add a Wants= type dependency on /tmp, as
# we support that unit being masked, and this should not be considered an error.
RequiresMountsFor=/var /var/tmp
-Wants=tmp.mount
+# RHEL-only: Disable /tmp on tmpfs.
+#Wants=tmp.mount

@ -0,0 +1,38 @@
From c5f1cc8f23dfe545c0d03eae88bbd91e8a1db226 Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Mon, 5 Sep 2016 12:47:09 +0200
Subject: [PATCH] unit: don't add Requires for tmp.mount
rhel-only
Related: #2138081
---
src/core/mount.c | 2 +-
src/core/unit.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/mount.c b/src/core/mount.c
index 5e8a6ead61..ba55f7dd86 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -336,7 +336,7 @@ static int mount_add_mount_dependencies(Mount *m) {
if (r < 0)
return r;
- if (UNIT(m)->fragment_path) {
+ if (UNIT(m)->fragment_path && !streq(UNIT(m)->id, "tmp.mount")) {
/* If we have fragment configuration, then make this dependency required */
r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH);
if (r < 0)
diff --git a/src/core/unit.c b/src/core/unit.c
index 1fad0b0ac8..5af44aaf4a 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1541,7 +1541,7 @@ static int unit_add_mount_dependencies(Unit *u) {
return r;
changed = changed || r > 0;
- if (m->fragment_path) {
+ if (m->fragment_path && !streq(m->id, "tmp.mount")) {
r = unit_add_dependency(u, UNIT_REQUIRES, m, true, di.origin_mask);
if (r < 0)
return r;

@ -0,0 +1,24 @@
From 90aa9644404fa40e67a158a383cc81ec0d6ab0f5 Mon Sep 17 00:00:00 2001
From: Jan Synacek <jsynacek@redhat.com>
Date: Tue, 22 Jan 2019 10:28:42 +0100
Subject: [PATCH] units: add [Install] section to tmp.mount
RHEL-only
Related: #2138081
---
units/tmp.mount | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/units/tmp.mount b/units/tmp.mount
index 734acea237..b9a41cd803 100644
--- a/units/tmp.mount
+++ b/units/tmp.mount
@@ -23,3 +23,7 @@ What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
+
+# Make 'systemctl enable tmp.mount' work:
+[Install]
+WantedBy=local-fs.target

@ -0,0 +1,29 @@
From 6eb6434d8d203e19f5fb58d3d0ec561088b691e9 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Thu, 11 Mar 2021 15:48:23 +0100
Subject: [PATCH] rc-local: order after network-online.target
I think this was the intent of commit 91b684c7300879a8d2006038f7d9185d92c3c3bf,
just network-online.target didn't exist back then.
RHEL-only
Related: #2138081
---
units/rc-local.service.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/units/rc-local.service.in b/units/rc-local.service.in
index 55e83dfe00..0eee722154 100644
--- a/units/rc-local.service.in
+++ b/units/rc-local.service.in
@@ -13,7 +13,8 @@
Description={{RC_LOCAL_PATH}} Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable={{RC_LOCAL_PATH}}
-After=network.target
+After=network-online.target
+Wants=network-online.target
[Service]
Type=forking

@ -0,0 +1,303 @@
From 36f9fb0c7e19bda07ce6de5f4b04f58a5da2f122 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Sun, 18 Apr 2021 20:46:06 +0200
Subject: [PATCH] ci: drop CIs irrelevant for downstream
* CIFuzz would need a separate project in oss-fuzz
* Coverity would also need a separate project
* the Labeler action is superfluous, since we already have a bot for
that
* mkosi testing on other distros is irrelevant for downstream RHEL
repo
Related: #2138081
rhel-only
---
.github/labeler.yml | 40 ---------------
.github/workflows/cifuzz.yml | 62 -----------------------
.github/workflows/coverity.yml | 30 ------------
.github/workflows/labeler.yml | 24 ---------
.github/workflows/mkosi.yml | 90 ----------------------------------
5 files changed, 246 deletions(-)
delete mode 100644 .github/labeler.yml
delete mode 100644 .github/workflows/cifuzz.yml
delete mode 100644 .github/workflows/coverity.yml
delete mode 100644 .github/workflows/labeler.yml
delete mode 100644 .github/workflows/mkosi.yml
diff --git a/.github/labeler.yml b/.github/labeler.yml
deleted file mode 100644
index 7d128f42d6..0000000000
--- a/.github/labeler.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-hwdb:
- - hwdb.d/**/*
-units:
- - units/**/*
-documentation:
- - NEWS
- - docs/*
-network:
- - src/libsystemd-network/**/*
- - src/network/**/*
-udev:
- - src/udev/**/*
- - src/libudev/*
-selinux:
- - '**/*selinux*'
-apparmor:
- - '**/*apparmor*'
-meson:
- - meson_option.txt
-mkosi:
- - .mkosi/*
- - mkosi.build
-busctl:
- - src/busctl/*
-systemctl:
- - src/systemctl/*
-journal:
- - src/journal/*
-journal-remote:
- - src/journal-remote/*
-portable:
- - src/portable/**/*
-resolve:
- - src/resolve/*
-timedate:
- - src/timedate/*
-timesync:
- - src/timesync/*
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
deleted file mode 100644
index 25731abc5a..0000000000
--- a/.github/workflows/cifuzz.yml
+++ /dev/null
@@ -1,62 +0,0 @@
----
-# vi: ts=2 sw=2 et:
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# See: https://google.github.io/oss-fuzz/getting-started/continuous-integration/
-
-name: CIFuzz
-
-permissions:
- contents: read
-
-on:
- pull_request:
- paths:
- - '**/meson.build'
- - '.github/workflows/**'
- - 'meson_options.txt'
- - 'src/**'
- - 'test/fuzz/**'
- - 'tools/oss-fuzz.sh'
- push:
- branches:
- - main
-jobs:
- Fuzzing:
- runs-on: ubuntu-latest
- if: github.repository == 'systemd/systemd'
- concurrency:
- group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ matrix.architecture }}-${{ github.ref }}
- cancel-in-progress: true
- strategy:
- fail-fast: false
- matrix:
- sanitizer: [address, undefined, memory]
- architecture: [x86_64]
- include:
- - sanitizer: address
- architecture: i386
- steps:
- - name: Build Fuzzers (${{ matrix.sanitizer }})
- id: build
- uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
- with:
- oss-fuzz-project-name: 'systemd'
- dry-run: false
- allowed-broken-targets-percentage: 0
- # keep-unaffected-fuzz-targets should be removed once https://github.com/google/oss-fuzz/issues/7011 is fixed
- keep-unaffected-fuzz-targets: true
- sanitizer: ${{ matrix.sanitizer }}
- architecture: ${{ matrix.architecture }}
- - name: Run Fuzzers (${{ matrix.sanitizer }})
- uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
- with:
- oss-fuzz-project-name: 'systemd'
- fuzz-seconds: 600
- dry-run: false
- sanitizer: ${{ matrix.sanitizer }}
- - name: Upload Crash
- uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
- if: failure() && steps.build.outcome == 'success'
- with:
- name: ${{ matrix.sanitizer }}-${{ matrix.architecture }}-artifacts
- path: ./out/artifacts
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
deleted file mode 100644
index 3fbebc6bbf..0000000000
--- a/.github/workflows/coverity.yml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-# vi: ts=2 sw=2 et:
-# SPDX-License-Identifier: LGPL-2.1-or-later
-#
-name: Coverity
-
-on:
- schedule:
- # Run Coverity daily at midnight
- - cron: '0 0 * * *'
-
-permissions:
- contents: read
-
-jobs:
- build:
- runs-on: ubuntu-22.04
- if: github.repository == 'systemd/systemd'
- env:
- # Set in repo settings -> secrets -> actions
- COVERITY_SCAN_TOKEN: "${{ secrets.COVERITY_SCAN_TOKEN }}"
- COVERITY_SCAN_NOTIFICATION_EMAIL: "${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}"
- steps:
- - name: Repository checkout
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- # Reuse the setup phase of the unit test script to avoid code duplication
- - name: Install build dependencies
- run: sudo -E .github/workflows/unit_tests.sh SETUP
- - name: Build & upload the results
- run: tools/coverity.sh
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
deleted file mode 100644
index 35766df591..0000000000
--- a/.github/workflows/labeler.yml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-# vi: ts=2 sw=2 et:
-# SPDX-License-Identifier: LGPL-2.1-or-later
-#
-name: "Pull Request Labeler"
-
-on:
-- pull_request_target
-
-permissions:
- contents: read
-
-jobs:
- triage:
- if: github.event.repository.name != 'systemd-security'
- runs-on: ubuntu-latest
- permissions:
- pull-requests: write
- steps:
- - uses: actions/labeler@e54e5b338fbd6e6cdb5d60f51c22335fc57c401e
- with:
- repo-token: "${{ secrets.GITHUB_TOKEN }}"
- configuration-path: .github/labeler.yml
- sync-labels: "" # This is a workaround for issue 18671
diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml
deleted file mode 100644
index 2a1163aa07..0000000000
--- a/.github/workflows/mkosi.yml
+++ /dev/null
@@ -1,90 +0,0 @@
----
-# vi: ts=2 sw=2 et:
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# Simple boot tests that build and boot the mkosi images generated by the mkosi config files in mkosi.default.d/.
-name: mkosi
-
-on:
- push:
- branches:
- - main
- - v[0-9]+-stable
- pull_request:
- branches:
- - main
- - v[0-9]+-stable
-
-permissions:
- contents: read
-
-env:
- # Enable debug logging in systemd, but keep udev's log level to info,
- # since it's _very_ verbose in the QEMU task
- # Disable the ISC DHCP servers, as they are failing in Ubuntu
- KERNEL_CMDLINE: "systemd.unit=mkosi-check-and-shutdown.service !quiet systemd.log_level=debug systemd.log_target=console udev.log_level=info systemd.default_standard_output=journal+console systemd.mask=isc-dhcp-server6.service systemd.mask=isc-dhcp-server.service"
-
-jobs:
- ci:
- runs-on: ubuntu-22.04
- concurrency:
- group: ${{ github.workflow }}-${{ matrix.distro }}-${{ matrix.release }}-${{ github.ref }}
- cancel-in-progress: true
- strategy:
- fail-fast: false
- matrix:
- include:
- - distro: arch
- release: rolling
- - distro: debian
- release: testing
- - distro: ubuntu
- release: jammy
- - distro: fedora
- release: "37"
- - distro: fedora
- release: rawhide
- - distro: opensuse
- release: tumbleweed
- - distro: centos_epel
- release: 9-stream
- - distro: centos_epel
- release: 8-stream
-
- steps:
- - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- - uses: systemd/mkosi@792cbc60eb2dc4a58d66bb3c212bf92f8d50f6ea
-
- - name: Install
- run: sudo apt-get update && sudo apt-get install --no-install-recommends python3-pexpect python3-jinja2
-
- - name: Configure
- run: |
- tee mkosi.default <<- EOF
- [Distribution]
- Distribution=${{ matrix.distro }}
- Release=${{ matrix.release }}
-
- [Content]
- Environment=CI_BUILD=1
-
- [Output]
- KernelCommandLine=${{ env.KERNEL_CMDLINE }}
- EOF
-
- - name: Build ${{ matrix.distro }}
- run: sudo python3 -m mkosi build
-
- - name: Show ${{ matrix.distro }} image summary
- run: sudo python3 -m mkosi summary
-
- - name: Boot ${{ matrix.distro }} systemd-nspawn
- run: sudo python3 -m mkosi boot ${{ env.KERNEL_CMDLINE }}
-
- - name: Check ${{ matrix.distro }} systemd-nspawn
- run: sudo python3 -m mkosi shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }"
-
- - name: Boot ${{ matrix.distro }} QEMU
- run: sudo timeout -k 30 10m python3 -m mkosi qemu
-
- - name: Check ${{ matrix.distro }} QEMU
- run: sudo python3 -m mkosi shell bash -c "[[ -e /testok ]] || { cat /failed-services; exit 1; }"

@ -0,0 +1,44 @@
From 16f2d0c4a25a717a9a0b49903a55db1263156055 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 9 Jun 2021 15:23:59 +0200
Subject: [PATCH] ci: reconfigure Packit for RHEL 9
Related: #2138081
rhel-only
---
.packit.yml | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/.packit.yml b/.packit.yml
index a7502b25b4..d0eebab181 100644
--- a/.packit.yml
+++ b/.packit.yml
@@ -17,14 +17,12 @@ srpm_build_deps: []
actions:
post-upstream-clone:
- # Use the Fedora Rawhide specfile
- - "git clone https://src.fedoraproject.org/rpms/systemd .packit_rpm --depth=1"
+ # Use the CentOS Stream specfile
+ - "git clone https://gitlab.com/redhat/centos-stream/rpms/systemd.git .packit_rpm --depth=1"
# Drop the "sources" file so rebase-helper doesn't think we're a dist-git
- "rm -fv .packit_rpm/sources"
- # Drop backported patches from the specfile, but keep the downstream-only ones
- # - Patch(0000-0499): backported patches from upstream
- # - Patch0500-9999: downstream-only patches
- - "sed -ri '/^Patch(0[0-4]?[0-9]{0,2})?\\:.+\\.patch/d' .packit_rpm/systemd.spec"
+ # Drop all patches, since they're already included in the tarball
+ - "sed -ri '/^Patch[0-9]+:/d' .packit_rpm/systemd.spec"
# Build the RPM with --werror. Even though --werror doesn't work in all
# cases (see [0]), we can't use -Dc_args=/-Dcpp_args= here because of the
# RPM hardening macros, that use $CFLAGS/$CPPFLAGS (see [1]).
@@ -33,7 +31,9 @@ actions:
# [1] https://github.com/systemd/systemd/pull/18908#issuecomment-792250110
- 'sed -i "/^CONFIGURE_OPTS=(/a--werror" .packit_rpm/systemd.spec'
+# Available targets can be listed via `copr-cli list-chroots`
jobs:
+# Build test
- job: copr_build
trigger: pull_request
metadata:

@ -0,0 +1,28 @@
From 9fd32478c32d9a96b62b992586b201cd4f509bc5 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 15 Jul 2021 12:23:27 +0200
Subject: [PATCH] ci: run unit tests on z-stream branches as well
Related: #2138081
rhel-only
---
.github/workflows/unit_tests.yml | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index cd6c33eb64..ca4464e95d 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -3,11 +3,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
name: Unit tests
-on:
- pull_request:
- branches:
- - main
- - v[0-9]+-stable
+on: [pull_request]
permissions:
contents: read

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save