import systemd-239-45.el8
This commit is contained in:
parent
e39ce11207
commit
77354762f2
@ -1,4 +1,4 @@
|
||||
From 37a4f8256410e3ba1bf1eb7523ebc9f1a68b65e1 Mon Sep 17 00:00:00 2001
|
||||
From 65e96327360ab41d44d5383dcecc82a19fad198c Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Fri, 22 Feb 2019 15:50:55 +0100
|
||||
Subject: [PATCH] logind: don't print warning when user@.service template is
|
||||
@ -10,9 +10,8 @@ instances of systemd for logged in users. We don't need to be verbose
|
||||
about it.
|
||||
|
||||
(cherry picked from commit 03b6fa0c5b51b0d39334ff6ba183a3391443bcf6)
|
||||
(cherry picked from commit 65e96327360ab41d44d5383dcecc82a19fad198c)
|
||||
|
||||
Resolves: #1894152
|
||||
Resolves: #1880270
|
||||
---
|
||||
src/login/logind-user.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
@ -0,0 +1,80 @@
|
||||
From a6d76bf2d21e01a2e031e204966d946925ecc3f6 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Synacek <jsynacek@redhat.com>
|
||||
Date: Mon, 17 Aug 2020 14:29:04 +0200
|
||||
Subject: [PATCH] build: use simple project version in pkgconfig files
|
||||
|
||||
Loosely based on commit a67c318df8800ba98d7361308937ed276dc73982.
|
||||
|
||||
Resolves: #1862714
|
||||
---
|
||||
meson.build | 2 ++
|
||||
src/core/systemd.pc.in | 2 +-
|
||||
src/libsystemd/libsystemd.pc.in | 2 +-
|
||||
src/libudev/libudev.pc.in | 2 +-
|
||||
src/udev/udev.pc.in | 2 +-
|
||||
5 files changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 0ba3f924ea..65c1d0785e 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -27,12 +27,14 @@ endif
|
||||
# names, sometimes. Not all variables are included in every
|
||||
# set. Ugh, ugh, ugh!
|
||||
conf = configuration_data()
|
||||
+conf.set_quoted('PROJECT_VERSION', meson.project_version())
|
||||
conf.set_quoted('PACKAGE_STRING', meson.project_name() + ' ' + dist_version)
|
||||
conf.set_quoted('PACKAGE_VERSION', dist_version)
|
||||
|
||||
substs = configuration_data()
|
||||
substs.set('PACKAGE_URL', 'https://www.freedesktop.org/wiki/Software/systemd')
|
||||
substs.set('PACKAGE_VERSION', dist_version)
|
||||
+substs.set('PROJECT_VERSION', meson.project_version())
|
||||
|
||||
#####################################################################
|
||||
|
||||
diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in
|
||||
index 655773ea8a..a350737cf2 100644
|
||||
--- a/src/core/systemd.pc.in
|
||||
+++ b/src/core/systemd.pc.in
|
||||
@@ -37,4 +37,4 @@ containeruidbasemax=@containeruidbasemax@
|
||||
Name: systemd
|
||||
Description: systemd System and Service Manager
|
||||
URL: @PACKAGE_URL@
|
||||
-Version: @PACKAGE_VERSION@
|
||||
+Version: @PROJECT_VERSION@
|
||||
diff --git a/src/libsystemd/libsystemd.pc.in b/src/libsystemd/libsystemd.pc.in
|
||||
index c861905b67..85d6ebf293 100644
|
||||
--- a/src/libsystemd/libsystemd.pc.in
|
||||
+++ b/src/libsystemd/libsystemd.pc.in
|
||||
@@ -15,6 +15,6 @@ includedir=@includedir@
|
||||
Name: systemd
|
||||
Description: systemd Library
|
||||
URL: @PACKAGE_URL@
|
||||
-Version: @PACKAGE_VERSION@
|
||||
+Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lsystemd
|
||||
Cflags: -I${includedir}
|
||||
diff --git a/src/libudev/libudev.pc.in b/src/libudev/libudev.pc.in
|
||||
index 69f5c6463e..40b340362e 100644
|
||||
--- a/src/libudev/libudev.pc.in
|
||||
+++ b/src/libudev/libudev.pc.in
|
||||
@@ -14,6 +14,6 @@ includedir=@includedir@
|
||||
|
||||
Name: libudev
|
||||
Description: Library to access udev device information
|
||||
-Version: @PACKAGE_VERSION@
|
||||
+Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -ludev
|
||||
Cflags: -I${includedir}
|
||||
diff --git a/src/udev/udev.pc.in b/src/udev/udev.pc.in
|
||||
index e384a6f7c9..5acbb2d01a 100644
|
||||
--- a/src/udev/udev.pc.in
|
||||
+++ b/src/udev/udev.pc.in
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: udev
|
||||
Description: udev
|
||||
-Version: @PACKAGE_VERSION@
|
||||
+Version: @PROJECT_VERSION@
|
||||
|
||||
udevdir=@udevlibexecdir@
|
@ -0,0 +1,57 @@
|
||||
From 2f584bd93d64a75ab11b5a5aa31d0b7145da5a86 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Fri, 26 Apr 2019 13:37:31 +0200
|
||||
Subject: [PATCH] basic/virt: try the /proc/1/sched hack also for PID1
|
||||
|
||||
If a container manager does not set $container, we could end up
|
||||
in a strange situation when detect-virt returns container-other when
|
||||
run as non-pid-1 and none when run as pid-1.
|
||||
|
||||
(cherry picked from commit 342bed02084c4396dd2f1054bd559bfb2699cfcb)
|
||||
Resolves: #1868877
|
||||
---
|
||||
src/basic/virt.c | 16 +++++++++++-----
|
||||
1 file changed, 11 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/basic/virt.c b/src/basic/virt.c
|
||||
index e05b3e6d99..dfa1525219 100644
|
||||
--- a/src/basic/virt.c
|
||||
+++ b/src/basic/virt.c
|
||||
@@ -427,7 +427,6 @@ finish:
|
||||
}
|
||||
|
||||
int detect_container(void) {
|
||||
-
|
||||
static const struct {
|
||||
const char *value;
|
||||
int id;
|
||||
@@ -456,9 +455,15 @@ int detect_container(void) {
|
||||
}
|
||||
|
||||
if (getpid_cached() == 1) {
|
||||
- /* If we are PID 1 we can just check our own environment variable, and that's authoritative. */
|
||||
-
|
||||
+ /* If we are PID 1 we can just check our own environment variable, and that's authoritative.
|
||||
+ * We distinguish three cases:
|
||||
+ * - the variable is not defined → we jump to other checks
|
||||
+ * - the variable is defined to an empty value → we are not in a container
|
||||
+ * - anything else → some container, either one of the known ones or "container-other"
|
||||
+ */
|
||||
e = getenv("container");
|
||||
+ if (!e)
|
||||
+ goto check_sched;
|
||||
if (isempty(e)) {
|
||||
r = VIRTUALIZATION_NONE;
|
||||
goto finish;
|
||||
@@ -486,8 +491,9 @@ int detect_container(void) {
|
||||
if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
|
||||
log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
|
||||
|
||||
- /* Interestingly /proc/1/sched actually shows the host's PID for what we see as PID 1. Hence, if the PID shown
|
||||
- * there is not 1, we know we are in a PID namespace. and hence a container. */
|
||||
+ /* Interestingly /proc/1/sched actually shows the host's PID for what we see as PID 1. If the PID
|
||||
+ * shown there is not 1, we know we are in a PID namespace and hence a container. */
|
||||
+ check_sched:
|
||||
r = read_one_line_file("/proc/1/sched", &m);
|
||||
if (r >= 0) {
|
||||
const char *t;
|
@ -0,0 +1,287 @@
|
||||
From 8cc497e735104080f6830a8f468b2724ae372990 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Wed, 3 Apr 2019 13:11:00 +0200
|
||||
Subject: [PATCH] seccomp: rework how the S[UG]ID filter is installed
|
||||
|
||||
If we know that a syscall is undefined on the given architecture, don't
|
||||
even try to add it.
|
||||
|
||||
Try to install the filter even if some syscalls fail. Also use a helper
|
||||
function to make the whole a bit less magic.
|
||||
|
||||
This allows the S[UG]ID test to pass on arm64.
|
||||
|
||||
(cherry picked from commit da4dc9a6748797e804b6bc92ad513d509abf581c)
|
||||
|
||||
Resolves: #1860374
|
||||
---
|
||||
src/shared/seccomp-util.c | 244 +++++++++++++++++++++-----------------
|
||||
1 file changed, 138 insertions(+), 106 deletions(-)
|
||||
|
||||
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
|
||||
index fd46b9f88d..d91fb4e269 100644
|
||||
--- a/src/shared/seccomp-util.c
|
||||
+++ b/src/shared/seccomp-util.c
|
||||
@@ -1750,9 +1750,139 @@ int seccomp_lock_personality(unsigned long personality) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) {
|
||||
+ /* Checks the mode_t parameter of the following system calls:
|
||||
+ *
|
||||
+ * → chmod() + fchmod() + fchmodat()
|
||||
+ * → open() + creat() + openat()
|
||||
+ * → mkdir() + mkdirat()
|
||||
+ * → mknod() + mknodat()
|
||||
+ *
|
||||
+ * Returns error if *everything* failed, and 0 otherwise.
|
||||
+ */
|
||||
+ int r = 0;
|
||||
+ bool any = false;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(chmod),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for chmod: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(fchmod),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for fchmod: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(fchmodat),
|
||||
+ 1,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for fchmodat: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mkdir),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for mkdir: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mkdirat),
|
||||
+ 1,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for mkdirat: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mknod),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for mknod: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(mknodat),
|
||||
+ 1,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for mknodat: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+#if SCMP_SYS(open) > 0
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(open),
|
||||
+ 2,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for open: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+#endif
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(openat),
|
||||
+ 2,
|
||||
+ SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||
+ SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for openat: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ r = seccomp_rule_add_exact(
|
||||
+ seccomp,
|
||||
+ SCMP_ACT_ERRNO(EPERM),
|
||||
+ SCMP_SYS(creat),
|
||||
+ 1,
|
||||
+ SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add filter for creat: %m");
|
||||
+ else
|
||||
+ any = true;
|
||||
+
|
||||
+ return any ? 0 : r;
|
||||
+}
|
||||
+
|
||||
int seccomp_restrict_suid_sgid(void) {
|
||||
uint32_t arch;
|
||||
- int r;
|
||||
+ int r, k;
|
||||
|
||||
SECCOMP_FOREACH_LOCAL_ARCH(arch) {
|
||||
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
|
||||
@@ -1761,114 +1891,16 @@ int seccomp_restrict_suid_sgid(void) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- /* Checks the mode_t parameter of the following system calls:
|
||||
- *
|
||||
- * → chmod() + fchmod() + fchmodat()
|
||||
- * → open() + creat() + openat()
|
||||
- * → mkdir() + mkdirat()
|
||||
- * → mknod() + mknodat()
|
||||
- */
|
||||
-
|
||||
- for (unsigned bit = 0; bit < 2; bit ++) {
|
||||
- /* Block S_ISUID in the first iteration, S_ISGID in the second */
|
||||
- mode_t m = bit == 0 ? S_ISUID : S_ISGID;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(chmod),
|
||||
- 1,
|
||||
- SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(fchmod),
|
||||
- 1,
|
||||
- SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(fchmodat),
|
||||
- 1,
|
||||
- SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(mkdir),
|
||||
- 1,
|
||||
- SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(mkdirat),
|
||||
- 1,
|
||||
- SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(mknod),
|
||||
- 1,
|
||||
- SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(mknodat),
|
||||
- 1,
|
||||
- SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
-
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(open),
|
||||
- 2,
|
||||
- SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||
- SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
+ r = seccomp_restrict_sxid(seccomp, S_ISUID);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to add suid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
|
||||
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(openat),
|
||||
- 2,
|
||||
- SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
|
||||
- SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
+ k = seccomp_restrict_sxid(seccomp, S_ISGID);
|
||||
+ if (k < 0)
|
||||
+ log_debug_errno(r, "Failed to add sgid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch));
|
||||
|
||||
- r = seccomp_rule_add_exact(
|
||||
- seccomp,
|
||||
- SCMP_ACT_ERRNO(EPERM),
|
||||
- SCMP_SYS(creat),
|
||||
- 1,
|
||||
- SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
|
||||
- if (r < 0)
|
||||
- break;
|
||||
- }
|
||||
- if (r < 0) {
|
||||
- log_debug_errno(r, "Failed to add suid/sgid rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
|
||||
+ if (r < 0 && k < 0)
|
||||
continue;
|
||||
- }
|
||||
|
||||
r = seccomp_load(seccomp);
|
||||
if (IN_SET(r, -EPERM, -EACCES))
|
@ -0,0 +1,91 @@
|
||||
From 860749038f508617c8fc31b8292b4019b1e621ba Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Thu, 16 Jul 2020 21:22:37 +0200
|
||||
Subject: [PATCH] vconsole-setup: downgrade log message when setting font fails
|
||||
on dummy console
|
||||
|
||||
Since commit 883eb9be985fd86d9cabe967eeeab91cdd396a81, vconsole-setup might be
|
||||
called again to operate on dummy console where font operations are not
|
||||
supported but where it's still important to have the correct keymap set [0][1].
|
||||
|
||||
vconsole-setup is mainly called by udev but can also be run via a dependency of
|
||||
an early service. Both cases might end up calling vconsole-setup on the dummy
|
||||
console.
|
||||
|
||||
The first case can happen during early boot even on systems that use (instead
|
||||
of the dummy console) a "simple" video console driver supporting font
|
||||
operations (such as vgacon) until a more specific driver (such as i915) takes
|
||||
the console over. While this is happening vgacon is deactivated and temporarly
|
||||
replaced by the dummy console [2].
|
||||
|
||||
There are also other cases where systemd-vconsole-setup might be called on
|
||||
dummy console especially during (very) early boot. Indeed
|
||||
systemd-vconsole-setup.service might be pulled in by early interactive services
|
||||
such as 'dracut-cmdline-ask.service` which is run before udev.
|
||||
|
||||
If that happens on platforms with no grapical HWs (such as embedded ARM) or
|
||||
with dummy console initially installed until a driver takes over (like Xen and
|
||||
xen-fbfront) then setting font will fail.
|
||||
|
||||
Therefore this patch downgrades the log message emitted when setting font fails
|
||||
to LOG_DEBUG and when font operations is not implemented like it's the case for
|
||||
the dummy console.
|
||||
|
||||
Fixes: #16406.
|
||||
|
||||
[0] https://github.com/systemd/systemd/issues/10826
|
||||
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1652473
|
||||
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/vga/vgaarb.c?h=v5.7#n204
|
||||
|
||||
(cherry picked from commit 0ef1adf51274960358e852d3bc36ae6c288a70d9)
|
||||
|
||||
Resolves: #1889996
|
||||
---
|
||||
src/vconsole/vconsole-setup.c | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
|
||||
index f162d29220..1b406c0bc5 100644
|
||||
--- a/src/vconsole/vconsole-setup.c
|
||||
+++ b/src/vconsole/vconsole-setup.c
|
||||
@@ -222,6 +222,7 @@ static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
|
||||
_cleanup_free_ struct unipair* unipairs = NULL;
|
||||
_cleanup_free_ void *fontbuf = NULL;
|
||||
unsigned i;
|
||||
+ int log_level;
|
||||
int r;
|
||||
|
||||
unipairs = new(struct unipair, USHRT_MAX);
|
||||
@@ -230,11 +231,20 @@ static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
|
||||
return;
|
||||
}
|
||||
|
||||
+ log_level = LOG_WARNING;
|
||||
+
|
||||
/* get metadata of the current font (width, height, count) */
|
||||
r = ioctl(src_fd, KDFONTOP, &cfo);
|
||||
- if (r < 0)
|
||||
- log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to get the font metadata: %m");
|
||||
- else {
|
||||
+ if (r < 0) {
|
||||
+ /* We might be called to operate on the dummy console (to setup keymap
|
||||
+ * mainly) when fbcon deferred takeover is used for example. In such case,
|
||||
+ * setting font is not supported and is expected to fail. */
|
||||
+ if (errno == ENOSYS)
|
||||
+ log_level = LOG_DEBUG;
|
||||
+
|
||||
+ log_full_errno(log_level, errno,
|
||||
+ "KD_FONT_OP_GET failed while trying to get the font metadata: %m");
|
||||
+ } else {
|
||||
/* verify parameter sanity first */
|
||||
if (cfo.width > 32 || cfo.height > 32 || cfo.charcount > 512)
|
||||
log_warning("Invalid font metadata - width: %u (max 32), height: %u (max 32), count: %u (max 512)",
|
||||
@@ -269,7 +279,7 @@ static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
|
||||
}
|
||||
|
||||
if (cfo.op != KD_FONT_OP_SET)
|
||||
- log_warning("Fonts will not be copied to remaining consoles");
|
||||
+ log_full(log_level, "Fonts will not be copied to remaining consoles");
|
||||
|
||||
for (i = 1; i <= 63; i++) {
|
||||
char ttyname[sizeof("/dev/tty63")];
|
@ -0,0 +1,26 @@
|
||||
From 46fa8ff1a62e3334582a971cc6bbd9b8a16680d5 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Biebl <biebl@debian.org>
|
||||
Date: Thu, 7 Mar 2019 12:02:53 +0100
|
||||
Subject: [PATCH] units: fix systemd.special man page reference in
|
||||
system-update-cleanup.service
|
||||
|
||||
(cherry picked from commit faab72d16b310c17be4b908cfe15eca122d16ae4)
|
||||
|
||||
Resolves: #1871827
|
||||
---
|
||||
units/system-update-cleanup.service | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/units/system-update-cleanup.service b/units/system-update-cleanup.service
|
||||
index 58baab3023..d5eca2546b 100644
|
||||
--- a/units/system-update-cleanup.service
|
||||
+++ b/units/system-update-cleanup.service
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
[Unit]
|
||||
Description=Remove the Offline System Updates symlink
|
||||
-Documentation=man:systemd.special(5) man:systemd.offline-updates(7)
|
||||
+Documentation=man:systemd.special(7) man:systemd.offline-updates(7)
|
||||
After=system-update.target
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
27
SOURCES/0442-units-drop-reference-to-sushell-man-page.patch
Normal file
27
SOURCES/0442-units-drop-reference-to-sushell-man-page.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 5aa59d172189adcbd7f9dedb3b909c6bf9b609f2 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 29 Apr 2019 16:10:51 +0200
|
||||
Subject: [PATCH] units: drop reference to sushell man page
|
||||
|
||||
sushell was a Fedoraism, and has been removed since. Hence our upstream
|
||||
unit files shouldn't reference it either.
|
||||
|
||||
(cherry picked from commit 6dc14d73664390682d47d7e5bcbdbb362d04f623)
|
||||
|
||||
Resolves: #1871827
|
||||
---
|
||||
units/debug-shell.service.in | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/units/debug-shell.service.in b/units/debug-shell.service.in
|
||||
index 1127e68b63..9f3868e106 100644
|
||||
--- a/units/debug-shell.service.in
|
||||
+++ b/units/debug-shell.service.in
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
[Unit]
|
||||
Description=Early root shell on @DEBUGTTY@ FOR DEBUGGING ONLY
|
||||
-Documentation=man:sushell(8)
|
||||
Documentation=man:systemd-debug-generator(8)
|
||||
DefaultDependencies=no
|
||||
IgnoreOnIsolate=yes
|
@ -0,0 +1,44 @@
|
||||
From 6a50c735a3bbf98d06fbfa7815f7bdc14ea96f9f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Wed, 14 Oct 2020 14:03:13 +0200
|
||||
Subject: [PATCH] sd-bus: break the loop in bus_ensure_running() if the bus is
|
||||
not connecting
|
||||
|
||||
This might fix #17025:
|
||||
> the call trace is
|
||||
> bus_ensure_running -> sd_bus_process -> bus_process_internal -> process_closeing --> sd_bus_close
|
||||
> |
|
||||
> \-> process_match
|
||||
|
||||
We ended doing callouts to the Disconnected matches from bus_ensure_running()
|
||||
and shouldn't. bus_ensure_running() should never do callouts. This change
|
||||
should fix this however: once we notice that the connection is going down we
|
||||
will now fail instantly with ENOTOCONN instead of calling any callbacks.
|
||||
|
||||
(cherry picked from commit 93a59b1ae5d3bcb0ec1488ebc13d0d1ff4d1729a)
|
||||
|
||||
Resolves: #1885553
|
||||
---
|
||||
src/libsystemd/sd-bus/sd-bus.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index a3509f7e89..c65e24b2d1 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -2059,12 +2059,13 @@ int bus_ensure_running(sd_bus *bus) {
|
||||
|
||||
assert(bus);
|
||||
|
||||
- if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
|
||||
- return -ENOTCONN;
|
||||
if (bus->state == BUS_RUNNING)
|
||||
return 1;
|
||||
|
||||
for (;;) {
|
||||
+ if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING))
|
||||
+ return -ENOTCONN;
|
||||
+
|
||||
r = sd_bus_process(bus, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
@ -0,0 +1,831 @@
|
||||
From 7155c010ef8c620295d230c284849636c07b40c0 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 22 Mar 2019 20:57:30 +0100
|
||||
Subject: [PATCH] core: add new API for enqueing a job with returning the
|
||||
transaction data
|
||||
|
||||
(cherry picked from commit 50cbaba4fe5a32850998682699322d012e597e4a)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
src/analyze/analyze-verify.c | 2 +-
|
||||
src/core/automount.c | 4 +-
|
||||
src/core/dbus-manager.c | 23 +++++-
|
||||
src/core/dbus-unit.c | 153 +++++++++++++++++++++++++++++++----
|
||||
src/core/dbus-unit.h | 8 +-
|
||||
src/core/dbus.c | 2 +-
|
||||
src/core/device.c | 2 +-
|
||||
src/core/emergency-action.c | 5 +-
|
||||
src/core/main.c | 4 +-
|
||||
src/core/manager.c | 38 +++++----
|
||||
src/core/manager.h | 6 +-
|
||||
src/core/path.c | 2 +-
|
||||
src/core/service.c | 2 +-
|
||||
src/core/socket.c | 4 +-
|
||||
src/core/timer.c | 2 +-
|
||||
src/core/transaction.c | 22 ++++-
|
||||
src/core/transaction.h | 2 +-
|
||||
src/core/unit.c | 16 ++--
|
||||
src/test/test-engine.c | 20 ++---
|
||||
19 files changed, 244 insertions(+), 73 deletions(-)
|
||||
|
||||
diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c
|
||||
index ed369532d4..1e143511b2 100644
|
||||
--- a/src/analyze/analyze-verify.c
|
||||
+++ b/src/analyze/analyze-verify.c
|
||||
@@ -205,7 +205,7 @@ static int verify_unit(Unit *u, bool check_man) {
|
||||
unit_dump(u, stdout, "\t");
|
||||
|
||||
log_unit_debug(u, "Creating %s/start job", u->id);
|
||||
- r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, &err, NULL);
|
||||
+ r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, NULL, &err, NULL);
|
||||
if (r < 0)
|
||||
log_unit_error_errno(u, r, "Failed to create %s/start: %s", u->id, bus_error_message(&err, r));
|
||||
|
||||
diff --git a/src/core/automount.c b/src/core/automount.c
|
||||
index b1a155d8d4..76e70f4dac 100644
|
||||
--- a/src/core/automount.c
|
||||
+++ b/src/core/automount.c
|
||||
@@ -776,7 +776,7 @@ static void automount_enter_running(Automount *a) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0) {
|
||||
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
|
||||
goto fail;
|
||||
@@ -1032,7 +1032,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0) {
|
||||
log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
|
||||
goto fail;
|
||||
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
|
||||
index a0777f63d5..0a1d3df42f 100644
|
||||
--- a/src/core/dbus-manager.c
|
||||
+++ b/src/core/dbus-manager.c
|
||||
@@ -549,6 +549,26 @@ static int method_reload_or_try_restart_unit(sd_bus_message *message, void *user
|
||||
return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error);
|
||||
}
|
||||
|
||||
+static int method_enqueue_unit_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
+ Manager *m = userdata;
|
||||
+ const char *name;
|
||||
+ Unit *u;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(message);
|
||||
+ assert(m);
|
||||
+
|
||||
+ r = sd_bus_message_read(message, "s", &name);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = manager_load_unit(m, name, NULL, error, &u);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return bus_unit_method_enqueue_job(message, u, error);
|
||||
+}
|
||||
+
|
||||
static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *m = userdata;
|
||||
const char *old_name;
|
||||
@@ -978,7 +998,7 @@ static int method_start_transient_unit(sd_bus_message *message, void *userdata,
|
||||
return r;
|
||||
|
||||
/* Finally, start it */
|
||||
- return bus_unit_queue_job(message, u, JOB_START, mode, false, error);
|
||||
+ return bus_unit_queue_job(message, u, JOB_START, mode, 0, error);
|
||||
}
|
||||
|
||||
static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
@@ -2547,6 +2567,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
||||
SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
+ SD_BUS_METHOD("EnqueueUnitJob", "sss", "uososa(uosos)", method_enqueue_unit_job, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("FreezeUnit", "s", NULL, method_freeze_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ThawUnit", "s", NULL, method_thaw_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
|
||||
index ce81103e92..549a166abc 100644
|
||||
--- a/src/core/dbus-unit.c
|
||||
+++ b/src/core/dbus-unit.c
|
||||
@@ -314,6 +314,14 @@ static int bus_verify_manage_units_async_full(
|
||||
error);
|
||||
}
|
||||
|
||||
+static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
|
||||
+ [JOB_START] = N_("Authentication is required to start '$(unit)'."),
|
||||
+ [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
|
||||
+ [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
|
||||
+ [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
|
||||
+ [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
|
||||
+};
|
||||
+
|
||||
int bus_unit_method_start_generic(
|
||||
sd_bus_message *message,
|
||||
Unit *u,
|
||||
@@ -324,13 +332,6 @@ int bus_unit_method_start_generic(
|
||||
const char *smode;
|
||||
JobMode mode;
|
||||
_cleanup_free_ char *verb = NULL;
|
||||
- static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = {
|
||||
- [JOB_START] = N_("Authentication is required to start '$(unit)'."),
|
||||
- [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."),
|
||||
- [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."),
|
||||
- [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."),
|
||||
- [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."),
|
||||
- };
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
@@ -372,7 +373,8 @@ int bus_unit_method_start_generic(
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
- return bus_unit_queue_job(message, u, job_type, mode, reload_if_possible, error);
|
||||
+ return bus_unit_queue_job(message, u, job_type, mode,
|
||||
+ reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0, error);
|
||||
}
|
||||
|
||||
static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
@@ -403,6 +405,62 @@ static int method_reload_or_try_restart(sd_bus_message *message, void *userdata,
|
||||
return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
|
||||
}
|
||||
|
||||
+int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
+ BusUnitQueueFlags flags = BUS_UNIT_QUEUE_VERBOSE_REPLY;
|
||||
+ const char *jtype, *smode;
|
||||
+ Unit *u = userdata;
|
||||
+ JobType type;
|
||||
+ JobMode mode;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(message);
|
||||
+ assert(u);
|
||||
+
|
||||
+ r = sd_bus_message_read(message, "ss", &jtype, &smode);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ /* Parse the two magic reload types "reload-or-…" manually */
|
||||
+ if (streq(jtype, "reload-or-restart")) {
|
||||
+ type = JOB_RESTART;
|
||||
+ flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
|
||||
+ } else if (streq(jtype, "reload-or-try-restart")) {
|
||||
+ type = JOB_TRY_RESTART;
|
||||
+ flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE;
|
||||
+ } else {
|
||||
+ /* And the rest generically */
|
||||
+ type = job_type_from_string(jtype);
|
||||
+ if (type < 0)
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job type %s invalid", jtype);
|
||||
+ }
|
||||
+
|
||||
+ mode = job_mode_from_string(smode);
|
||||
+ if (mode < 0)
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
|
||||
+
|
||||
+ r = mac_selinux_unit_access_check(
|
||||
+ u, message,
|
||||
+ job_type_to_access_method(type),
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = bus_verify_manage_units_async_full(
|
||||
+ u,
|
||||
+ jtype,
|
||||
+ CAP_SYS_ADMIN,
|
||||
+ polkit_message_for_job[type],
|
||||
+ true,
|
||||
+ message,
|
||||
+ error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r == 0)
|
||||
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
+
|
||||
+ return bus_unit_queue_job(message, u, type, mode, flags, error);
|
||||
+}
|
||||
+
|
||||
int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Unit *u = userdata;
|
||||
const char *swho;
|
||||
@@ -722,6 +780,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
|
||||
SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
+ SD_BUS_METHOD("EnqueueJob", "ss", "uososa(uosos)", bus_unit_method_enqueue_job, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
@@ -1354,11 +1413,14 @@ int bus_unit_queue_job(
|
||||
Unit *u,
|
||||
JobType type,
|
||||
JobMode mode,
|
||||
- bool reload_if_possible,
|
||||
+ BusUnitQueueFlags flags,
|
||||
sd_bus_error *error) {
|
||||
|
||||
- _cleanup_free_ char *path = NULL;
|
||||
- Job *j;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
+ _cleanup_free_ char *job_path = NULL, *unit_path = NULL;
|
||||
+ _cleanup_(set_freep) Set *affected = NULL;
|
||||
+ Iterator i;
|
||||
+ Job *j, *a;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
@@ -1373,7 +1435,7 @@ int bus_unit_queue_job(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- if (reload_if_possible && unit_can_reload(u)) {
|
||||
+ if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) {
|
||||
if (type == JOB_RESTART)
|
||||
type = JOB_RELOAD_OR_START;
|
||||
else if (type == JOB_TRY_RESTART)
|
||||
@@ -1391,7 +1453,13 @@ int bus_unit_queue_job(
|
||||
(type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
|
||||
return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
|
||||
|
||||
- r = manager_add_job(u->manager, type, u, mode, error, &j);
|
||||
+ if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) {
|
||||
+ affected = set_new(NULL);
|
||||
+ if (!affected)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ r = manager_add_job(u->manager, type, u, mode, affected, error, &j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1399,11 +1467,64 @@ int bus_unit_queue_job(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- path = job_dbus_path(j);
|
||||
- if (!path)
|
||||
+ job_path = job_dbus_path(j);
|
||||
+ if (!job_path)
|
||||
return -ENOMEM;
|
||||
|
||||
- return sd_bus_reply_method_return(message, "o", path);
|
||||
+ /* The classic response is just a job object path */
|
||||
+ if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY))
|
||||
+ return sd_bus_reply_method_return(message, "o", job_path);
|
||||
+
|
||||
+ /* In verbose mode respond with the anchor job plus everything that has been affected */
|
||||
+ r = sd_bus_message_new_method_return(message, &reply);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ unit_path = unit_dbus_path(j->unit);
|
||||
+ if (!unit_path)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ r = sd_bus_message_append(reply, "uosos",
|
||||
+ j->id, job_path,
|
||||
+ j->unit->id, unit_path,
|
||||
+ job_type_to_string(j->type));
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_bus_message_open_container(reply, 'a', "(uosos)");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ SET_FOREACH(a, affected, i) {
|
||||
+
|
||||
+ if (a->id == j->id)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Free paths from previous iteration */
|
||||
+ job_path = mfree(job_path);
|
||||
+ unit_path = mfree(unit_path);
|
||||
+
|
||||
+ job_path = job_dbus_path(a);
|
||||
+ if (!job_path)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ unit_path = unit_dbus_path(a->unit);
|
||||
+ if (!unit_path)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ r = sd_bus_message_append(reply, "(uosos)",
|
||||
+ a->id, job_path,
|
||||
+ a->unit->id, unit_path,
|
||||
+ job_type_to_string(a->type));
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ r = sd_bus_message_close_container(reply);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return sd_bus_send(NULL, reply, NULL);
|
||||
}
|
||||
|
||||
static int bus_unit_set_live_property(
|
||||
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
|
||||
index 39aa1bb53c..d298fcc99e 100644
|
||||
--- a/src/core/dbus-unit.h
|
||||
+++ b/src/core/dbus-unit.h
|
||||
@@ -15,6 +15,7 @@ int bus_unit_send_pending_freezer_message(Unit *u);
|
||||
void bus_unit_send_removed_signal(Unit *u);
|
||||
|
||||
int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error);
|
||||
+int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
|
||||
@@ -27,7 +28,12 @@ int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error
|
||||
int bus_unit_method_freeze(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_unit_method_thaw(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
|
||||
-int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error);
|
||||
+typedef enum BusUnitQueueFlags {
|
||||
+ BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE = 1 << 0,
|
||||
+ BUS_UNIT_QUEUE_VERBOSE_REPLY = 1 << 1,
|
||||
+} BusUnitQueueFlags;
|
||||
+
|
||||
+int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, BusUnitQueueFlags flags, sd_bus_error *error);
|
||||
int bus_unit_validate_load_state(Unit *u, sd_bus_error *error);
|
||||
|
||||
int bus_unit_track_add_name(Unit *u, const char *name);
|
||||
diff --git a/src/core/dbus.c b/src/core/dbus.c
|
||||
index b69c11c519..584a8a1b01 100644
|
||||
--- a/src/core/dbus.c
|
||||
+++ b/src/core/dbus.c
|
||||
@@ -176,7 +176,7 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd
|
||||
goto failed;
|
||||
}
|
||||
|
||||
- r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(m, JOB_START, u, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
goto failed;
|
||||
|
||||
diff --git a/src/core/device.c b/src/core/device.c
|
||||
index 021c28dfbd..cb8b66dfc5 100644
|
||||
--- a/src/core/device.c
|
||||
+++ b/src/core/device.c
|
||||
@@ -419,7 +419,7 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
|
||||
if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */
|
||||
continue;
|
||||
|
||||
- r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, &error, NULL);
|
||||
+ r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(u, r, "Failed to enqueue SYSTEMD_WANTS= job, ignoring: %s", bus_error_message(&error, r));
|
||||
}
|
||||
diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c
|
||||
index 76e1124cff..766a3b4d2b 100644
|
||||
--- a/src/core/emergency-action.c
|
||||
+++ b/src/core/emergency-action.c
|
||||
@@ -54,8 +54,7 @@ int emergency_action(
|
||||
log_and_status(m, "Rebooting", reason);
|
||||
|
||||
(void) update_reboot_parameter_and_warn(reboot_arg);
|
||||
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
|
||||
-
|
||||
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
|
||||
break;
|
||||
|
||||
case EMERGENCY_ACTION_REBOOT_FORCE:
|
||||
@@ -83,7 +82,7 @@ int emergency_action(
|
||||
|
||||
case EMERGENCY_ACTION_POWEROFF:
|
||||
log_and_status(m, "Powering off", reason);
|
||||
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
|
||||
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
|
||||
break;
|
||||
|
||||
case EMERGENCY_ACTION_POWEROFF_FORCE:
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index 25536054b3..d897155644 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -1952,13 +1952,13 @@ static int do_queue_default_job(
|
||||
|
||||
assert(target->load_state == UNIT_LOADED);
|
||||
|
||||
- r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &default_unit_job);
|
||||
+ r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, NULL, &error, &default_unit_job);
|
||||
if (r == -EPERM) {
|
||||
log_debug_errno(r, "Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
|
||||
|
||||
sd_bus_error_free(&error);
|
||||
|
||||
- r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &default_unit_job);
|
||||
+ r = manager_add_job(m, JOB_START, target, JOB_REPLACE, NULL, &error, &default_unit_job);
|
||||
if (r < 0) {
|
||||
*ret_error_message = "Failed to start default target";
|
||||
return log_emergency_errno(r, "Failed to start default target: %s", bus_error_message(&error, r));
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 4c04896aaa..012615e537 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1242,7 +1242,7 @@ static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) {
|
||||
}
|
||||
|
||||
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
|
||||
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
|
||||
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
|
||||
}
|
||||
@@ -1685,9 +1685,17 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret) {
|
||||
- int r;
|
||||
+int manager_add_job(
|
||||
+ Manager *m,
|
||||
+ JobType type,
|
||||
+ Unit *unit,
|
||||
+ JobMode mode,
|
||||
+ Set *affected_jobs,
|
||||
+ sd_bus_error *error,
|
||||
+ Job **ret) {
|
||||
+
|
||||
Transaction *tr;
|
||||
+ int r;
|
||||
|
||||
assert(m);
|
||||
assert(type < _JOB_TYPE_MAX);
|
||||
@@ -1695,10 +1703,10 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_e
|
||||
assert(mode < _JOB_MODE_MAX);
|
||||
|
||||
if (mode == JOB_ISOLATE && type != JOB_START)
|
||||
- return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
|
||||
|
||||
if (mode == JOB_ISOLATE && !unit->allow_isolate)
|
||||
- return sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
|
||||
+ return sd_bus_error_setf(error, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
|
||||
|
||||
log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
|
||||
|
||||
@@ -1710,7 +1718,7 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_e
|
||||
|
||||
r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, false,
|
||||
IN_SET(mode, JOB_IGNORE_DEPENDENCIES, JOB_IGNORE_REQUIREMENTS),
|
||||
- mode == JOB_IGNORE_DEPENDENCIES, e);
|
||||
+ mode == JOB_IGNORE_DEPENDENCIES, error);
|
||||
if (r < 0)
|
||||
goto tr_abort;
|
||||
|
||||
@@ -1720,7 +1728,7 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_e
|
||||
goto tr_abort;
|
||||
}
|
||||
|
||||
- r = transaction_activate(tr, m, mode, e);
|
||||
+ r = transaction_activate(tr, m, mode, affected_jobs, error);
|
||||
if (r < 0)
|
||||
goto tr_abort;
|
||||
|
||||
@@ -1728,8 +1736,8 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_e
|
||||
"Enqueued job %s/%s as %u", unit->id,
|
||||
job_type_to_string(type), (unsigned) tr->anchor_job->id);
|
||||
|
||||
- if (_ret)
|
||||
- *_ret = tr->anchor_job;
|
||||
+ if (ret)
|
||||
+ *ret = tr->anchor_job;
|
||||
|
||||
transaction_free(tr);
|
||||
return 0;
|
||||
@@ -1740,7 +1748,7 @@ tr_abort:
|
||||
return r;
|
||||
}
|
||||
|
||||
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) {
|
||||
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **ret) {
|
||||
Unit *unit = NULL; /* just to appease gcc, initialization is not really necessary */
|
||||
int r;
|
||||
|
||||
@@ -1754,10 +1762,10 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode
|
||||
return r;
|
||||
assert(unit);
|
||||
|
||||
- return manager_add_job(m, type, unit, mode, e, ret);
|
||||
+ return manager_add_job(m, type, unit, mode, affected_jobs, e, ret);
|
||||
}
|
||||
|
||||
-int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
|
||||
+int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
@@ -1766,7 +1774,7 @@ int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name,
|
||||
assert(name);
|
||||
assert(mode < _JOB_MODE_MAX);
|
||||
|
||||
- r = manager_add_job_by_name(m, type, name, mode, &error, ret);
|
||||
+ r = manager_add_job_by_name(m, type, name, mode, affected_jobs, &error, ret);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r));
|
||||
|
||||
@@ -1794,7 +1802,7 @@ int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error
|
||||
/* Failure in adding individual dependencies is ignored, so this always succeeds. */
|
||||
transaction_add_propagate_reload_jobs(tr, unit, tr->anchor_job, mode == JOB_IGNORE_DEPENDENCIES, e);
|
||||
|
||||
- r = transaction_activate(tr, m, mode, e);
|
||||
+ r = transaction_activate(tr, m, mode, NULL, e);
|
||||
if (r < 0)
|
||||
goto tr_abort;
|
||||
|
||||
@@ -2512,7 +2520,7 @@ static void manager_start_target(Manager *m, const char *name, JobMode mode) {
|
||||
|
||||
log_debug("Activating special unit %s", name);
|
||||
|
||||
- r = manager_add_job_by_name(m, JOB_START, name, mode, &error, NULL);
|
||||
+ r = manager_add_job_by_name(m, JOB_START, name, mode, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
|
||||
}
|
||||
diff --git a/src/core/manager.h b/src/core/manager.h
|
||||
index 40568d3c8b..c4b8e80093 100644
|
||||
--- a/src/core/manager.h
|
||||
+++ b/src/core/manager.h
|
||||
@@ -397,9 +397,9 @@ int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_err
|
||||
int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
|
||||
int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
|
||||
|
||||
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret);
|
||||
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **_ret);
|
||||
-int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret);
|
||||
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret);
|
||||
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret);
|
||||
+int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret);
|
||||
int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e);
|
||||
|
||||
void manager_dump_units(Manager *s, FILE *f, const char *prefix);
|
||||
diff --git a/src/core/path.c b/src/core/path.c
|
||||
index dda4a3036b..ed40bc6c19 100644
|
||||
--- a/src/core/path.c
|
||||
+++ b/src/core/path.c
|
||||
@@ -474,7 +474,7 @@ static void path_enter_running(Path *p) {
|
||||
return;
|
||||
}
|
||||
|
||||
- r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 7cff419e4e..5e3e75b5ae 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -2176,7 +2176,7 @@ static void service_enter_restart(Service *s) {
|
||||
* restarted. We use JOB_RESTART (instead of the more obvious
|
||||
* JOB_START) here so that those dependency jobs will be added
|
||||
* as well. */
|
||||
- r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index 7c6d3dfad1..fe061eb73b 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -2274,7 +2274,7 @@ static void socket_enter_running(Socket *s, int cfd) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
@@ -2349,7 +2349,7 @@ static void socket_enter_running(Socket *s, int cfd) {
|
||||
|
||||
service->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */
|
||||
|
||||
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0) {
|
||||
/* We failed to activate the new service, but it still exists. Let's make sure the service
|
||||
* closes and forgets the connection fd again, immediately. */
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 2876d54a59..281ac7f97f 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -566,7 +566,7 @@ static void timer_enter_running(Timer *t) {
|
||||
return;
|
||||
}
|
||||
|
||||
- r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
|
||||
+ r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
diff --git a/src/core/transaction.c b/src/core/transaction.c
|
||||
index 045930838b..cdaaff4f55 100644
|
||||
--- a/src/core/transaction.c
|
||||
+++ b/src/core/transaction.c
|
||||
@@ -585,7 +585,12 @@ rescan:
|
||||
}
|
||||
}
|
||||
|
||||
-static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
|
||||
+static int transaction_apply(
|
||||
+ Transaction *tr,
|
||||
+ Manager *m,
|
||||
+ JobMode mode,
|
||||
+ Set *affected_jobs) {
|
||||
+
|
||||
Iterator i;
|
||||
Job *j;
|
||||
int r;
|
||||
@@ -642,6 +647,11 @@ static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
|
||||
job_add_to_dbus_queue(j);
|
||||
job_start_timer(j, false);
|
||||
job_shutdown_magic(j);
|
||||
+
|
||||
+ /* When 'affected' is specified, let's track all in it all jobs that were touched because of
|
||||
+ * this transaction. */
|
||||
+ if (affected_jobs)
|
||||
+ (void) set_put(affected_jobs, j);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -654,7 +664,13 @@ rollback:
|
||||
return r;
|
||||
}
|
||||
|
||||
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
|
||||
+int transaction_activate(
|
||||
+ Transaction *tr,
|
||||
+ Manager *m,
|
||||
+ JobMode mode,
|
||||
+ Set *affected_jobs,
|
||||
+ sd_bus_error *e) {
|
||||
+
|
||||
Iterator i;
|
||||
Job *j;
|
||||
int r;
|
||||
@@ -731,7 +747,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error
|
||||
return log_notice_errno(r, "Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
|
||||
|
||||
/* Tenth step: apply changes */
|
||||
- r = transaction_apply(tr, m, mode);
|
||||
+ r = transaction_apply(tr, m, mode, affected_jobs);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to apply transaction: %m");
|
||||
|
||||
diff --git a/src/core/transaction.h b/src/core/transaction.h
|
||||
index 70d74a4ccb..4b5620f5c8 100644
|
||||
--- a/src/core/transaction.h
|
||||
+++ b/src/core/transaction.h
|
||||
@@ -29,6 +29,6 @@ int transaction_add_job_and_dependencies(
|
||||
bool ignore_requirements,
|
||||
bool ignore_order,
|
||||
sd_bus_error *e);
|
||||
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e);
|
||||
+int transaction_activate(Transaction *tr, Manager *m, JobMode mode, Set *affected, sd_bus_error *e);
|
||||
int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
|
||||
void transaction_abort(Transaction *tr);
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 29ce6c1fb7..ffbf3cfd48 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2033,7 +2033,7 @@ static void unit_check_binds_to(Unit *u) {
|
||||
log_unit_info(u, "Unit is bound to inactive unit %s. Stopping, too.", other->id);
|
||||
|
||||
/* A unit we need to run is gone. Sniff. Let's stop this. */
|
||||
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
|
||||
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
|
||||
}
|
||||
@@ -2049,25 +2049,25 @@ static void retroactively_start_dependencies(Unit *u) {
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES], i)
|
||||
if (!hashmap_get(u->dependencies[UNIT_AFTER], other) &&
|
||||
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
|
||||
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL);
|
||||
+ manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL);
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i)
|
||||
if (!hashmap_get(u->dependencies[UNIT_AFTER], other) &&
|
||||
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
|
||||
- manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL);
|
||||
+ manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL);
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS], i)
|
||||
if (!hashmap_get(u->dependencies[UNIT_AFTER], other) &&
|
||||
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
|
||||
- manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL);
|
||||
+ manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL, NULL);
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTS], i)
|
||||
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
|
||||
+ manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL);
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTED_BY], i)
|
||||
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
|
||||
+ manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void retroactively_stop_dependencies(Unit *u) {
|
||||
@@ -2081,7 +2081,7 @@ static void retroactively_stop_dependencies(Unit *u) {
|
||||
/* Pull down units which are bound to us recursively if enabled */
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BOUND_BY], i)
|
||||
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
|
||||
- manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL);
|
||||
+ manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void unit_start_on_failure(Unit *u) {
|
||||
@@ -2100,7 +2100,7 @@ void unit_start_on_failure(Unit *u) {
|
||||
HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_ON_FAILURE], i) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
|
||||
- r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, &error, NULL);
|
||||
+ r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(u, r, "Failed to enqueue OnFailure= job, ignoring: %s", bus_error_message(&error, r));
|
||||
}
|
||||
diff --git a/src/test/test-engine.c b/src/test/test-engine.c
|
||||
index 0f3e244dc1..f2e327b3f5 100644
|
||||
--- a/src/test/test-engine.c
|
||||
+++ b/src/test/test-engine.c
|
||||
@@ -46,7 +46,7 @@ int main(int argc, char *argv[]) {
|
||||
manager_dump_units(m, stdout, "\t");
|
||||
|
||||
printf("Test1: (Trivial)\n");
|
||||
- r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j);
|
||||
+ r = manager_add_job(m, JOB_START, c, JOB_REPLACE, NULL, &err, &j);
|
||||
if (sd_bus_error_is_set(&err))
|
||||
log_error("error: %s: %s", err.name, err.message);
|
||||
assert_se(r == 0);
|
||||
@@ -59,15 +59,15 @@ int main(int argc, char *argv[]) {
|
||||
manager_dump_units(m, stdout, "\t");
|
||||
|
||||
printf("Test2: (Cyclic Order, Unfixable)\n");
|
||||
- assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK);
|
||||
+ assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
|
||||
- assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0);
|
||||
+ assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, NULL, &j) == 0);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Test4: (Identical transaction)\n");
|
||||
- assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0);
|
||||
+ assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, NULL, &j) == 0);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Load3:\n");
|
||||
@@ -75,21 +75,21 @@ int main(int argc, char *argv[]) {
|
||||
manager_dump_units(m, stdout, "\t");
|
||||
|
||||
printf("Test5: (Colliding transaction, fail)\n");
|
||||
- assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK);
|
||||
+ assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK);
|
||||
|
||||
printf("Test6: (Colliding transaction, replace)\n");
|
||||
- assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0);
|
||||
+ assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, NULL, &j) == 0);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Test7: (Unmergeable job type, fail)\n");
|
||||
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK);
|
||||
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK);
|
||||
|
||||
printf("Test8: (Mergeable job type, fail)\n");
|
||||
- assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0);
|
||||
+ assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, NULL, &j) == 0);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Test9: (Unmergeable job type, replace)\n");
|
||||
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0);
|
||||
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, NULL, &j) == 0);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
printf("Load4:\n");
|
||||
@@ -97,7 +97,7 @@ int main(int argc, char *argv[]) {
|
||||
manager_dump_units(m, stdout, "\t");
|
||||
|
||||
printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
|
||||
- assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0);
|
||||
+ assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, NULL, &j) == 0);
|
||||
manager_dump_jobs(m, stdout, "\t");
|
||||
|
||||
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b));
|
@ -0,0 +1,115 @@
|
||||
From 8b34041ee97069bee8bf03ae5ba651b34b1b8460 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 26 Mar 2019 15:20:26 +0100
|
||||
Subject: [PATCH] systemctl: replace switch statement by table of structures
|
||||
|
||||
(cherry picked from commit c45e5fb877033c9e3f9b79121644ed71032af379)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
src/systemctl/systemctl.c | 68 ++++++++++++---------------------------
|
||||
1 file changed, 21 insertions(+), 47 deletions(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index e963f19b0a..04e24691d8 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -3179,64 +3179,38 @@ static int logind_set_wall_message(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
-/* Ask systemd-logind, which might grant access to unprivileged users
|
||||
- * through PolicyKit */
|
||||
+/* Ask systemd-logind, which might grant access to unprivileged users through polkit */
|
||||
static int logind_reboot(enum action a) {
|
||||
#if ENABLE_LOGIND
|
||||
+ static const struct {
|
||||
+ const char *method;
|
||||
+ const char *description;
|
||||
+ } actions[_ACTION_MAX] = {
|
||||
+ [ACTION_POWEROFF] = { "PowerOff", "power off system" },
|
||||
+ [ACTION_REBOOT] = { "Reboot", "reboot system" },
|
||||
+ [ACTION_HALT] = { "Halt", "halt system" },
|
||||
+ [ACTION_SUSPEND] = { "Suspend", "suspend system" },
|
||||
+ [ACTION_HIBERNATE] = { "Hibernate", "hibernate system" },
|
||||
+ [ACTION_HYBRID_SLEEP] = { "HybridSleep", "put system into hybrid sleep" },
|
||||
+ [ACTION_SUSPEND_THEN_HIBERNATE] = { "SuspendThenHibernate", "suspend system, hibernate later" },
|
||||
+ };
|
||||
+
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
- const char *method, *description;
|
||||
sd_bus *bus;
|
||||
int r;
|
||||
|
||||
+ if (a < 0 || a >= _ACTION_MAX || !actions[a].method)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
r = acquire_bus(BUS_FULL, &bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- switch (a) {
|
||||
-
|
||||
- case ACTION_POWEROFF:
|
||||
- method = "PowerOff";
|
||||
- description = "power off system";
|
||||
- break;
|
||||
-
|
||||
- case ACTION_REBOOT:
|
||||
- method = "Reboot";
|
||||
- description = "reboot system";
|
||||
- break;
|
||||
-
|
||||
- case ACTION_HALT:
|
||||
- method = "Halt";
|
||||
- description = "halt system";
|
||||
- break;
|
||||
-
|
||||
- case ACTION_SUSPEND:
|
||||
- method = "Suspend";
|
||||
- description = "suspend system";
|
||||
- break;
|
||||
-
|
||||
- case ACTION_HIBERNATE:
|
||||
- method = "Hibernate";
|
||||
- description = "hibernate system";
|
||||
- break;
|
||||
-
|
||||
- case ACTION_HYBRID_SLEEP:
|
||||
- method = "HybridSleep";
|
||||
- description = "put system into hybrid sleep";
|
||||
- break;
|
||||
-
|
||||
- case ACTION_SUSPEND_THEN_HIBERNATE:
|
||||
- method = "SuspendThenHibernate";
|
||||
- description = "put system into suspend followed by hibernate";
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
polkit_agent_open_maybe();
|
||||
(void) logind_set_wall_message();
|
||||
|
||||
- log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", method);
|
||||
+ log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", actions[a].method);
|
||||
+
|
||||
if (arg_dry_run)
|
||||
return 0;
|
||||
|
||||
@@ -3245,12 +3219,12 @@ static int logind_reboot(enum action a) {
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
- method,
|
||||
+ actions[a].method,
|
||||
&error,
|
||||
NULL,
|
||||
"b", arg_ask_password);
|
||||
if (r < 0)
|
||||
- return log_error_errno(r, "Failed to %s via logind: %s", description, bus_error_message(&error, r));
|
||||
+ return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
|
||||
|
||||
return 0;
|
||||
#else
|
53
SOURCES/0446-systemctl-reindent-table.patch
Normal file
53
SOURCES/0446-systemctl-reindent-table.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From 26d2d89c6216672cedf6abfe1b73081adebbdcf8 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 26 Mar 2019 15:49:52 +0100
|
||||
Subject: [PATCH] systemctl: reindent table
|
||||
|
||||
(cherry picked from commit 5fd77930ad9980af5257f9f871556d6973db736c)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
src/systemctl/systemctl.c | 30 +++++++++++++++---------------
|
||||
1 file changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index 04e24691d8..f057dc829c 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -2974,21 +2974,21 @@ static const struct {
|
||||
const char *verb;
|
||||
const char *mode;
|
||||
} action_table[_ACTION_MAX] = {
|
||||
- [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
|
||||
- [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
|
||||
- [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
|
||||
- [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
|
||||
- [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
|
||||
- [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
|
||||
- [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
|
||||
- [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
|
||||
- [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
|
||||
- [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
|
||||
- [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
|
||||
- [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
|
||||
- [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
|
||||
- [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
|
||||
- [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
|
||||
+ [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
|
||||
+ [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
|
||||
+ [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
|
||||
+ [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
|
||||
+ [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
|
||||
+ [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
|
||||
+ [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
|
||||
+ [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
|
||||
+ [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
|
||||
+ [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
|
||||
+ [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
|
||||
+ [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
|
||||
+ [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
|
||||
+ [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
|
||||
+ [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
|
||||
[ACTION_SUSPEND_THEN_HIBERNATE] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, "suspend-then-hibernate", "replace-irreversibly" },
|
||||
};
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 91c83bde0904581fbc33eb7821119e665b9505ce Mon Sep 17 00:00:00 2001
|
||||
From: Filipe Brandenburger <filbranden@google.com>
|
||||
Date: Fri, 20 Jul 2018 11:32:55 -0700
|
||||
Subject: [PATCH] systemctl: Only wait when there's something to wait for.
|
||||
|
||||
Tested:
|
||||
- `systemctl --wait start i-do-not-exist.service` does not wait.
|
||||
- `systemctl --wait start i-do-not-exist.service valid-unit.service` does.
|
||||
|
||||
(cherry picked from commit 46f2579c2ac9f6780d5afec1000764defc6b581e)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
src/systemctl/systemctl.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index f057dc829c..1929692480 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -3130,7 +3130,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
check_triggering_units(bus, *name);
|
||||
}
|
||||
|
||||
- if (r >= 0 && arg_wait) {
|
||||
+ if (r >= 0 && arg_wait && !set_isempty(wait_context.unit_paths)) {
|
||||
int q;
|
||||
q = sd_event_loop(wait_context.event);
|
||||
if (q < 0)
|
@ -0,0 +1,99 @@
|
||||
From 7569756d005d4f780fffd2504eb6f461982833f2 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Sat, 13 Oct 2018 14:38:46 +0200
|
||||
Subject: [PATCH] systemctl: clean up start_unit_one() error handling
|
||||
|
||||
Let's split exit code handling in two: "r" is only used for errno-style
|
||||
errors, and "ret" is used for exit() codes. Then, let's use EXIT_SUCCESS
|
||||
for checking whether the latter is already used.
|
||||
|
||||
This way it should always be clear what kind of error we are processing,
|
||||
and when we propaate one into the other.
|
||||
|
||||
Moreover this allows us to drop "q" form all inner loops, avoiding
|
||||
confusion when to use "q" and when "r" to store received errors.
|
||||
|
||||
Fixes: #9704
|
||||
(cherry picked from commit 0e8d9c0c4d7e71487c486f626c59853cfb031d16)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
src/systemctl/systemctl.c | 32 +++++++++++++++-----------------
|
||||
1 file changed, 15 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index 1929692480..4af9deb98d 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -3004,12 +3004,12 @@ static enum action verb_to_action(const char *verb) {
|
||||
|
||||
static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||
+ _cleanup_(wait_context_free) WaitContext wait_context = {};
|
||||
const char *method, *mode, *one_name, *suffix = NULL;
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
+ int r, ret = EXIT_SUCCESS;
|
||||
sd_bus *bus;
|
||||
- _cleanup_(wait_context_free) WaitContext wait_context = {};
|
||||
char **name;
|
||||
- int r = 0;
|
||||
|
||||
if (arg_wait && !STR_IN_SET(argv[0], "start", "restart")) {
|
||||
log_error("--wait may only be used with the 'start' or 'restart' commands.");
|
||||
@@ -3096,16 +3096,15 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
|
||||
STRV_FOREACH(name, names) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
- int q;
|
||||
|
||||
- q = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
|
||||
- if (r >= 0 && q < 0)
|
||||
- r = translate_bus_error_to_exit_status(q, &error);
|
||||
+ r = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
|
||||
+ if (ret == EXIT_SUCCESS && r < 0)
|
||||
+ ret = translate_bus_error_to_exit_status(r, &error);
|
||||
}
|
||||
|
||||
if (!arg_no_block) {
|
||||
- int q, arg_count = 0;
|
||||
const char* extra_args[4] = {};
|
||||
+ int arg_count = 0;
|
||||
|
||||
if (arg_scope != UNIT_FILE_SYSTEM)
|
||||
extra_args[arg_count++] = "--user";
|
||||
@@ -3119,9 +3118,9 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
extra_args[arg_count++] = arg_host;
|
||||
}
|
||||
|
||||
- q = bus_wait_for_jobs(w, arg_quiet, extra_args);
|
||||
- if (q < 0)
|
||||
- return q;
|
||||
+ r = bus_wait_for_jobs(w, arg_quiet, extra_args);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
|
||||
/* When stopping units, warn if they can still be triggered by
|
||||
* another active unit (socket, path, timer) */
|
||||
@@ -3130,16 +3129,15 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
check_triggering_units(bus, *name);
|
||||
}
|
||||
|
||||
- if (r >= 0 && arg_wait && !set_isempty(wait_context.unit_paths)) {
|
||||
- int q;
|
||||
- q = sd_event_loop(wait_context.event);
|
||||
- if (q < 0)
|
||||
- return log_error_errno(q, "Failed to run event loop: %m");
|
||||
+ if (ret == EXIT_SUCCESS && arg_wait && !set_isempty(wait_context.unit_paths)) {
|
||||
+ r = sd_event_loop(wait_context.event);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to run event loop: %m");
|
||||
if (wait_context.any_failed)
|
||||
- r = EXIT_FAILURE;
|
||||
+ ret = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
- return r;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
#if ENABLE_LOGIND
|
@ -0,0 +1,68 @@
|
||||
From cfb124260a0a9e68102a373c0d136f792e2d4ea7 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 26 Mar 2019 16:19:35 +0100
|
||||
Subject: [PATCH] systemctl: split out extra args generation into helper
|
||||
function of its own
|
||||
|
||||
(cherry picked from commit 94369fc0663255bbd327f97dba288ececf51a514)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
src/systemctl/systemctl.c | 36 +++++++++++++++++++++---------------
|
||||
1 file changed, 21 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index 4af9deb98d..e7a8fd559f 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -3002,6 +3002,25 @@ static enum action verb_to_action(const char *verb) {
|
||||
return _ACTION_INVALID;
|
||||
}
|
||||
|
||||
+static const char** make_extra_args(const char *extra_args[static 4]) {
|
||||
+ size_t n = 0;
|
||||
+
|
||||
+ if (arg_scope != UNIT_FILE_SYSTEM)
|
||||
+ extra_args[n++] = "--user";
|
||||
+
|
||||
+ if (arg_transport == BUS_TRANSPORT_REMOTE) {
|
||||
+ extra_args[n++] = "-H";
|
||||
+ extra_args[n++] = arg_host;
|
||||
+ } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
|
||||
+ extra_args[n++] = "-M";
|
||||
+ extra_args[n++] = arg_host;
|
||||
+ } else
|
||||
+ assert(arg_transport == BUS_TRANSPORT_LOCAL);
|
||||
+
|
||||
+ extra_args[n] = NULL;
|
||||
+ return extra_args;
|
||||
+}
|
||||
+
|
||||
static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||
_cleanup_(wait_context_free) WaitContext wait_context = {};
|
||||
@@ -3103,22 +3122,9 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
if (!arg_no_block) {
|
||||
- const char* extra_args[4] = {};
|
||||
- int arg_count = 0;
|
||||
-
|
||||
- if (arg_scope != UNIT_FILE_SYSTEM)
|
||||
- extra_args[arg_count++] = "--user";
|
||||
-
|
||||
- assert(IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_REMOTE, BUS_TRANSPORT_MACHINE));
|
||||
- if (arg_transport == BUS_TRANSPORT_REMOTE) {
|
||||
- extra_args[arg_count++] = "-H";
|
||||
- extra_args[arg_count++] = arg_host;
|
||||
- } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
|
||||
- extra_args[arg_count++] = "-M";
|
||||
- extra_args[arg_count++] = arg_host;
|
||||
- }
|
||||
+ const char* extra_args[4];
|
||||
|
||||
- r = bus_wait_for_jobs(w, arg_quiet, extra_args);
|
||||
+ r = bus_wait_for_jobs(w, arg_quiet, make_extra_args(extra_args));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
362
SOURCES/0450-systemctl-add-new-show-transaction-switch.patch
Normal file
362
SOURCES/0450-systemctl-add-new-show-transaction-switch.patch
Normal file
@ -0,0 +1,362 @@
|
||||
From cacf7a619cdccd9a6da6c2fe7361eac121b9ea0b Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 22 Mar 2019 20:58:13 +0100
|
||||
Subject: [PATCH] systemctl: add new --show-transaction switch
|
||||
|
||||
This new switch uses the new method call EnqueueUnitJob() for enqueuing
|
||||
a job and showing the jobs it enqueued.
|
||||
|
||||
Fixes: #2297
|
||||
(cherry picked from commit 85d9b5981ba6b7ee3955f95fa6cf3bb8cdf3444d)
|
||||
|
||||
Resolves: #846319
|
||||
---
|
||||
src/systemctl/systemctl.c | 183 ++++++++++++++++++++++++++------------
|
||||
1 file changed, 128 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index e7a8fd559f..8bec798373 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -126,6 +126,7 @@ static bool arg_dry_run = false;
|
||||
static bool arg_quiet = false;
|
||||
static bool arg_full = false;
|
||||
static bool arg_recursive = false;
|
||||
+static bool arg_show_transaction = false;
|
||||
static int arg_force = 0;
|
||||
static bool arg_ask_password = false;
|
||||
static bool arg_runtime = false;
|
||||
@@ -734,7 +735,6 @@ static int get_unit_list_recursive(
|
||||
*_machines = NULL;
|
||||
|
||||
*_unit_infos = TAKE_PTR(unit_infos);
|
||||
-
|
||||
*_replies = TAKE_PTR(replies);
|
||||
|
||||
return c;
|
||||
@@ -2688,25 +2688,26 @@ static int check_triggering_units(sd_bus *bus, const char *name) {
|
||||
}
|
||||
|
||||
static const struct {
|
||||
- const char *verb;
|
||||
- const char *method;
|
||||
+ const char *verb; /* systemctl verb */
|
||||
+ const char *method; /* Name of the specific D-Bus method */
|
||||
+ const char *job_type; /* Job type when passing to the generic EnqueueUnitJob() method */
|
||||
} unit_actions[] = {
|
||||
- { "start", "StartUnit" },
|
||||
- { "stop", "StopUnit" },
|
||||
- { "condstop", "StopUnit" },
|
||||
- { "reload", "ReloadUnit" },
|
||||
- { "restart", "RestartUnit" },
|
||||
- { "try-restart", "TryRestartUnit" },
|
||||
- { "condrestart", "TryRestartUnit" },
|
||||
- { "reload-or-restart", "ReloadOrRestartUnit" },
|
||||
- { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
|
||||
- { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
|
||||
- { "condreload", "ReloadOrTryRestartUnit" },
|
||||
- { "force-reload", "ReloadOrTryRestartUnit" }
|
||||
+ { "start", "StartUnit", "start" },
|
||||
+ { "stop", "StopUnit", "stop" },
|
||||
+ { "condstop", "StopUnit", "stop" }, /* legacy alias */
|
||||
+ { "reload", "ReloadUnit", "reload" },
|
||||
+ { "restart", "RestartUnit", "restart" },
|
||||
+ { "try-restart", "TryRestartUnit", "try-restart" },
|
||||
+ { "condrestart", "TryRestartUnit", "try-restart" }, /* legacy alias */
|
||||
+ { "reload-or-restart", "ReloadOrRestartUnit", "reload-or-restart" },
|
||||
+ { "try-reload-or-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" },
|
||||
+ { "reload-or-try-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
|
||||
+ { "condreload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
|
||||
+ { "force-reload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */
|
||||
};
|
||||
|
||||
static const char *verb_to_method(const char *verb) {
|
||||
- uint i;
|
||||
+ size_t i;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(unit_actions); i++)
|
||||
if (streq_ptr(unit_actions[i].verb, verb))
|
||||
@@ -2715,14 +2716,14 @@ static const char *verb_to_method(const char *verb) {
|
||||
return "StartUnit";
|
||||
}
|
||||
|
||||
-static const char *method_to_verb(const char *method) {
|
||||
- uint i;
|
||||
+static const char *verb_to_job_type(const char *verb) {
|
||||
+ size_t i;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(unit_actions); i++)
|
||||
- if (streq_ptr(unit_actions[i].method, method))
|
||||
- return unit_actions[i].verb;
|
||||
+ if (streq_ptr(unit_actions[i].verb, verb))
|
||||
+ return unit_actions[i].job_type;
|
||||
|
||||
- return "n/a";
|
||||
+ return "start";
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -2805,7 +2806,8 @@ static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error
|
||||
|
||||
static int start_unit_one(
|
||||
sd_bus *bus,
|
||||
- const char *method,
|
||||
+ const char *method, /* When using classic per-job bus methods */
|
||||
+ const char *job_type, /* When using new-style EnqueueUnitJob() */
|
||||
const char *name,
|
||||
const char *mode,
|
||||
sd_bus_error *error,
|
||||
@@ -2814,6 +2816,7 @@ static int start_unit_one(
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
const char *path;
|
||||
+ bool done = false;
|
||||
int r;
|
||||
|
||||
assert(method);
|
||||
@@ -2859,44 +2862,81 @@ static int start_unit_one(
|
||||
log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)",
|
||||
arg_dry_run ? "Would execute" : "Executing",
|
||||
method, name, mode);
|
||||
+
|
||||
if (arg_dry_run)
|
||||
return 0;
|
||||
|
||||
- r = sd_bus_call_method(
|
||||
- bus,
|
||||
- "org.freedesktop.systemd1",
|
||||
- "/org/freedesktop/systemd1",
|
||||
- "org.freedesktop.systemd1.Manager",
|
||||
- method,
|
||||
- error,
|
||||
- &reply,
|
||||
- "ss", name, mode);
|
||||
- if (r < 0) {
|
||||
- const char *verb;
|
||||
+ if (arg_show_transaction) {
|
||||
+ _cleanup_(sd_bus_error_free) sd_bus_error enqueue_error = SD_BUS_ERROR_NULL;
|
||||
|
||||
- /* There's always a fallback possible for legacy actions. */
|
||||
- if (arg_action != ACTION_SYSTEMCTL)
|
||||
- return r;
|
||||
+ /* Use the new, fancy EnqueueUnitJob() API if the user wants us to print the transaction */
|
||||
+ r = sd_bus_call_method(
|
||||
+ bus,
|
||||
+ "org.freedesktop.systemd1",
|
||||
+ "/org/freedesktop/systemd1",
|
||||
+ "org.freedesktop.systemd1.Manager",
|
||||
+ "EnqueueUnitJob",
|
||||
+ &enqueue_error,
|
||||
+ &reply,
|
||||
+ "sss",
|
||||
+ name, job_type, mode);
|
||||
+ if (r < 0) {
|
||||
+ if (!sd_bus_error_has_name(&enqueue_error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
|
||||
+ (void) sd_bus_error_copy(error, &enqueue_error);
|
||||
+ sd_bus_error_free(&enqueue_error);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* Hmm, the API is not yet available. Let's use the classic API instead (see below). */
|
||||
+ log_notice("--show-transaction not supported by this service manager, proceeding without.");
|
||||
+ } else {
|
||||
+ const char *u, *jt;
|
||||
+ uint32_t id;
|
||||
|
||||
- verb = method_to_verb(method);
|
||||
+ r = sd_bus_message_read(reply, "uosos", &id, &path, &u, NULL, &jt);
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
|
||||
- log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
|
||||
+ log_info("Enqueued anchor job %" PRIu32 " %s/%s.", id, u, jt);
|
||||
|
||||
- if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
|
||||
- !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED) &&
|
||||
- !sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE))
|
||||
- log_error("See %s logs and 'systemctl%s status%s %s' for details.",
|
||||
- arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
|
||||
- arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
|
||||
- name[0] == '-' ? " --" : "",
|
||||
- name);
|
||||
+ r = sd_bus_message_enter_container(reply, 'a', "(uosos)");
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+ for (;;) {
|
||||
+ r = sd_bus_message_read(reply, "(uosos)", &id, NULL, &u, NULL, &jt);
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+ if (r == 0)
|
||||
+ break;
|
||||
|
||||
- return r;
|
||||
+ log_info("Enqueued auxiliary job %" PRIu32 " %s/%s.", id, u, jt);
|
||||
+ }
|
||||
+
|
||||
+ r = sd_bus_message_exit_container(reply);
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+
|
||||
+ done = true;
|
||||
+ }
|
||||
}
|
||||
|
||||
- r = sd_bus_message_read(reply, "o", &path);
|
||||
- if (r < 0)
|
||||
- return bus_log_parse_error(r);
|
||||
+ if (!done) {
|
||||
+ r = sd_bus_call_method(
|
||||
+ bus,
|
||||
+ "org.freedesktop.systemd1",
|
||||
+ "/org/freedesktop/systemd1",
|
||||
+ "org.freedesktop.systemd1.Manager",
|
||||
+ method,
|
||||
+ error,
|
||||
+ &reply,
|
||||
+ "ss", name, mode);
|
||||
+ if (r < 0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ r = sd_bus_message_read(reply, "o", &path);
|
||||
+ if (r < 0)
|
||||
+ return bus_log_parse_error(r);
|
||||
+ }
|
||||
|
||||
if (need_daemon_reload(bus, name) > 0)
|
||||
warn_unit_file_changed(name);
|
||||
@@ -2909,6 +2949,24 @@ static int start_unit_one(
|
||||
}
|
||||
|
||||
return 0;
|
||||
+
|
||||
+fail:
|
||||
+ /* There's always a fallback possible for legacy actions. */
|
||||
+ if (arg_action != ACTION_SYSTEMCTL)
|
||||
+ return r;
|
||||
+
|
||||
+ log_error_errno(r, "Failed to %s %s: %s", job_type, name, bus_error_message(error, r));
|
||||
+
|
||||
+ if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
|
||||
+ !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED) &&
|
||||
+ !sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE))
|
||||
+ log_error("See %s logs and 'systemctl%s status%s %s' for details.",
|
||||
+ arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
|
||||
+ arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
|
||||
+ name[0] == '-' ? " --" : "",
|
||||
+ name);
|
||||
+
|
||||
+ return r;
|
||||
}
|
||||
|
||||
static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
|
||||
@@ -2965,7 +3023,6 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(mangled);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3024,7 +3081,7 @@ static const char** make_extra_args(const char *extra_args[static 4]) {
|
||||
static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||
_cleanup_(wait_context_free) WaitContext wait_context = {};
|
||||
- const char *method, *mode, *one_name, *suffix = NULL;
|
||||
+ const char *method, *job_type, *mode, *one_name, *suffix = NULL;
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
int r, ret = EXIT_SUCCESS;
|
||||
sd_bus *bus;
|
||||
@@ -3050,27 +3107,34 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
action = verb_to_action(argv[0]);
|
||||
|
||||
if (action != _ACTION_INVALID) {
|
||||
+ /* A command in style "systemctl reboot", "systemctl poweroff", … */
|
||||
method = "StartUnit";
|
||||
+ job_type = "start";
|
||||
mode = action_table[action].mode;
|
||||
one_name = action_table[action].target;
|
||||
} else {
|
||||
if (streq(argv[0], "isolate")) {
|
||||
+ /* A "systemctl isolate <unit1> <unit2> …" command */
|
||||
method = "StartUnit";
|
||||
+ job_type = "start";
|
||||
mode = "isolate";
|
||||
-
|
||||
suffix = ".target";
|
||||
} else {
|
||||
+ /* A command in style of "systemctl start <unit1> <unit2> …", "sysemctl stop <unit1> <unit2> …" and so on */
|
||||
method = verb_to_method(argv[0]);
|
||||
+ job_type = verb_to_job_type(argv[0]);
|
||||
mode = arg_job_mode;
|
||||
}
|
||||
one_name = NULL;
|
||||
}
|
||||
} else {
|
||||
+ /* A SysV legacy command such as "halt", "reboot", "poweroff", … */
|
||||
assert(arg_action >= 0 && arg_action < _ACTION_MAX);
|
||||
assert(action_table[arg_action].target);
|
||||
assert(action_table[arg_action].mode);
|
||||
|
||||
method = "StartUnit";
|
||||
+ job_type = "start";
|
||||
mode = action_table[arg_action].mode;
|
||||
one_name = action_table[arg_action].target;
|
||||
}
|
||||
@@ -3105,9 +3169,11 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enable subscription: %m");
|
||||
+
|
||||
r = sd_event_default(&wait_context.event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
+
|
||||
r = sd_bus_attach_event(bus, wait_context.event, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
@@ -3116,7 +3182,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
STRV_FOREACH(name, names) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
|
||||
- r = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
|
||||
+ r = start_unit_one(bus, method, job_type, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
|
||||
if (ret == EXIT_SUCCESS && r < 0)
|
||||
ret = translate_bus_error_to_exit_status(r, &error);
|
||||
}
|
||||
@@ -7167,6 +7233,8 @@ static void systemctl_help(void) {
|
||||
" --reverse Show reverse dependencies with 'list-dependencies'\n"
|
||||
" --job-mode=MODE Specify how to deal with already queued jobs, when\n"
|
||||
" queueing a new job\n"
|
||||
+ " -T --show-transaction\n"
|
||||
+ " When enqueuing a unit job, show full transaction\n"
|
||||
" --show-types When showing sockets, explicitly show their type\n"
|
||||
" --value When showing properties, only print the value\n"
|
||||
" -i --ignore-inhibitors\n"
|
||||
@@ -7482,6 +7550,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
{ "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
|
||||
{ "now", no_argument, NULL, ARG_NOW },
|
||||
{ "message", required_argument, NULL, ARG_MESSAGE },
|
||||
+ { "show-transaction", no_argument, NULL, 'T' },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -7494,7 +7563,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
/* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
|
||||
arg_ask_password = true;
|
||||
|
||||
- while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
|
||||
+ while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:iTr", options, NULL)) >= 0)
|
||||
|
||||
switch (c) {
|
||||
|
||||
@@ -7815,6 +7884,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
+ case 'T':
|
||||
+ arg_show_transaction = true;
|
||||
+ break;
|
||||
+
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
@ -0,0 +1,31 @@
|
||||
From f31afbfd2fa68e20a10a8432fb4714a6d4e1170a Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 26 Mar 2019 17:39:36 +0100
|
||||
Subject: [PATCH] test: add some basic testing that "systemctl start -T" does
|
||||
something
|
||||
|
||||
(cherry picked from commit f087c7e072bb338d5c7c0781c9fbc900612efd18)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
test/TEST-03-JOBS/test-jobs.sh | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh
|
||||
index e66ea53621..42190cf478 100755
|
||||
--- a/test/TEST-03-JOBS/test-jobs.sh
|
||||
+++ b/test/TEST-03-JOBS/test-jobs.sh
|
||||
@@ -26,6 +26,13 @@ grep 'sleep\.service.*running' /root/list-jobs.txt
|
||||
grep 'hello\.service' /root/list-jobs.txt && exit 1
|
||||
systemctl stop sleep.service hello-after-sleep.target
|
||||
|
||||
+# Some basic testing that --show-transaction does something useful
|
||||
+! systemctl is-active systemd-importd
|
||||
+systemctl -T start systemd-importd
|
||||
+systemctl is-active systemd-importd
|
||||
+systemctl --show-transaction stop systemd-importd
|
||||
+! systemctl is-active systemd-importd
|
||||
+
|
||||
# Test for a crash when enqueuing a JOB_NOP when other job already exists
|
||||
systemctl start --no-block hello-after-sleep.target
|
||||
# hello.service should still be waiting, so these try-restarts will collapse
|
@ -0,0 +1,37 @@
|
||||
From 588e3e8008d24021ec025d54318fb07d2212293c Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 26 Mar 2019 18:02:49 +0100
|
||||
Subject: [PATCH] man: document the new systemctl --show-transaction option
|
||||
|
||||
(cherry picked from commit df4a7cb7323c8cf00553d766913312c5b7ccd508)
|
||||
|
||||
Related: #846319
|
||||
---
|
||||
man/systemctl.xml | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/man/systemctl.xml b/man/systemctl.xml
|
||||
index 6145486123..fa08ab6c0a 100644
|
||||
--- a/man/systemctl.xml
|
||||
+++ b/man/systemctl.xml
|
||||
@@ -298,6 +298,20 @@
|
||||
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><option>-T</option></term>
|
||||
+ <term><option>--show-transaction</option></term>
|
||||
+
|
||||
+ <listitem>
|
||||
+ <para>When enqueuing a unit job (for example as effect of a <command>systemctl start</command>
|
||||
+ invocation or similar), show brief information about all jobs enqueued, covering both the requested
|
||||
+ job and any added because of unit dependencies. Note that the output will only include jobs
|
||||
+ immediately part of the transaction requested. It is possible that service start-up program code
|
||||
+ run as effect of the enqueued jobs might request further jobs to be pulled in. This means that
|
||||
+ completion of the listed jobs might ultimately entail more jobs than the listed ones.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><option>--fail</option></term>
|
||||
|
@ -0,0 +1,153 @@
|
||||
From 262544a451c11c38e92c45047ec2adeaeb2a0a7e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
|
||||
Date: Thu, 20 Aug 2020 13:00:37 +0200
|
||||
Subject: [PATCH] socket: New option 'FlushPending' (boolean) to flush socket
|
||||
before entering listening state
|
||||
|
||||
Disabled by default. When Enabled, before listening on the socket, flush the content.
|
||||
Applies when Accept=no only.
|
||||
|
||||
(cherry picked from commit 3e5f04bf6468fcb79c080f02b0eab08f258bff0c)
|
||||
|
||||
Resolves: #1870638
|
||||
---
|
||||
doc/TRANSIENT-SETTINGS.md | 1 +
|
||||
man/systemd.socket.xml | 12 ++++++++++++
|
||||
src/core/dbus-socket.c | 4 ++++
|
||||
src/core/load-fragment-gperf.gperf.m4 | 1 +
|
||||
src/core/socket.c | 11 +++++++++++
|
||||
src/core/socket.h | 1 +
|
||||
src/shared/bus-unit-util.c | 3 ++-
|
||||
7 files changed, 32 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
|
||||
index 1a4e79190a..995b8797ef 100644
|
||||
--- a/doc/TRANSIENT-SETTINGS.md
|
||||
+++ b/doc/TRANSIENT-SETTINGS.md
|
||||
@@ -388,6 +388,7 @@ Most socket unit settings are available to transient units.
|
||||
✓ SocketMode=
|
||||
✓ DirectoryMode=
|
||||
✓ Accept=
|
||||
+✓ FlushPending=
|
||||
✓ Writable=
|
||||
✓ MaxConnections=
|
||||
✓ MaxConnectionsPerSource=
|
||||
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
|
||||
index 19c2ca9907..8676b4e03f 100644
|
||||
--- a/man/systemd.socket.xml
|
||||
+++ b/man/systemd.socket.xml
|
||||
@@ -425,6 +425,18 @@
|
||||
false, in read-only mode. Defaults to false.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>FlushPending=</varname></term>
|
||||
+ <listitem><para>Takes a boolean argument. May only be used when
|
||||
+ <option>Accept=no</option>. If yes, the socket's buffers are cleared after the
|
||||
+ triggered service exited. This causes any pending data to be
|
||||
+ flushed and any pending incoming connections to be rejected. If no, the
|
||||
+ socket's buffers won't be cleared, permitting the service to handle any
|
||||
+ pending connections after restart, which is the usually expected behaviour.
|
||||
+ Defaults to <option>no</option>.
|
||||
+ </para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>MaxConnections=</varname></term>
|
||||
<listitem><para>The maximum number of connections to
|
||||
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
|
||||
index 913cc74918..bb77539030 100644
|
||||
--- a/src/core/dbus-socket.c
|
||||
+++ b/src/core/dbus-socket.c
|
||||
@@ -85,6 +85,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("FlushPending", "b", bus_property_get_bool, offsetof(Socket, flush_pending), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Writable", "b", bus_property_get_bool, offsetof(Socket, writable), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("KeepAliveTimeUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_time), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -177,6 +178,9 @@ static int bus_socket_set_transient_property(
|
||||
if (streq(name, "Accept"))
|
||||
return bus_set_transient_bool(u, name, &s->accept, message, flags, error);
|
||||
|
||||
+ if (streq(name, "FlushPending"))
|
||||
+ return bus_set_transient_bool(u, name, &s->flush_pending, message, flags, error);
|
||||
+
|
||||
if (streq(name, "Writable"))
|
||||
return bus_set_transient_bool(u, name, &s->writable, message, flags, error);
|
||||
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index 6d21b2e433..24ee5ae6fe 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -359,6 +359,7 @@ Socket.SocketGroup, config_parse_user_group, 0,
|
||||
Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
|
||||
Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
|
||||
Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
|
||||
+Socket.FlushPending, config_parse_bool, 0, offsetof(Socket, flush_pending)
|
||||
Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable)
|
||||
Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
|
||||
Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source)
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index fe061eb73b..97c3a7fc9a 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -70,6 +70,7 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
|
||||
|
||||
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
|
||||
static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
|
||||
+static void flush_ports(Socket *s);
|
||||
|
||||
static void socket_init(Unit *u) {
|
||||
Socket *s = SOCKET(u);
|
||||
@@ -703,6 +704,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
prefix, s->n_connections,
|
||||
prefix, s->max_connections,
|
||||
prefix, s->max_connections_per_source);
|
||||
+ else
|
||||
+ fprintf(f,
|
||||
+ "%sFlushPending: %s\n",
|
||||
+ prefix, yes_no(s->flush_pending));
|
||||
+
|
||||
|
||||
if (s->priority >= 0)
|
||||
fprintf(f,
|
||||
@@ -2111,6 +2117,11 @@ static void socket_enter_listening(Socket *s) {
|
||||
int r;
|
||||
assert(s);
|
||||
|
||||
+ if (!s->accept && s->flush_pending) {
|
||||
+ log_unit_debug(UNIT(s), "Flushing socket before listening.");
|
||||
+ flush_ports(s);
|
||||
+ }
|
||||
+
|
||||
r = socket_watch_fds(s);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m");
|
||||
diff --git a/src/core/socket.h b/src/core/socket.h
|
||||
index c4e25db1fc..b7a25d91fd 100644
|
||||
--- a/src/core/socket.h
|
||||
+++ b/src/core/socket.h
|
||||
@@ -109,6 +109,7 @@ struct Socket {
|
||||
bool accept;
|
||||
bool remove_on_stop;
|
||||
bool writable;
|
||||
+ bool flush_pending;
|
||||
|
||||
int socket_protocol;
|
||||
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index 77788f0fe2..7029aa5615 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -1468,7 +1468,8 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
|
||||
|
||||
if (STR_IN_SET(field,
|
||||
"Accept", "Writable", "KeepAlive", "NoDelay", "FreeBind", "Transparent", "Broadcast",
|
||||
- "PassCredentials", "PassSecurity", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet"))
|
||||
+ "PassCredentials", "PassSecurity", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet",
|
||||
+ "FlushPending"))
|
||||
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
@ -0,0 +1,62 @@
|
||||
From 9c0ed82f661a2296784970678746b0b4f130870e Mon Sep 17 00:00:00 2001
|
||||
From: Alan Jenkins <alan.christopher.jenkins@gmail.com>
|
||||
Date: Thu, 21 Jun 2018 14:12:30 +0100
|
||||
Subject: [PATCH] core: remove support for API bus "started outside our own
|
||||
logic"
|
||||
|
||||
Looking at a recent Bad Day, my log contains over 100 lines of
|
||||
|
||||
systemd[23895]: Failed to connect to API bus: Connection refused
|
||||
|
||||
It is due to "systemd --user" retrying to connect to an API bus.[*] I
|
||||
would prefer to avoid spamming the logs. I don't think it is good for us
|
||||
to retry so much like this.
|
||||
|
||||
systemd was mislead by something setting DBUS_SESSION_BUS_ADDRESS. My best
|
||||
guess is an unfortunate series of events caused gdm to set this. gdm has
|
||||
code to start a session dbus if there is not a bus available already (and
|
||||
in this case it exports the environment variable). I believe it does not
|
||||
normally do this when running under systemd, because "systemd --user" and
|
||||
hence "dbus.service" would already have been started by pam_systemd.
|
||||
|
||||
I see two possibilities
|
||||
|
||||
1. Rip out the check for DBUS_SESSION_BUS_ADDRESS entirely.
|
||||
2. Only check for DBUS_SESSION_BUS_ADDRESS on startup. Not in the
|
||||
"recheck" logic.
|
||||
|
||||
The justification for 2), is that the recheck is called from unit_notify(),
|
||||
this is used to check whether the service just started (or stopped) was
|
||||
"dbus.service". This reason for rechecking does not apply if we think
|
||||
the session bus was started outside our logic.
|
||||
|
||||
But I think we can justify 1). dbus-daemon ships a statically-enabled
|
||||
/usr/lib/systemd/user/dbus.service, which would conflict with an attempt to
|
||||
use an external dbus. Also "systemd --user" is started from user@.service;
|
||||
if you try to start it manually so that it inherits an environment
|
||||
variable, it will conflict if user@.service was started by pam_systemd
|
||||
(or loginctl enable-linger).
|
||||
|
||||
(cherry picked from commit d3243f55ca9b5f305306ba4105ab29768e372a78)
|
||||
|
||||
Resolves: #1764282
|
||||
---
|
||||
src/core/manager.c | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 012615e537..3c44ad3dbc 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1519,11 +1519,6 @@ static bool manager_dbus_is_running(Manager *m, bool deserialized) {
|
||||
if (m->test_run_flags != 0)
|
||||
return false;
|
||||
|
||||
- /* If we are in the user instance, and the env var is already set for us, then this means D-Bus is ran
|
||||
- * somewhere outside of our own logic. Let's use it */
|
||||
- if (MANAGER_IS_USER(m) && getenv("DBUS_SESSION_BUS_ADDRESS"))
|
||||
- return true;
|
||||
-
|
||||
u = manager_get_unit(m, SPECIAL_DBUS_SOCKET);
|
||||
if (!u)
|
||||
return false;
|
@ -0,0 +1,56 @@
|
||||
From 1c8d1c3bbdf8bdfb2ee4f85b9f559f54c6e4cac4 Mon Sep 17 00:00:00 2001
|
||||
From: Wen Yang <wenyang@linux.alibaba.com>
|
||||
Date: Wed, 1 Jul 2020 04:45:33 +0800
|
||||
Subject: [PATCH] mount-setup: fix segfault in mount_cgroup_controllers when
|
||||
using gcc9 compiler
|
||||
|
||||
According to the documentation:
|
||||
https://gcc.gnu.org/gcc-9/porting_to.html#complit
|
||||
|
||||
The 'join_controllers' that relied on the extended lifetime needs
|
||||
to be fixed, move the compound literals to the function scope it
|
||||
need to accessible in.
|
||||
|
||||
Resolves: #1868877
|
||||
---
|
||||
src/core/mount-setup.c | 24 +++++++++++++-----------
|
||||
1 file changed, 13 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
|
||||
index 16880e6157..a6594580e5 100644
|
||||
--- a/src/core/mount-setup.c
|
||||
+++ b/src/core/mount-setup.c
|
||||
@@ -237,20 +237,22 @@ int mount_cgroup_controllers(char ***join_controllers) {
|
||||
if (!cg_is_legacy_wanted())
|
||||
return 0;
|
||||
|
||||
+ /* The defaults:
|
||||
+ * mount "cpu" + "cpuacct" together, and "net_cls" + "net_prio".
|
||||
+ *
|
||||
+ * We'd like to add "cpuset" to the mix, but "cpuset" doesn't really
|
||||
+ * work for groups with no initialized attributes.
|
||||
+ */
|
||||
+ char ***default_join_controllers = (char**[]) {
|
||||
+ STRV_MAKE("cpu", "cpuacct"),
|
||||
+ STRV_MAKE("net_cls", "net_prio"),
|
||||
+ NULL,
|
||||
+ };
|
||||
+
|
||||
/* Mount all available cgroup controllers that are built into the kernel. */
|
||||
|
||||
if (!has_argument)
|
||||
- /* The defaults:
|
||||
- * mount "cpu" + "cpuacct" together, and "net_cls" + "net_prio".
|
||||
- *
|
||||
- * We'd like to add "cpuset" to the mix, but "cpuset" doesn't really
|
||||
- * work for groups with no initialized attributes.
|
||||
- */
|
||||
- join_controllers = (char**[]) {
|
||||
- STRV_MAKE("cpu", "cpuacct"),
|
||||
- STRV_MAKE("net_cls", "net_prio"),
|
||||
- NULL,
|
||||
- };
|
||||
+ join_controllers = default_join_controllers;
|
||||
|
||||
r = cg_kernel_controllers(&controllers);
|
||||
if (r < 0)
|
@ -0,0 +1,39 @@
|
||||
From 1730f7bb306e13689a7684fd93ae5b8383a28d2f Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekletar@users.noreply.github.com>
|
||||
Date: Fri, 31 May 2019 15:23:23 +0200
|
||||
Subject: [PATCH] dbus-execute: make transfer of CPUAffinity endian safe
|
||||
(#12711)
|
||||
|
||||
We store the affinity mask in the native endian. However, over D-Bus we
|
||||
must transfer the mask in little endian byte order.
|
||||
|
||||
This is the second part of c367f996f5f091a63f812f0140b304c649be77fc.
|
||||
|
||||
(cherry picked from commit 75e40119a471454516ad0acc96f6f4094e7fb652)
|
||||
|
||||
Related: #1740657
|
||||
---
|
||||
src/core/dbus-execute.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index f9527e56b2..d5acca384f 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -215,12 +215,15 @@ static int property_get_cpu_affinity(
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = userdata;
|
||||
+ _cleanup_free_ uint8_t *array = NULL;
|
||||
+ size_t allocated;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
assert(c);
|
||||
|
||||
- return sd_bus_message_append_array(reply, 'y', c->cpu_set.set, c->cpu_set.allocated);
|
||||
+ (void) cpu_set_to_dbus(&c->cpu_set, &array, &allocated);
|
||||
+ return sd_bus_message_append_array(reply, 'y', array, allocated);
|
||||
}
|
||||
|
||||
static int property_get_numa_mask(
|
@ -0,0 +1,426 @@
|
||||
From 1a822dbe19ab6634ffb2c0d3ce92b27b503e1612 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Mon, 17 Feb 2020 13:50:31 +0100
|
||||
Subject: [PATCH] core: add support for setting CPUAffinity= to special "numa"
|
||||
value
|
||||
|
||||
systemd will automatically derive CPU affinity mask from NUMA node
|
||||
mask.
|
||||
|
||||
Fixes #13248
|
||||
|
||||
(cherry picked from commit e2b2fb7f566d13a3de61952b5356cd4d2eaee917)
|
||||
|
||||
Resolves: #1740657
|
||||
---
|
||||
man/systemd.exec.xml | 9 +++---
|
||||
src/basic/cpu-set-util.c | 43 ++++++++++++++++++++++++--
|
||||
src/basic/cpu-set-util.h | 1 +
|
||||
src/core/dbus-execute.c | 30 +++++++++++++++++-
|
||||
src/core/execute.c | 46 ++++++++++++++++++++++++++--
|
||||
src/core/execute.h | 3 ++
|
||||
src/core/load-fragment.c | 14 ++++++++-
|
||||
src/shared/bus-unit-util.c | 9 ++++++
|
||||
src/test/test-cpu-set-util.c | 6 ++--
|
||||
test/TEST-36-NUMAPOLICY/testsuite.sh | 18 +++++++++++
|
||||
10 files changed, 166 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
|
||||
index e2a5ede968..696438c4ef 100644
|
||||
--- a/man/systemd.exec.xml
|
||||
+++ b/man/systemd.exec.xml
|
||||
@@ -706,10 +706,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
<term><varname>CPUAffinity=</varname></term>
|
||||
|
||||
<listitem><para>Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges
|
||||
- separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated
|
||||
- by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are
|
||||
- merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no
|
||||
- effect. See
|
||||
+ separated by either whitespace or commas. Alternatively, takes a special "numa" value in which case systemd
|
||||
+ automatically derives allowed CPU range based on the value of <varname>NUMAMask=</varname> option. CPU ranges
|
||||
+ are specified by the lower and upper CPU indices separated by a dash. This option may be specified more than
|
||||
+ once, in which case the specified CPU affinity masks are merged. If the empty string is assigned, the mask
|
||||
+ is reset, all assignments prior to this will have no effect. See
|
||||
<citerefentry><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
||||
details.</para></listitem>
|
||||
</varlistentry>
|
||||
diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c
|
||||
index 51752ad1a6..1922c95864 100644
|
||||
--- a/src/basic/cpu-set-util.c
|
||||
+++ b/src/basic/cpu-set-util.c
|
||||
@@ -12,12 +12,14 @@
|
||||
#include "cpu-set-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "extract-word.h"
|
||||
+#include "fileio.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "stat-util.h"
|
||||
+#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
@@ -179,7 +181,7 @@ int cpu_set_add_all(CPUSet *a, const CPUSet *b) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int parse_cpu_set_full(
|
||||
@@ -264,7 +266,7 @@ int parse_cpu_set_extend(
|
||||
if (!old->set) {
|
||||
*old = cpuset;
|
||||
cpuset = (CPUSet) {};
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
return cpu_set_add_all(old, &cpuset);
|
||||
@@ -417,6 +419,43 @@ int apply_numa_policy(const NUMAPolicy *policy) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) {
|
||||
+ int r;
|
||||
+ size_t i;
|
||||
+ _cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
+
|
||||
+ assert(policy);
|
||||
+ assert(ret);
|
||||
+
|
||||
+ for (i = 0; i < policy->nodes.allocated * 8; i++) {
|
||||
+ _cleanup_free_ char *l = NULL;
|
||||
+ char p[STRLEN("/sys/devices/system/node/node//cpulist") + DECIMAL_STR_MAX(size_t) + 1];
|
||||
+ _cleanup_(cpu_set_reset) CPUSet part = {};
|
||||
+
|
||||
+ if (!CPU_ISSET_S(i, policy->nodes.allocated, policy->nodes.set))
|
||||
+ continue;
|
||||
+
|
||||
+ xsprintf(p, "/sys/devices/system/node/node%zu/cpulist", i);
|
||||
+
|
||||
+ r = read_one_line_file(p, &l);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = parse_cpu_set(l, &part);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = cpu_set_add_all(&s, &part);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ *ret = s;
|
||||
+ s = (CPUSet) {};
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const char* const mpol_table[] = {
|
||||
[MPOL_DEFAULT] = "default",
|
||||
[MPOL_PREFERRED] = "preferred",
|
||||
diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h
|
||||
index 8519a9b6c8..795be807af 100644
|
||||
--- a/src/basic/cpu-set-util.h
|
||||
+++ b/src/basic/cpu-set-util.h
|
||||
@@ -78,6 +78,7 @@ static inline void numa_policy_reset(NUMAPolicy *p) {
|
||||
}
|
||||
|
||||
int apply_numa_policy(const NUMAPolicy *policy);
|
||||
+int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret);
|
||||
|
||||
const char* mpol_to_string(int i) _const_;
|
||||
int mpol_from_string(const char *s) _pure_;
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index d5acca384f..0fe4c14e48 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -58,6 +58,8 @@ static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext,
|
||||
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
|
||||
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
|
||||
+static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa, "b", ExecContext, exec_context_get_cpu_affinity_from_numa);
|
||||
+
|
||||
|
||||
static int property_get_environment_files(
|
||||
sd_bus *bus,
|
||||
@@ -215,6 +217,7 @@ static int property_get_cpu_affinity(
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = userdata;
|
||||
+ _cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
@@ -222,7 +225,16 @@ static int property_get_cpu_affinity(
|
||||
assert(reply);
|
||||
assert(c);
|
||||
|
||||
- (void) cpu_set_to_dbus(&c->cpu_set, &array, &allocated);
|
||||
+ if (c->cpu_affinity_from_numa) {
|
||||
+ int r;
|
||||
+
|
||||
+ r = numa_to_cpu_set(&c->numa_policy, &s);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ (void) cpu_set_to_dbus(c->cpu_affinity_from_numa ? &s : &c->cpu_set, &array, &allocated);
|
||||
+
|
||||
return sd_bus_message_append_array(reply, 'y', array, allocated);
|
||||
}
|
||||
|
||||
@@ -743,6 +755,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("CPUAffinityFromNUMA", "b", property_get_cpu_affinity_from_numa, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1639,6 +1652,20 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
+ } else if (streq(name, "CPUAffinityFromNUMA")) {
|
||||
+ int q;
|
||||
+
|
||||
+ r = sd_bus_message_read_basic(message, 'b', &q);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
+ c->cpu_affinity_from_numa = q;
|
||||
+ unit_write_settingf(u, flags, name, "%s=%s", "CPUAffinity", "numa");
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+
|
||||
} else if (streq(name, "NUMAPolicy")) {
|
||||
int32_t type;
|
||||
|
||||
@@ -1653,6 +1680,7 @@ int bus_exec_context_set_transient_property(
|
||||
c->numa_policy.type = type;
|
||||
|
||||
return 1;
|
||||
+
|
||||
} else if (streq(name, "IOSchedulingClass")) {
|
||||
int32_t q;
|
||||
|
||||
diff --git a/src/core/execute.c b/src/core/execute.c
|
||||
index 3c54ac1110..d528d08830 100644
|
||||
--- a/src/core/execute.c
|
||||
+++ b/src/core/execute.c
|
||||
@@ -2750,6 +2750,33 @@ static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p
|
||||
|
||||
static char *exec_command_line(char **argv);
|
||||
|
||||
+static int exec_context_cpu_affinity_from_numa(const ExecContext *c, CPUSet *ret) {
|
||||
+ _cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
+ int r;
|
||||
+
|
||||
+ assert(c);
|
||||
+ assert(ret);
|
||||
+
|
||||
+ if (!c->numa_policy.nodes.set) {
|
||||
+ log_debug("Can't derive CPU affinity mask from NUMA mask because NUMA mask is not set, ignoring");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = numa_to_cpu_set(&c->numa_policy, &s);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ cpu_set_reset(ret);
|
||||
+
|
||||
+ return cpu_set_add_all(ret, &s);
|
||||
+}
|
||||
+
|
||||
+bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c) {
|
||||
+ assert(c);
|
||||
+
|
||||
+ return c->cpu_affinity_from_numa;
|
||||
+}
|
||||
+
|
||||
static int exec_child(
|
||||
Unit *unit,
|
||||
const ExecCommand *command,
|
||||
@@ -3012,11 +3039,26 @@ static int exec_child(
|
||||
}
|
||||
}
|
||||
|
||||
- if (context->cpu_set.set)
|
||||
- if (sched_setaffinity(0, context->cpu_set.allocated, context->cpu_set.set) < 0) {
|
||||
+ if (context->cpu_affinity_from_numa || context->cpu_set.set) {
|
||||
+ _cleanup_(cpu_set_reset) CPUSet converted_cpu_set = {};
|
||||
+ const CPUSet *cpu_set;
|
||||
+
|
||||
+ if (context->cpu_affinity_from_numa) {
|
||||
+ r = exec_context_cpu_affinity_from_numa(context, &converted_cpu_set);
|
||||
+ if (r < 0) {
|
||||
+ *exit_status = EXIT_CPUAFFINITY;
|
||||
+ return log_unit_error_errno(unit, r, "Failed to derive CPU affinity mask from NUMA mask: %m");
|
||||
+ }
|
||||
+
|
||||
+ cpu_set = &converted_cpu_set;
|
||||
+ } else
|
||||
+ cpu_set = &context->cpu_set;
|
||||
+
|
||||
+ if (sched_setaffinity(0, cpu_set->allocated, cpu_set->set) < 0) {
|
||||
*exit_status = EXIT_CPUAFFINITY;
|
||||
return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m");
|
||||
}
|
||||
+ }
|
||||
|
||||
if (mpol_is_valid(numa_policy_get_type(&context->numa_policy))) {
|
||||
r = apply_numa_policy(&context->numa_policy);
|
||||
diff --git a/src/core/execute.h b/src/core/execute.h
|
||||
index 86c1cee84c..62c6229621 100644
|
||||
--- a/src/core/execute.h
|
||||
+++ b/src/core/execute.h
|
||||
@@ -152,6 +152,7 @@ struct ExecContext {
|
||||
|
||||
CPUSet cpu_set;
|
||||
NUMAPolicy numa_policy;
|
||||
+ bool cpu_affinity_from_numa;
|
||||
|
||||
ExecInput std_input;
|
||||
ExecOutput std_output;
|
||||
@@ -375,6 +376,8 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value,
|
||||
void exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds);
|
||||
void exec_runtime_vacuum(Manager *m);
|
||||
|
||||
+bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c);
|
||||
+
|
||||
const char* exec_output_to_string(ExecOutput i) _const_;
|
||||
ExecOutput exec_output_from_string(const char *s) _pure_;
|
||||
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index 33fdb82754..740401a582 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -1251,13 +1251,25 @@ int config_parse_exec_cpu_affinity(const char *unit,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = data;
|
||||
+ int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
- return parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
|
||||
+ if (streq(rvalue, "numa")) {
|
||||
+ c->cpu_affinity_from_numa = true;
|
||||
+ cpu_set_reset(&c->cpu_set);
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
|
||||
+ if (r >= 0)
|
||||
+ c->cpu_affinity_from_numa = false;
|
||||
+
|
||||
+ return r;
|
||||
}
|
||||
|
||||
int config_parse_capability_set(
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index 7029aa5615..daa2c2dce5 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "securebits-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-protocol-list.h"
|
||||
+#include "socket-util.h"
|
||||
+#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "syslog-util.h"
|
||||
#include "terminal-util.h"
|
||||
@@ -997,6 +999,13 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
+ if (eq && streq(eq, "numa")) {
|
||||
+ r = sd_bus_message_append(m, "(sv)", "CPUAffinityFromNUMA", "b", true);
|
||||
+ if (r < 0)
|
||||
+ return bus_log_create_error(r);
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
r = parse_cpu_set(eq, &cpuset);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
|
||||
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
|
||||
index 136eaca82d..1b7be5df4e 100644
|
||||
--- a/src/test/test-cpu-set-util.c
|
||||
+++ b/src/test/test-cpu-set-util.c
|
||||
@@ -218,12 +218,12 @@ static void test_parse_cpu_set_extend(void) {
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
- assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
|
||||
+ assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 1);
|
||||
assert_se(CPU_COUNT_S(c.allocated, c.set) == 2);
|
||||
assert_se(s1 = cpu_set_to_string(&c));
|
||||
log_info("cpu_set_to_string: %s", s1);
|
||||
|
||||
- assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
|
||||
+ assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 1);
|
||||
assert_se(CPU_COUNT_S(c.allocated, c.set) == 3);
|
||||
assert_se(s2 = cpu_set_to_string(&c));
|
||||
log_info("cpu_set_to_string: %s", s2);
|
||||
@@ -240,7 +240,7 @@ static void test_cpu_set_to_from_dbus(void) {
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
- assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
|
||||
+ assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 1);
|
||||
assert_se(s = cpu_set_to_string(&c));
|
||||
log_info("cpu_set_to_string: %s", s);
|
||||
assert_se(CPU_COUNT_S(c.allocated, c.set) == 104);
|
||||
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
index bffac4ffe6..7ccaa5b412 100755
|
||||
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
|
||||
@@ -279,6 +279,18 @@ else
|
||||
# Maks must be ignored
|
||||
grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
|
||||
|
||||
+ echo "Unit file CPUAffinity=NUMA support"
|
||||
+ writeTestUnitNUMAPolicy "bind" "0"
|
||||
+ echo "CPUAffinity=numa" >> $testUnitNUMAConf
|
||||
+ systemctl daemon-reload
|
||||
+ systemctl start $testUnit
|
||||
+ systemctlCheckNUMAProperties $testUnit "bind" "0"
|
||||
+ pid=$(systemctl show --value -p MainPID $testUnit)
|
||||
+ cpulist=$(cat /sys/devices/system/node/node0/cpulist)
|
||||
+ affinity_systemd=$(systemctl show --value -p CPUAffinity $testUnit)
|
||||
+ [ $cpulist = $affinity_systemd ]
|
||||
+ pid1StopUnit $testUnit
|
||||
+
|
||||
echo "systemd-run NUMAPolicy support"
|
||||
runUnit='numa-systemd-run-test.service'
|
||||
|
||||
@@ -309,6 +321,12 @@ else
|
||||
systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
|
||||
systemctlCheckNUMAProperties $runUnit "local" ""
|
||||
pid1StopUnit $runUnit
|
||||
+
|
||||
+ systemd-run -p NUMAPolicy=local -p NUMAMask=0 -p CPUAffinity=numa --unit $runUnit sleep 1000
|
||||
+ systemctlCheckNUMAProperties $runUnit "local" ""
|
||||
+ systemctl cat $runUnit | grep -q 'CPUAffinity=numa'
|
||||
+ pid1StopUnit $runUnit
|
||||
+
|
||||
fi
|
||||
|
||||
# Cleanup
|
@ -0,0 +1,93 @@
|
||||
From 57d2e6e64ba490054f8de1a2aad4ffae7778eddc Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Sun, 31 May 2020 18:21:09 +0200
|
||||
Subject: [PATCH] basic/user-util: always use base 10 for user/group numbers
|
||||
|
||||
We would parse numbers with base prefixes as user identifiers. For example,
|
||||
"0x2b3bfa0" would be interpreted as UID==45334432 and "01750" would be
|
||||
interpreted as UID==1000. This parsing was used also in cases where either a
|
||||
user/group name or number may be specified. This means that names like
|
||||
0x2b3bfa0 would be ambiguous: they are a valid user name according to our
|
||||
documented relaxed rules, but they would also be parsed as numeric uids.
|
||||
|
||||
This behaviour is definitely not expected by users, since tools generally only
|
||||
accept decimal numbers (e.g. id, getent passwd), while other tools only accept
|
||||
user names and thus will interpret such strings as user names without even
|
||||
attempting to convert them to numbers (su, ssh). So let's follow suit and only
|
||||
accept numbers in decimal notation. Effectively this means that we will reject
|
||||
such strings as a username/uid/groupname/gid where strict mode is used, and try
|
||||
to look up a user/group with such a name in relaxed mode.
|
||||
|
||||
Since the function changed is fairly low-level and fairly widely used, this
|
||||
affects multiple tools: loginctl show-user/enable-linger/disable-linger foo',
|
||||
the third argument in sysusers.d, fourth and fifth arguments in tmpfiles.d,
|
||||
etc.
|
||||
|
||||
Fixes #15985.
|
||||
|
||||
(cherry picked from commit 156a5fd297b61bce31630d7a52c15614bf784843)
|
||||
|
||||
Resolves: #1848373
|
||||
---
|
||||
src/basic/parse-util.h | 8 ++++++--
|
||||
src/basic/user-util.c | 2 +-
|
||||
src/test/test-user-util.c | 10 ++++++++++
|
||||
3 files changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
|
||||
index f3267f4cfe..1fc1af7615 100644
|
||||
--- a/src/basic/parse-util.h
|
||||
+++ b/src/basic/parse-util.h
|
||||
@@ -50,9 +50,13 @@ static inline int safe_atoux16(const char *s, uint16_t *ret) {
|
||||
|
||||
int safe_atoi16(const char *s, int16_t *ret);
|
||||
|
||||
-static inline int safe_atou32(const char *s, uint32_t *ret_u) {
|
||||
+static inline int safe_atou32_full(const char *s, unsigned base, uint32_t *ret_u) {
|
||||
assert_cc(sizeof(uint32_t) == sizeof(unsigned));
|
||||
- return safe_atou(s, (unsigned*) ret_u);
|
||||
+ return safe_atou_full(s, base, (unsigned*) ret_u);
|
||||
+}
|
||||
+
|
||||
+static inline int safe_atou32(const char *s, uint32_t *ret_u) {
|
||||
+ return safe_atou32_full(s, 0, (unsigned*) ret_u);
|
||||
}
|
||||
|
||||
static inline int safe_atoi32(const char *s, int32_t *ret_i) {
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index d92969c966..10eeb256cd 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -49,7 +49,7 @@ int parse_uid(const char *s, uid_t *ret) {
|
||||
assert(s);
|
||||
|
||||
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
|
||||
- r = safe_atou32(s, &uid);
|
||||
+ r = safe_atou32_full(s, 10, &uid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
|
||||
index 9114d30b8c..8bf3dcd567 100644
|
||||
--- a/src/test/test-user-util.c
|
||||
+++ b/src/test/test-user-util.c
|
||||
@@ -46,9 +46,19 @@ static void test_parse_uid(void) {
|
||||
|
||||
r = parse_uid("65535", &uid);
|
||||
assert_se(r == -ENXIO);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("0x1234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("01234", &uid);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(uid == 1234);
|
||||
|
||||
r = parse_uid("asdsdas", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 1234);
|
||||
}
|
||||
|
||||
static void test_uid_ptr(void) {
|
@ -0,0 +1,149 @@
|
||||
From 2fd9a21a8b6a93c4fb2747839766adca15faa008 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 14 Nov 2019 14:49:40 +0100
|
||||
Subject: [PATCH] parse-util: sometimes it is useful to check if a string is a
|
||||
valid integer, but not actually parse it
|
||||
|
||||
(cherry picked from commit 22810041c2200fe72b0e0c985d0e404f8b80f9e2)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 34 ++++++++++++++++++++--------------
|
||||
1 file changed, 20 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 6becf85878..056e56765e 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -383,7 +383,6 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret_u);
|
||||
assert(base <= 16);
|
||||
|
||||
/* strtoul() is happy to parse negative values, and silently
|
||||
@@ -407,7 +406,9 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
if ((unsigned long) (unsigned) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
- *ret_u = (unsigned) l;
|
||||
+ if (ret_u)
|
||||
+ *ret_u = (unsigned) l;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -416,7 +417,6 @@ int safe_atoi(const char *s, int *ret_i) {
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret_i);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
@@ -427,7 +427,9 @@ int safe_atoi(const char *s, int *ret_i) {
|
||||
if ((long) (int) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
- *ret_i = (int) l;
|
||||
+ if (ret_i)
|
||||
+ *ret_i = (int) l;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -436,7 +438,6 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
unsigned long long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret_llu);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
@@ -449,7 +450,9 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
if (*s == '-')
|
||||
return -ERANGE;
|
||||
|
||||
- *ret_llu = l;
|
||||
+ if (ret_llu)
|
||||
+ *ret_llu = l;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -458,7 +461,6 @@ int safe_atolli(const char *s, long long int *ret_lli) {
|
||||
long long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret_lli);
|
||||
|
||||
errno = 0;
|
||||
l = strtoll(s, &x, 0);
|
||||
@@ -467,7 +469,9 @@ int safe_atolli(const char *s, long long int *ret_lli) {
|
||||
if (!x || x == s || *x != 0)
|
||||
return -EINVAL;
|
||||
|
||||
- *ret_lli = l;
|
||||
+ if (ret_lli)
|
||||
+ *ret_lli = l;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -476,7 +480,6 @@ int safe_atou8(const char *s, uint8_t *ret) {
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
@@ -491,7 +494,8 @@ int safe_atou8(const char *s, uint8_t *ret) {
|
||||
if ((unsigned long) (uint8_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
- *ret = (uint8_t) l;
|
||||
+ if (ret)
|
||||
+ *ret = (uint8_t) l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -525,7 +529,6 @@ int safe_atoi16(const char *s, int16_t *ret) {
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret);
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
@@ -536,7 +539,9 @@ int safe_atoi16(const char *s, int16_t *ret) {
|
||||
if ((long) (int16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
- *ret = (int16_t) l;
|
||||
+ if (ret)
|
||||
+ *ret = (int16_t) l;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -546,7 +551,6 @@ int safe_atod(const char *s, double *ret_d) {
|
||||
double d = 0;
|
||||
|
||||
assert(s);
|
||||
- assert(ret_d);
|
||||
|
||||
loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
|
||||
if (loc == (locale_t) 0)
|
||||
@@ -559,7 +563,9 @@ int safe_atod(const char *s, double *ret_d) {
|
||||
if (!x || x == s || *x != 0)
|
||||
return -EINVAL;
|
||||
|
||||
- *ret_d = (double) d;
|
||||
+ if (ret_d)
|
||||
+ *ret_d = (double) d;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
130
SOURCES/0460-basic-parse-util-add-safe_atoux64.patch
Normal file
130
SOURCES/0460-basic-parse-util-add-safe_atoux64.patch
Normal file
@ -0,0 +1,130 @@
|
||||
From bd47a98d3ce2c5e1d74deb7bc384e416a9070b96 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Thu, 9 Apr 2020 11:18:26 +0200
|
||||
Subject: [PATCH] basic/parse-util: add safe_atoux64()
|
||||
|
||||
(cherry picked from commit ce51632a357d347737bf40d3817df331cd8874cb)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 4 ++--
|
||||
src/basic/parse-util.h | 12 +++++++++++-
|
||||
src/test/test-parse-util.c | 39 ++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 52 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 056e56765e..67056c0434 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -433,7 +433,7 @@ int safe_atoi(const char *s, int *ret_i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
+int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) {
|
||||
char *x = NULL;
|
||||
unsigned long long l;
|
||||
|
||||
@@ -442,7 +442,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
errno = 0;
|
||||
- l = strtoull(s, &x, 0);
|
||||
+ l = strtoull(s, &x, base);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
|
||||
index 1fc1af7615..8a49257050 100644
|
||||
--- a/src/basic/parse-util.h
|
||||
+++ b/src/basic/parse-util.h
|
||||
@@ -33,7 +33,6 @@ static inline int safe_atou(const char *s, unsigned *ret_u) {
|
||||
}
|
||||
|
||||
int safe_atoi(const char *s, int *ret_i);
|
||||
-int safe_atollu(const char *s, unsigned long long *ret_u);
|
||||
int safe_atolli(const char *s, long long int *ret_i);
|
||||
|
||||
int safe_atou8(const char *s, uint8_t *ret);
|
||||
@@ -64,6 +63,12 @@ static inline int safe_atoi32(const char *s, int32_t *ret_i) {
|
||||
return safe_atoi(s, (int*) ret_i);
|
||||
}
|
||||
|
||||
+int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu);
|
||||
+
|
||||
+static inline int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
+ return safe_atollu_full(s, 0, ret_llu);
|
||||
+}
|
||||
+
|
||||
static inline int safe_atou64(const char *s, uint64_t *ret_u) {
|
||||
assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
|
||||
return safe_atollu(s, (unsigned long long*) ret_u);
|
||||
@@ -74,6 +79,11 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) {
|
||||
return safe_atolli(s, (long long int*) ret_i);
|
||||
}
|
||||
|
||||
+static inline int safe_atoux64(const char *s, uint64_t *ret) {
|
||||
+ assert_cc(sizeof(int64_t) == sizeof(long long unsigned));
|
||||
+ return safe_atollu_full(s, 16, (long long unsigned*) ret);
|
||||
+}
|
||||
+
|
||||
#if LONG_MAX == INT_MAX
|
||||
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
|
||||
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
|
||||
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
|
||||
index e9aef5e882..8b182d9bdc 100644
|
||||
--- a/src/test/test-parse-util.c
|
||||
+++ b/src/test/test-parse-util.c
|
||||
@@ -561,6 +561,44 @@ static void test_safe_atoi64(void) {
|
||||
assert_se(r == -EINVAL);
|
||||
}
|
||||
|
||||
+static void test_safe_atoux64(void) {
|
||||
+ int r;
|
||||
+ uint64_t l;
|
||||
+
|
||||
+ r = safe_atoux64("12345", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 0x12345);
|
||||
+
|
||||
+ r = safe_atoux64(" 12345", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 0x12345);
|
||||
+
|
||||
+ r = safe_atoux64("0x12345", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 0x12345);
|
||||
+
|
||||
+ r = safe_atoux64("18446744073709551617", &l);
|
||||
+ assert_se(r == -ERANGE);
|
||||
+
|
||||
+ r = safe_atoux64("-1", &l);
|
||||
+ assert_se(r == -ERANGE);
|
||||
+
|
||||
+ r = safe_atoux64(" -1", &l);
|
||||
+ assert_se(r == -ERANGE);
|
||||
+
|
||||
+ r = safe_atoux64("junk", &l);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+
|
||||
+ r = safe_atoux64("123x", &l);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+
|
||||
+ r = safe_atoux64("12.3", &l);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+
|
||||
+ r = safe_atoux64("", &l);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+}
|
||||
+
|
||||
static void test_safe_atod(void) {
|
||||
int r;
|
||||
double d;
|
||||
@@ -836,6 +874,7 @@ int main(int argc, char *argv[]) {
|
||||
test_safe_atoux16();
|
||||
test_safe_atou64();
|
||||
test_safe_atoi64();
|
||||
+ test_safe_atoux64();
|
||||
test_safe_atod();
|
||||
test_parse_percent();
|
||||
test_parse_percent_unbounded();
|
@ -0,0 +1,137 @@
|
||||
From 1d11e79fefea34b4395043e8e951414c5b7817ba Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:06:19 +0200
|
||||
Subject: [PATCH] parse-util: allow tweaking how to parse integers
|
||||
|
||||
This allows disabling a few alternative ways to decode integers
|
||||
formatted as strings, for safety reasons.
|
||||
|
||||
See: #15991
|
||||
(cherry picked from commit 707e93aff8f358f8a62117e54b857530d6594e4b)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 65 +++++++++++++++++++++++++++++++++---------
|
||||
src/basic/parse-util.h | 6 ++++
|
||||
2 files changed, 58 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 67056c0434..6cc4fc3e57 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -383,20 +383,35 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
- assert(base <= 16);
|
||||
+ assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
|
||||
|
||||
- /* strtoul() is happy to parse negative values, and silently
|
||||
- * converts them to unsigned values without generating an
|
||||
- * error. We want a clean error, hence let's look for the "-"
|
||||
- * prefix on our own, and generate an error. But let's do so
|
||||
- * only after strtoul() validated that the string is clean
|
||||
- * otherwise, so that we return EINVAL preferably over
|
||||
- * ERANGE. */
|
||||
+ /* strtoul() is happy to parse negative values, and silently converts them to unsigned values without
|
||||
+ * generating an error. We want a clean error, hence let's look for the "-" prefix on our own, and
|
||||
+ * generate an error. But let's do so only after strtoul() validated that the string is clean
|
||||
+ * otherwise, so that we return EINVAL preferably over ERANGE. */
|
||||
+
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
|
||||
+ strchr(WHITESPACE, s[0]))
|
||||
+ return -EINVAL;
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
|
||||
+ IN_SET(s[0], '+', '-'))
|
||||
+ return -EINVAL; /* Note that we check the "-" prefix again a second time below, but return a
|
||||
+ * different error. I.e. if the SAFE_ATO_REFUSE_PLUS_MINUS flag is set we
|
||||
+ * blanket refuse +/- prefixed integers, while if it is missing we'll just
|
||||
+ * return ERANGE, because the string actually parses correctly, but doesn't
|
||||
+ * fit in the return type. */
|
||||
+
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
|
||||
+ s[0] == '0' && !streq(s, "0"))
|
||||
+ return -EINVAL; /* This is particularly useful to avoid ambiguities between C's octal
|
||||
+ * notation and assumed-to-be-decimal integers with a leading zero. */
|
||||
+
|
||||
errno = 0;
|
||||
- l = strtoul(s, &x, base);
|
||||
+ l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base) /* Let's mask off the flags bits so that only the actual
|
||||
+ * base is left */);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
@@ -438,11 +453,24 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu)
|
||||
unsigned long long l;
|
||||
|
||||
assert(s);
|
||||
+ assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
|
||||
+
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
|
||||
+ strchr(WHITESPACE, s[0]))
|
||||
+ return -EINVAL;
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
|
||||
+ IN_SET(s[0], '+', '-'))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
|
||||
+ s[0] == '0' && s[1] != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
errno = 0;
|
||||
- l = strtoull(s, &x, base);
|
||||
+ l = strtoull(s, &x, SAFE_ATO_MASK_FLAGS(base));
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
@@ -504,13 +532,24 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
|
||||
unsigned long l;
|
||||
|
||||
assert(s);
|
||||
- assert(ret);
|
||||
- assert(base <= 16);
|
||||
+ assert(SAFE_ATO_MASK_FLAGS(base) <= 16);
|
||||
+
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) &&
|
||||
+ strchr(WHITESPACE, s[0]))
|
||||
+ return -EINVAL;
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) &&
|
||||
+ IN_SET(s[0], '+', '-'))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) &&
|
||||
+ s[0] == '0' && s[1] != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
errno = 0;
|
||||
- l = strtoul(s, &x, base);
|
||||
+ l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base));
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
|
||||
index 8a49257050..c6bbc98dff 100644
|
||||
--- a/src/basic/parse-util.h
|
||||
+++ b/src/basic/parse-util.h
|
||||
@@ -26,6 +26,12 @@ int parse_syscall_and_errno(const char *in, char **name, int *error);
|
||||
#define FORMAT_BYTES_MAX 8
|
||||
char *format_bytes(char *buf, size_t l, uint64_t t);
|
||||
|
||||
+#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30)
|
||||
+#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29)
|
||||
+#define SAFE_ATO_REFUSE_LEADING_WHITESPACE (1U << 28)
|
||||
+#define SAFE_ATO_ALL_FLAGS (SAFE_ATO_REFUSE_PLUS_MINUS|SAFE_ATO_REFUSE_LEADING_ZERO|SAFE_ATO_REFUSE_LEADING_WHITESPACE)
|
||||
+#define SAFE_ATO_MASK_FLAGS(base) ((base) & ~SAFE_ATO_ALL_FLAGS)
|
||||
+
|
||||
int safe_atou_full(const char *s, unsigned base, unsigned *ret_u);
|
||||
|
||||
static inline int safe_atou(const char *s, unsigned *ret_u) {
|
@ -0,0 +1,60 @@
|
||||
From 1c8e5070d8a88f35b5577e091de66727fa785ef7 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:08:38 +0200
|
||||
Subject: [PATCH] parse-util: allow '-0' as alternative to '0' and '+0'
|
||||
|
||||
Let's allow "-0" as alternative to "+0" and "0" when parsing integers,
|
||||
unless the new SAFE_ATO_REFUSE_PLUS_MINUS flag is specified.
|
||||
|
||||
In cases where allowing the +/- syntax shall not be allowed
|
||||
SAFE_ATO_REFUSE_PLUS_MINUS is the right flag to use, but this also means
|
||||
that -0 as only negative integer that fits into an unsigned value should
|
||||
be acceptable if the flag is not specified.
|
||||
|
||||
(cherry picked from commit c78eefc13562a8fc0c22c00a6d3001af89860258)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 6cc4fc3e57..53d181dd60 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -416,7 +416,7 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
return -EINVAL;
|
||||
- if (s[0] == '-')
|
||||
+ if (l != 0 && s[0] == '-')
|
||||
return -ERANGE;
|
||||
if ((unsigned long) (unsigned) l != l)
|
||||
return -ERANGE;
|
||||
@@ -475,7 +475,7 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
return -EINVAL;
|
||||
- if (*s == '-')
|
||||
+ if (l != 0 && s[0] == '-')
|
||||
return -ERANGE;
|
||||
|
||||
if (ret_llu)
|
||||
@@ -517,7 +517,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
return -EINVAL;
|
||||
- if (s[0] == '-')
|
||||
+ if (l != 0 && s[0] == '-')
|
||||
return -ERANGE;
|
||||
if ((unsigned long) (uint8_t) l != l)
|
||||
return -ERANGE;
|
||||
@@ -554,7 +554,7 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
return -EINVAL;
|
||||
- if (s[0] == '-')
|
||||
+ if (l != 0 && s[0] == '-')
|
||||
return -ERANGE;
|
||||
if ((unsigned long) (uint16_t) l != l)
|
||||
return -ERANGE;
|
@ -0,0 +1,31 @@
|
||||
From 91ed5edcdea79773f6918e739637521e47129b07 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:10:27 +0200
|
||||
Subject: [PATCH] parse-util: make return parameter optional in
|
||||
safe_atou16_full()
|
||||
|
||||
All other safe_atoXYZ_full() functions have the parameter optional,
|
||||
let's make it optoinal here, too.
|
||||
|
||||
(cherry picked from commit aa85e4d3cef8ca8436e480bce9fa4ce72876b636)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 53d181dd60..7a7cefe6ff 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -559,7 +559,9 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
|
||||
if ((unsigned long) (uint16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
- *ret = (uint16_t) l;
|
||||
+ if (ret)
|
||||
+ *ret = (uint16_t) l;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
From 147a3696b45a872e0e21fb74e1497f02543ce871 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:16:04 +0200
|
||||
Subject: [PATCH] parse-util: rewrite parse_mode() on top of safe_atou_full()
|
||||
|
||||
Parsing is hard, hence let's use our own careful wrappers wherever
|
||||
possible.
|
||||
|
||||
(cherry picked from commit c44702a8bd8cc8b7f2f1df21db9308d9af7dda5b)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 28 +++++++++++++---------------
|
||||
1 file changed, 13 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 7a7cefe6ff..68c156c543 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -54,26 +54,24 @@ int parse_pid(const char *s, pid_t* ret_pid) {
|
||||
}
|
||||
|
||||
int parse_mode(const char *s, mode_t *ret) {
|
||||
- char *x;
|
||||
- long l;
|
||||
+ unsigned m;
|
||||
+ int r;
|
||||
|
||||
assert(s);
|
||||
- assert(ret);
|
||||
|
||||
- s += strspn(s, WHITESPACE);
|
||||
- if (s[0] == '-')
|
||||
- return -ERANGE;
|
||||
-
|
||||
- errno = 0;
|
||||
- l = strtol(s, &x, 8);
|
||||
- if (errno > 0)
|
||||
- return -errno;
|
||||
- if (!x || x == s || *x != 0)
|
||||
- return -EINVAL;
|
||||
- if (l < 0 || l > 07777)
|
||||
+ r = safe_atou_full(s, 8 |
|
||||
+ SAFE_ATO_REFUSE_PLUS_MINUS, /* Leading '+' or even '-' char? that's just weird,
|
||||
+ * refuse. User might have wanted to add mode flags or
|
||||
+ * so, but this parser doesn't allow that, so let's
|
||||
+ * better be safe. */
|
||||
+ &m);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (m > 07777)
|
||||
return -ERANGE;
|
||||
|
||||
- *ret = (mode_t) l;
|
||||
+ if (ret)
|
||||
+ *ret = m;
|
||||
return 0;
|
||||
}
|
||||
|
78
SOURCES/0465-user-util-be-stricter-in-parse_uid.patch
Normal file
78
SOURCES/0465-user-util-be-stricter-in-parse_uid.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 87c22d3bb794118d25bc138108fd5bdd607365ef Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:16:46 +0200
|
||||
Subject: [PATCH] user-util: be stricter in parse_uid()
|
||||
|
||||
Let's refuse "+" and "-" prefixed UIDs. Let's refuse whitespace-prefixed
|
||||
UIDS, Let's refuse zero-prefixed UIDs. Let's be safe than sorry.
|
||||
|
||||
(cherry picked from commit f5979b63cc305ba217dfd174b1bf0583bcf75a73)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/user-util.c | 10 +++++++++-
|
||||
src/test/test-user-util.c | 26 +++++++++++++++++++++++---
|
||||
2 files changed, 32 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index 10eeb256cd..40f4e45db6 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -49,7 +49,15 @@ int parse_uid(const char *s, uid_t *ret) {
|
||||
assert(s);
|
||||
|
||||
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
|
||||
- r = safe_atou32_full(s, 10, &uid);
|
||||
+
|
||||
+ /* We are very strict when parsing UIDs, and prohibit +/- as prefix, leading zero as prefix, and
|
||||
+ * whitespace. We do this, since this call is often used in a context where we parse things as UID
|
||||
+ * first, and if that doesn't work we fall back to NSS. Thus we really want to make sure that UIDs
|
||||
+ * are parsed as UIDs only if they really really look like UIDs. */
|
||||
+ r = safe_atou32_full(s, 10
|
||||
+ | SAFE_ATO_REFUSE_PLUS_MINUS
|
||||
+ | SAFE_ATO_REFUSE_LEADING_ZERO
|
||||
+ | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &uid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
|
||||
index 8bf3dcd567..99203f7e48 100644
|
||||
--- a/src/test/test-user-util.c
|
||||
+++ b/src/test/test-user-util.c
|
||||
@@ -52,13 +52,33 @@ static void test_parse_uid(void) {
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
+ r = parse_uid("+1234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("-1234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid(" 1234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
r = parse_uid("01234", &uid);
|
||||
- assert_se(r == 0);
|
||||
- assert_se(uid == 1234);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("-0", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("+0", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
|
||||
r = parse_uid("asdsdas", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
- assert_se(uid == 1234);
|
||||
+ assert_se(uid == 100);
|
||||
}
|
||||
|
||||
static void test_uid_ptr(void) {
|
75
SOURCES/0466-strv-add-new-macro-STARTSWITH_SET.patch
Normal file
75
SOURCES/0466-strv-add-new-macro-STARTSWITH_SET.patch
Normal file
@ -0,0 +1,75 @@
|
||||
From 50b103a982dfd6f1b2bf98bbc98a8063fa153e89 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 23 Nov 2018 16:27:15 +0100
|
||||
Subject: [PATCH] strv: add new macro STARTSWITH_SET()
|
||||
|
||||
This is to startswith() what PATH_STARTSWITH_SET() is to
|
||||
path_startswith().
|
||||
|
||||
Or in other words, checks if the specified string has any of the listed
|
||||
prefixes, and if so, returns the remainder of the string.
|
||||
|
||||
(cherry picked from commit 52f1552073047195d51901f7e5a5a4fa3189034e)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/strv.h | 12 ++++++++++++
|
||||
src/test/test-strv.c | 15 +++++++++++++++
|
||||
2 files changed, 27 insertions(+)
|
||||
|
||||
diff --git a/src/basic/strv.h b/src/basic/strv.h
|
||||
index 51d03db940..c1e4c973b6 100644
|
||||
--- a/src/basic/strv.h
|
||||
+++ b/src/basic/strv.h
|
||||
@@ -136,6 +136,18 @@ void strv_print(char **l);
|
||||
_x && strv_contains(STRV_MAKE(__VA_ARGS__), _x); \
|
||||
})
|
||||
|
||||
+#define STARTSWITH_SET(p, ...) \
|
||||
+ ({ \
|
||||
+ const char *_p = (p); \
|
||||
+ char *_found = NULL, **_i; \
|
||||
+ STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \
|
||||
+ _found = startswith(_p, *_i); \
|
||||
+ if (_found) \
|
||||
+ break; \
|
||||
+ } \
|
||||
+ _found; \
|
||||
+ })
|
||||
+
|
||||
#define FOREACH_STRING(x, ...) \
|
||||
for (char **_l = ({ \
|
||||
char **_ll = STRV_MAKE(__VA_ARGS__); \
|
||||
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
|
||||
index 1c192239a2..79d999d3ed 100644
|
||||
--- a/src/test/test-strv.c
|
||||
+++ b/src/test/test-strv.c
|
||||
@@ -56,6 +56,20 @@ static void test_strptr_in_set(void) {
|
||||
assert_se(!STRPTR_IN_SET(NULL, NULL));
|
||||
}
|
||||
|
||||
+static void test_startswith_set(void) {
|
||||
+ assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo"));
|
||||
+ assert_se(!STARTSWITH_SET("foo", "bar"));
|
||||
+
|
||||
+ assert_se(STARTSWITH_SET("abc", "a", "ab", "abc"));
|
||||
+ assert_se(STARTSWITH_SET("abc", "ax", "ab", "abc"));
|
||||
+ assert_se(STARTSWITH_SET("abc", "ax", "abx", "abc"));
|
||||
+ assert_se(!STARTSWITH_SET("abc", "ax", "abx", "abcx"));
|
||||
+
|
||||
+ assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "foo", "zzz"), "bar"));
|
||||
+ assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "", "zzz"), "foobar"));
|
||||
+ assert_se(streq_ptr(STARTSWITH_SET("", "hhh", "kkk", "zzz", ""), ""));
|
||||
+}
|
||||
+
|
||||
static const char* const input_table_multiple[] = {
|
||||
"one",
|
||||
"two",
|
||||
@@ -700,6 +714,7 @@ int main(int argc, char *argv[]) {
|
||||
test_specifier_printf();
|
||||
test_str_in_set();
|
||||
test_strptr_in_set();
|
||||
+ test_startswith_set();
|
||||
test_strv_foreach();
|
||||
test_strv_foreach_backwards();
|
||||
test_strv_foreach_pair();
|
@ -0,0 +1,164 @@
|
||||
From e67e29d91a1ef90af545e4130c7b4c4cfde6202a Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:31:51 +0200
|
||||
Subject: [PATCH] parse-util: also parse integers prefixed with 0b and 0o
|
||||
|
||||
Let's adopt Python 3 style 0b and 0x syntaxes, because it makes a ton of
|
||||
sense, in particular in bitmask settings.
|
||||
|
||||
(cherry picked from commit fc80cabcf584a8b486bdff5be0c074fec4059cdc)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/parse-util.c | 56 ++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 51 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 68c156c543..992ea3605b 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
+#include "strv.h"
|
||||
|
||||
int parse_boolean(const char *v) {
|
||||
assert(v);
|
||||
@@ -373,7 +374,32 @@ char *format_bytes(char *buf, size_t l, uint64_t t) {
|
||||
finish:
|
||||
buf[l-1] = 0;
|
||||
return buf;
|
||||
+}
|
||||
+
|
||||
+static const char *mangle_base(const char *s, unsigned *base) {
|
||||
+ const char *k;
|
||||
+
|
||||
+ assert(s);
|
||||
+ assert(base);
|
||||
+
|
||||
+ /* Base already explicitly specified, then don't do anything. */
|
||||
+ if (SAFE_ATO_MASK_FLAGS(*base) != 0)
|
||||
+ return s;
|
||||
|
||||
+ /* Support Python 3 style "0b" and 0x" prefixes, because they truly make sense, much more than C's "0" prefix for octal. */
|
||||
+ k = STARTSWITH_SET(s, "0b", "0B");
|
||||
+ if (k) {
|
||||
+ *base = 2 | (*base & SAFE_ATO_ALL_FLAGS);
|
||||
+ return k;
|
||||
+ }
|
||||
+
|
||||
+ k = STARTSWITH_SET(s, "0o", "0O");
|
||||
+ if (k) {
|
||||
+ *base = 8 | (*base & SAFE_ATO_ALL_FLAGS);
|
||||
+ return k;
|
||||
+ }
|
||||
+
|
||||
+ return s;
|
||||
}
|
||||
|
||||
int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
@@ -407,6 +433,8 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
return -EINVAL; /* This is particularly useful to avoid ambiguities between C's octal
|
||||
* notation and assumed-to-be-decimal integers with a leading zero. */
|
||||
|
||||
+ s = mangle_base(s, &base);
|
||||
+
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base) /* Let's mask off the flags bits so that only the actual
|
||||
* base is left */);
|
||||
@@ -426,13 +454,17 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) {
|
||||
}
|
||||
|
||||
int safe_atoi(const char *s, int *ret_i) {
|
||||
+ unsigned base = 0;
|
||||
char *x = NULL;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
|
||||
+ s += strspn(s, WHITESPACE);
|
||||
+ s = mangle_base(s, &base);
|
||||
+
|
||||
errno = 0;
|
||||
- l = strtol(s, &x, 0);
|
||||
+ l = strtol(s, &x, base);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
@@ -467,6 +499,8 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu)
|
||||
s[0] == '0' && s[1] != 0)
|
||||
return -EINVAL;
|
||||
|
||||
+ s = mangle_base(s, &base);
|
||||
+
|
||||
errno = 0;
|
||||
l = strtoull(s, &x, SAFE_ATO_MASK_FLAGS(base));
|
||||
if (errno > 0)
|
||||
@@ -483,13 +517,17 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu)
|
||||
}
|
||||
|
||||
int safe_atolli(const char *s, long long int *ret_lli) {
|
||||
+ unsigned base = 0;
|
||||
char *x = NULL;
|
||||
long long l;
|
||||
|
||||
assert(s);
|
||||
|
||||
+ s += strspn(s, WHITESPACE);
|
||||
+ s = mangle_base(s, &base);
|
||||
+
|
||||
errno = 0;
|
||||
- l = strtoll(s, &x, 0);
|
||||
+ l = strtoll(s, &x, base);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
@@ -502,15 +540,17 @@ int safe_atolli(const char *s, long long int *ret_lli) {
|
||||
}
|
||||
|
||||
int safe_atou8(const char *s, uint8_t *ret) {
|
||||
- char *x = NULL;
|
||||
+ unsigned base = 0;
|
||||
unsigned long l;
|
||||
+ char *x = NULL;
|
||||
|
||||
assert(s);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
+ s = mangle_base(s, &base);
|
||||
|
||||
errno = 0;
|
||||
- l = strtoul(s, &x, 0);
|
||||
+ l = strtoul(s, &x, base);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
@@ -546,6 +586,8 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
|
||||
s[0] == '0' && s[1] != 0)
|
||||
return -EINVAL;
|
||||
|
||||
+ s = mangle_base(s, &base);
|
||||
+
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base));
|
||||
if (errno > 0)
|
||||
@@ -564,13 +606,17 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) {
|
||||
}
|
||||
|
||||
int safe_atoi16(const char *s, int16_t *ret) {
|
||||
+ unsigned base = 0;
|
||||
char *x = NULL;
|
||||
long l;
|
||||
|
||||
assert(s);
|
||||
|
||||
+ s += strspn(s, WHITESPACE);
|
||||
+ s = mangle_base(s, &base);
|
||||
+
|
||||
errno = 0;
|
||||
- l = strtol(s, &x, 0);
|
||||
+ l = strtol(s, &x, base);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
204
SOURCES/0468-tests-beef-up-integer-parsing-tests.patch
Normal file
204
SOURCES/0468-tests-beef-up-integer-parsing-tests.patch
Normal file
@ -0,0 +1,204 @@
|
||||
From 457eada27f606e39f0efc6adc226542fd11eb815 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 1 Jun 2020 17:48:41 +0200
|
||||
Subject: [PATCH] tests: beef up integer parsing tests
|
||||
|
||||
(cherry picked from commit 53c6db99fa4b52f97e19977f21d3133f8ceb3dcd)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/test/test-parse-util.c | 58 ++++++++++++++++++++++++++++++++++++++
|
||||
src/test/test-user-util.c | 40 ++++++++++++++++++++++++++
|
||||
2 files changed, 98 insertions(+)
|
||||
|
||||
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
|
||||
index 8b182d9bdc..699499b665 100644
|
||||
--- a/src/test/test-parse-util.c
|
||||
+++ b/src/test/test-parse-util.c
|
||||
@@ -75,14 +75,22 @@ static void test_parse_mode(void) {
|
||||
mode_t m;
|
||||
|
||||
assert_se(parse_mode("-1", &m) < 0);
|
||||
+ assert_se(parse_mode("+1", &m) < 0);
|
||||
assert_se(parse_mode("", &m) < 0);
|
||||
assert_se(parse_mode("888", &m) < 0);
|
||||
assert_se(parse_mode("77777", &m) < 0);
|
||||
|
||||
assert_se(parse_mode("544", &m) >= 0 && m == 0544);
|
||||
+ assert_se(parse_mode("0544", &m) >= 0 && m == 0544);
|
||||
+ assert_se(parse_mode("00544", &m) >= 0 && m == 0544);
|
||||
assert_se(parse_mode("777", &m) >= 0 && m == 0777);
|
||||
+ assert_se(parse_mode("0777", &m) >= 0 && m == 0777);
|
||||
+ assert_se(parse_mode("00777", &m) >= 0 && m == 0777);
|
||||
assert_se(parse_mode("7777", &m) >= 0 && m == 07777);
|
||||
+ assert_se(parse_mode("07777", &m) >= 0 && m == 07777);
|
||||
+ assert_se(parse_mode("007777", &m) >= 0 && m == 07777);
|
||||
assert_se(parse_mode("0", &m) >= 0 && m == 0);
|
||||
+ assert_se(parse_mode(" 1", &m) >= 0 && m == 1);
|
||||
}
|
||||
|
||||
static void test_parse_size(void) {
|
||||
@@ -358,6 +366,18 @@ static void test_safe_atolli(void) {
|
||||
assert_se(r == 0);
|
||||
assert_se(l == -12345);
|
||||
|
||||
+ r = safe_atolli("0x5", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 5);
|
||||
+
|
||||
+ r = safe_atolli("0o6", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 6);
|
||||
+
|
||||
+ r = safe_atolli("0B101", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 5);
|
||||
+
|
||||
r = safe_atolli("12345678901234567890", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
@@ -431,6 +451,14 @@ static void test_safe_atoi16(void) {
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 32767);
|
||||
|
||||
+ r = safe_atoi16("0o11", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 9);
|
||||
+
|
||||
+ r = safe_atoi16("0B110", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 6);
|
||||
+
|
||||
r = safe_atoi16("36536", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
@@ -475,6 +503,13 @@ static void test_safe_atoux16(void) {
|
||||
r = safe_atoux16(" -1", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
+ r = safe_atoux16("0b1", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 177);
|
||||
+
|
||||
+ r = safe_atoux16("0o70", &l);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+
|
||||
r = safe_atoux16("junk", &l);
|
||||
assert_se(r == -EINVAL);
|
||||
|
||||
@@ -500,6 +535,14 @@ static void test_safe_atou64(void) {
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 12345);
|
||||
|
||||
+ r = safe_atou64("0o11", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 9);
|
||||
+
|
||||
+ r = safe_atou64("0b11", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 3);
|
||||
+
|
||||
r = safe_atou64("18446744073709551617", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
@@ -542,6 +585,14 @@ static void test_safe_atoi64(void) {
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 32767);
|
||||
|
||||
+ r = safe_atoi64(" 0o20", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 16);
|
||||
+
|
||||
+ r = safe_atoi64(" 0b01010", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 10);
|
||||
+
|
||||
r = safe_atoi64("9223372036854775813", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
@@ -577,6 +628,13 @@ static void test_safe_atoux64(void) {
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 0x12345);
|
||||
|
||||
+ r = safe_atoux64("0b11011", &l);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(l == 11603985);
|
||||
+
|
||||
+ r = safe_atoux64("0o11011", &l);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+
|
||||
r = safe_atoux64("18446744073709551617", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
|
||||
index 99203f7e48..04e86f5ac3 100644
|
||||
--- a/src/test/test-user-util.c
|
||||
+++ b/src/test/test-user-util.c
|
||||
@@ -40,6 +40,22 @@ static void test_parse_uid(void) {
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
+ r = parse_uid("0", &uid);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(uid == 0);
|
||||
+
|
||||
+ r = parse_uid("1", &uid);
|
||||
+ assert_se(r == 0);
|
||||
+ assert_se(uid == 1);
|
||||
+
|
||||
+ r = parse_uid("01", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 1);
|
||||
+
|
||||
+ r = parse_uid("001", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 1);
|
||||
+
|
||||
r = parse_uid("100", &uid);
|
||||
assert_se(r == 0);
|
||||
assert_se(uid == 100);
|
||||
@@ -52,6 +68,14 @@ static void test_parse_uid(void) {
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
+ r = parse_uid("0o1234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("0b1234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
r = parse_uid("+1234", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
@@ -68,6 +92,14 @@ static void test_parse_uid(void) {
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
+ r = parse_uid("001234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("0001234", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
r = parse_uid("-0", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
@@ -76,6 +108,14 @@ static void test_parse_uid(void) {
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
||||
|
||||
+ r = parse_uid("00", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
+ r = parse_uid("000", &uid);
|
||||
+ assert_se(r == -EINVAL);
|
||||
+ assert_se(uid == 100);
|
||||
+
|
||||
r = parse_uid("asdsdas", &uid);
|
||||
assert_se(r == -EINVAL);
|
||||
assert_se(uid == 100);
|
@ -0,0 +1,270 @@
|
||||
From 1e4ec1b29d15684a305bbc9ab54c6c8321504e7b Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Tue, 27 Oct 2020 10:31:05 +0100
|
||||
Subject: [PATCH] shared/user-util: add compat forms of user name checking
|
||||
functions
|
||||
|
||||
New functions are called valid_user_group_name_compat() and
|
||||
valid_user_group_name_or_id_compat() and accept dots in the user
|
||||
or group name. No functional change except the tests.
|
||||
|
||||
(cherry picked from commit 1a29610f5fa1bcb2eeb37d2c6b79d8d1a6dbb865)
|
||||
|
||||
This completes previous partial cherry-pick of the same commit (commit
|
||||
76176de0889c3e8b9b3a176da24e4f8dbbd380a3).
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/user-util.c | 32 +++++++-------
|
||||
src/basic/user-util.h | 16 ++++++-
|
||||
src/test/test-user-util.c | 91 +++++++++++++++++++++++++++++++++++++--
|
||||
3 files changed, 117 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index 40f4e45db6..03cbbc2503 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -576,7 +576,7 @@ int take_etc_passwd_lock(const char *root) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
-bool valid_user_group_name(const char *u) {
|
||||
+bool valid_user_group_name_full(const char *u, bool strict) {
|
||||
const char *i;
|
||||
long sz;
|
||||
|
||||
@@ -585,12 +585,12 @@ bool valid_user_group_name(const char *u) {
|
||||
*
|
||||
* - We require that names fit into the appropriate utmp field
|
||||
* - We don't allow empty user names
|
||||
+ * - No dots or digits in the first character
|
||||
*
|
||||
- * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
|
||||
+ * If strict==true, additionally:
|
||||
+ * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator)
|
||||
*
|
||||
- * jsynacek: We now allow dots in user names. The checks are not exhaustive as user names like "..." are allowed
|
||||
- * and valid according to POSIX, but can't be created using useradd. However, ".user" can be created. Let's not
|
||||
- * complicate the code by adding additional checks for weird corner cases like these, as they don't really matter here.
|
||||
+ * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
|
||||
*/
|
||||
|
||||
if (isempty(u))
|
||||
@@ -598,16 +598,16 @@ bool valid_user_group_name(const char *u) {
|
||||
|
||||
if (!(u[0] >= 'a' && u[0] <= 'z') &&
|
||||
!(u[0] >= 'A' && u[0] <= 'Z') &&
|
||||
- u[0] != '_' && u[0] != '.')
|
||||
+ u[0] != '_')
|
||||
return false;
|
||||
|
||||
- for (i = u+1; *i; i++) {
|
||||
- if (!(*i >= 'a' && *i <= 'z') &&
|
||||
- !(*i >= 'A' && *i <= 'Z') &&
|
||||
- !(*i >= '0' && *i <= '9') &&
|
||||
- !IN_SET(*i, '_', '-', '.'))
|
||||
+ for (i = u+1; *i; i++)
|
||||
+ if (!((*i >= 'a' && *i <= 'z') ||
|
||||
+ (*i >= 'A' && *i <= 'Z') ||
|
||||
+ (*i >= '0' && *i <= '9') ||
|
||||
+ IN_SET(*i, '_', '-') ||
|
||||
+ (!strict && *i == '.')))
|
||||
return false;
|
||||
- }
|
||||
|
||||
sz = sysconf(_SC_LOGIN_NAME_MAX);
|
||||
assert_se(sz > 0);
|
||||
@@ -621,15 +621,15 @@ bool valid_user_group_name(const char *u) {
|
||||
return true;
|
||||
}
|
||||
|
||||
-bool valid_user_group_name_or_id(const char *u) {
|
||||
+bool valid_user_group_name_or_id_full(const char *u, bool strict) {
|
||||
|
||||
- /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right
|
||||
- * range, and not the invalid user ids. */
|
||||
+ /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the
|
||||
+ * right range, and not the invalid user ids. */
|
||||
|
||||
if (isempty(u))
|
||||
return false;
|
||||
|
||||
- if (valid_user_group_name(u))
|
||||
+ if (valid_user_group_name_full(u, strict))
|
||||
return true;
|
||||
|
||||
return parse_uid(u, NULL) >= 0;
|
||||
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
|
||||
index b74f168859..5ad0b2a2f9 100644
|
||||
--- a/src/basic/user-util.h
|
||||
+++ b/src/basic/user-util.h
|
||||
@@ -78,8 +78,20 @@ static inline bool userns_supported(void) {
|
||||
return access("/proc/self/uid_map", F_OK) >= 0;
|
||||
}
|
||||
|
||||
-bool valid_user_group_name(const char *u);
|
||||
-bool valid_user_group_name_or_id(const char *u);
|
||||
+bool valid_user_group_name_full(const char *u, bool strict);
|
||||
+bool valid_user_group_name_or_id_full(const char *u, bool strict);
|
||||
+static inline bool valid_user_group_name(const char *u) {
|
||||
+ return valid_user_group_name_full(u, true);
|
||||
+}
|
||||
+static inline bool valid_user_group_name_or_id(const char *u) {
|
||||
+ return valid_user_group_name_or_id_full(u, true);
|
||||
+}
|
||||
+static inline bool valid_user_group_name_compat(const char *u) {
|
||||
+ return valid_user_group_name_full(u, false);
|
||||
+}
|
||||
+static inline bool valid_user_group_name_or_id_compat(const char *u) {
|
||||
+ return valid_user_group_name_or_id_full(u, false);
|
||||
+}
|
||||
bool valid_gecos(const char *d);
|
||||
bool valid_home(const char *p);
|
||||
|
||||
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
|
||||
index 04e86f5ac3..3a4211655d 100644
|
||||
--- a/src/test/test-user-util.c
|
||||
+++ b/src/test/test-user-util.c
|
||||
@@ -131,6 +131,43 @@ static void test_uid_ptr(void) {
|
||||
assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
|
||||
}
|
||||
|
||||
+static void test_valid_user_group_name_compat(void) {
|
||||
+ log_info("/* %s */", __func__);
|
||||
+
|
||||
+ assert_se(!valid_user_group_name_compat(NULL));
|
||||
+ assert_se(!valid_user_group_name_compat(""));
|
||||
+ assert_se(!valid_user_group_name_compat("1"));
|
||||
+ assert_se(!valid_user_group_name_compat("65535"));
|
||||
+ assert_se(!valid_user_group_name_compat("-1"));
|
||||
+ assert_se(!valid_user_group_name_compat("-kkk"));
|
||||
+ assert_se(!valid_user_group_name_compat("rööt"));
|
||||
+ assert_se(!valid_user_group_name_compat("."));
|
||||
+ assert_se(!valid_user_group_name_compat(".eff"));
|
||||
+ assert_se(!valid_user_group_name_compat("foo\nbar"));
|
||||
+ assert_se(!valid_user_group_name_compat("0123456789012345678901234567890123456789"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("aaa:bbb"));
|
||||
+ assert_se(!valid_user_group_name_compat("."));
|
||||
+ assert_se(!valid_user_group_name_compat(".1"));
|
||||
+ assert_se(!valid_user_group_name_compat(".65535"));
|
||||
+ assert_se(!valid_user_group_name_compat(".-1"));
|
||||
+ assert_se(!valid_user_group_name_compat(".-kkk"));
|
||||
+ assert_se(!valid_user_group_name_compat(".rööt"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat(".aaa:bbb"));
|
||||
+
|
||||
+ assert_se(valid_user_group_name_compat("root"));
|
||||
+ assert_se(valid_user_group_name_compat("lennart"));
|
||||
+ assert_se(valid_user_group_name_compat("LENNART"));
|
||||
+ assert_se(valid_user_group_name_compat("_kkk"));
|
||||
+ assert_se(valid_user_group_name_compat("kkk-"));
|
||||
+ assert_se(valid_user_group_name_compat("kk-k"));
|
||||
+ assert_se(valid_user_group_name_compat("eff.eff"));
|
||||
+ assert_se(valid_user_group_name_compat("eff."));
|
||||
+
|
||||
+ assert_se(valid_user_group_name_compat("some5"));
|
||||
+ assert_se(!valid_user_group_name_compat("5some"));
|
||||
+ assert_se(valid_user_group_name_compat("INNER5NUMBER"));
|
||||
+}
|
||||
+
|
||||
static void test_valid_user_group_name(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
@@ -141,9 +178,18 @@ static void test_valid_user_group_name(void) {
|
||||
assert_se(!valid_user_group_name("-1"));
|
||||
assert_se(!valid_user_group_name("-kkk"));
|
||||
assert_se(!valid_user_group_name("rööt"));
|
||||
+ assert_se(!valid_user_group_name("."));
|
||||
+ assert_se(!valid_user_group_name(".eff"));
|
||||
assert_se(!valid_user_group_name("foo\nbar"));
|
||||
assert_se(!valid_user_group_name("0123456789012345678901234567890123456789"));
|
||||
assert_se(!valid_user_group_name_or_id("aaa:bbb"));
|
||||
+ assert_se(!valid_user_group_name("."));
|
||||
+ assert_se(!valid_user_group_name(".1"));
|
||||
+ assert_se(!valid_user_group_name(".65535"));
|
||||
+ assert_se(!valid_user_group_name(".-1"));
|
||||
+ assert_se(!valid_user_group_name(".-kkk"));
|
||||
+ assert_se(!valid_user_group_name(".rööt"));
|
||||
+ assert_se(!valid_user_group_name_or_id(".aaa:bbb"));
|
||||
|
||||
assert_se(valid_user_group_name("root"));
|
||||
assert_se(valid_user_group_name("lennart"));
|
||||
@@ -151,14 +197,47 @@ static void test_valid_user_group_name(void) {
|
||||
assert_se(valid_user_group_name("_kkk"));
|
||||
assert_se(valid_user_group_name("kkk-"));
|
||||
assert_se(valid_user_group_name("kk-k"));
|
||||
- assert_se(valid_user_group_name(".moo"));
|
||||
- assert_se(valid_user_group_name("eff.eff"));
|
||||
+ assert_se(!valid_user_group_name("eff.eff"));
|
||||
+ assert_se(!valid_user_group_name("eff."));
|
||||
|
||||
assert_se(valid_user_group_name("some5"));
|
||||
assert_se(!valid_user_group_name("5some"));
|
||||
assert_se(valid_user_group_name("INNER5NUMBER"));
|
||||
}
|
||||
|
||||
+static void test_valid_user_group_name_or_id_compat(void) {
|
||||
+ log_info("/* %s */", __func__);
|
||||
+
|
||||
+ assert_se(!valid_user_group_name_or_id_compat(NULL));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat(""));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("0"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("1"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("65534"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("65535"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("65536"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("-1"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("-kkk"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("rööt"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("."));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat(".eff"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("eff.eff"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("eff."));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("foo\nbar"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("0123456789012345678901234567890123456789"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("aaa:bbb"));
|
||||
+
|
||||
+ assert_se(valid_user_group_name_or_id_compat("root"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("lennart"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("LENNART"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("_kkk"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("kkk-"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("kk-k"));
|
||||
+
|
||||
+ assert_se(valid_user_group_name_or_id_compat("some5"));
|
||||
+ assert_se(!valid_user_group_name_or_id_compat("5some"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER"));
|
||||
+}
|
||||
+
|
||||
static void test_valid_user_group_name_or_id(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
@@ -172,6 +251,10 @@ static void test_valid_user_group_name_or_id(void) {
|
||||
assert_se(!valid_user_group_name_or_id("-1"));
|
||||
assert_se(!valid_user_group_name_or_id("-kkk"));
|
||||
assert_se(!valid_user_group_name_or_id("rööt"));
|
||||
+ assert_se(!valid_user_group_name_or_id("."));
|
||||
+ assert_se(!valid_user_group_name_or_id(".eff"));
|
||||
+ assert_se(!valid_user_group_name_or_id("eff.eff"));
|
||||
+ assert_se(!valid_user_group_name_or_id("eff."));
|
||||
assert_se(!valid_user_group_name_or_id("foo\nbar"));
|
||||
assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789"));
|
||||
assert_se(!valid_user_group_name_or_id("aaa:bbb"));
|
||||
@@ -182,8 +265,6 @@ static void test_valid_user_group_name_or_id(void) {
|
||||
assert_se(valid_user_group_name_or_id("_kkk"));
|
||||
assert_se(valid_user_group_name_or_id("kkk-"));
|
||||
assert_se(valid_user_group_name_or_id("kk-k"));
|
||||
- assert_se(valid_user_group_name_or_id(".moo"));
|
||||
- assert_se(valid_user_group_name_or_id("eff.eff"));
|
||||
|
||||
assert_se(valid_user_group_name_or_id("some5"));
|
||||
assert_se(!valid_user_group_name_or_id("5some"));
|
||||
@@ -286,7 +367,9 @@ int main(int argc, char*argv[]) {
|
||||
test_parse_uid();
|
||||
test_uid_ptr();
|
||||
|
||||
+ test_valid_user_group_name_compat();
|
||||
test_valid_user_group_name();
|
||||
+ test_valid_user_group_name_or_id_compat();
|
||||
test_valid_user_group_name_or_id();
|
||||
test_valid_gecos();
|
||||
test_valid_home();
|
@ -0,0 +1,50 @@
|
||||
From fa1fa19951fdadd63f2b5df6224678f91753f260 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Wed, 28 Aug 2019 12:05:52 +0200
|
||||
Subject: [PATCH] shared/user-util: emit a warning on names with dots
|
||||
|
||||
(cherry picked from commit 88e2ed0b5bf6f08f5a2d4d64b1fefdc7192b9aac)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/user-util.c | 27 ++++++++++++++++++++-------
|
||||
1 file changed, 20 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index 03cbbc2503..359da08a83 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -601,13 +601,26 @@ bool valid_user_group_name_full(const char *u, bool strict) {
|
||||
u[0] != '_')
|
||||
return false;
|
||||
|
||||
- for (i = u+1; *i; i++)
|
||||
- if (!((*i >= 'a' && *i <= 'z') ||
|
||||
- (*i >= 'A' && *i <= 'Z') ||
|
||||
- (*i >= '0' && *i <= '9') ||
|
||||
- IN_SET(*i, '_', '-') ||
|
||||
- (!strict && *i == '.')))
|
||||
- return false;
|
||||
+ bool warned = false;
|
||||
+
|
||||
+ for (i = u+1; *i; i++) {
|
||||
+ if (((*i >= 'a' && *i <= 'z') ||
|
||||
+ (*i >= 'A' && *i <= 'Z') ||
|
||||
+ (*i >= '0' && *i <= '9') ||
|
||||
+ IN_SET(*i, '_', '-')))
|
||||
+ continue;
|
||||
+
|
||||
+ if (*i == '.' && !strict) {
|
||||
+ if (!warned) {
|
||||
+ log_warning("Bad user or group name \"%s\", accepting for compatibility.", u);
|
||||
+ warned = true;
|
||||
+ }
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
sz = sysconf(_SC_LOGIN_NAME_MAX);
|
||||
assert_se(sz > 0);
|
103
SOURCES/0471-user-util-Allow-names-starting-with-a-digit.patch
Normal file
103
SOURCES/0471-user-util-Allow-names-starting-with-a-digit.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From f06434cc51eedd72f7d4a640a1fa118f57a5e68e Mon Sep 17 00:00:00 2001
|
||||
From: Balint Reczey <balint.reczey@canonical.com>
|
||||
Date: Wed, 18 Mar 2020 18:29:02 +0100
|
||||
Subject: [PATCH] user-util: Allow names starting with a digit
|
||||
|
||||
In 1a29610f5fa1bcb2eeb37d2c6b79d8d1a6dbb865 the change inadvertedly
|
||||
disabled names with digit as the first character. This follow-up change
|
||||
allows a digit as the first character in compat mode.
|
||||
|
||||
Fixes: #15141
|
||||
(cherry picked from commit 93c23c9297e48e594785e0bb9c51504aae5fbe3e)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/user-util.c | 20 +++++++++++++++++---
|
||||
src/test/test-user-util.c | 4 ++--
|
||||
2 files changed, 19 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index 359da08a83..7dd2bb2c84 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -579,16 +579,18 @@ int take_etc_passwd_lock(const char *root) {
|
||||
bool valid_user_group_name_full(const char *u, bool strict) {
|
||||
const char *i;
|
||||
long sz;
|
||||
+ bool warned = false;
|
||||
|
||||
/* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition,
|
||||
* 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules:
|
||||
*
|
||||
* - We require that names fit into the appropriate utmp field
|
||||
* - We don't allow empty user names
|
||||
- * - No dots or digits in the first character
|
||||
+ * - No dots in the first character
|
||||
*
|
||||
* If strict==true, additionally:
|
||||
* - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator)
|
||||
+ * - We don't allow a digit as the first character
|
||||
*
|
||||
* Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
|
||||
*/
|
||||
@@ -598,17 +600,26 @@ bool valid_user_group_name_full(const char *u, bool strict) {
|
||||
|
||||
if (!(u[0] >= 'a' && u[0] <= 'z') &&
|
||||
!(u[0] >= 'A' && u[0] <= 'Z') &&
|
||||
+ !(u[0] >= '0' && u[0] <= '9' && !strict) &&
|
||||
u[0] != '_')
|
||||
return false;
|
||||
|
||||
- bool warned = false;
|
||||
+ bool only_digits_seen = u[0] >= '0' && u[0] <= '9';
|
||||
+
|
||||
+ if (only_digits_seen) {
|
||||
+ log_warning("User or group name \"%s\" starts with a digit, accepting for compatibility.", u);
|
||||
+ warned = true;
|
||||
+ }
|
||||
|
||||
for (i = u+1; *i; i++) {
|
||||
if (((*i >= 'a' && *i <= 'z') ||
|
||||
(*i >= 'A' && *i <= 'Z') ||
|
||||
(*i >= '0' && *i <= '9') ||
|
||||
- IN_SET(*i, '_', '-')))
|
||||
+ IN_SET(*i, '_', '-'))) {
|
||||
+ if (!(*i >= '0' && *i <= '9'))
|
||||
+ only_digits_seen = false;
|
||||
continue;
|
||||
+ }
|
||||
|
||||
if (*i == '.' && !strict) {
|
||||
if (!warned) {
|
||||
@@ -622,6 +633,9 @@ bool valid_user_group_name_full(const char *u, bool strict) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (only_digits_seen)
|
||||
+ return false;
|
||||
+
|
||||
sz = sysconf(_SC_LOGIN_NAME_MAX);
|
||||
assert_se(sz > 0);
|
||||
|
||||
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
|
||||
index 3a4211655d..56079f1486 100644
|
||||
--- a/src/test/test-user-util.c
|
||||
+++ b/src/test/test-user-util.c
|
||||
@@ -164,7 +164,7 @@ static void test_valid_user_group_name_compat(void) {
|
||||
assert_se(valid_user_group_name_compat("eff."));
|
||||
|
||||
assert_se(valid_user_group_name_compat("some5"));
|
||||
- assert_se(!valid_user_group_name_compat("5some"));
|
||||
+ assert_se(valid_user_group_name_compat("5some"));
|
||||
assert_se(valid_user_group_name_compat("INNER5NUMBER"));
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ static void test_valid_user_group_name_or_id_compat(void) {
|
||||
assert_se(valid_user_group_name_or_id_compat("kk-k"));
|
||||
|
||||
assert_se(valid_user_group_name_or_id_compat("some5"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("5some"));
|
||||
+ assert_se(valid_user_group_name_or_id_compat("5some"));
|
||||
assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER"));
|
||||
}
|
||||
|
@ -0,0 +1,193 @@
|
||||
From 40dff18947fa198810db4cd3e5291349fc84a0e8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Thu, 1 Aug 2019 10:02:14 +0200
|
||||
Subject: [PATCH] shared/user-util: allow usernames with dots in specific
|
||||
fields
|
||||
|
||||
People do have usernames with dots, and it makes them very unhappy that systemd
|
||||
doesn't like their that. It seems that there is no actual problem with allowing
|
||||
dots in the username. In particular chown declares ":" as the official
|
||||
separator, and internally in systemd we never rely on "." as the seperator
|
||||
between user and group (nor do we call chown directly). Using dots in the name
|
||||
is probably not a very good idea, but we don't need to care. Debian tools
|
||||
(adduser) do not allow users with dots to be created.
|
||||
|
||||
This patch allows *existing* names with dots to be used in User, Group,
|
||||
SupplementaryGroups, SocketUser, SocketGroup fields, both in unit files and on
|
||||
the command line. DynamicUsers and sysusers still follow the strict policy.
|
||||
user@.service and tmpfiles already allowed arbitrary user names, and this
|
||||
remains unchanged.
|
||||
|
||||
Fixes #12754.
|
||||
|
||||
(cherry picked from commit ae480f0b09aec815b64579bb1828ea935d8ee236)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/core/dbus-execute.c | 12 ++++++------
|
||||
src/core/dbus-socket.c | 4 ++--
|
||||
src/core/dbus-util.c | 2 +-
|
||||
src/core/dbus-util.h | 2 +-
|
||||
src/core/load-fragment-gperf.gperf.m4 | 10 +++++-----
|
||||
src/core/load-fragment.c | 8 ++++----
|
||||
src/core/load-fragment.h | 4 ++--
|
||||
7 files changed, 21 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index 0fe4c14e48..e004fb55c9 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -1113,10 +1113,10 @@ int bus_exec_context_set_transient_property(
|
||||
flags |= UNIT_PRIVATE;
|
||||
|
||||
if (streq(name, "User"))
|
||||
- return bus_set_transient_user(u, name, &c->user, message, flags, error);
|
||||
+ return bus_set_transient_user_compat(u, name, &c->user, message, flags, error);
|
||||
|
||||
if (streq(name, "Group"))
|
||||
- return bus_set_transient_user(u, name, &c->group, message, flags, error);
|
||||
+ return bus_set_transient_user_compat(u, name, &c->group, message, flags, error);
|
||||
|
||||
if (streq(name, "TTYPath"))
|
||||
return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
|
||||
@@ -1297,10 +1297,10 @@ int bus_exec_context_set_transient_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- STRV_FOREACH(p, l) {
|
||||
- if (!isempty(*p) && !valid_user_group_name_or_id(*p))
|
||||
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
|
||||
- }
|
||||
+ STRV_FOREACH(p, l)
|
||||
+ if (!isempty(*p) && !valid_user_group_name_or_id_compat(*p))
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
+ "Invalid supplementary group names");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (strv_isempty(l)) {
|
||||
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
|
||||
index bb77539030..8fdbc05409 100644
|
||||
--- a/src/core/dbus-socket.c
|
||||
+++ b/src/core/dbus-socket.c
|
||||
@@ -281,10 +281,10 @@ static int bus_socket_set_transient_property(
|
||||
return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error);
|
||||
|
||||
if (streq(name, "SocketUser"))
|
||||
- return bus_set_transient_user(u, name, &s->user, message, flags, error);
|
||||
+ return bus_set_transient_user_compat(u, name, &s->user, message, flags, error);
|
||||
|
||||
if (streq(name, "SocketGroup"))
|
||||
- return bus_set_transient_user(u, name, &s->group, message, flags, error);
|
||||
+ return bus_set_transient_user_compat(u, name, &s->group, message, flags, error);
|
||||
|
||||
if (streq(name, "BindIPv6Only"))
|
||||
return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error);
|
||||
diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c
|
||||
index f4fbb72cb9..7862beaacb 100644
|
||||
--- a/src/core/dbus-util.c
|
||||
+++ b/src/core/dbus-util.c
|
||||
@@ -30,7 +30,7 @@ int bus_property_get_triggered_unit(
|
||||
|
||||
BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o");
|
||||
BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32);
|
||||
-BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user, valid_user_group_name_or_id);
|
||||
+BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user_compat, valid_user_group_name_or_id_compat);
|
||||
BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(path, path_is_absolute);
|
||||
|
||||
int bus_set_transient_string(
|
||||
diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h
|
||||
index 12b055e4ac..a3316c6701 100644
|
||||
--- a/src/core/dbus-util.h
|
||||
+++ b/src/core/dbus-util.h
|
||||
@@ -235,7 +235,7 @@ int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *i
|
||||
|
||||
int bus_set_transient_mode_t(Unit *u, const char *name, mode_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_unsigned(Unit *u, const char *name, unsigned *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
-int bus_set_transient_user(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
+int bus_set_transient_user_compat(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index 24ee5ae6fe..156a4d0a6d 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -25,9 +25,9 @@ m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
|
||||
`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context)
|
||||
$1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory)
|
||||
$1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image)
|
||||
-$1.User, config_parse_user_group, 0, offsetof($1, exec_context.user)
|
||||
-$1.Group, config_parse_user_group, 0, offsetof($1, exec_context.group)
|
||||
-$1.SupplementaryGroups, config_parse_user_group_strv, 0, offsetof($1, exec_context.supplementary_groups)
|
||||
+$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user)
|
||||
+$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group)
|
||||
+$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups)
|
||||
$1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context)
|
||||
$1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context)
|
||||
$1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context)
|
||||
@@ -354,8 +354,8 @@ Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC
|
||||
Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command)
|
||||
Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command)
|
||||
Socket.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Socket, timeout_usec)
|
||||
-Socket.SocketUser, config_parse_user_group, 0, offsetof(Socket, user)
|
||||
-Socket.SocketGroup, config_parse_user_group, 0, offsetof(Socket, group)
|
||||
+Socket.SocketUser, config_parse_user_group_compat, 0, offsetof(Socket, user)
|
||||
+Socket.SocketGroup, config_parse_user_group_compat, 0, offsetof(Socket, group)
|
||||
Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
|
||||
Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
|
||||
Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index 740401a582..ba81d94504 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -1899,7 +1899,7 @@ int config_parse_sec_fix_0(
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int config_parse_user_group(
|
||||
+int config_parse_user_group_compat(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@@ -1932,7 +1932,7 @@ int config_parse_user_group(
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name_or_id(k)) {
|
||||
+ if (!valid_user_group_name_or_id_compat(k)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
@@ -1940,7 +1940,7 @@ int config_parse_user_group(
|
||||
return free_and_replace(*user, k);
|
||||
}
|
||||
|
||||
-int config_parse_user_group_strv(
|
||||
+int config_parse_user_group_strv_compat(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@@ -1986,7 +1986,7 @@ int config_parse_user_group_strv(
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name_or_id(k)) {
|
||||
+ if (!valid_user_group_name_or_id_compat(k)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
|
||||
index 65a94d53cc..f9d34d484d 100644
|
||||
--- a/src/core/load-fragment.h
|
||||
+++ b/src/core/load-fragment.h
|
||||
@@ -96,8 +96,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_utmp_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_working_directory);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_fdname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sec_fix_0);
|
||||
-CONFIG_PARSER_PROTOTYPE(config_parse_user_group);
|
||||
-CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_user_group_compat);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv_compat);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_restrict_namespaces);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_bind_paths);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_keyring_mode);
|
@ -0,0 +1,38 @@
|
||||
From 7569168bea3d7e11cd3afe6167fcf4a3ac65a1a6 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 30 Mar 2020 21:46:01 +0200
|
||||
Subject: [PATCH] user-util: switch order of checks in
|
||||
valid_user_group_name_or_id_full()
|
||||
|
||||
When we are supposed to accept numeric UIDs formatted as string, then
|
||||
let's check that first, before passing things on to
|
||||
valid_user_group_name_full(), since that might log about, and not the
|
||||
other way round.
|
||||
|
||||
See: #15201
|
||||
Follow-up for: 93c23c9297e48e594785e0bb9c51504aae5fbe3e
|
||||
|
||||
(cherry picked from commit a85daa0dfb3eb03be9845760e90e54b9af8fb00e)
|
||||
|
||||
Related: #1848373
|
||||
---
|
||||
src/basic/user-util.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index 7dd2bb2c84..68a924770b 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -656,10 +656,10 @@ bool valid_user_group_name_or_id_full(const char *u, bool strict) {
|
||||
if (isempty(u))
|
||||
return false;
|
||||
|
||||
- if (valid_user_group_name_full(u, strict))
|
||||
+ if (parse_uid(u, NULL) >= 0)
|
||||
return true;
|
||||
|
||||
- return parse_uid(u, NULL) >= 0;
|
||||
+ return valid_user_group_name_full(u, strict);
|
||||
}
|
||||
|
||||
bool valid_gecos(const char *d) {
|
803
SOURCES/0474-user-util-rework-how-we-validate-user-names.patch
Normal file
803
SOURCES/0474-user-util-rework-how-we-validate-user-names.patch
Normal file
@ -0,0 +1,803 @@
|
||||
From 33b851f0c30e47fe71a293e2c990ef26573efe86 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Sat, 4 Apr 2020 12:23:02 +0200
|
||||
Subject: [PATCH] user-util: rework how we validate user names
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This reworks the user validation infrastructure. There are now two
|
||||
modes. In regular mode we are strict and test against a strict set of
|
||||
valid chars. And in "relaxed" mode we just filter out some really
|
||||
obvious, dangerous stuff. i.e. strict is whitelisting what is OK, but
|
||||
"relaxed" is blacklisting what is really not OK.
|
||||
|
||||
The idea is that we use strict mode whenver we allocate a new user
|
||||
(i.e. in sysusers.d or homed), while "relaxed" mode is when we process
|
||||
users registered elsewhere, (i.e. userdb, logind, …)
|
||||
|
||||
The requirements on user name validity vary wildly. SSSD thinks its fine
|
||||
to embedd "@" for example, while the suggested NAME_REGEX field on
|
||||
Debian does not even allow uppercase chars…
|
||||
|
||||
This effectively liberaralizes a lot what we expect from usernames.
|
||||
|
||||
The code that warns about questionnable user names is now optional and
|
||||
only used at places such as unit file parsing, so that it doesn't show
|
||||
up on every userdb query, but only when processing configuration files
|
||||
that know better.
|
||||
|
||||
Fixes: #15149 #15090
|
||||
(cherry picked from commit 7a8867abfab10e5bbca10590ec2aa40c5b27d8fb)
|
||||
|
||||
Resolves: #1848373
|
||||
---
|
||||
src/basic/user-util.c | 185 +++++++++++++----------
|
||||
src/basic/user-util.h | 21 +--
|
||||
src/core/dbus-execute.c | 6 +-
|
||||
src/core/dbus-manager.c | 2 +-
|
||||
src/core/dbus-socket.c | 4 +-
|
||||
src/core/dbus-util.c | 7 +-
|
||||
src/core/dbus-util.h | 2 +-
|
||||
src/core/dynamic-user.c | 2 +-
|
||||
src/core/load-fragment.c | 4 +-
|
||||
src/core/unit.c | 2 +-
|
||||
src/nss-systemd/nss-systemd.c | 6 +-
|
||||
src/systemd/sd-messages.h | 3 +
|
||||
src/sysusers/sysusers.c | 4 +-
|
||||
src/test/test-user-util.c | 271 ++++++++++++++++++----------------
|
||||
14 files changed, 287 insertions(+), 232 deletions(-)
|
||||
|
||||
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
|
||||
index 68a924770b..cd870c4361 100644
|
||||
--- a/src/basic/user-util.c
|
||||
+++ b/src/basic/user-util.c
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
+#include "sd-messages.h"
|
||||
+
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@@ -576,92 +578,125 @@ int take_etc_passwd_lock(const char *root) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
-bool valid_user_group_name_full(const char *u, bool strict) {
|
||||
+bool valid_user_group_name(const char *u, ValidUserFlags flags) {
|
||||
const char *i;
|
||||
- long sz;
|
||||
- bool warned = false;
|
||||
|
||||
- /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition,
|
||||
- * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules:
|
||||
- *
|
||||
- * - We require that names fit into the appropriate utmp field
|
||||
- * - We don't allow empty user names
|
||||
- * - No dots in the first character
|
||||
+ /* Checks if the specified name is a valid user/group name. There are two flavours of this call:
|
||||
+ * strict mode is the default which is POSIX plus some extra rules; and relaxed mode where we accept
|
||||
+ * pretty much everything except the really worst offending names.
|
||||
*
|
||||
- * If strict==true, additionally:
|
||||
- * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator)
|
||||
- * - We don't allow a digit as the first character
|
||||
- *
|
||||
- * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
|
||||
- */
|
||||
+ * Whenever we synthesize users ourselves we should use the strict mode. But when we process users
|
||||
+ * created by other stuff, let's be more liberal. */
|
||||
|
||||
- if (isempty(u))
|
||||
+ if (isempty(u)) /* An empty user name is never valid */
|
||||
return false;
|
||||
|
||||
- if (!(u[0] >= 'a' && u[0] <= 'z') &&
|
||||
- !(u[0] >= 'A' && u[0] <= 'Z') &&
|
||||
- !(u[0] >= '0' && u[0] <= '9' && !strict) &&
|
||||
- u[0] != '_')
|
||||
- return false;
|
||||
-
|
||||
- bool only_digits_seen = u[0] >= '0' && u[0] <= '9';
|
||||
-
|
||||
- if (only_digits_seen) {
|
||||
- log_warning("User or group name \"%s\" starts with a digit, accepting for compatibility.", u);
|
||||
- warned = true;
|
||||
- }
|
||||
-
|
||||
- for (i = u+1; *i; i++) {
|
||||
- if (((*i >= 'a' && *i <= 'z') ||
|
||||
- (*i >= 'A' && *i <= 'Z') ||
|
||||
- (*i >= '0' && *i <= '9') ||
|
||||
- IN_SET(*i, '_', '-'))) {
|
||||
- if (!(*i >= '0' && *i <= '9'))
|
||||
- only_digits_seen = false;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (*i == '.' && !strict) {
|
||||
- if (!warned) {
|
||||
- log_warning("Bad user or group name \"%s\", accepting for compatibility.", u);
|
||||
- warned = true;
|
||||
- }
|
||||
-
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ if (parse_uid(u, NULL) >= 0) /* Something that parses as numeric UID string is valid exactly when the
|
||||
+ * flag for it is set */
|
||||
+ return FLAGS_SET(flags, VALID_USER_ALLOW_NUMERIC);
|
||||
+
|
||||
+ if (FLAGS_SET(flags, VALID_USER_RELAX)) {
|
||||
+
|
||||
+ /* In relaxed mode we just check very superficially. Apparently SSSD and other stuff is
|
||||
+ * extremely liberal (way too liberal if you ask me, even inserting "@" in user names, which
|
||||
+ * is bound to cause problems for example when used with an MTA), hence only filter the most
|
||||
+ * obvious cases, or where things would result in an invalid entry if such a user name would
|
||||
+ * show up in /etc/passwd (or equivalent getent output).
|
||||
+ *
|
||||
+ * Note that we stepped far out of POSIX territory here. It's not our fault though, but
|
||||
+ * SSSD's, Samba's and everybody else who ignored POSIX on this. (I mean, I am happy to step
|
||||
+ * outside of POSIX' bounds any day, but I must say in this case I probably wouldn't
|
||||
+ * have...) */
|
||||
+
|
||||
+ if (startswith(u, " ") || endswith(u, " ")) /* At least expect whitespace padding is removed
|
||||
+ * at front and back (accept in the middle, since
|
||||
+ * that's apparently a thing on Windows). Note
|
||||
+ * that this also blocks usernames consisting of
|
||||
+ * whitespace only. */
|
||||
+ return false;
|
||||
+
|
||||
+ if (!utf8_is_valid(u)) /* We want to synthesize JSON from this, hence insist on UTF-8 */
|
||||
+ return false;
|
||||
+
|
||||
+ if (string_has_cc(u, NULL)) /* CC characters are just dangerous (and \n in particular is the
|
||||
+ * record separator in /etc/passwd), so we can't allow that. */
|
||||
+ return false;
|
||||
+
|
||||
+ if (strpbrk(u, ":/")) /* Colons are the field separator in /etc/passwd, we can't allow
|
||||
+ * that. Slashes are special to file systems paths and user names
|
||||
+ * typically show up in the file system as home directories, hence
|
||||
+ * don't allow slashes. */
|
||||
+ return false;
|
||||
+
|
||||
+ if (in_charset(u, "0123456789")) /* Don't allow fully numeric strings, they might be confused
|
||||
+ * with with UIDs (note that this test is more broad than
|
||||
+ * the parse_uid() test above, as it will cover more than
|
||||
+ * the 32bit range, and it will detect 65535 (which is in
|
||||
+ * invalid UID, even though in the unsigned 32 bit range) */
|
||||
+ return false;
|
||||
+
|
||||
+ if (u[0] == '-' && in_charset(u + 1, "0123456789")) /* Don't allow negative fully numeric
|
||||
+ * strings either. After all some people
|
||||
+ * write 65535 as -1 (even though that's
|
||||
+ * not even true on 32bit uid_t
|
||||
+ * anyway) */
|
||||
+ return false;
|
||||
+
|
||||
+ if (dot_or_dot_dot(u)) /* User names typically become home directory names, and these two are
|
||||
+ * special in that context, don't allow that. */
|
||||
+ return false;
|
||||
+
|
||||
+ /* Compare with strict result and warn if result doesn't match */
|
||||
+ if (FLAGS_SET(flags, VALID_USER_WARN) && !valid_user_group_name(u, 0))
|
||||
+ log_struct(LOG_NOTICE,
|
||||
+ "MESSAGE=Accepting user/group name '%s', which does not match strict user/group name rules.", u,
|
||||
+ "USER_GROUP_NAME=%s", u,
|
||||
+ "MESSAGE_ID=" SD_MESSAGE_UNSAFE_USER_NAME_STR);
|
||||
+
|
||||
+ /* Note that we make no restrictions on the length in relaxed mode! */
|
||||
+ } else {
|
||||
+ long sz;
|
||||
+ size_t l;
|
||||
+
|
||||
+ /* Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, 3.437. We are a bit stricter here
|
||||
+ * however. Specifically we deviate from POSIX rules:
|
||||
+ *
|
||||
+ * - We don't allow empty user names (see above)
|
||||
+ * - We require that names fit into the appropriate utmp field
|
||||
+ * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator)
|
||||
+ * - We don't allow dashes or digit as the first character
|
||||
+ *
|
||||
+ * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
|
||||
+ */
|
||||
+
|
||||
+ if (!(u[0] >= 'a' && u[0] <= 'z') &&
|
||||
+ !(u[0] >= 'A' && u[0] <= 'Z') &&
|
||||
+ u[0] != '_')
|
||||
+ return false;
|
||||
+
|
||||
+ for (i = u+1; *i; i++)
|
||||
+ if (!(*i >= 'a' && *i <= 'z') &&
|
||||
+ !(*i >= 'A' && *i <= 'Z') &&
|
||||
+ !(*i >= '0' && *i <= '9') &&
|
||||
+ !IN_SET(*i, '_', '-'))
|
||||
+ return false;
|
||||
+
|
||||
+ l = i - u;
|
||||
+
|
||||
+ sz = sysconf(_SC_LOGIN_NAME_MAX);
|
||||
+ assert_se(sz > 0);
|
||||
+
|
||||
+ if (l > (size_t) sz)
|
||||
+ return false;
|
||||
+ if (l > FILENAME_MAX)
|
||||
+ return false;
|
||||
+ if (l > UT_NAMESIZE - 1)
|
||||
+ return false;
|
||||
}
|
||||
|
||||
- if (only_digits_seen)
|
||||
- return false;
|
||||
-
|
||||
- sz = sysconf(_SC_LOGIN_NAME_MAX);
|
||||
- assert_se(sz > 0);
|
||||
-
|
||||
- if ((size_t) (i-u) > (size_t) sz)
|
||||
- return false;
|
||||
-
|
||||
- if ((size_t) (i-u) > UT_NAMESIZE - 1)
|
||||
- return false;
|
||||
-
|
||||
return true;
|
||||
}
|
||||
|
||||
-bool valid_user_group_name_or_id_full(const char *u, bool strict) {
|
||||
-
|
||||
- /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the
|
||||
- * right range, and not the invalid user ids. */
|
||||
-
|
||||
- if (isempty(u))
|
||||
- return false;
|
||||
-
|
||||
- if (parse_uid(u, NULL) >= 0)
|
||||
- return true;
|
||||
-
|
||||
- return valid_user_group_name_full(u, strict);
|
||||
-}
|
||||
-
|
||||
bool valid_gecos(const char *d) {
|
||||
|
||||
if (!d)
|
||||
diff --git a/src/basic/user-util.h b/src/basic/user-util.h
|
||||
index 5ad0b2a2f9..939bded40d 100644
|
||||
--- a/src/basic/user-util.h
|
||||
+++ b/src/basic/user-util.h
|
||||
@@ -78,20 +78,13 @@ static inline bool userns_supported(void) {
|
||||
return access("/proc/self/uid_map", F_OK) >= 0;
|
||||
}
|
||||
|
||||
-bool valid_user_group_name_full(const char *u, bool strict);
|
||||
-bool valid_user_group_name_or_id_full(const char *u, bool strict);
|
||||
-static inline bool valid_user_group_name(const char *u) {
|
||||
- return valid_user_group_name_full(u, true);
|
||||
-}
|
||||
-static inline bool valid_user_group_name_or_id(const char *u) {
|
||||
- return valid_user_group_name_or_id_full(u, true);
|
||||
-}
|
||||
-static inline bool valid_user_group_name_compat(const char *u) {
|
||||
- return valid_user_group_name_full(u, false);
|
||||
-}
|
||||
-static inline bool valid_user_group_name_or_id_compat(const char *u) {
|
||||
- return valid_user_group_name_or_id_full(u, false);
|
||||
-}
|
||||
+typedef enum ValidUserFlags {
|
||||
+ VALID_USER_RELAX = 1 << 0,
|
||||
+ VALID_USER_WARN = 1 << 1,
|
||||
+ VALID_USER_ALLOW_NUMERIC = 1 << 2,
|
||||
+} ValidUserFlags;
|
||||
+
|
||||
+bool valid_user_group_name(const char *u, ValidUserFlags flags);
|
||||
bool valid_gecos(const char *d);
|
||||
bool valid_home(const char *p);
|
||||
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index e004fb55c9..8348663000 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -1113,10 +1113,10 @@ int bus_exec_context_set_transient_property(
|
||||
flags |= UNIT_PRIVATE;
|
||||
|
||||
if (streq(name, "User"))
|
||||
- return bus_set_transient_user_compat(u, name, &c->user, message, flags, error);
|
||||
+ return bus_set_transient_user_relaxed(u, name, &c->user, message, flags, error);
|
||||
|
||||
if (streq(name, "Group"))
|
||||
- return bus_set_transient_user_compat(u, name, &c->group, message, flags, error);
|
||||
+ return bus_set_transient_user_relaxed(u, name, &c->group, message, flags, error);
|
||||
|
||||
if (streq(name, "TTYPath"))
|
||||
return bus_set_transient_path(u, name, &c->tty_path, message, flags, error);
|
||||
@@ -1298,7 +1298,7 @@ int bus_exec_context_set_transient_property(
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(p, l)
|
||||
- if (!isempty(*p) && !valid_user_group_name_or_id_compat(*p))
|
||||
+ if (!isempty(*p) && !valid_user_group_name(*p, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Invalid supplementary group names");
|
||||
|
||||
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
|
||||
index 0a1d3df42f..7488f22116 100644
|
||||
--- a/src/core/dbus-manager.c
|
||||
+++ b/src/core/dbus-manager.c
|
||||
@@ -1762,7 +1762,7 @@ static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *use
|
||||
|
||||
if (!MANAGER_IS_SYSTEM(m))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance.");
|
||||
- if (!valid_user_group_name(name))
|
||||
+ if (!valid_user_group_name(name, VALID_USER_RELAX))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name);
|
||||
|
||||
r = dynamic_user_lookup_name(m, name, &uid);
|
||||
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
|
||||
index 8fdbc05409..fa6bbe2c6f 100644
|
||||
--- a/src/core/dbus-socket.c
|
||||
+++ b/src/core/dbus-socket.c
|
||||
@@ -281,10 +281,10 @@ static int bus_socket_set_transient_property(
|
||||
return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error);
|
||||
|
||||
if (streq(name, "SocketUser"))
|
||||
- return bus_set_transient_user_compat(u, name, &s->user, message, flags, error);
|
||||
+ return bus_set_transient_user_relaxed(u, name, &s->user, message, flags, error);
|
||||
|
||||
if (streq(name, "SocketGroup"))
|
||||
- return bus_set_transient_user_compat(u, name, &s->group, message, flags, error);
|
||||
+ return bus_set_transient_user_relaxed(u, name, &s->group, message, flags, error);
|
||||
|
||||
if (streq(name, "BindIPv6Only"))
|
||||
return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error);
|
||||
diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c
|
||||
index 7862beaacb..951450e53d 100644
|
||||
--- a/src/core/dbus-util.c
|
||||
+++ b/src/core/dbus-util.c
|
||||
@@ -30,7 +30,12 @@ int bus_property_get_triggered_unit(
|
||||
|
||||
BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o");
|
||||
BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32);
|
||||
-BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user_compat, valid_user_group_name_or_id_compat);
|
||||
+
|
||||
+static inline bool valid_user_group_name_or_id_relaxed(const char *u) {
|
||||
+ return valid_user_group_name(u, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX);
|
||||
+}
|
||||
+
|
||||
+BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user_relaxed, valid_user_group_name_or_id_relaxed);
|
||||
BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(path, path_is_absolute);
|
||||
|
||||
int bus_set_transient_string(
|
||||
diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h
|
||||
index a3316c6701..713b464dd9 100644
|
||||
--- a/src/core/dbus-util.h
|
||||
+++ b/src/core/dbus-util.h
|
||||
@@ -235,7 +235,7 @@ int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *i
|
||||
|
||||
int bus_set_transient_mode_t(Unit *u, const char *name, mode_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_unsigned(Unit *u, const char *name, unsigned *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
-int bus_set_transient_user_compat(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
+int bus_set_transient_user_relaxed(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c
|
||||
index 021fd93a76..548b3cc9df 100644
|
||||
--- a/src/core/dynamic-user.c
|
||||
+++ b/src/core/dynamic-user.c
|
||||
@@ -108,7 +108,7 @@ static int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name_or_id(name))
|
||||
+ if (!valid_user_group_name(name, VALID_USER_ALLOW_NUMERIC))
|
||||
return -EINVAL;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, storage_socket) < 0)
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index ba81d94504..e0d7b8f7f8 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -1932,7 +1932,7 @@ int config_parse_user_group_compat(
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name_or_id_compat(k)) {
|
||||
+ if (!valid_user_group_name(k, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
@@ -1986,7 +1986,7 @@ int config_parse_user_group_strv_compat(
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name_or_id_compat(k)) {
|
||||
+ if (!valid_user_group_name(k, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index ffbf3cfd48..cd3e7c806d 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -4088,7 +4088,7 @@ static int user_from_unit_name(Unit *u, char **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- if (valid_user_group_name(n)) {
|
||||
+ if (valid_user_group_name(n, 0)) {
|
||||
*ret = TAKE_PTR(n);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
|
||||
index f8db27ae27..615c710257 100644
|
||||
--- a/src/nss-systemd/nss-systemd.c
|
||||
+++ b/src/nss-systemd/nss-systemd.c
|
||||
@@ -123,7 +123,7 @@ static int direct_lookup_uid(uid_t uid, char **ret) {
|
||||
r = readlink_malloc(path, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
- if (!valid_user_group_name(s)) { /* extra safety check */
|
||||
+ if (!valid_user_group_name(s, VALID_USER_RELAX)) { /* extra safety check */
|
||||
free(s);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ enum nss_status _nss_systemd_getpwnam_r(
|
||||
|
||||
/* If the username is not valid, then we don't know it. Ideally libc would filter these for us anyway. We don't
|
||||
* generate EINVAL here, because it isn't really out business to complain about invalid user names. */
|
||||
- if (!valid_user_group_name(name))
|
||||
+ if (!valid_user_group_name(name, VALID_USER_RELAX))
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
|
||||
/* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */
|
||||
@@ -356,7 +356,7 @@ enum nss_status _nss_systemd_getgrnam_r(
|
||||
assert(name);
|
||||
assert(gr);
|
||||
|
||||
- if (!valid_user_group_name(name))
|
||||
+ if (!valid_user_group_name(name, VALID_USER_RELAX))
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
|
||||
/* Synthesize records for root and nobody, in case they are missing form /etc/group */
|
||||
diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h
|
||||
index bdd4fd3974..847b698ba4 100644
|
||||
--- a/src/systemd/sd-messages.h
|
||||
+++ b/src/systemd/sd-messages.h
|
||||
@@ -152,6 +152,9 @@ _SD_BEGIN_DECLARATIONS;
|
||||
#define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57)
|
||||
#define SD_MESSAGE_DNSSEC_DOWNGRADE_STR SD_ID128_MAKE_STR(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57)
|
||||
|
||||
+#define SD_MESSAGE_UNSAFE_USER_NAME SD_ID128_MAKE(b6,1f,da,c6,12,e9,4b,91,82,28,5b,99,88,43,06,1f)
|
||||
+#define SD_MESSAGE_UNSAFE_USER_NAME_STR SD_ID128_MAKE_STR(b6,1f,da,c6,12,e9,4b,91,82,28,5b,99,88,43,06,1f)
|
||||
+
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
#endif
|
||||
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
|
||||
index 33959d3c11..a374ebaaf4 100644
|
||||
--- a/src/sysusers/sysusers.c
|
||||
+++ b/src/sysusers/sysusers.c
|
||||
@@ -1413,7 +1413,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name(resolved_name)) {
|
||||
+ if (!valid_user_group_name(resolved_name, 0)) {
|
||||
log_error("[%s:%u] '%s' is not a valid user or group name.", fname, line, resolved_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1524,7 +1524,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (!valid_user_group_name(resolved_id)) {
|
||||
+ if (!valid_user_group_name(resolved_id, 0)) {
|
||||
log_error("[%s:%u] '%s' is not a valid user or group name.", fname, line, resolved_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
|
||||
index 56079f1486..31ac018da9 100644
|
||||
--- a/src/test/test-user-util.c
|
||||
+++ b/src/test/test-user-util.c
|
||||
@@ -131,144 +131,163 @@ static void test_uid_ptr(void) {
|
||||
assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000);
|
||||
}
|
||||
|
||||
-static void test_valid_user_group_name_compat(void) {
|
||||
+static void test_valid_user_group_name_relaxed(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
- assert_se(!valid_user_group_name_compat(NULL));
|
||||
- assert_se(!valid_user_group_name_compat(""));
|
||||
- assert_se(!valid_user_group_name_compat("1"));
|
||||
- assert_se(!valid_user_group_name_compat("65535"));
|
||||
- assert_se(!valid_user_group_name_compat("-1"));
|
||||
- assert_se(!valid_user_group_name_compat("-kkk"));
|
||||
- assert_se(!valid_user_group_name_compat("rööt"));
|
||||
- assert_se(!valid_user_group_name_compat("."));
|
||||
- assert_se(!valid_user_group_name_compat(".eff"));
|
||||
- assert_se(!valid_user_group_name_compat("foo\nbar"));
|
||||
- assert_se(!valid_user_group_name_compat("0123456789012345678901234567890123456789"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("aaa:bbb"));
|
||||
- assert_se(!valid_user_group_name_compat("."));
|
||||
- assert_se(!valid_user_group_name_compat(".1"));
|
||||
- assert_se(!valid_user_group_name_compat(".65535"));
|
||||
- assert_se(!valid_user_group_name_compat(".-1"));
|
||||
- assert_se(!valid_user_group_name_compat(".-kkk"));
|
||||
- assert_se(!valid_user_group_name_compat(".rööt"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat(".aaa:bbb"));
|
||||
-
|
||||
- assert_se(valid_user_group_name_compat("root"));
|
||||
- assert_se(valid_user_group_name_compat("lennart"));
|
||||
- assert_se(valid_user_group_name_compat("LENNART"));
|
||||
- assert_se(valid_user_group_name_compat("_kkk"));
|
||||
- assert_se(valid_user_group_name_compat("kkk-"));
|
||||
- assert_se(valid_user_group_name_compat("kk-k"));
|
||||
- assert_se(valid_user_group_name_compat("eff.eff"));
|
||||
- assert_se(valid_user_group_name_compat("eff."));
|
||||
-
|
||||
- assert_se(valid_user_group_name_compat("some5"));
|
||||
- assert_se(valid_user_group_name_compat("5some"));
|
||||
- assert_se(valid_user_group_name_compat("INNER5NUMBER"));
|
||||
+ assert_se(!valid_user_group_name(NULL, VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("1", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("65535", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("-1", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("foo\nbar", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name(".aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name(".", VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("..", VALID_USER_RELAX));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("root", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("lennart", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("LENNART", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("_kkk", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("kkk-", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("kk-k", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("eff.eff", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("eff.", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("-kkk", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("rööt", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".eff", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".1", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".65535", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".-1", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".-kkk", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".rööt", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("...", VALID_USER_RELAX));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("some5", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("5some", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_RELAX));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("Dāvis", VALID_USER_RELAX));
|
||||
}
|
||||
|
||||
static void test_valid_user_group_name(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
- assert_se(!valid_user_group_name(NULL));
|
||||
- assert_se(!valid_user_group_name(""));
|
||||
- assert_se(!valid_user_group_name("1"));
|
||||
- assert_se(!valid_user_group_name("65535"));
|
||||
- assert_se(!valid_user_group_name("-1"));
|
||||
- assert_se(!valid_user_group_name("-kkk"));
|
||||
- assert_se(!valid_user_group_name("rööt"));
|
||||
- assert_se(!valid_user_group_name("."));
|
||||
- assert_se(!valid_user_group_name(".eff"));
|
||||
- assert_se(!valid_user_group_name("foo\nbar"));
|
||||
- assert_se(!valid_user_group_name("0123456789012345678901234567890123456789"));
|
||||
- assert_se(!valid_user_group_name_or_id("aaa:bbb"));
|
||||
- assert_se(!valid_user_group_name("."));
|
||||
- assert_se(!valid_user_group_name(".1"));
|
||||
- assert_se(!valid_user_group_name(".65535"));
|
||||
- assert_se(!valid_user_group_name(".-1"));
|
||||
- assert_se(!valid_user_group_name(".-kkk"));
|
||||
- assert_se(!valid_user_group_name(".rööt"));
|
||||
- assert_se(!valid_user_group_name_or_id(".aaa:bbb"));
|
||||
-
|
||||
- assert_se(valid_user_group_name("root"));
|
||||
- assert_se(valid_user_group_name("lennart"));
|
||||
- assert_se(valid_user_group_name("LENNART"));
|
||||
- assert_se(valid_user_group_name("_kkk"));
|
||||
- assert_se(valid_user_group_name("kkk-"));
|
||||
- assert_se(valid_user_group_name("kk-k"));
|
||||
- assert_se(!valid_user_group_name("eff.eff"));
|
||||
- assert_se(!valid_user_group_name("eff."));
|
||||
-
|
||||
- assert_se(valid_user_group_name("some5"));
|
||||
- assert_se(!valid_user_group_name("5some"));
|
||||
- assert_se(valid_user_group_name("INNER5NUMBER"));
|
||||
+ assert_se(!valid_user_group_name(NULL, 0));
|
||||
+ assert_se(!valid_user_group_name("", 0));
|
||||
+ assert_se(!valid_user_group_name("1", 0));
|
||||
+ assert_se(!valid_user_group_name("65535", 0));
|
||||
+ assert_se(!valid_user_group_name("-1", 0));
|
||||
+ assert_se(!valid_user_group_name("-kkk", 0));
|
||||
+ assert_se(!valid_user_group_name("rööt", 0));
|
||||
+ assert_se(!valid_user_group_name(".", 0));
|
||||
+ assert_se(!valid_user_group_name(".eff", 0));
|
||||
+ assert_se(!valid_user_group_name("foo\nbar", 0));
|
||||
+ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", 0));
|
||||
+ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name(".", 0));
|
||||
+ assert_se(!valid_user_group_name("..", 0));
|
||||
+ assert_se(!valid_user_group_name("...", 0));
|
||||
+ assert_se(!valid_user_group_name(".1", 0));
|
||||
+ assert_se(!valid_user_group_name(".65535", 0));
|
||||
+ assert_se(!valid_user_group_name(".-1", 0));
|
||||
+ assert_se(!valid_user_group_name(".-kkk", 0));
|
||||
+ assert_se(!valid_user_group_name(".rööt", 0));
|
||||
+ assert_se(!valid_user_group_name(".aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("root", 0));
|
||||
+ assert_se(valid_user_group_name("lennart", 0));
|
||||
+ assert_se(valid_user_group_name("LENNART", 0));
|
||||
+ assert_se(valid_user_group_name("_kkk", 0));
|
||||
+ assert_se(valid_user_group_name("kkk-", 0));
|
||||
+ assert_se(valid_user_group_name("kk-k", 0));
|
||||
+ assert_se(!valid_user_group_name("eff.eff", 0));
|
||||
+ assert_se(!valid_user_group_name("eff.", 0));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("some5", 0));
|
||||
+ assert_se(!valid_user_group_name("5some", 0));
|
||||
+ assert_se(valid_user_group_name("INNER5NUMBER", 0));
|
||||
+
|
||||
+ assert_se(!valid_user_group_name("piff.paff@ad.domain.example", 0));
|
||||
+ assert_se(!valid_user_group_name("Dāvis", 0));
|
||||
}
|
||||
|
||||
-static void test_valid_user_group_name_or_id_compat(void) {
|
||||
+static void test_valid_user_group_name_or_numeric_relaxed(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
- assert_se(!valid_user_group_name_or_id_compat(NULL));
|
||||
- assert_se(!valid_user_group_name_or_id_compat(""));
|
||||
- assert_se(valid_user_group_name_or_id_compat("0"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("1"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("65534"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("65535"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("65536"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("-1"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("-kkk"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("rööt"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("."));
|
||||
- assert_se(!valid_user_group_name_or_id_compat(".eff"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("eff.eff"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("eff."));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("foo\nbar"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("0123456789012345678901234567890123456789"));
|
||||
- assert_se(!valid_user_group_name_or_id_compat("aaa:bbb"));
|
||||
-
|
||||
- assert_se(valid_user_group_name_or_id_compat("root"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("lennart"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("LENNART"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("_kkk"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("kkk-"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("kk-k"));
|
||||
-
|
||||
- assert_se(valid_user_group_name_or_id_compat("some5"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("5some"));
|
||||
- assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER"));
|
||||
+ assert_se(!valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(!valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
+ assert_se(valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX));
|
||||
}
|
||||
|
||||
-static void test_valid_user_group_name_or_id(void) {
|
||||
+static void test_valid_user_group_name_or_numeric(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
- assert_se(!valid_user_group_name_or_id(NULL));
|
||||
- assert_se(!valid_user_group_name_or_id(""));
|
||||
- assert_se(valid_user_group_name_or_id("0"));
|
||||
- assert_se(valid_user_group_name_or_id("1"));
|
||||
- assert_se(valid_user_group_name_or_id("65534"));
|
||||
- assert_se(!valid_user_group_name_or_id("65535"));
|
||||
- assert_se(valid_user_group_name_or_id("65536"));
|
||||
- assert_se(!valid_user_group_name_or_id("-1"));
|
||||
- assert_se(!valid_user_group_name_or_id("-kkk"));
|
||||
- assert_se(!valid_user_group_name_or_id("rööt"));
|
||||
- assert_se(!valid_user_group_name_or_id("."));
|
||||
- assert_se(!valid_user_group_name_or_id(".eff"));
|
||||
- assert_se(!valid_user_group_name_or_id("eff.eff"));
|
||||
- assert_se(!valid_user_group_name_or_id("eff."));
|
||||
- assert_se(!valid_user_group_name_or_id("foo\nbar"));
|
||||
- assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789"));
|
||||
- assert_se(!valid_user_group_name_or_id("aaa:bbb"));
|
||||
-
|
||||
- assert_se(valid_user_group_name_or_id("root"));
|
||||
- assert_se(valid_user_group_name_or_id("lennart"));
|
||||
- assert_se(valid_user_group_name_or_id("LENNART"));
|
||||
- assert_se(valid_user_group_name_or_id("_kkk"));
|
||||
- assert_se(valid_user_group_name_or_id("kkk-"));
|
||||
- assert_se(valid_user_group_name_or_id("kk-k"));
|
||||
-
|
||||
- assert_se(valid_user_group_name_or_id("some5"));
|
||||
- assert_se(!valid_user_group_name_or_id("5some"));
|
||||
- assert_se(valid_user_group_name_or_id("INNER5NUMBER"));
|
||||
+ assert_se(!valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC));
|
||||
+
|
||||
+ assert_se(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC));
|
||||
+
|
||||
+ assert_se(!valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC));
|
||||
+ assert_se(!valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC));
|
||||
}
|
||||
|
||||
static void test_valid_gecos(void) {
|
||||
@@ -367,10 +386,10 @@ int main(int argc, char*argv[]) {
|
||||
test_parse_uid();
|
||||
test_uid_ptr();
|
||||
|
||||
- test_valid_user_group_name_compat();
|
||||
+ test_valid_user_group_name_relaxed();
|
||||
test_valid_user_group_name();
|
||||
- test_valid_user_group_name_or_id_compat();
|
||||
- test_valid_user_group_name_or_id();
|
||||
+ test_valid_user_group_name_or_numeric_relaxed();
|
||||
+ test_valid_user_group_name_or_numeric();
|
||||
test_valid_gecos();
|
||||
test_valid_home();
|
||||
|
@ -0,0 +1,35 @@
|
||||
From 11a9ea82827d7b57dbce307b77ef8233a4cc028a Mon Sep 17 00:00:00 2001
|
||||
From: Lukas Nykryn <lnykryn@redhat.com>
|
||||
Date: Thu, 28 Aug 2014 15:12:10 +0200
|
||||
Subject: [PATCH] man: mention System Administrator's Guide in systemctl
|
||||
manpage
|
||||
|
||||
(cherry picked from commit d4582346f47064de24470b5f92e418966004925f)
|
||||
|
||||
Resolves: #1623116
|
||||
---
|
||||
man/systemctl.xml | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/man/systemctl.xml b/man/systemctl.xml
|
||||
index fa08ab6c0a..56f94d084c 100644
|
||||
--- a/man/systemctl.xml
|
||||
+++ b/man/systemctl.xml
|
||||
@@ -2000,6 +2000,17 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<xi:include href="less-variables.xml" xpointer="lesscharset"/>
|
||||
</refsect1>
|
||||
|
||||
+ <refsect1>
|
||||
+ <title>Examples</title>
|
||||
+ <para>
|
||||
+ For examples how to use systemctl in comparsion
|
||||
+ with old service and chkconfig command please see:
|
||||
+ <ulink url="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sect-Managing_Services_with_systemd-Services.html">
|
||||
+ Managing System Services
|
||||
+ </ulink>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
257
SOURCES/0476-udev-introduce-udev-net_id-naming-schemes.patch
Normal file
257
SOURCES/0476-udev-introduce-udev-net_id-naming-schemes.patch
Normal file
@ -0,0 +1,257 @@
|
||||
From 08ac9f7f55c138678c6415139e7510a05a75b81d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Wed, 14 Oct 2020 16:57:44 +0200
|
||||
Subject: [PATCH] udev: introduce udev net_id "naming schemes"
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
With this we can stabilize how naming works for network interfaces. A
|
||||
user can request through a kernel cmdline option or an env var which
|
||||
scheme to follow. The idea is that installers use this to set into stone
|
||||
(a very soft stone though) the scheme used during installation so that
|
||||
interface naming doesn't change afterwards anymore.
|
||||
|
||||
Why use env vars and kernel cmdline options, and not a config file of
|
||||
its own?
|
||||
|
||||
Well, first of all there's no obvious existing one to use. But more
|
||||
importantly: I have the feeling that this logic is kind of an incomplete
|
||||
hack, and I simply don't want to do advertise this as a perfectly
|
||||
working solution. So far we used env vars for the non-so-official
|
||||
options and proper config files for the official stuff. Given how
|
||||
incomplete this logic is (i.e. the big variable for naming remains the
|
||||
kernel, which might expose sysfs attributes in newer versions that we
|
||||
check for and didn't exist in older versions — and other problems like
|
||||
this), I am simply not confident in giving this first-class exposure in
|
||||
a primary configuration file.
|
||||
|
||||
Fixes: #10448
|
||||
|
||||
(cherry-picked from commit f7e81fd96fdfe0ac6dcdb72de43f7cb4720e363a)
|
||||
|
||||
Related: #1827462
|
||||
|
||||
[msekleta: note that we are introducing our own naming schemes based on
|
||||
RHEL-8 minor versions. Also we are not backporting all naming scheme
|
||||
features that appeared in the original commit. We are backporting only
|
||||
features relevant for v239 while original commit also converted
|
||||
changes introduced in v240 into naming scheme flags.]
|
||||
---
|
||||
doc/ENVIRONMENT.md | 9 +++
|
||||
man/kernel-command-line.xml | 1 +
|
||||
man/systemd-udevd.service.xml | 16 +++++
|
||||
src/udev/udev-builtin-net_id.c | 106 ++++++++++++++++++++++++++++++++-
|
||||
4 files changed, 130 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
|
||||
index 39a36a52cc..1a4aa01ef4 100644
|
||||
--- a/doc/ENVIRONMENT.md
|
||||
+++ b/doc/ENVIRONMENT.md
|
||||
@@ -76,6 +76,15 @@ systemd-logind:
|
||||
hibernation is available even if the swap devices do not provide enough room
|
||||
for it.
|
||||
|
||||
+* `$NET_NAMING_SCHEME=` – if set, takes a network naming scheme (i.e. one of
|
||||
+ v238, v239, v240 …) as parameter. If specified udev's net_id builtin will
|
||||
+ follow the specified naming scheme when determining stable network interface
|
||||
+ names. This may be used to revert to naming schemes of older udev versions,
|
||||
+ in order to provide more stable naming across updates. This environment
|
||||
+ variable takes precedence over the kernel command line option
|
||||
+ `net.naming-scheme=`, except if the value is prefixed with `:` in which case
|
||||
+ the kernel command line option takes precedence, if it is specified as well.
|
||||
+
|
||||
installed systemd tests:
|
||||
|
||||
* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if
|
||||
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
|
||||
index 4d8cb4e50e..b753d0592c 100644
|
||||
--- a/man/kernel-command-line.xml
|
||||
+++ b/man/kernel-command-line.xml
|
||||
@@ -246,6 +246,7 @@
|
||||
<term><varname>udev.event_timeout=</varname></term>
|
||||
<term><varname>rd.udev.event_timeout=</varname></term>
|
||||
<term><varname>net.ifnames=</varname></term>
|
||||
+ <term><varname>net.naming-scheme=</varname></term>
|
||||
|
||||
<listitem>
|
||||
<para>Parameters understood by the device event managing
|
||||
diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml
|
||||
index 73c77ea690..6449103441 100644
|
||||
--- a/man/systemd-udevd.service.xml
|
||||
+++ b/man/systemd-udevd.service.xml
|
||||
@@ -170,6 +170,22 @@
|
||||
when possible. It is enabled by default; specifying 0 disables it.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><varname>net.naming-scheme=</varname></term>
|
||||
+ <listitem>
|
||||
+ <para>Network interfaces are renamed to give them predictable names when possible (unless
|
||||
+ <varname>net.ifnames=0</varname> is specified, see above). The names are derived from various device metadata
|
||||
+ fields. Newer versions of <filename>systemd-udevd.service</filename> take more of these fields into account,
|
||||
+ improving (and thus possibly changing) the names used for the same devices. With this kernel command line
|
||||
+ option it is possible to pick a specific version of this algorithm. It expects a naming scheme identifier as
|
||||
+ argument. Currently the following identifiers are known: <literal>v238</literal>, <literal>v239</literal>,
|
||||
+ <literal>v240</literal> which each implement the naming scheme that was the default in the indicated systemd
|
||||
+ version. Note that selecting a specific scheme is not sufficient to fully stabilize interface naming: the
|
||||
+ naming is generally derived from driver attributes exposed by the kernel. As the kernel is updated,
|
||||
+ previously missing attributes <filename>systemd-udevd.service</filename> is checking might appear, which
|
||||
+ affects older name derivation algorithms, too.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
</variablelist>
|
||||
<!-- when adding entries here, consider also adding them
|
||||
in kernel-command-line.xml -->
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index 147e04ab8c..148696183e 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -96,6 +96,7 @@
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "parse-util.h"
|
||||
+#include "proc-cmdline.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "udev.h"
|
||||
@@ -103,6 +104,52 @@
|
||||
|
||||
#define ONBOARD_INDEX_MAX (16*1024-1)
|
||||
|
||||
+/* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we
|
||||
+ * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are
|
||||
+ * contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out
|
||||
+ * of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new
|
||||
+ * flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via
|
||||
+ * a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow:
|
||||
+ * installers could "freeze" the used scheme at the moment of installation this way.
|
||||
+ *
|
||||
+ * Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with
|
||||
+ * it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags.
|
||||
+ *
|
||||
+ * Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the
|
||||
+ * kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually
|
||||
+ * do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across
|
||||
+ * OS versions, but not fully stabilize them. */
|
||||
+typedef enum NamingSchemeFlags {
|
||||
+ /* First, the individual features */
|
||||
+ NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
|
||||
+ NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
|
||||
+
|
||||
+ /* And now the masks that combine the features above */
|
||||
+ NAMING_V238 = 0,
|
||||
+ NAMING_V239 = NAMING_V238|NAMING_SR_IOV_V|NAMING_NPAR_ARI,
|
||||
+ NAMING_RHEL_8_0 = NAMING_V239,
|
||||
+ NAMING_RHEL_8_1 = NAMING_V239,
|
||||
+ NAMING_RHEL_8_2 = NAMING_V239,
|
||||
+ NAMING_RHEL_8_3 = NAMING_V239,
|
||||
+
|
||||
+ _NAMING_SCHEME_FLAGS_INVALID = -1,
|
||||
+} NamingSchemeFlags;
|
||||
+
|
||||
+typedef struct NamingScheme {
|
||||
+ const char *name;
|
||||
+ NamingSchemeFlags flags;
|
||||
+} NamingScheme;
|
||||
+
|
||||
+static const NamingScheme naming_schemes[] = {
|
||||
+ { "v238", NAMING_V238 },
|
||||
+ { "v239", NAMING_V239 },
|
||||
+ { "rhel-8.0", NAMING_RHEL_8_0 },
|
||||
+ { "rhel-8.1", NAMING_RHEL_8_1 },
|
||||
+ { "rhel-8.2", NAMING_RHEL_8_2 },
|
||||
+ { "rhel-8.3", NAMING_RHEL_8_3 },
|
||||
+ /* … add more schemes here, as the logic to name devices is updated … */
|
||||
+};
|
||||
+
|
||||
enum netname_type{
|
||||
NET_UNDEF,
|
||||
NET_PCI,
|
||||
@@ -138,6 +185,56 @@ struct virtfn_info {
|
||||
char suffix[IFNAMSIZ];
|
||||
};
|
||||
|
||||
+static const NamingScheme* naming_scheme(void) {
|
||||
+ static const NamingScheme *cache = NULL;
|
||||
+ _cleanup_free_ char *buffer = NULL;
|
||||
+ const char *e, *k;
|
||||
+
|
||||
+ if (cache)
|
||||
+ return cache;
|
||||
+
|
||||
+ /* Acquire setting from the kernel command line */
|
||||
+ (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer);
|
||||
+
|
||||
+ /* Also acquire it from an env var */
|
||||
+ e = getenv("NET_NAMING_SCHEME");
|
||||
+ if (e) {
|
||||
+ if (*e == ':') {
|
||||
+ /* If prefixed with ':' the kernel cmdline takes precedence */
|
||||
+ k = buffer ?: e + 1;
|
||||
+ } else
|
||||
+ k = e; /* Otherwise the env var takes precedence */
|
||||
+ } else
|
||||
+ k = buffer;
|
||||
+
|
||||
+ if (k) {
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
|
||||
+ if (streq(naming_schemes[i].name, k)) {
|
||||
+ cache = naming_schemes + i;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!cache)
|
||||
+ log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
|
||||
+ }
|
||||
+
|
||||
+ if (cache)
|
||||
+ log_info("Using interface naming scheme '%s'.", cache->name);
|
||||
+ else {
|
||||
+ /* RHEL-only: here we differ from the upstream and if no naming scheme was selected we default to naming from systemd-239 */
|
||||
+ cache = &naming_schemes[2];
|
||||
+ log_info("Using default interface naming scheme '%s'.", cache->name);
|
||||
+ }
|
||||
+
|
||||
+ return cache;
|
||||
+}
|
||||
+
|
||||
+static bool naming_scheme_has(NamingSchemeFlags flags) {
|
||||
+ return FLAGS_SET(naming_scheme()->flags, flags);
|
||||
+}
|
||||
+
|
||||
/* skip intermediate virtio devices */
|
||||
static struct udev_device *skip_virtio(struct udev_device *dev) {
|
||||
struct udev_device *parent = dev;
|
||||
@@ -299,7 +396,9 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
|
||||
|
||||
if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4)
|
||||
return -ENOENT;
|
||||
- if (is_pci_ari_enabled(names->pcidev))
|
||||
+
|
||||
+ if (naming_scheme_has(NAMING_NPAR_ARI) &&
|
||||
+ is_pci_ari_enabled(names->pcidev))
|
||||
/* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
|
||||
* traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
|
||||
* where the slot makes up the upper 5 bits. */
|
||||
@@ -494,7 +593,8 @@ static int names_pci(struct udev_device *dev, struct netnames *names) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
- if (get_virtfn_info(dev, names, &vf_info) >= 0) {
|
||||
+ if (naming_scheme_has(NAMING_SR_IOV_V) &&
|
||||
+ get_virtfn_info(dev, names, &vf_info) >= 0) {
|
||||
/* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
|
||||
vf_names.pcidev = vf_info.physfn_pcidev;
|
||||
dev_pci_onboard(dev, &vf_names);
|
||||
@@ -741,6 +841,8 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool
|
||||
prefix = "ww";
|
||||
}
|
||||
|
||||
+ udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name);
|
||||
+
|
||||
err = names_mac(dev, &names);
|
||||
if (err >= 0 && names.mac_valid) {
|
||||
char str[IFNAMSIZ];
|
@ -0,0 +1,188 @@
|
||||
From 8c263758fe196624005f19bd6f46d63e3841c5be Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Tue, 11 Dec 2018 23:28:29 +0100
|
||||
Subject: [PATCH] meson: make net.naming-scheme= default configurable
|
||||
|
||||
This is useful for distributions, where the stability of interface names should
|
||||
be preseved after an upgrade of systemd. So when some specific release of the
|
||||
distro is made available, systemd defaults to the latest & greatest naming
|
||||
scheme, and subsequent updates set the same default. This default may still
|
||||
be overriden through the kernel and env var options.
|
||||
|
||||
A special value "latest" is also allowed. Without a specific name, it is harder
|
||||
to verride from meson. In case of 'combo' options, meson reads the default
|
||||
during the initial configuration, and "remembers" this choice. When systemd is
|
||||
updated, old build/ directories could keep the old default, which would be
|
||||
annoying. Hence, "latest" is introduced to make it explicit, yet follow the
|
||||
upstream. This is actually useful for the user too, because it may be used
|
||||
as an override, without having to actually specify a version.
|
||||
|
||||
(cherry picked from commit 06da5c63dd697ea4087e76c6d809b60b5780b87c)
|
||||
|
||||
Related: #1827462
|
||||
|
||||
[msekleta: note that our default is not latest but rhel-8.0]
|
||||
---
|
||||
doc/ENVIRONMENT.md | 15 +++++++-------
|
||||
man/systemd-udevd.service.xml | 24 ++++++++++++---------
|
||||
meson.build | 4 ++++
|
||||
meson_options.txt | 3 +++
|
||||
src/udev/udev-builtin-net_id.c | 38 ++++++++++++++++++++--------------
|
||||
5 files changed, 51 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
|
||||
index 1a4aa01ef4..0e763b6302 100644
|
||||
--- a/doc/ENVIRONMENT.md
|
||||
+++ b/doc/ENVIRONMENT.md
|
||||
@@ -77,13 +77,14 @@ systemd-logind:
|
||||
for it.
|
||||
|
||||
* `$NET_NAMING_SCHEME=` – if set, takes a network naming scheme (i.e. one of
|
||||
- v238, v239, v240 …) as parameter. If specified udev's net_id builtin will
|
||||
- follow the specified naming scheme when determining stable network interface
|
||||
- names. This may be used to revert to naming schemes of older udev versions,
|
||||
- in order to provide more stable naming across updates. This environment
|
||||
- variable takes precedence over the kernel command line option
|
||||
- `net.naming-scheme=`, except if the value is prefixed with `:` in which case
|
||||
- the kernel command line option takes precedence, if it is specified as well.
|
||||
+ "rhel-8.0", "rhel-8.1", "rhel-8.2"…, or the special value "latest") as
|
||||
+ parameter. If specified udev's net_id builtin will follow the specified
|
||||
+ naming scheme when determining stable network interface names. This may be
|
||||
+ used to revert to naming schemes of older udev versions, in order to provide
|
||||
+ more stable naming across updates. This environment variable takes precedence
|
||||
+ over the kernel command line option `net.naming-scheme=`, except if the value
|
||||
+ is prefixed with `:` in which case the kernel command line option takes
|
||||
+ precedence, if it is specified as well.
|
||||
|
||||
installed systemd tests:
|
||||
|
||||
diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml
|
||||
index 6449103441..b738591c93 100644
|
||||
--- a/man/systemd-udevd.service.xml
|
||||
+++ b/man/systemd-udevd.service.xml
|
||||
@@ -174,16 +174,20 @@
|
||||
<term><varname>net.naming-scheme=</varname></term>
|
||||
<listitem>
|
||||
<para>Network interfaces are renamed to give them predictable names when possible (unless
|
||||
- <varname>net.ifnames=0</varname> is specified, see above). The names are derived from various device metadata
|
||||
- fields. Newer versions of <filename>systemd-udevd.service</filename> take more of these fields into account,
|
||||
- improving (and thus possibly changing) the names used for the same devices. With this kernel command line
|
||||
- option it is possible to pick a specific version of this algorithm. It expects a naming scheme identifier as
|
||||
- argument. Currently the following identifiers are known: <literal>v238</literal>, <literal>v239</literal>,
|
||||
- <literal>v240</literal> which each implement the naming scheme that was the default in the indicated systemd
|
||||
- version. Note that selecting a specific scheme is not sufficient to fully stabilize interface naming: the
|
||||
- naming is generally derived from driver attributes exposed by the kernel. As the kernel is updated,
|
||||
- previously missing attributes <filename>systemd-udevd.service</filename> is checking might appear, which
|
||||
- affects older name derivation algorithms, too.</para>
|
||||
+ <varname>net.ifnames=0</varname> is specified, see above). The names are derived from various
|
||||
+ device metadata fields. Newer versions of <filename>systemd-udevd.service</filename> take more of
|
||||
+ these fields into account, improving (and thus possibly changing) the names used for the same
|
||||
+ devices. With this kernel command line option it is possible to pick a specific version of this
|
||||
+ algorithm. It expects a naming scheme identifier as argument. Currently the following identifiers
|
||||
+ are known: <literal>rhel-8.0</literal>, <literal>rhel-8.1</literal>, <literal>rhel-8.2</literal>,
|
||||
+ <literal>rhel-8.3</literal> which each implement the naming scheme that was the default in the
|
||||
+ indicated Red Hat Enterprise Linux minor version. In addition, <literal>latest</literal> may be
|
||||
+ used to designate the latest scheme known (to this particular version of
|
||||
+ <filename>systemd-udevd.service</filename>).</para>
|
||||
+ <para>Note that selecting a specific scheme is not sufficient to fully stabilize interface naming:
|
||||
+ the naming is generally derived from driver attributes exposed by the kernel. As the kernel is
|
||||
+ updated, previously missing attributes <filename>systemd-udevd.service</filename> is checking might
|
||||
+ appear, which affects older name derivation algorithms, too.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 65c1d0785e..57de947367 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -639,6 +639,9 @@ else
|
||||
conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_ALL')
|
||||
endif
|
||||
|
||||
+default_net_naming_scheme = get_option('default-net-naming-scheme')
|
||||
+conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme)
|
||||
+
|
||||
time_epoch = get_option('time-epoch')
|
||||
if time_epoch == ''
|
||||
NEWS = files('NEWS')
|
||||
@@ -2925,6 +2928,7 @@ status = [
|
||||
'default DNSSEC mode: @0@'.format(default_dnssec),
|
||||
'default DNS-over-TLS mode: @0@'.format(default_dns_over_tls),
|
||||
'default cgroup hierarchy: @0@'.format(default_hierarchy),
|
||||
+ 'default net.naming-scheme setting: @0@'.format(default_net_naming_scheme),
|
||||
'default KillUserProcesses setting: @0@'.format(kill_user_processes)]
|
||||
|
||||
alt_dns_servers = '\n '.join(dns_servers.split(' '))
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index 0996891177..213079ac15 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -158,6 +158,9 @@ option('default-hierarchy', type : 'combo',
|
||||
description : 'default cgroup hierarchy')
|
||||
option('time-epoch', type : 'string',
|
||||
description : 'time epoch for time clients')
|
||||
+option('default-net-naming-scheme', type : 'combo',
|
||||
+ choices : ['rhel-8.0', 'rhel-8.1', 'rhel-8.2', 'rhel-8.3', 'latest'],
|
||||
+ description : 'default net.naming-scheme= value')
|
||||
option('system-uid-max', type : 'string',
|
||||
description : 'maximum system UID')
|
||||
option('system-gid-max', type : 'string',
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index 148696183e..d85dc2848b 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -185,6 +185,19 @@ struct virtfn_info {
|
||||
char suffix[IFNAMSIZ];
|
||||
};
|
||||
|
||||
+static const NamingScheme* naming_scheme_from_name(const char *name) {
|
||||
+ size_t i;
|
||||
+
|
||||
+ if (streq(name, "latest"))
|
||||
+ return naming_schemes + ELEMENTSOF(naming_schemes) - 1;
|
||||
+
|
||||
+ for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
|
||||
+ if (streq(naming_schemes[i].name, name))
|
||||
+ return naming_schemes + i;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static const NamingScheme* naming_scheme(void) {
|
||||
static const NamingScheme *cache = NULL;
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
@@ -208,25 +221,18 @@ static const NamingScheme* naming_scheme(void) {
|
||||
k = buffer;
|
||||
|
||||
if (k) {
|
||||
- size_t i;
|
||||
-
|
||||
- for (i = 0; i < ELEMENTSOF(naming_schemes); i++)
|
||||
- if (streq(naming_schemes[i].name, k)) {
|
||||
- cache = naming_schemes + i;
|
||||
- break;
|
||||
- }
|
||||
+ cache = naming_scheme_from_name(k);
|
||||
+ if (cache) {
|
||||
+ log_info("Using interface naming scheme '%s'.", cache->name);
|
||||
+ return cache;
|
||||
+ }
|
||||
|
||||
- if (!cache)
|
||||
- log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
|
||||
+ log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k);
|
||||
}
|
||||
|
||||
- if (cache)
|
||||
- log_info("Using interface naming scheme '%s'.", cache->name);
|
||||
- else {
|
||||
- /* RHEL-only: here we differ from the upstream and if no naming scheme was selected we default to naming from systemd-239 */
|
||||
- cache = &naming_schemes[2];
|
||||
- log_info("Using default interface naming scheme '%s'.", cache->name);
|
||||
- }
|
||||
+ cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME);
|
||||
+ assert(cache);
|
||||
+ log_info("Using default interface naming scheme '%s'.", cache->name);
|
||||
|
||||
return cache;
|
||||
}
|
522
SOURCES/0478-man-describe-naming-schemes-in-a-new-man-page.patch
Normal file
522
SOURCES/0478-man-describe-naming-schemes-in-a-new-man-page.patch
Normal file
@ -0,0 +1,522 @@
|
||||
From af528dcffaab1efea760395cc6676fe4b01e89b5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Thu, 9 May 2019 12:34:30 +0200
|
||||
Subject: [PATCH] man: describe naming schemes in a new man page
|
||||
|
||||
I decided to make this a separate man page because it is freakin' long.
|
||||
This content could equally well go in systemd-udevd.service(8), systemd.link(5),
|
||||
or a new man page for the net_id builtin.
|
||||
|
||||
v2:
|
||||
- rename to systemd.net-naming-scheme
|
||||
- add udevadm test-builtin net_id example
|
||||
|
||||
(cherry picked from commit 0b1e5b6ed8c6b9a2bc53709eb75e381d360f05bf)
|
||||
|
||||
Related: #1827462
|
||||
|
||||
[msekleta: I've removed parts that describe features which are not
|
||||
available in RHEL-8]
|
||||
---
|
||||
man/rules/meson.build | 1 +
|
||||
man/systemd-udevd.service.xml | 19 +-
|
||||
man/systemd.link.xml | 10 +-
|
||||
man/systemd.net-naming-scheme.xml | 385 ++++++++++++++++++++++++++++++
|
||||
src/udev/udev-builtin-net_id.c | 1 +
|
||||
5 files changed, 402 insertions(+), 14 deletions(-)
|
||||
create mode 100644 man/systemd.net-naming-scheme.xml
|
||||
|
||||
diff --git a/man/rules/meson.build b/man/rules/meson.build
|
||||
index 7ae94ea265..e6c0a99bbd 100644
|
||||
--- a/man/rules/meson.build
|
||||
+++ b/man/rules/meson.build
|
||||
@@ -714,6 +714,7 @@ manpages = [
|
||||
['systemd.kill', '5', [], ''],
|
||||
['systemd.link', '5', [], ''],
|
||||
['systemd.mount', '5', [], ''],
|
||||
+ ['systemd.net-naming-scheme', '7', [], ''],
|
||||
['systemd.netdev', '5', [], 'ENABLE_NETWORKD'],
|
||||
['systemd.network', '5', [], 'ENABLE_NETWORKD'],
|
||||
['systemd.nspawn', '5', [], ''],
|
||||
diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml
|
||||
index b738591c93..f4cdb2f1e7 100644
|
||||
--- a/man/systemd-udevd.service.xml
|
||||
+++ b/man/systemd-udevd.service.xml
|
||||
@@ -174,15 +174,11 @@
|
||||
<term><varname>net.naming-scheme=</varname></term>
|
||||
<listitem>
|
||||
<para>Network interfaces are renamed to give them predictable names when possible (unless
|
||||
- <varname>net.ifnames=0</varname> is specified, see above). The names are derived from various
|
||||
- device metadata fields. Newer versions of <filename>systemd-udevd.service</filename> take more of
|
||||
- these fields into account, improving (and thus possibly changing) the names used for the same
|
||||
- devices. With this kernel command line option it is possible to pick a specific version of this
|
||||
- algorithm. It expects a naming scheme identifier as argument. Currently the following identifiers
|
||||
- are known: <literal>rhel-8.0</literal>, <literal>rhel-8.1</literal>, <literal>rhel-8.2</literal>,
|
||||
- <literal>rhel-8.3</literal> which each implement the naming scheme that was the default in the
|
||||
- indicated Red Hat Enterprise Linux minor version. In addition, <literal>latest</literal> may be
|
||||
- used to designate the latest scheme known (to this particular version of
|
||||
+ <varname>net.ifnames=0</varname> is specified, see above). With this kernel command line option it
|
||||
+ is possible to pick a specific version of this algorithm and override the default chosen at
|
||||
+ compilation time. Expects one of the naming scheme identifiers listed in
|
||||
+ <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||
+ or <literal>latest</literal> to select the latest scheme known (to this particular version of
|
||||
<filename>systemd-udevd.service</filename>).</para>
|
||||
<para>Note that selecting a specific scheme is not sufficient to fully stabilize interface naming:
|
||||
the naming is generally derived from driver attributes exposed by the kernel. As the kernel is
|
||||
@@ -191,9 +187,8 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
- <!-- when adding entries here, consider also adding them
|
||||
- in kernel-command-line.xml -->
|
||||
- </refsect1>
|
||||
+ <!-- when adding entries here, consider also adding them in kernel-command-line.xml -->
|
||||
+ </refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
diff --git a/man/systemd.link.xml b/man/systemd.link.xml
|
||||
index 6708753e82..32657308d0 100644
|
||||
--- a/man/systemd.link.xml
|
||||
+++ b/man/systemd.link.xml
|
||||
@@ -286,6 +286,7 @@
|
||||
<para>The name is set based on information given by
|
||||
the firmware for on-board devices, as exported by the
|
||||
udev property <literal>ID_NET_NAME_ONBOARD</literal>.
|
||||
+ See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -295,6 +296,7 @@
|
||||
<para>The name is set based on information given by
|
||||
the firmware for hot-plug devices, as exported by the
|
||||
udev property <literal>ID_NET_NAME_SLOT</literal>.
|
||||
+ See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -303,7 +305,9 @@
|
||||
<listitem>
|
||||
<para>The name is set based on the device's physical
|
||||
location, as exported by the udev property
|
||||
- <literal>ID_NET_NAME_PATH</literal>.</para>
|
||||
+ <literal>ID_NET_NAME_PATH</literal>.
|
||||
+ See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
+ </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@@ -311,7 +315,9 @@
|
||||
<listitem>
|
||||
<para>The name is set based on the device's persistent
|
||||
MAC address, as exported by the udev property
|
||||
- <literal>ID_NET_NAME_MAC</literal>.</para>
|
||||
+ <literal>ID_NET_NAME_MAC</literal>.
|
||||
+ See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
|
||||
+ </para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
|
||||
new file mode 100644
|
||||
index 0000000000..a12cc3c460
|
||||
--- /dev/null
|
||||
+++ b/man/systemd.net-naming-scheme.xml
|
||||
@@ -0,0 +1,385 @@
|
||||
+<?xml version='1.0'?>
|
||||
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
|
||||
+
|
||||
+<refentry id="systemd.net-naming-scheme">
|
||||
+ <refentryinfo>
|
||||
+ <title>systemd.net-naming-scheme</title>
|
||||
+ <productname>systemd</productname>
|
||||
+ </refentryinfo>
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>systemd.net-naming-scheme</refentrytitle>
|
||||
+ <manvolnum>7</manvolnum>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv>
|
||||
+ <refname>systemd.net-naming-scheme</refname>
|
||||
+ <refpurpose>Network device naming schemes</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>Description</title>
|
||||
+
|
||||
+ <para>Network interfaces may be renamed to give them predictable names when there's enough information to
|
||||
+ generate appropriate names and the use of certain types of names is configured. This page describes the
|
||||
+ first part, i.e. what possible names may be generated. Those names are generated by the
|
||||
+ <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
+ builtin <command>net_id</command> and exported as udev properties
|
||||
+ (<varname>ID_NET_NAME_ONBOARD=</varname>, <varname>ID_NET_LABEL_ONBOARD=</varname>,
|
||||
+ <varname>ID_NET_NAME_PATH=</varname>, <varname>ID_NET_NAME_SLOT=</varname>).</para>
|
||||
+
|
||||
+ <para>Names are derived from various device metadata attributes. Newer versions of udev take more of
|
||||
+ these attributes into account, improving (and thus possibly changing) the names used for the same
|
||||
+ devices. Differents version of the naming rules are called "naming schemes". The default naming scheme is
|
||||
+ chosen at compilation time. Usually this will be the latest implemented version, but it is also possible
|
||||
+ to set one of the older versions to preserve compatibility. This may be useful for example for
|
||||
+ distributions, which may introduce new versions of systemd in stable releases without changing the naming
|
||||
+ scheme. The naming scheme may also be overriden using the <varname>net.naming-scheme=</varname> kernel
|
||||
+ command line switch, see
|
||||
+ <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
+ Available naming schemes are described below.</para>
|
||||
+
|
||||
+ <para>After the udev proprties have been generated, appropriate udev rules may be used to actually rename
|
||||
+ devices based on those properties. See the description of <varname>NamePolicy=</varname> in
|
||||
+ <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>Naming</title>
|
||||
+
|
||||
+ <para>All names start with a two-character prefix that signifies the interface type.</para>
|
||||
+
|
||||
+ <table>
|
||||
+ <title>Two character prefixes based on the type of interface</title>
|
||||
+
|
||||
+ <tgroup cols='2'>
|
||||
+ <thead>
|
||||
+ <row>
|
||||
+ <entry>Prefix</entry>
|
||||
+ <entry>Description</entry>
|
||||
+ </row>
|
||||
+ </thead>
|
||||
+ <tbody>
|
||||
+ <row>
|
||||
+ <entry><constant>en</constant></entry>
|
||||
+ <entry>Ethernet</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry><constant>sl</constant></entry>
|
||||
+ <entry>serial line IP (slip)</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry><constant>wl</constant></entry>
|
||||
+ <entry>Wireless local area network (WLAN)</entry>
|
||||
+ </row>
|
||||
+ <row>
|
||||
+ <entry><constant>ww</constant></entry>
|
||||
+ <entry>Wireless wide area network (WWAN)</entry>
|
||||
+ </row>
|
||||
+ </tbody>
|
||||
+ </tgroup>
|
||||
+ </table>
|
||||
+
|
||||
+ <para>The udev <command>net_id</command> builtin exports the following udev device properties:</para>
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ID_NET_NAME_ONBOARD=<replaceable>prefix</replaceable><constant>o</constant><replaceable>number</replaceable></varname></term>
|
||||
+
|
||||
+ <listitem><para>This name is set based on the ordering information given by the firmware for
|
||||
+ on-board devices. The name consists of the prefix, letter <constant>o</constant>, and a number
|
||||
+ specified by the firmware. This is only available for PCI devices.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ID_NET_LABEL_ONBOARD=<replaceable>prefix</replaceable> <replaceable>label</replaceable></varname></term>
|
||||
+
|
||||
+ <listitem><para>This property is set based on label given by the firmware for on-board devices. The
|
||||
+ name consists of the prefix concatenated with the label. This is only available for PCI devices.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ID_NET_NAME_MAC=<replaceable>prefix</replaceable><constant>x</constant><replaceable>AABBCCDDEEFF</replaceable></varname></term>
|
||||
+
|
||||
+ <listitem><para>This name consists of the prefix, letter <constant>x</constant>, and 12 hexadecimal
|
||||
+ digits of the MAC address. It is available if the device has a fixed MAC address. Because this name
|
||||
+ is based on an attribute of the card itself, it remains "stable" when the device is moved (even
|
||||
+ between machines), but will change when the hardware is replaced.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]</varname></term>
|
||||
+ <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
|
||||
+ <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
|
||||
+ <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>v</constant><replaceable>slot</replaceable></varname></term>
|
||||
+
|
||||
+ <listitem><para>This property describes the slot position. Different schemes are used depending on
|
||||
+ the bus type, as described in the table below. In all cases, PCI slot information must be known. In
|
||||
+ case of USB, BCMA, and SR-VIO devices, the full name consists of the prefix, PCI slot identifier,
|
||||
+ and USB or BCMA or SR-VIO slot identifier. The first two parts are denoted as "…" in the table
|
||||
+ below.</para>
|
||||
+
|
||||
+ <table>
|
||||
+ <title>Slot naming schemes</title>
|
||||
+
|
||||
+ <tgroup cols='2'>
|
||||
+ <thead>
|
||||
+ <row>
|
||||
+ <entry>Format</entry>
|
||||
+ <entry>Description</entry>
|
||||
+ </row>
|
||||
+ </thead>
|
||||
+
|
||||
+ <tbody>
|
||||
+ <row>
|
||||
+ <entry><replaceable>prefix</replaceable> [<constant>P</constant><replaceable>domain</replaceable>] <constant>s</constant><replaceable>slot</replaceable> [<constant>f</constant><replaceable>function</replaceable>] [<constant>n</constant><replaceable>port_name</replaceable> | <constant>d</constant><replaceable>dev_port</replaceable>]</entry>
|
||||
+ <entry>PCI slot number</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry>… <constant>b</constant><replaceable>number</replaceable></entry>
|
||||
+ <entry>Broadcom bus (BCMA) core number</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry>… <constant>u</constant><replaceable>port</replaceable>… [<constant>c</constant><replaceable>config</replaceable>] [<constant>i</constant><replaceable>interface</replaceable>]</entry>
|
||||
+ <entry>USB port number chain</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry>… <constant>v</constant><replaceable>slot</replaceable></entry>
|
||||
+ <entry>SR-VIO slot number</entry>
|
||||
+ </row>
|
||||
+ </tbody>
|
||||
+ </tgroup>
|
||||
+ </table>
|
||||
+
|
||||
+ <para>The PCI domain is only prepended when it is not 0. All multi-function PCI devices will carry
|
||||
+ the <constant>f<replaceable>function</replaceable></constant> number in the device name, including
|
||||
+ the function 0 device. For non-multi-function devices, the number is suppressed if 0. The port name
|
||||
+ <replaceable>port_name</replaceable> is used, or the port number
|
||||
+ <constant>d</constant><replaceable>dev_port</replaceable> if the name is not known.</para>
|
||||
+
|
||||
+ <para>For BCMA devices, the core number is suppressed when 0.</para>
|
||||
+
|
||||
+ <para>For USB devices the full chain of port numbers of hubs is composed. If the name gets longer
|
||||
+ than the maximum number of 15 characters, the name is not exported. The usual USB configuration
|
||||
+ number 1 and interface number 0 values are suppressed.</para>
|
||||
+ </listitem>
|
||||
+
|
||||
+ <para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
|
||||
+ <constant>v</constant> and the virtual device number, with any leading zeros removed. The bus
|
||||
+ number is ignored. This device type is found in IBM PowerVMs.</para>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>c</constant><replaceable>bus_id</replaceable></varname></term>
|
||||
+ <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>a</constant><replaceable>vendor</replaceable><replaceable>model</replaceable><constant>i</constant><replaceable>instance</replaceable></varname></term>
|
||||
+ <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>i</constant><replaceable>address</replaceable><constant>n</constant><replaceable>port_name</replaceable></varname></term>
|
||||
+ <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]</varname></term>
|
||||
+ <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
|
||||
+ <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
|
||||
+
|
||||
+ <listitem><para>This property describes the device installation location. Different schemes are
|
||||
+ used depending on the bus type, as described in the table below. For BCMA and USB devices, PCI path
|
||||
+ information must known, and the full name consists of the prefix, PCI slot identifier, and USB or
|
||||
+ BCMA location. The first two parts are denoted as "…" in the table below.</para>
|
||||
+
|
||||
+ <table>
|
||||
+ <title>Path naming schemes</title>
|
||||
+
|
||||
+ <tgroup cols='2'>
|
||||
+ <thead>
|
||||
+ <row>
|
||||
+ <entry>Format</entry>
|
||||
+ <entry>Description</entry>
|
||||
+ </row>
|
||||
+ </thead>
|
||||
+
|
||||
+ <tbody>
|
||||
+ <row>
|
||||
+ <entry><replaceable>prefix</replaceable> <constant>c</constant><replaceable>bus_id</replaceable></entry>
|
||||
+ <entry>CCW or grouped CCW device identifier</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry><replaceable>prefix</replaceable> <constant>a</constant><replaceable>vendor</replaceable> <replaceable>model</replaceable> <constant>i</constant><replaceable>instance</replaceable></entry>
|
||||
+ <entry>ACPI path names for ARM64 platform devices</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry><replaceable>prefix</replaceable> [<constant>P</constant><replaceable>domain</replaceable>] <constant>p</constant><replaceable>bus</replaceable> <constant>s</constant><replaceable>slot</replaceable> [<constant>f</constant><replaceable>function</replaceable>] [<constant>n</constant><replaceable>phys_port_name</replaceable> | <constant>d</constant><replaceable>dev_port</replaceable>]</entry>
|
||||
+ <entry>PCI geographical location</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry>… <constant>b</constant><replaceable>number</replaceable></entry>
|
||||
+ <entry>Broadcom bus (BCMA) core number</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ <row>
|
||||
+ <entry>… <constant>u</constant><replaceable>port</replaceable>… [<constant>c</constant><replaceable>config</replaceable>] [<constant>i</constant><replaceable>interface</replaceable>]</entry>
|
||||
+ <entry>USB port number chain</entry>
|
||||
+ </row>
|
||||
+
|
||||
+ </tbody>
|
||||
+ </tgroup>
|
||||
+ </table>
|
||||
+
|
||||
+ <para>CCW and grouped CCW devices are found in IBM System Z mainframes. Any leading zeros and
|
||||
+ dots are suppressed.</para>
|
||||
+
|
||||
+ <para>For PCI, BCMA, and USB devices, the same rules as described above for slot naming are
|
||||
+ used.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>History</title>
|
||||
+
|
||||
+ <para>The following "naming schemes" have been defined:</para>
|
||||
+
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><constant>rhel-8.0</constant></term>
|
||||
+
|
||||
+ <listitem><para>Naming was changed for virtual network interfaces created with SR-IOV and NPAR and
|
||||
+ for devices where the PCI network controller device does not have a slot number associated.</para>
|
||||
+
|
||||
+ <para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
|
||||
+ <literal>v<replaceable>port</replaceable></literal>, where <replaceable>port</replaceable> is the
|
||||
+ virtual device number. Previously those virtual devices were named as if completely independent.
|
||||
+ </para>
|
||||
+
|
||||
+ <para>The ninth and later NPAR virtual devices are named following the scheme used for the first
|
||||
+ eight NPAR partitions. Previously those devices were not renamed and the kernel default
|
||||
+ ("eth<replaceable>N</replaceable>") was used.</para>
|
||||
+
|
||||
+ <para>Names are also generated for PCI devices where the PCI network controller device does not
|
||||
+ have an associated slot number itself, but one of its parents does. Previously those devices were
|
||||
+ not renamed and the kernel default was used.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><constant>rhel-8.1</constant></term>
|
||||
+
|
||||
+ <para>Same as naming scheme <constant>rhel-8.0</constant>.</para>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><constant>rhel-8.2</constant></term>
|
||||
+
|
||||
+ <para>Same as naming scheme <constant>rhel-8.0</constant>.</para>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><constant>rhel-8.3</constant></term>
|
||||
+
|
||||
+ <para>Same as naming scheme <constant>rhel-8.0</constant>.</para>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
|
||||
+ particular version of systemd.</para>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>Examples</title>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>Using <command>udevadm test-builtin</command> to display device properties</title>
|
||||
+
|
||||
+ <programlisting>$ udevadm test-builtin net_id /sys/class/net/enp0s31f6
|
||||
+...
|
||||
+Using default interface naming scheme 'rhel-8.3'.
|
||||
+ID_NET_NAMING_SCHEME=rhel-8.3
|
||||
+ID_NET_NAME_MAC=enx54ee75cb1dc0
|
||||
+ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
|
||||
+ID_NET_NAME_PATH=enp0s31f6
|
||||
+...</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>PCI Ethernet card with firmware index "1"</title>
|
||||
+
|
||||
+ <programlisting>ID_NET_NAME_ONBOARD=eno1
|
||||
+ID_NET_NAME_ONBOARD_LABEL=enEthernet Port 1
|
||||
+ </programlisting>
|
||||
+ <!-- FIXME: nuke the prefix! -->
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>PCI Ethernet card in hotplug slot with firmware index number</title>
|
||||
+
|
||||
+ <programlisting># /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
|
||||
+ID_NET_NAME_MAC=enx000000000466
|
||||
+ID_NET_NAME_PATH=enp5s0
|
||||
+ID_NET_NAME_SLOT=ens1</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>PCI Ethernet multi-function card with 2 ports</title>
|
||||
+
|
||||
+ <programlisting># /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
|
||||
+ID_NET_NAME_MAC=enx78e7d1ea46da
|
||||
+ID_NET_NAME_PATH=enp2s0f0
|
||||
+
|
||||
+# /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
|
||||
+ID_NET_NAME_MAC=enx78e7d1ea46dc
|
||||
+ID_NET_NAME_PATH=enp2s0f1</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>PCI WLAN card</title>
|
||||
+
|
||||
+ <programlisting># /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
|
||||
+ID_NET_NAME_MAC=wlx0024d7e31130
|
||||
+ID_NET_NAME_PATH=wlp3s0</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>USB built-in 3G modem</title>
|
||||
+
|
||||
+ <programlisting># /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
|
||||
+ID_NET_NAME_MAC=wwx028037ec0200
|
||||
+ID_NET_NAME_PATH=wwp0s29u1u4i6</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>USB Android phone</title>
|
||||
+
|
||||
+ <programlisting># /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
|
||||
+ID_NET_NAME_MAC=enxd626b3450fb5
|
||||
+ID_NET_NAME_PATH=enp0s29u1u2</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <example>
|
||||
+ <title>s390 grouped CCW interface</title>
|
||||
+
|
||||
+ <programlisting># /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0
|
||||
+ID_NET_NAME_MAC=enx026d3c00000a
|
||||
+ID_NET_NAME_PATH=encf5f0</programlisting>
|
||||
+ </example>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>See Also</title>
|
||||
+ <para>
|
||||
+ <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||
+ <citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames">the
|
||||
+ original page describing stable interface names</ulink>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+</refentry>
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index d85dc2848b..aa553d5ade 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -78,6 +78,7 @@
|
||||
* /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0
|
||||
* ID_NET_NAME_MAC=enx026d3c00000a
|
||||
* ID_NET_NAME_PATH=encf5f0
|
||||
+ * When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
@ -0,0 +1,51 @@
|
||||
From 462420bc7ea22a05bfc2d021d395aade2b8ee7dc Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Mon, 19 Oct 2020 10:56:11 +0200
|
||||
Subject: [PATCH] udev/net_id: parse _SUN ACPI index as a signed integer
|
||||
|
||||
Negative value means there is no match between a PCI device and any of
|
||||
the slots. In the following commit we will extend this and value of 0
|
||||
will indicate that there is a match between some slot and PCI device,
|
||||
but that device is a PCI bridge.
|
||||
|
||||
(cherry picked from commit 3e545ae5abcf258791eacbee60c829c100a33274)
|
||||
|
||||
Related: #1827462
|
||||
---
|
||||
src/udev/udev-builtin-net_id.c | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index aa553d5ade..ede24dee41 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -391,7 +391,8 @@ static bool is_pci_ari_enabled(struct udev_device *dev) {
|
||||
|
||||
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
|
||||
struct udev *udev = udev_device_get_udev(names->pcidev);
|
||||
- unsigned domain, bus, slot, func, dev_port = 0, hotplug_slot = 0;
|
||||
+ unsigned domain, bus, slot, func, dev_port = 0;
|
||||
+ int hotplug_slot = -1;
|
||||
size_t l;
|
||||
char *s;
|
||||
const char *attr, *port_name;
|
||||
@@ -449,15 +450,15 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
|
||||
hotplug_slot_dev = names->pcidev;
|
||||
while (hotplug_slot_dev) {
|
||||
FOREACH_DIRENT_ALL(dent, dir, break) {
|
||||
- unsigned i;
|
||||
- int r;
|
||||
+ int i, r;
|
||||
char str[PATH_MAX];
|
||||
_cleanup_free_ char *address = NULL;
|
||||
|
||||
if (dent->d_name[0] == '.')
|
||||
continue;
|
||||
- r = safe_atou_full(dent->d_name, 10, &i);
|
||||
- if (i < 1 || r < 0)
|
||||
+
|
||||
+ r = safe_atoi(dent->d_name, &i);
|
||||
+ if (r < 0 || i <= 0)
|
||||
continue;
|
||||
|
||||
if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
|
@ -0,0 +1,124 @@
|
||||
From bb6114af097da0cd9c5081e42db718559130687f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Mon, 19 Oct 2020 11:10:31 +0200
|
||||
Subject: [PATCH] udev/net_id: don't generate slot based names if multiple
|
||||
devices might claim the same slot
|
||||
|
||||
(cherry picked from commit 2c8ec0095e6fd2e72879d4915ff8a9e5c0664d0b)
|
||||
|
||||
Resolves: #1827462
|
||||
---
|
||||
man/systemd.net-naming-scheme.xml | 15 ++++++++++-
|
||||
src/udev/udev-builtin-net_id.c | 41 ++++++++++++++++++++++++++-----
|
||||
2 files changed, 49 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
|
||||
index a12cc3c460..10e71dcb15 100644
|
||||
--- a/man/systemd.net-naming-scheme.xml
|
||||
+++ b/man/systemd.net-naming-scheme.xml
|
||||
@@ -176,7 +176,10 @@
|
||||
|
||||
<para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
|
||||
<constant>v</constant> and the virtual device number, with any leading zeros removed. The bus
|
||||
- number is ignored. This device type is found in IBM PowerVMs.</para>
|
||||
+ number is ignored.</para>
|
||||
+
|
||||
+ <para>In some configurations a parent PCI bridge of a given network controller may be associated
|
||||
+ with a slot. In such case we don't generate this device property to avoid possible naming conflicts.</para>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -288,6 +291,16 @@
|
||||
<para>Same as naming scheme <constant>rhel-8.0</constant>.</para>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><constant>rhel-8.4</constant></term>
|
||||
+
|
||||
+ <listitem><para>If the PCI slot is assocated with PCI bridge and that has multiple child network
|
||||
+ controllers then all of them might derive the same value of <varname>ID_NET_NAME_SLOT</varname>
|
||||
+ property. That could cause naming conflict if the property is selected as a device name. Now, we detect the
|
||||
+ situation, slot - bridge relation, and we don't produce the <varname>ID_NET_NAME_SLOT</varname> property to
|
||||
+ avoid possible naming conflict.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
|
||||
particular version of systemd.</para>
|
||||
</variablelist>
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index ede24dee41..d8c56b62bb 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -124,6 +124,7 @@ typedef enum NamingSchemeFlags {
|
||||
/* First, the individual features */
|
||||
NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
|
||||
NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
|
||||
+ NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */
|
||||
|
||||
/* And now the masks that combine the features above */
|
||||
NAMING_V238 = 0,
|
||||
@@ -132,6 +133,7 @@ typedef enum NamingSchemeFlags {
|
||||
NAMING_RHEL_8_1 = NAMING_V239,
|
||||
NAMING_RHEL_8_2 = NAMING_V239,
|
||||
NAMING_RHEL_8_3 = NAMING_V239,
|
||||
+ NAMING_RHEL_8_4 = NAMING_V239|NAMING_BRIDGE_NO_SLOT,
|
||||
|
||||
_NAMING_SCHEME_FLAGS_INVALID = -1,
|
||||
} NamingSchemeFlags;
|
||||
@@ -389,6 +391,26 @@ static bool is_pci_ari_enabled(struct udev_device *dev) {
|
||||
return streq_ptr(udev_device_get_sysattr_value(dev, "ari_enabled"), "1");
|
||||
}
|
||||
|
||||
+static bool is_pci_bridge(struct udev_device *dev) {
|
||||
+ const char *v, *p;
|
||||
+
|
||||
+ v = udev_device_get_sysattr_value(dev, "modalias");
|
||||
+ if (!v)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!startswith(v, "pci:"))
|
||||
+ return false;
|
||||
+
|
||||
+ p = strrchr(v, 's');
|
||||
+ if (!p)
|
||||
+ return false;
|
||||
+ if (p[1] != 'c')
|
||||
+ return false;
|
||||
+
|
||||
+ /* PCI device subclass 04 corresponds to PCI bridge */
|
||||
+ return strneq(p + 2, "04", 2);
|
||||
+}
|
||||
+
|
||||
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
|
||||
struct udev *udev = udev_device_get_udev(names->pcidev);
|
||||
unsigned domain, bus, slot, func, dev_port = 0;
|
||||
@@ -461,16 +483,23 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
|
||||
if (r < 0 || i <= 0)
|
||||
continue;
|
||||
|
||||
+ /* match slot address with device by stripping the function */
|
||||
if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
|
||||
- read_one_line_file(str, &address) >= 0)
|
||||
- /* match slot address with device by stripping the function */
|
||||
- if (startswith(udev_device_get_sysname(hotplug_slot_dev), address))
|
||||
- hotplug_slot = i;
|
||||
+ read_one_line_file(str, &address) >= 0 &&
|
||||
+ startswith(udev_device_get_sysname(hotplug_slot_dev), address)) {
|
||||
+ hotplug_slot = i;
|
||||
+
|
||||
+ /* We found the match between PCI device and slot. However, we won't use the
|
||||
+ * slot index if the device is a PCI bridge, because it can have other child
|
||||
+ * devices that will try to claim the same index and that would create name
|
||||
+ * collision. */
|
||||
+ if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev))
|
||||
+ hotplug_slot = 0;
|
||||
|
||||
- if (hotplug_slot > 0)
|
||||
break;
|
||||
+ }
|
||||
}
|
||||
- if (hotplug_slot > 0)
|
||||
+ if (hotplug_slot >= 0)
|
||||
break;
|
||||
rewinddir(dir);
|
||||
hotplug_slot_dev = udev_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL);
|
@ -1,13 +1,11 @@
|
||||
From bf1b76b47629a7f0eacce4f26d01f3eea46e7bd6 Mon Sep 17 00:00:00 2001
|
||||
From 573229efeb2c5ade25794deee8cfe2f967414ef7 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Fri, 6 Nov 2020 10:13:19 +0100
|
||||
Subject: [PATCH] fix typo in ProtectSystem= option
|
||||
|
||||
This was introduced by commit d9ae3222cfbd5d2a48e6dbade6617085cc76f1c1 .
|
||||
|
||||
(cherry picked from commit 573229efeb2c5ade25794deee8cfe2f967414ef7)
|
||||
|
||||
Resolves: #1934500
|
||||
Resolves: #1871139
|
||||
---
|
||||
units/systemd-resolved.service.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
@ -0,0 +1,34 @@
|
||||
From 5e74048399c4610da27b5f7fbbb53784030aeb70 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Mon, 9 Nov 2020 09:27:02 +0100
|
||||
Subject: [PATCH] remove references of non-existent man pages
|
||||
|
||||
This is a follow-up to commit 8ad89170001c9aba8849630ddb5da81d9e24a1bc,
|
||||
which introduced the man page change.
|
||||
|
||||
Resolves: #1876807
|
||||
---
|
||||
man/systemd.special.xml | 10 ----------
|
||||
1 file changed, 10 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.special.xml b/man/systemd.special.xml
|
||||
index c9d4345016..fe6324a4a0 100644
|
||||
--- a/man/systemd.special.xml
|
||||
+++ b/man/systemd.special.xml
|
||||
@@ -657,16 +657,6 @@
|
||||
target unit and pull in the target from it, also with <varname>Requires=</varname>. Note that by default this
|
||||
target unit is not part of the initial boot transaction, but is supposed to be pulled in only if required by
|
||||
units that want to run only on successful boots.</para>
|
||||
-
|
||||
- <para>See
|
||||
- <citerefentry><refentrytitle>systemd-boot-check-no-failures.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
- for a service that implements a generic system health check and orders itself before
|
||||
- <filename>boot-complete.target</filename>.</para>
|
||||
-
|
||||
- <para>See
|
||||
- <citerefentry><refentrytitle>systemd-bless-boot.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
- for a service that propagates boot success information to the boot loader, and orders itself after
|
||||
- <filename>boot-complete.target</filename>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
@ -0,0 +1,91 @@
|
||||
From b14c82dd9f9fcc42810614cf02efe8651897d36f Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Wed, 10 Jun 2020 20:19:41 +0200
|
||||
Subject: [PATCH] log: Prefer logging to CLI unless JOURNAL_STREAM is set
|
||||
|
||||
(cherry picked from commit bc694c06e60505efeb09e5278a7b22cdfa23975e)
|
||||
|
||||
Resolves: #1865840
|
||||
---
|
||||
src/basic/log.c | 32 +++++++++++++++++++++++++++++---
|
||||
test/TEST-21-SYSUSERS/test.sh | 3 +--
|
||||
2 files changed, 30 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/basic/log.c b/src/basic/log.c
|
||||
index 48c094b548..9387e56a57 100644
|
||||
--- a/src/basic/log.c
|
||||
+++ b/src/basic/log.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/socket.h>
|
||||
+#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "sd-messages.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
+#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "io-util.h"
|
||||
@@ -220,6 +222,32 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
+static bool stderr_is_journal(void) {
|
||||
+ _cleanup_free_ char *w = NULL;
|
||||
+ const char *e;
|
||||
+ uint64_t dev, ino;
|
||||
+ struct stat st;
|
||||
+
|
||||
+ e = getenv("JOURNAL_STREAM");
|
||||
+ if (!e)
|
||||
+ return false;
|
||||
+
|
||||
+ if (extract_first_word(&e, &w, ":", EXTRACT_DONT_COALESCE_SEPARATORS) <= 0)
|
||||
+ return false;
|
||||
+ if (!e)
|
||||
+ return false;
|
||||
+
|
||||
+ if (safe_atou64(w, &dev) < 0)
|
||||
+ return false;
|
||||
+ if (safe_atou64(e, &ino) < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ if (fstat(STDERR_FILENO, &st) < 0)
|
||||
+ return false;
|
||||
+
|
||||
+ return st.st_dev == dev && st.st_ino == ino;
|
||||
+}
|
||||
+
|
||||
int log_open(void) {
|
||||
int r;
|
||||
|
||||
@@ -239,9 +267,7 @@ int log_open(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (log_target != LOG_TARGET_AUTO ||
|
||||
- getpid_cached() == 1 ||
|
||||
- isatty(STDERR_FILENO) <= 0) {
|
||||
+ if (log_target != LOG_TARGET_AUTO || getpid_cached() == 1 || stderr_is_journal()) {
|
||||
|
||||
if (!prohibit_ipc &&
|
||||
IN_SET(log_target, LOG_TARGET_AUTO,
|
||||
diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh
|
||||
index b1049e720d..3460d71f22 100755
|
||||
--- a/test/TEST-21-SYSUSERS/test.sh
|
||||
+++ b/test/TEST-21-SYSUSERS/test.sh
|
||||
@@ -108,8 +108,7 @@ test_run() {
|
||||
echo "*** Running test $f"
|
||||
prepare_testdir ${f%.input}
|
||||
cp $f $TESTDIR/usr/lib/sysusers.d/test.conf
|
||||
- systemd-sysusers --root=$TESTDIR 2> /dev/null
|
||||
- journalctl -t systemd-sysusers -o cat | tail -n1 > $TESTDIR/tmp/err
|
||||
+ systemd-sysusers --root=$TESTDIR 2>&1 | tail -n1 > $TESTDIR/tmp/err
|
||||
if ! diff -u $TESTDIR/tmp/err ${f%.*}.expected-err; then
|
||||
echo "**** Unexpected error output for $f"
|
||||
cat $TESTDIR/tmp/err
|
@ -0,0 +1,58 @@
|
||||
From f0d9e0cb24958bc11c8d83f0a3de651def2aa1d6 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 30 Apr 2020 18:30:56 +0200
|
||||
Subject: [PATCH] locale-util: add new helper locale_is_installed()
|
||||
|
||||
This new helper checks whether the specified locale is installed. It's
|
||||
distinct from locale_is_valid() which just superficially checks if a
|
||||
string looks like something that could be a valid locale.
|
||||
|
||||
Heavily inspired by @jsynacek's #13964.
|
||||
|
||||
Replaces: #13964
|
||||
(cherry picked from commit 23fa786ca67ed3a32930ff1a7b175ac823db187c)
|
||||
|
||||
Related: #1755287
|
||||
---
|
||||
src/basic/locale-util.c | 15 +++++++++++++++
|
||||
src/basic/locale-util.h | 1 +
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
|
||||
index 7cd143ea6f..42ef309ebd 100644
|
||||
--- a/src/basic/locale-util.c
|
||||
+++ b/src/basic/locale-util.c
|
||||
@@ -204,6 +204,21 @@ bool locale_is_valid(const char *name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+int locale_is_installed(const char *name) {
|
||||
+ if (!locale_is_valid(name))
|
||||
+ return false;
|
||||
+
|
||||
+ if (STR_IN_SET(name, "C", "POSIX")) /* These ones are always OK */
|
||||
+ return true;
|
||||
+
|
||||
+ _cleanup_(freelocalep) locale_t loc =
|
||||
+ newlocale(LC_ALL_MASK, name, 0);
|
||||
+ if (loc == (locale_t) 0)
|
||||
+ return errno == ENOMEM ? -ENOMEM : false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void init_gettext(void) {
|
||||
setlocale(LC_ALL, "");
|
||||
textdomain(GETTEXT_PACKAGE);
|
||||
diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h
|
||||
index 368675f286..b40f9c641a 100644
|
||||
--- a/src/basic/locale-util.h
|
||||
+++ b/src/basic/locale-util.h
|
||||
@@ -31,6 +31,7 @@ typedef enum LocaleVariable {
|
||||
|
||||
int get_locales(char ***l);
|
||||
bool locale_is_valid(const char *name);
|
||||
+int locale_is_installed(const char *name);
|
||||
|
||||
#define _(String) gettext(String)
|
||||
#define N_(String) String
|
@ -0,0 +1,53 @@
|
||||
From 3d08c7971a80370f60dd14b068779851e0f82c24 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 30 Apr 2020 18:32:55 +0200
|
||||
Subject: [PATCH] test: add test case for locale_is_installed()
|
||||
|
||||
(cherry picked from commit b45b0a69bb7ef3e6e66d443eae366b6d1c387cab)
|
||||
|
||||
Related: #1755287
|
||||
---
|
||||
src/test/test-locale-util.c | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
|
||||
index 0c3f6a62ed..0d50c33ce5 100644
|
||||
--- a/src/test/test-locale-util.c
|
||||
+++ b/src/test/test-locale-util.c
|
||||
@@ -34,6 +34,28 @@ static void test_locale_is_valid(void) {
|
||||
assert_se(!locale_is_valid("\x01gar\x02 bage\x03"));
|
||||
}
|
||||
|
||||
+static void test_locale_is_installed(void) {
|
||||
+ log_info("/* %s */", __func__);
|
||||
+
|
||||
+ /* Always available */
|
||||
+ assert_se(locale_is_installed("POSIX") > 0);
|
||||
+ assert_se(locale_is_installed("C") > 0);
|
||||
+
|
||||
+ /* Might, or might not be installed. */
|
||||
+ assert_se(locale_is_installed("en_EN.utf8") >= 0);
|
||||
+ assert_se(locale_is_installed("fr_FR.utf8") >= 0);
|
||||
+ assert_se(locale_is_installed("fr_FR@euro") >= 0);
|
||||
+ assert_se(locale_is_installed("fi_FI") >= 0);
|
||||
+
|
||||
+ /* Definitely not valid */
|
||||
+ assert_se(locale_is_installed("") == 0);
|
||||
+ assert_se(locale_is_installed("/usr/bin/foo") == 0);
|
||||
+ assert_se(locale_is_installed("\x01gar\x02 bage\x03") == 0);
|
||||
+
|
||||
+ /* Definitely not installed */
|
||||
+ assert_se(locale_is_installed("zz_ZZ") == 0);
|
||||
+}
|
||||
+
|
||||
static void test_keymaps(void) {
|
||||
_cleanup_strv_free_ char **kmaps = NULL;
|
||||
char **p;
|
||||
@@ -95,6 +117,7 @@ static void dump_special_glyphs(void) {
|
||||
int main(int argc, char *argv[]) {
|
||||
test_get_locales();
|
||||
test_locale_is_valid();
|
||||
+ test_locale_is_installed();
|
||||
test_keymaps();
|
||||
|
||||
dump_special_glyphs();
|
@ -0,0 +1,232 @@
|
||||
From 5813180a75aa1ef90f6d3459fc5beb099b815cfb Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 30 Apr 2020 18:32:44 +0200
|
||||
Subject: [PATCH] tree-wide: port various bits over to locale_is_installed()
|
||||
|
||||
(cherry picked from commit a00a78b84e2ab352b3144bfae8bc578d172303be)
|
||||
|
||||
Resolves: #1755287
|
||||
---
|
||||
src/firstboot/firstboot.c | 30 ++++++++------
|
||||
src/locale/localed.c | 87 ++++++++++++++++++++++++---------------
|
||||
2 files changed, 71 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
|
||||
index a98e53b3a3..7e177a50fa 100644
|
||||
--- a/src/firstboot/firstboot.c
|
||||
+++ b/src/firstboot/firstboot.c
|
||||
@@ -192,6 +192,14 @@ static int prompt_loop(const char *text, char **l, bool (*is_valid)(const char *
|
||||
}
|
||||
}
|
||||
|
||||
+static bool locale_is_ok(const char *name) {
|
||||
+
|
||||
+ if (arg_root)
|
||||
+ return locale_is_valid(name);
|
||||
+
|
||||
+ return locale_is_installed(name) > 0;
|
||||
+}
|
||||
+
|
||||
static int prompt_locale(void) {
|
||||
_cleanup_strv_free_ char **locales = NULL;
|
||||
int r;
|
||||
@@ -215,14 +223,14 @@ static int prompt_locale(void) {
|
||||
|
||||
putchar('\n');
|
||||
|
||||
- r = prompt_loop("Please enter system locale name or number", locales, locale_is_valid, &arg_locale);
|
||||
+ r = prompt_loop("Please enter system locale name or number", locales, locale_is_ok, &arg_locale);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (isempty(arg_locale))
|
||||
return 0;
|
||||
|
||||
- r = prompt_loop("Please enter system message locale name or number", locales, locale_is_valid, &arg_locale_messages);
|
||||
+ r = prompt_loop("Please enter system message locale name or number", locales, locale_is_ok, &arg_locale_messages);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -780,11 +788,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_LOCALE:
|
||||
- if (!locale_is_valid(optarg)) {
|
||||
- log_error("Locale %s is not valid.", optarg);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
r = free_and_strdup(&arg_locale, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@@ -792,11 +795,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_LOCALE_MESSAGES:
|
||||
- if (!locale_is_valid(optarg)) {
|
||||
- log_error("Locale %s is not valid.", optarg);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
r = free_and_strdup(&arg_locale_messages, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@@ -922,6 +920,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
+ /* We check if the specified locale strings are valid down here, so that we can take --root= into
|
||||
+ * account when looking for the locale files. */
|
||||
+
|
||||
+ if (arg_locale && !locale_is_ok(arg_locale))
|
||||
+ return log_error_errno(EINVAL, "Locale %s is not installed.", arg_locale);
|
||||
+ if (arg_locale_messages && !locale_is_ok(arg_locale_messages))
|
||||
+ return log_error_errno(EINVAL, "Locale %s is not installed.", arg_locale_messages);
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
|
||||
diff --git a/src/locale/localed.c b/src/locale/localed.c
|
||||
index 253973fd49..d6ed40babe 100644
|
||||
--- a/src/locale/localed.c
|
||||
+++ b/src/locale/localed.c
|
||||
@@ -259,18 +259,57 @@ static void locale_free(char ***l) {
|
||||
(*l)[p] = mfree((*l)[p]);
|
||||
}
|
||||
|
||||
+static int process_locale_list_item(
|
||||
+ const char *assignment,
|
||||
+ char *new_locale[static _VARIABLE_LC_MAX],
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ assert(assignment);
|
||||
+ assert(new_locale);
|
||||
+
|
||||
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
+ const char *name, *e;
|
||||
+
|
||||
+ assert_se(name = locale_variable_to_string(p));
|
||||
+
|
||||
+ e = startswith(assignment, name);
|
||||
+ if (!e)
|
||||
+ continue;
|
||||
+
|
||||
+ if (*e != '=')
|
||||
+ continue;
|
||||
+
|
||||
+ e++;
|
||||
+
|
||||
+ if (!locale_is_valid(e))
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s is not valid, refusing.", e);
|
||||
+ if (locale_is_installed(e) <= 0)
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale %s not installed, refusing.", e);
|
||||
+ if (new_locale[p])
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale variable %s set twice, refusing.", name);
|
||||
+
|
||||
+ new_locale[p] = strdup(e);
|
||||
+ if (!new_locale[p])
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Locale assignment %s not valid, refusing.", assignment);
|
||||
+}
|
||||
+
|
||||
static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
Context *c = userdata;
|
||||
_cleanup_strv_free_ char **settings = NULL, **l = NULL;
|
||||
char *new_locale[_VARIABLE_LC_MAX] = {}, **i;
|
||||
_cleanup_(locale_free) _unused_ char **dummy = new_locale;
|
||||
bool modified = false;
|
||||
- int interactive, p, r;
|
||||
+ int interactive, r;
|
||||
|
||||
assert(m);
|
||||
assert(c);
|
||||
|
||||
- r = bus_message_read_strv_extend(m, &l);
|
||||
+ r = sd_bus_message_read_strv(m, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -279,11 +318,13 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
return r;
|
||||
|
||||
/* If single locale without variable name is provided, then we assume it is LANG=. */
|
||||
- if (strv_length(l) == 1 && !strchr(*l, '=')) {
|
||||
- if (!locale_is_valid(*l))
|
||||
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
|
||||
+ if (strv_length(l) == 1 && !strchr(l[0], '=')) {
|
||||
+ if (!locale_is_valid(l[0]))
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid locale specification: %s", l[0]);
|
||||
+ if (locale_is_installed(l[0]) <= 0)
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified locale is not installed: %s", l[0]);
|
||||
|
||||
- new_locale[VARIABLE_LANG] = strdup(*l);
|
||||
+ new_locale[VARIABLE_LANG] = strdup(l[0]);
|
||||
if (!new_locale[VARIABLE_LANG])
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -292,31 +333,9 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
|
||||
/* Check whether a variable is valid */
|
||||
STRV_FOREACH(i, l) {
|
||||
- bool valid = false;
|
||||
-
|
||||
- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
|
||||
- size_t k;
|
||||
- const char *name;
|
||||
-
|
||||
- name = locale_variable_to_string(p);
|
||||
- assert(name);
|
||||
-
|
||||
- k = strlen(name);
|
||||
- if (startswith(*i, name) &&
|
||||
- (*i)[k] == '=' &&
|
||||
- locale_is_valid((*i) + k + 1)) {
|
||||
- valid = true;
|
||||
-
|
||||
- new_locale[p] = strdup((*i) + k + 1);
|
||||
- if (!new_locale[p])
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (!valid)
|
||||
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data.");
|
||||
+ r = process_locale_list_item(*i, new_locale, error);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
}
|
||||
|
||||
/* If LANG was specified, but not LANGUAGE, check if we should
|
||||
@@ -339,7 +358,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
}
|
||||
|
||||
/* Merge with the current settings */
|
||||
- for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
if (!isempty(c->locale[p]) && isempty(new_locale[p])) {
|
||||
new_locale[p] = strdup(c->locale[p]);
|
||||
if (!new_locale[p])
|
||||
@@ -348,7 +367,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
|
||||
locale_simplify(new_locale);
|
||||
|
||||
- for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
if (!streq_ptr(c->locale[p], new_locale[p])) {
|
||||
modified = true;
|
||||
break;
|
||||
@@ -373,7 +392,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
- for (p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
+ for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
|
||||
free_and_replace(c->locale[p], new_locale[p]);
|
||||
|
||||
r = locale_write_data(c, &settings);
|
@ -0,0 +1,339 @@
|
||||
From 4c41ad9418058aefb2d2732b0b65da9c7cdf5151 Mon Sep 17 00:00:00 2001
|
||||
From: Ruixin Bao <rubao@redhat.com>
|
||||
Date: Tue, 21 Aug 2018 20:40:56 +0000
|
||||
Subject: [PATCH] install: allow instantiated units to be enabled via presets
|
||||
|
||||
This patch implements https://github.com/systemd/systemd/issues/9421.
|
||||
|
||||
The .preset file now is able to take a rule in the format of:(e.g)
|
||||
enable foo@.service bar0 bar1 bar2
|
||||
|
||||
In the above example, when preset-all is called, all three instances of
|
||||
foo@bar0.service, foo@bar1.service and foo@bar2.service will be enabled.
|
||||
|
||||
When preset is called on a single service(e.g: foo@bar1.service), only
|
||||
the mentioned one(foo@bar1.service) will be enabled.
|
||||
|
||||
Tests are added for future regression.
|
||||
|
||||
(cherry picked from commit 4c9565eea534cd233a913c8c21f7920dba229743)
|
||||
|
||||
Resolves: #1812972
|
||||
---
|
||||
src/shared/install.c | 155 ++++++++++++++++++++++++++++++-----
|
||||
src/test/test-install-root.c | 57 +++++++++++++
|
||||
2 files changed, 193 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/src/shared/install.c b/src/shared/install.c
|
||||
index 77ae812878..1d4beaa83b 100644
|
||||
--- a/src/shared/install.c
|
||||
+++ b/src/shared/install.c
|
||||
@@ -60,6 +60,7 @@ typedef enum {
|
||||
typedef struct {
|
||||
char *pattern;
|
||||
PresetAction action;
|
||||
+ char **instances;
|
||||
} PresetRule;
|
||||
|
||||
typedef struct {
|
||||
@@ -87,8 +88,10 @@ static inline void presets_freep(Presets *p) {
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
- for (i = 0; i < p->n_rules; i++)
|
||||
+ for (i = 0; i < p->n_rules; i++) {
|
||||
free(p->rules[i].pattern);
|
||||
+ strv_free(p->rules[i].instances);
|
||||
+ }
|
||||
|
||||
free(p->rules);
|
||||
p->n_rules = 0;
|
||||
@@ -2755,6 +2758,39 @@ int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int split_pattern_into_name_and_instances(const char *pattern, char **out_unit_name, char ***out_instances) {
|
||||
+ _cleanup_strv_free_ char **instances = NULL;
|
||||
+ _cleanup_free_ char *unit_name = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(pattern);
|
||||
+ assert(out_instances);
|
||||
+ assert(out_unit_name);
|
||||
+
|
||||
+ r = extract_first_word(&pattern, &unit_name, NULL, 0);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ /* We handle the instances logic when unit name is extracted */
|
||||
+ if (pattern) {
|
||||
+ /* We only create instances when a rule of templated unit
|
||||
+ * is seen. A rule like enable foo@.service a b c will
|
||||
+ * result in an array of (a, b, c) as instance names */
|
||||
+ if (!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ instances = strv_split(pattern, WHITESPACE);
|
||||
+ if (!instances)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ *out_instances = TAKE_PTR(instances);
|
||||
+ }
|
||||
+
|
||||
+ *out_unit_name = TAKE_PTR(unit_name);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
|
||||
_cleanup_(presets_freep) Presets ps = {};
|
||||
size_t n_allocated = 0;
|
||||
@@ -2824,15 +2860,20 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
|
||||
|
||||
parameter = first_word(l, "enable");
|
||||
if (parameter) {
|
||||
- char *pattern;
|
||||
+ char *unit_name;
|
||||
+ char **instances = NULL;
|
||||
|
||||
- pattern = strdup(parameter);
|
||||
- if (!pattern)
|
||||
- return -ENOMEM;
|
||||
+ /* Unit_name will remain the same as parameter when no instances are specified */
|
||||
+ r = split_pattern_into_name_and_instances(parameter, &unit_name, &instances);
|
||||
+ if (r < 0) {
|
||||
+ log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line);
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
rule = (PresetRule) {
|
||||
- .pattern = pattern,
|
||||
+ .pattern = unit_name,
|
||||
.action = PRESET_ENABLE,
|
||||
+ .instances = instances,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2868,15 +2909,71 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int query_presets(const char *name, const Presets presets) {
|
||||
+static int pattern_match_multiple_instances(
|
||||
+ const PresetRule rule,
|
||||
+ const char *unit_name,
|
||||
+ char ***ret) {
|
||||
+
|
||||
+ _cleanup_free_ char *templated_name = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ /* If no ret is needed or the rule itself does not have instances
|
||||
+ * initalized, we return not matching */
|
||||
+ if (!ret || !rule.instances)
|
||||
+ return 0;
|
||||
+
|
||||
+ r = unit_name_template(unit_name, &templated_name);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (!streq(rule.pattern, templated_name))
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Compose a list of specified instances when unit name is a template */
|
||||
+ if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
|
||||
+ _cleanup_free_ char *prefix = NULL;
|
||||
+ _cleanup_strv_free_ char **out_strv = NULL;
|
||||
+ char **iter;
|
||||
+
|
||||
+ r = unit_name_to_prefix(unit_name, &prefix);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ STRV_FOREACH(iter, rule.instances) {
|
||||
+ _cleanup_free_ char *name = NULL;
|
||||
+ r = unit_name_build(prefix, *iter, ".service", &name);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ r = strv_extend(&out_strv, name);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
+ *ret = TAKE_PTR(out_strv);
|
||||
+ return 1;
|
||||
+ } else {
|
||||
+ /* We now know the input unit name is an instance name */
|
||||
+ _cleanup_free_ char *instance_name = NULL;
|
||||
+
|
||||
+ r = unit_name_to_instance(unit_name, &instance_name);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (strv_find(rule.instances, instance_name))
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int query_presets(const char *name, const Presets presets, char ***instance_name_list) {
|
||||
PresetAction action = PRESET_UNKNOWN;
|
||||
size_t i;
|
||||
-
|
||||
+ char **s;
|
||||
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < presets.n_rules; i++)
|
||||
- if (fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
|
||||
+ if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 ||
|
||||
+ fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
|
||||
action = presets.rules[i].action;
|
||||
break;
|
||||
}
|
||||
@@ -2886,7 +2983,11 @@ static int query_presets(const char *name, const Presets presets) {
|
||||
log_debug("Preset files don't specify rule for %s. Enabling.", name);
|
||||
return 1;
|
||||
case PRESET_ENABLE:
|
||||
- log_debug("Preset files say enable %s.", name);
|
||||
+ if (instance_name_list && *instance_name_list)
|
||||
+ STRV_FOREACH(s, *instance_name_list)
|
||||
+ log_debug("Preset files say enable %s.", *s);
|
||||
+ else
|
||||
+ log_debug("Preset files say enable %s.", name);
|
||||
return 1;
|
||||
case PRESET_DISABLE:
|
||||
log_debug("Preset files say disable %s.", name);
|
||||
@@ -2904,7 +3005,7 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- return query_presets(name, presets);
|
||||
+ return query_presets(name, presets, NULL);
|
||||
}
|
||||
|
||||
static int execute_preset(
|
||||
@@ -2964,6 +3065,7 @@ static int preset_prepare_one(
|
||||
size_t *n_changes) {
|
||||
|
||||
_cleanup_(install_context_done) InstallContext tmp = {};
|
||||
+ _cleanup_strv_free_ char **instance_name_list = NULL;
|
||||
UnitFileInstallInfo *i;
|
||||
int r;
|
||||
|
||||
@@ -2979,19 +3081,34 @@ static int preset_prepare_one(
|
||||
return 0;
|
||||
}
|
||||
|
||||
- r = query_presets(name, presets);
|
||||
+ r = query_presets(name, presets, &instance_name_list);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (r > 0) {
|
||||
- r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
- &i, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ if (instance_name_list) {
|
||||
+ char **s;
|
||||
+ STRV_FOREACH(s, instance_name_list) {
|
||||
+ r = install_info_discover(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &i, changes, n_changes);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = install_info_may_process(i, paths, changes, n_changes);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+ } else {
|
||||
+ r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &i, changes, n_changes);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = install_info_may_process(i, paths, changes, n_changes);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
- r = install_info_may_process(i, paths, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
} else
|
||||
r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
&i, changes, n_changes);
|
||||
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
|
||||
index 15dd3c6966..dbbcfe4297 100644
|
||||
--- a/src/test/test-install-root.c
|
||||
+++ b/src/test/test-install-root.c
|
||||
@@ -983,6 +983,62 @@ static void test_with_dropin_template(const char *root) {
|
||||
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
}
|
||||
|
||||
+static void test_preset_multiple_instances(const char *root) {
|
||||
+ UnitFileChange *changes = NULL;
|
||||
+ size_t n_changes = 0;
|
||||
+ const char *p;
|
||||
+ UnitFileState state;
|
||||
+
|
||||
+ /* Set up template service files and preset file */
|
||||
+ p = strjoina(root, "/usr/lib/systemd/system/foo@.service");
|
||||
+ assert_se(write_string_file(p,
|
||||
+ "[Install]\n"
|
||||
+ "DefaultInstance=def\n"
|
||||
+ "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0);
|
||||
+
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||
+
|
||||
+ p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset");
|
||||
+ assert_se(write_string_file(p,
|
||||
+ "enable foo@.service bar0 bar1 bartest\n"
|
||||
+ "enable emptylist@.service\n" /* This line ensures the old functionality for templated unit still works */
|
||||
+ "disable *\n" , WRITE_STRING_FILE_CREATE) >= 0);
|
||||
+
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||
+
|
||||
+ /* Preset a single instantiated unit specified in the list */
|
||||
+ assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
+ assert_se(n_changes == 1);
|
||||
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
|
||||
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service");
|
||||
+ assert_se(streq(changes[0].path, p));
|
||||
+ unit_file_changes_free(changes, n_changes);
|
||||
+ changes = NULL; n_changes = 0;
|
||||
+
|
||||
+ assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), &changes, &n_changes) >= 0);
|
||||
+ assert_se(n_changes == 1);
|
||||
+ assert_se(changes[0].type == UNIT_FILE_UNLINK);
|
||||
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service");
|
||||
+ assert_se(streq(changes[0].path, p));
|
||||
+ unit_file_changes_free(changes, n_changes);
|
||||
+ changes = NULL; n_changes = 0;
|
||||
+
|
||||
+ /* Check for preset-all case, only instances on the list should be enabled, not including the default instance */
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||
+
|
||||
+ assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0);
|
||||
+ assert_se(n_changes > 0);
|
||||
+
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
+
|
||||
+}
|
||||
+
|
||||
int main(int argc, char *argv[]) {
|
||||
char root[] = "/tmp/rootXXXXXX";
|
||||
const char *p;
|
||||
@@ -1012,6 +1068,7 @@ int main(int argc, char *argv[]) {
|
||||
test_indirect(root);
|
||||
test_preset_and_list(root);
|
||||
test_preset_order(root);
|
||||
+ test_preset_multiple_instances(root);
|
||||
test_revert(root);
|
||||
test_static_instance(root);
|
||||
test_with_dropin(root);
|
@ -0,0 +1,127 @@
|
||||
From eacb511fc0d1e3c5857cb041ad162fb78b4381cc Mon Sep 17 00:00:00 2001
|
||||
From: Ruixin Bao <rubao@redhat.com>
|
||||
Date: Sun, 26 Aug 2018 20:00:03 +0000
|
||||
Subject: [PATCH] install: small refactor to combine two function calls into
|
||||
one function
|
||||
|
||||
Combine consecutive function calls of install_info_discover and
|
||||
install_info_may_process into one short helper function.
|
||||
|
||||
(cherry picked from commit 1e475a0ab4c46eb07f3df3fb24f5a7c3e1fa20b1)
|
||||
|
||||
Related: #1812972
|
||||
---
|
||||
src/shared/install.c | 61 ++++++++++++++++++++++----------------------
|
||||
1 file changed, 30 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/src/shared/install.c b/src/shared/install.c
|
||||
index 1d4beaa83b..263b239f10 100644
|
||||
--- a/src/shared/install.c
|
||||
+++ b/src/shared/install.c
|
||||
@@ -1676,6 +1676,25 @@ static int install_info_discover(
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int install_info_discover_and_check(
|
||||
+ UnitFileScope scope,
|
||||
+ InstallContext *c,
|
||||
+ const LookupPaths *paths,
|
||||
+ const char *name,
|
||||
+ SearchFlags flags,
|
||||
+ UnitFileInstallInfo **ret,
|
||||
+ UnitFileChange **changes,
|
||||
+ size_t *n_changes) {
|
||||
+
|
||||
+ int r;
|
||||
+
|
||||
+ r = install_info_discover(scope, c, paths, name, flags, ret, changes, n_changes);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return install_info_may_process(ret ? *ret : NULL, paths, changes, n_changes);
|
||||
+}
|
||||
+
|
||||
static int install_info_symlink_alias(
|
||||
UnitFileInstallInfo *i,
|
||||
const LookupPaths *paths,
|
||||
@@ -2399,11 +2418,8 @@ int unit_file_add_dependency(
|
||||
if (!config_path)
|
||||
return -ENXIO;
|
||||
|
||||
- r = install_info_discover(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
- &target_info, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- r = install_info_may_process(target_info, &paths, changes, n_changes);
|
||||
+ r = install_info_discover_and_check(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &target_info, changes, n_changes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2412,11 +2428,8 @@ int unit_file_add_dependency(
|
||||
STRV_FOREACH(f, files) {
|
||||
char ***l;
|
||||
|
||||
- r = install_info_discover(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
- &i, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- r = install_info_may_process(i, &paths, changes, n_changes);
|
||||
+ r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &i, changes, n_changes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2467,11 +2480,8 @@ int unit_file_enable(
|
||||
return -ENXIO;
|
||||
|
||||
STRV_FOREACH(f, files) {
|
||||
- r = install_info_discover(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
- &i, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- r = install_info_may_process(i, &paths, changes, n_changes);
|
||||
+ r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &i, changes, n_changes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2585,10 +2595,7 @@ int unit_file_set_default(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = install_info_discover(scope, &c, &paths, name, 0, &i, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- r = install_info_may_process(i, &paths, changes, n_changes);
|
||||
+ r = install_info_discover_and_check(scope, &c, &paths, name, 0, &i, changes, n_changes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -3089,22 +3096,14 @@ static int preset_prepare_one(
|
||||
if (instance_name_list) {
|
||||
char **s;
|
||||
STRV_FOREACH(s, instance_name_list) {
|
||||
- r = install_info_discover(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
- &i, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- r = install_info_may_process(i, paths, changes, n_changes);
|
||||
+ r = install_info_discover_and_check(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &i, changes, n_changes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
- r = install_info_discover(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
- &i, changes, n_changes);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- r = install_info_may_process(i, paths, changes, n_changes);
|
||||
+ r = install_info_discover_and_check(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS,
|
||||
+ &i, changes, n_changes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
28
SOURCES/0489-test-fix-a-memleak.patch
Normal file
28
SOURCES/0489-test-fix-a-memleak.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 7444c6ed3628484dfed2f204c5b78a06a50f4bd8 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 29 Aug 2018 23:27:42 +0900
|
||||
Subject: [PATCH] test: fix a memleak
|
||||
|
||||
Follow-up for #9901.
|
||||
|
||||
Fixes #9968.
|
||||
|
||||
(cherry picked from commit efa146369398fdb73f1cd177eb2522822ebf559c)
|
||||
|
||||
Related: #1812972
|
||||
---
|
||||
src/test/test-install-root.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
|
||||
index dbbcfe4297..fe1ca5b16f 100644
|
||||
--- a/src/test/test-install-root.c
|
||||
+++ b/src/test/test-install-root.c
|
||||
@@ -1037,6 +1037,7 @@ static void test_preset_multiple_instances(const char *root) {
|
||||
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
|
||||
|
||||
+ unit_file_changes_free(changes, n_changes);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
@ -0,0 +1,55 @@
|
||||
From 55df2fd634f900419b718ed354132cc86cd533dd Mon Sep 17 00:00:00 2001
|
||||
From: Joerg Behrmann <behrmann@physik.fu-berlin.de>
|
||||
Date: Tue, 10 Mar 2020 16:34:13 +0100
|
||||
Subject: [PATCH] docs: Add syntax for templated units to systemd.preset man
|
||||
page
|
||||
|
||||
This documents the syntax
|
||||
|
||||
enable template@.service foo bar baz
|
||||
|
||||
that was introduced in #9901 to preset templated units.
|
||||
|
||||
(cherry picked from commit 1f667d8a7cff4355cd23ebebeb4d7179e3498eb8)
|
||||
|
||||
Related: #1812972
|
||||
---
|
||||
man/systemd.preset.xml | 18 ++++++++++++++++--
|
||||
1 file changed, 16 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml
|
||||
index cf807bd4c8..df401f00f3 100644
|
||||
--- a/man/systemd.preset.xml
|
||||
+++ b/man/systemd.preset.xml
|
||||
@@ -71,8 +71,11 @@
|
||||
either the word <literal>enable</literal> or
|
||||
<literal>disable</literal> followed by a space and a unit name
|
||||
(possibly with shell style wildcards), separated by newlines.
|
||||
- Empty lines and lines whose first non-whitespace character is # or
|
||||
- ; are ignored.</para>
|
||||
+ Empty lines and lines whose first non-whitespace character is <literal>#</literal> or
|
||||
+ <literal>;</literal> are ignored. Multiple instance names for unit
|
||||
+ templates may be specified as a space separated list at the end of
|
||||
+ the line instead of the customary position between <literal>@</literal>
|
||||
+ and the unit suffix.</para>
|
||||
|
||||
<para>Presets must refer to the "real" unit file, and not to any aliases. See
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
@@ -124,6 +127,17 @@ disable *</programlisting>
|
||||
<literal>99-</literal>, it will be read last and hence can easily
|
||||
be overridden by spin or administrator preset policy.</para>
|
||||
|
||||
+ <example>
|
||||
+ <title>Enable multiple template instances</title>
|
||||
+
|
||||
+ <programlisting># /usr/lib/systemd/system-preset/80-dirsrv.preset
|
||||
+
|
||||
+enable dirsrv@.service foo bar baz</programlisting>
|
||||
+ </example>
|
||||
+
|
||||
+ <para>This enables all three of <filename>dirsrv@foo.service</filename>,
|
||||
+ <filename>dirsrv@bar.service</filename> and <filename>dirsrv@baz.service</filename>.</para>
|
||||
+
|
||||
<example>
|
||||
<title>A GNOME spin</title>
|
||||
|
@ -0,0 +1,45 @@
|
||||
From db2816ee32fc81ba339175469e46b5dca7af8833 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Sat, 22 Aug 2020 11:58:15 +0200
|
||||
Subject: [PATCH] shared/install: fix preset operations for non-service
|
||||
instantiated units
|
||||
|
||||
Fixes https://github.com/coreos/ignition/issues/1064.
|
||||
|
||||
(cherry picked from commit 47ab95fe4315b3f7ee5a3694460a744bb88c52fd)
|
||||
|
||||
Related: #1812972
|
||||
---
|
||||
src/shared/install.c | 13 +++++--------
|
||||
1 file changed, 5 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/shared/install.c b/src/shared/install.c
|
||||
index 263b239f10..c2847df3f8 100644
|
||||
--- a/src/shared/install.c
|
||||
+++ b/src/shared/install.c
|
||||
@@ -2937,20 +2937,17 @@ static int pattern_match_multiple_instances(
|
||||
|
||||
/* Compose a list of specified instances when unit name is a template */
|
||||
if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
|
||||
- _cleanup_free_ char *prefix = NULL;
|
||||
_cleanup_strv_free_ char **out_strv = NULL;
|
||||
- char **iter;
|
||||
-
|
||||
- r = unit_name_to_prefix(unit_name, &prefix);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
|
||||
+ char **iter;
|
||||
STRV_FOREACH(iter, rule.instances) {
|
||||
_cleanup_free_ char *name = NULL;
|
||||
- r = unit_name_build(prefix, *iter, ".service", &name);
|
||||
+
|
||||
+ r = unit_name_replace_instance(unit_name, *iter, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
- r = strv_extend(&out_strv, name);
|
||||
+
|
||||
+ r = strv_consume(&out_strv, TAKE_PTR(name));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
30
SOURCES/0492-introduce-setsockopt_int-helper.patch
Normal file
30
SOURCES/0492-introduce-setsockopt_int-helper.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 8cff80d7fc28ca04bd6c8e2257b46d96bea338ce Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 18 Oct 2018 19:48:18 +0200
|
||||
Subject: [PATCH] introduce setsockopt_int() helper
|
||||
|
||||
As suggested by @heftig:
|
||||
|
||||
https://github.com/systemd/systemd/commit/6d5e65f6454212cd400d0ebda34978a9f20cc26a#commitcomment-30938667
|
||||
(cherry picked from commit 2ff48e981e6cd1ccbfae49943274d9c8319a5e5d)
|
||||
|
||||
Related: #1887181
|
||||
---
|
||||
src/basic/socket-util.h | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
|
||||
index 82781a0de1..616f2e0d05 100644
|
||||
--- a/src/basic/socket-util.h
|
||||
+++ b/src/basic/socket-util.h
|
||||
@@ -183,3 +183,10 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng
|
||||
})
|
||||
|
||||
int socket_ioctl_fd(void);
|
||||
+
|
||||
+static inline int setsockopt_int(int fd, int level, int optname, int value) {
|
||||
+ if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
@ -0,0 +1,57 @@
|
||||
From 96681723232e9eb0182279086fef291283004806 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 27 May 2020 19:27:51 +0200
|
||||
Subject: [PATCH] socket-util: add generic socket_pass_pktinfo() helper
|
||||
|
||||
The helper turns on the protocol specific "packet info" structure cmsg
|
||||
for three relevant protocols we know.
|
||||
|
||||
(cherry picked from commit 35a3eb9bdc95d1e6ba25bc65c78959ea104e45a1)
|
||||
|
||||
Related: #1887181
|
||||
---
|
||||
src/basic/socket-util.c | 23 +++++++++++++++++++++++
|
||||
src/basic/socket-util.h | 2 ++
|
||||
2 files changed, 25 insertions(+)
|
||||
|
||||
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
|
||||
index 986bc6e67f..053bcba670 100644
|
||||
--- a/src/basic/socket-util.c
|
||||
+++ b/src/basic/socket-util.c
|
||||
@@ -1246,3 +1246,26 @@ int socket_ioctl_fd(void) {
|
||||
|
||||
return fd;
|
||||
}
|
||||
+
|
||||
+int socket_pass_pktinfo(int fd, bool b) {
|
||||
+ int af;
|
||||
+ socklen_t sl = sizeof(af);
|
||||
+
|
||||
+ if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
+ switch (af) {
|
||||
+
|
||||
+ case AF_INET:
|
||||
+ return setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, b);
|
||||
+
|
||||
+ case AF_INET6:
|
||||
+ return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, b);
|
||||
+
|
||||
+ case AF_NETLINK:
|
||||
+ return setsockopt_int(fd, SOL_NETLINK, NETLINK_PKTINFO, b);
|
||||
+
|
||||
+ default:
|
||||
+ return -EAFNOSUPPORT;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
|
||||
index 616f2e0d05..c7c9ad34d6 100644
|
||||
--- a/src/basic/socket-util.h
|
||||
+++ b/src/basic/socket-util.h
|
||||
@@ -190,3 +190,5 @@ static inline int setsockopt_int(int fd, int level, int optname, int value) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int socket_pass_pktinfo(int fd, bool b);
|
@ -0,0 +1,156 @@
|
||||
From 905a97ce65352d80af7260d34b74fd8342792c35 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 27 May 2020 19:36:56 +0200
|
||||
Subject: [PATCH] core: add new PassPacketInfo= socket unit property
|
||||
|
||||
(cherry picked from commit a3d19f5d99c44940831a33df8b5bece4aaf749f7)
|
||||
|
||||
Resolves: #1887181
|
||||
---
|
||||
doc/TRANSIENT-SETTINGS.md | 1 +
|
||||
man/systemd.socket.xml | 9 +++++++++
|
||||
src/core/dbus-socket.c | 4 ++++
|
||||
src/core/load-fragment-gperf.gperf.m4 | 1 +
|
||||
src/core/socket.c | 8 ++++++++
|
||||
src/core/socket.h | 1 +
|
||||
src/shared/bus-unit-util.c | 3 +--
|
||||
test/fuzz/fuzz-unit-file/directives.service | 1 +
|
||||
8 files changed, 26 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/TRANSIENT-SETTINGS.md b/doc/TRANSIENT-SETTINGS.md
|
||||
index 995b8797ef..de0ef9cc49 100644
|
||||
--- a/doc/TRANSIENT-SETTINGS.md
|
||||
+++ b/doc/TRANSIENT-SETTINGS.md
|
||||
@@ -410,6 +410,7 @@ Most socket unit settings are available to transient units.
|
||||
✓ Broadcast=
|
||||
✓ PassCredentials=
|
||||
✓ PassSecurity=
|
||||
+✓ PassPacketInfo=
|
||||
✓ TCPCongestion=
|
||||
✓ ReusePort=
|
||||
✓ MessageQueueMaxMessages=
|
||||
diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
|
||||
index 8676b4e03f..a908d5b6d8 100644
|
||||
--- a/man/systemd.socket.xml
|
||||
+++ b/man/systemd.socket.xml
|
||||
@@ -712,6 +712,15 @@
|
||||
Defaults to <option>false</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>PassPacketInfo=</varname></term>
|
||||
+ <listitem><para>Takes a boolean value. This controls the <constant>IP_PKTINFO</constant>,
|
||||
+ <constant>IPV6_RECVPKTINFO</constant> and <constant>NETLINK_PKTINFO</constant> socket options, which
|
||||
+ enable reception of additional per-packet metadata as ancillary message, on
|
||||
+ <constant>AF_INET</constant>, <constant>AF_INET6</constant> and <constant>AF_UNIX</constant> sockets.
|
||||
+ Defaults to <option>false</option>.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>TCPCongestion=</varname></term>
|
||||
<listitem><para>Takes a string value. Controls the TCP
|
||||
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
|
||||
index fa6bbe2c6f..17494b80c8 100644
|
||||
--- a/src/core/dbus-socket.c
|
||||
+++ b/src/core/dbus-socket.c
|
||||
@@ -104,6 +104,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("PassPacketInfo", "b", bus_property_get_bool, offsetof(Socket, pass_pktinfo), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -205,6 +206,9 @@ static int bus_socket_set_transient_property(
|
||||
if (streq(name, "PassSecurity"))
|
||||
return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error);
|
||||
|
||||
+ if (streq(name, "PassPacketInfo"))
|
||||
+ return bus_set_transient_bool(u, name, &s->pass_pktinfo, message, flags, error);
|
||||
+
|
||||
if (streq(name, "ReusePort"))
|
||||
return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error);
|
||||
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
||||
index 156a4d0a6d..7d683cc84b 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.m4
|
||||
+++ b/src/core/load-fragment-gperf.gperf.m4
|
||||
@@ -381,6 +381,7 @@ Socket.Transparent, config_parse_bool, 0,
|
||||
Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast)
|
||||
Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
|
||||
Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
|
||||
+Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo)
|
||||
Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
|
||||
Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
|
||||
Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index 97c3a7fc9a..50c32ed8f4 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -660,6 +660,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
"%sBroadcast: %s\n"
|
||||
"%sPassCredentials: %s\n"
|
||||
"%sPassSecurity: %s\n"
|
||||
+ "%sPassPacketInfo: %s\n"
|
||||
"%sTCPCongestion: %s\n"
|
||||
"%sRemoveOnStop: %s\n"
|
||||
"%sWritable: %s\n"
|
||||
@@ -678,6 +679,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
prefix, yes_no(s->broadcast),
|
||||
prefix, yes_no(s->pass_cred),
|
||||
prefix, yes_no(s->pass_sec),
|
||||
+ prefix, yes_no(s->pass_pktinfo),
|
||||
prefix, strna(s->tcp_congestion),
|
||||
prefix, yes_no(s->remove_on_stop),
|
||||
prefix, yes_no(s->writable),
|
||||
@@ -1099,6 +1101,12 @@ static void socket_apply_socket_options(Socket *s, int fd) {
|
||||
log_unit_warning_errno(UNIT(s), errno, "SO_PASSSEC failed: %m");
|
||||
}
|
||||
|
||||
+ if (s->pass_pktinfo) {
|
||||
+ r = socket_pass_pktinfo(fd, true);
|
||||
+ if (r < 0)
|
||||
+ log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m");
|
||||
+ }
|
||||
+
|
||||
if (s->priority >= 0)
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &s->priority, sizeof(s->priority)) < 0)
|
||||
log_unit_warning_errno(UNIT(s), errno, "SO_PRIORITY failed: %m");
|
||||
diff --git a/src/core/socket.h b/src/core/socket.h
|
||||
index b7a25d91fd..2409dbf2a0 100644
|
||||
--- a/src/core/socket.h
|
||||
+++ b/src/core/socket.h
|
||||
@@ -121,6 +121,7 @@ struct Socket {
|
||||
bool broadcast;
|
||||
bool pass_cred;
|
||||
bool pass_sec;
|
||||
+ bool pass_pktinfo;
|
||||
|
||||
/* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
|
||||
SocketAddressBindIPv6Only bind_ipv6_only;
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index daa2c2dce5..9010448aaf 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -1478,8 +1478,7 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
|
||||
if (STR_IN_SET(field,
|
||||
"Accept", "Writable", "KeepAlive", "NoDelay", "FreeBind", "Transparent", "Broadcast",
|
||||
"PassCredentials", "PassSecurity", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet",
|
||||
- "FlushPending"))
|
||||
-
|
||||
+ "FlushPending", "PassPacketInfo"))
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "Priority", "IPTTL", "Mark"))
|
||||
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
|
||||
index 9d0530df72..8fde27fc90 100644
|
||||
--- a/test/fuzz/fuzz-unit-file/directives.service
|
||||
+++ b/test/fuzz/fuzz-unit-file/directives.service
|
||||
@@ -161,6 +161,7 @@ PIDFile=
|
||||
PartOf=
|
||||
PassCredentials=
|
||||
PassSecurity=
|
||||
+PassPacketInfo=
|
||||
PathChanged=
|
||||
PathExists=
|
||||
PathExistsGlob=
|
30
SOURCES/0495-resolved-tweak-cmsg-calculation.patch
Normal file
30
SOURCES/0495-resolved-tweak-cmsg-calculation.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 6ece87bef14ac5741fc870644504737b00607546 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 27 May 2020 19:38:38 +0200
|
||||
Subject: [PATCH] resolved: tweak cmsg calculation
|
||||
|
||||
We ask for the TTL, then have enough space for it.
|
||||
|
||||
We probably can drop the extra cmsg space now, but let's figure that out
|
||||
another time, since the extra cmsg space is used elsewhere in resolved
|
||||
as well.
|
||||
|
||||
(cherry picked from commit 08ab18618ec59022582f1513c0718ba369f5ba85)
|
||||
|
||||
Related: #1887181
|
||||
---
|
||||
src/resolve/resolved-dns-stream.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
|
||||
index 066daef96e..555e200a23 100644
|
||||
--- a/src/resolve/resolved-dns-stream.c
|
||||
+++ b/src/resolve/resolved-dns-stream.c
|
||||
@@ -70,6 +70,7 @@ static int dns_stream_identify(DnsStream *s) {
|
||||
union {
|
||||
struct cmsghdr header; /* For alignment */
|
||||
uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
|
||||
+ + CMSG_SPACE(int) + /* for the TTL */
|
||||
+ EXTRA_CMSG_SPACE /* kernel appears to require extra space */];
|
||||
} control;
|
||||
struct msghdr mh = {};
|
@ -0,0 +1,26 @@
|
||||
From 07b154fbc817e93f58c597644570a633c38d1c72 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Fri, 15 Jan 2021 12:51:02 +0100
|
||||
Subject: [PATCH] ci: PowerTools repo was renamed to powertools in RHEL 8.3
|
||||
|
||||
See: https://wiki.centos.org/Manuals/ReleaseNotes/CentOS8.2011#Yum_repo_file_and_repoid_changes
|
||||
|
||||
rhel-only
|
||||
Related: #1871827
|
||||
---
|
||||
ci/travis-centos-rhel8.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ci/travis-centos-rhel8.sh b/ci/travis-centos-rhel8.sh
|
||||
index cd0857fd29..43e2cb2585 100755
|
||||
--- a/ci/travis-centos-rhel8.sh
|
||||
+++ b/ci/travis-centos-rhel8.sh
|
||||
@@ -95,7 +95,7 @@ for phase in "${PHASES[@]}"; do
|
||||
# Upgrade the container to get the most recent environment
|
||||
$DOCKER_EXEC dnf -y upgrade
|
||||
# Install systemd's build dependencies
|
||||
- $DOCKER_EXEC dnf -q -y --enablerepo "PowerTools" builddep systemd
|
||||
+ $DOCKER_EXEC dnf -q -y --enablerepo "powertools" builddep systemd
|
||||
;;
|
||||
RUN)
|
||||
info "Run phase"
|
@ -0,0 +1,33 @@
|
||||
From 2dd82aad646bde5a0d49df8562e2578c8b3d04f4 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Fri, 15 Jan 2021 13:00:33 +0100
|
||||
Subject: [PATCH] ci: use quay.io instead of Docker Hub to avoid rate limits
|
||||
|
||||
Docker Hub introduced rate limits for anonymous users (100 requests per
|
||||
six hours), which break our CI in the busier periods. Let's try to use
|
||||
the quay.io CentOS image to mitigate this.
|
||||
|
||||
rhel-only
|
||||
Related: #1871827
|
||||
---
|
||||
ci/travis-centos-rhel8.sh | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ci/travis-centos-rhel8.sh b/ci/travis-centos-rhel8.sh
|
||||
index 43e2cb2585..ffe5813b1a 100755
|
||||
--- a/ci/travis-centos-rhel8.sh
|
||||
+++ b/ci/travis-centos-rhel8.sh
|
||||
@@ -81,11 +81,11 @@ for phase in "${PHASES[@]}"; do
|
||||
info "Setup phase"
|
||||
info "Using Travis $CENTOS_RELEASE"
|
||||
# Pull a Docker image and start a new container
|
||||
- docker pull centos:$CENTOS_RELEASE
|
||||
+ docker pull quay.io/centos/centos:$CENTOS_RELEASE
|
||||
info "Starting container $CONT_NAME"
|
||||
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
||||
-w /build --privileged=true --name $CONT_NAME \
|
||||
- -dit --net=host centos:$CENTOS_RELEASE /sbin/init
|
||||
+ -dit --net=host quay.io/centos/centos:$CENTOS_RELEASE /sbin/init
|
||||
# Beautiful workaround for Fedora's version of Docker
|
||||
sleep 1
|
||||
$DOCKER_EXEC dnf makecache
|
338
SOURCES/0498-ci-move-jobs-from-Travis-CI-to-GH-Actions.patch
Normal file
338
SOURCES/0498-ci-move-jobs-from-Travis-CI-to-GH-Actions.patch
Normal file
@ -0,0 +1,338 @@
|
||||
From 88ac207cc619935c64923e6f8fdef324a5b733d8 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Fri, 15 Jan 2021 15:13:53 +0100
|
||||
Subject: [PATCH] ci: move jobs from Travis CI to GH Actions
|
||||
|
||||
The OSS version of Travis CI is going to be merged with the commercial
|
||||
one soon, essentially dropping the free tier, so let's move the CI jobs
|
||||
to GitHub Actions to keep them up.
|
||||
|
||||
rhel-only
|
||||
Related: #1871827
|
||||
---
|
||||
.../workflows/unit_tests.sh | 28 +++----
|
||||
.github/workflows/unit_tests.yml | 28 +++++++
|
||||
.travis.yml | 48 ------------
|
||||
ci/travis-centos-rhel7.sh | 73 -------------------
|
||||
ci/travis_wait.bash | 61 ----------------
|
||||
5 files changed, 37 insertions(+), 201 deletions(-)
|
||||
rename ci/travis-centos-rhel8.sh => .github/workflows/unit_tests.sh (82%)
|
||||
create mode 100644 .github/workflows/unit_tests.yml
|
||||
delete mode 100644 .travis.yml
|
||||
delete mode 100755 ci/travis-centos-rhel7.sh
|
||||
delete mode 100644 ci/travis_wait.bash
|
||||
|
||||
diff --git a/ci/travis-centos-rhel8.sh b/.github/workflows/unit_tests.sh
|
||||
similarity index 82%
|
||||
rename from ci/travis-centos-rhel8.sh
|
||||
rename to .github/workflows/unit_tests.sh
|
||||
index ffe5813b1a..ea4f7e7592 100755
|
||||
--- a/ci/travis-centos-rhel8.sh
|
||||
+++ b/.github/workflows/unit_tests.sh
|
||||
@@ -1,18 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
-# Run this script from the root of the systemd's git repository
|
||||
-# or set REPO_ROOT to a correct path.
|
||||
-#
|
||||
-# Example execution on Fedora:
|
||||
-# dnf install docker
|
||||
-# systemctl start docker
|
||||
-# export CONT_NAME="my-fancy-container"
|
||||
-# ci/travis-centos.sh SETUP RUN CLEANUP
|
||||
-
|
||||
PHASES=(${@:-SETUP RUN CLEANUP})
|
||||
CENTOS_RELEASE="${CENTOS_RELEASE:-latest}"
|
||||
CONT_NAME="${CONT_NAME:-centos-$CENTOS_RELEASE-$RANDOM}"
|
||||
-DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
|
||||
+DOCKER_EXEC="${DOCKER_EXEC:-docker exec $CONT_NAME}"
|
||||
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
||||
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
||||
ADDITIONAL_DEPS=(libasan libubsan net-tools strace nc e2fsprogs quota dnsmasq diffutils)
|
||||
@@ -71,9 +62,7 @@ function info() {
|
||||
echo -e "\033[33;1m$1\033[0m"
|
||||
}
|
||||
|
||||
-set -e
|
||||
-
|
||||
-source "$(dirname $0)/travis_wait.bash"
|
||||
+set -ex
|
||||
|
||||
for phase in "${PHASES[@]}"; do
|
||||
case $phase in
|
||||
@@ -86,6 +75,7 @@ for phase in "${PHASES[@]}"; do
|
||||
$DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
||||
-w /build --privileged=true --name $CONT_NAME \
|
||||
-dit --net=host quay.io/centos/centos:$CENTOS_RELEASE /sbin/init
|
||||
+
|
||||
# Beautiful workaround for Fedora's version of Docker
|
||||
sleep 1
|
||||
$DOCKER_EXEC dnf makecache
|
||||
@@ -97,10 +87,10 @@ for phase in "${PHASES[@]}"; do
|
||||
# Install systemd's build dependencies
|
||||
$DOCKER_EXEC dnf -q -y --enablerepo "powertools" builddep systemd
|
||||
;;
|
||||
- RUN)
|
||||
+ RUN|RUN_GCC)
|
||||
info "Run phase"
|
||||
# Build systemd
|
||||
- docker exec -it -e CFLAGS='-g -O0 -ftrapv' $CONT_NAME meson build -Dtests=unsafe -Dslow-tests=true "${CONFIGURE_OPTS[@]}"
|
||||
+ docker exec -e CFLAGS='-g -O0 -ftrapv' $CONT_NAME meson build -Dtests=unsafe -Dslow-tests=true "${CONFIGURE_OPTS[@]}"
|
||||
$DOCKER_EXEC ninja -v -C build
|
||||
# Let's install the new systemd and "reboot" the container to avoid
|
||||
# unexpected fails due to incompatibilities with older systemd
|
||||
@@ -108,16 +98,16 @@ for phase in "${PHASES[@]}"; do
|
||||
docker restart $CONT_NAME
|
||||
$DOCKER_EXEC ninja -C build test
|
||||
;;
|
||||
- RUN_ASAN|RUN_CLANG_ASAN)
|
||||
+ RUN_ASAN|RUN_GCC_ASAN|RUN_CLANG_ASAN)
|
||||
if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
|
||||
ENV_VARS="-e CC=clang -e CXX=clang++"
|
||||
MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764
|
||||
fi
|
||||
- docker exec $ENV_VARS -it $CONT_NAME meson build --werror -Dtests=unsafe -Db_sanitize=address,undefined $MESON_ARGS "${CONFIGURE_OPTS[@]}"
|
||||
- docker exec -it $CONT_NAME ninja -v -C build
|
||||
+ docker exec $ENV_VARS $CONT_NAME meson build --werror -Dtests=unsafe -Db_sanitize=address,undefined $MESON_ARGS "${CONFIGURE_OPTS[@]}"
|
||||
+ docker exec $CONT_NAME ninja -v -C build
|
||||
|
||||
# Never remove halt_on_error from UBSAN_OPTIONS. See https://github.com/systemd/systemd/commit/2614d83aa06592aedb.
|
||||
- travis_wait docker exec --interactive=false \
|
||||
+ docker exec --interactive=false \
|
||||
-e UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 \
|
||||
-e ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 \
|
||||
-e "TRAVIS=$TRAVIS" \
|
||||
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
|
||||
new file mode 100644
|
||||
index 0000000000..15f5127a75
|
||||
--- /dev/null
|
||||
+++ b/.github/workflows/unit_tests.yml
|
||||
@@ -0,0 +1,28 @@
|
||||
+---
|
||||
+# vi: ts=2 sw=2 et:
|
||||
+#
|
||||
+name: Unit tests
|
||||
+on:
|
||||
+ pull_request:
|
||||
+ branches:
|
||||
+ - master
|
||||
+
|
||||
+jobs:
|
||||
+ build:
|
||||
+ runs-on: ubuntu-20.04
|
||||
+ env:
|
||||
+ CENTOS_RELEASE: "centos8"
|
||||
+ CONT_NAME: "systemd-centos8-ci"
|
||||
+ strategy:
|
||||
+ fail-fast: false
|
||||
+ matrix:
|
||||
+ run_phase: [GCC, GCC_ASAN]
|
||||
+ steps:
|
||||
+ - name: Repository checkout
|
||||
+ uses: actions/checkout@v1
|
||||
+ - name: Install build dependencies
|
||||
+ run: sudo -E .github/workflows/unit_tests.sh SETUP
|
||||
+ - name: Build & test (${{ matrix.run_phase }})
|
||||
+ run: sudo -E .github/workflows/unit_tests.sh RUN_${{ matrix.run_phase }}
|
||||
+ - name: Cleanup
|
||||
+ run: sudo -E .github/workflows/unit_tests.sh CLEANUP
|
||||
diff --git a/.travis.yml b/.travis.yml
|
||||
deleted file mode 100644
|
||||
index 70c60cf24e..0000000000
|
||||
--- a/.travis.yml
|
||||
+++ /dev/null
|
||||
@@ -1,48 +0,0 @@
|
||||
-sudo: required
|
||||
-dist: xenial
|
||||
-services:
|
||||
- - docker
|
||||
-
|
||||
-env:
|
||||
- global:
|
||||
- - CI_ROOT="$TRAVIS_BUILD_DIR/ci/"
|
||||
-
|
||||
-jobs:
|
||||
- include:
|
||||
- - name: CentOS 8
|
||||
- language: bash
|
||||
- env:
|
||||
- - CENTOS_RELEASE="centos8"
|
||||
- - CONT_NAME="systemd-centos-$CENTOS_RELEASE"
|
||||
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
|
||||
- before_install:
|
||||
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
||||
- - docker --version
|
||||
- install:
|
||||
- - $CI_ROOT/travis-centos-rhel8.sh SETUP
|
||||
- script:
|
||||
- - set -e
|
||||
- # Build systemd
|
||||
- - $CI_ROOT/travis-centos-rhel8.sh RUN
|
||||
- - set +e
|
||||
- after_script:
|
||||
- - $CI_ROOT/travis-centos-rhel8.sh CLEANUP
|
||||
-
|
||||
- - name: CentOS 8 (ASan+UBSan)
|
||||
- language: bash
|
||||
- env:
|
||||
- - CENTOS_RELEASE="centos8"
|
||||
- - CONT_NAME="systemd-centos-$CENTOS_RELEASE"
|
||||
- - DOCKER_EXEC="docker exec -ti $CONT_NAME"
|
||||
- before_install:
|
||||
- - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
||||
- - docker --version
|
||||
- install:
|
||||
- - $CI_ROOT/travis-centos-rhel8.sh SETUP
|
||||
- script:
|
||||
- - set -e
|
||||
- # Build systemd
|
||||
- - $CI_ROOT/travis-centos-rhel8.sh RUN_ASAN
|
||||
- - set +e
|
||||
- after_script:
|
||||
- - $CI_ROOT/travis-centos-rhel8.sh CLEANUP
|
||||
diff --git a/ci/travis-centos-rhel7.sh b/ci/travis-centos-rhel7.sh
|
||||
deleted file mode 100755
|
||||
index 73416798ed..0000000000
|
||||
--- a/ci/travis-centos-rhel7.sh
|
||||
+++ /dev/null
|
||||
@@ -1,73 +0,0 @@
|
||||
-#!/bin/bash
|
||||
-
|
||||
-# Run this script from the root of the systemd's git repository
|
||||
-# or set REPO_ROOT to a correct path.
|
||||
-#
|
||||
-# Example execution on Fedora:
|
||||
-# dnf install docker
|
||||
-# systemctl start docker
|
||||
-# export CONT_NAME="my-fancy-container"
|
||||
-# ci/travis-centos.sh SETUP RUN CLEANUP
|
||||
-
|
||||
-PHASES=(${@:-SETUP RUN CLEANUP})
|
||||
-CENTOS_RELEASE="${CENTOS_RELEASE:-latest}"
|
||||
-CONT_NAME="${CONT_NAME:-centos-$CENTOS_RELEASE-$RANDOM}"
|
||||
-DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
|
||||
-DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
||||
-REPO_ROOT="${REPO_ROOT:-$PWD}"
|
||||
-ADDITIONAL_DEPS=(yum-utils iputils hostname libasan libubsan clang llvm)
|
||||
-
|
||||
-function info() {
|
||||
- echo -e "\033[33;1m$1\033[0m"
|
||||
-}
|
||||
-
|
||||
-set -e
|
||||
-
|
||||
-source "$(dirname $0)/travis_wait.bash"
|
||||
-
|
||||
-for phase in "${PHASES[@]}"; do
|
||||
- case $phase in
|
||||
- SETUP)
|
||||
- info "Setup phase"
|
||||
- info "Using Travis $CENTOS_RELEASE"
|
||||
- # Pull a Docker image and start a new container
|
||||
- docker pull centos:$CENTOS_RELEASE
|
||||
- info "Starting container $CONT_NAME"
|
||||
- $DOCKER_RUN -v $REPO_ROOT:/build:rw \
|
||||
- -w /build --privileged=true --name $CONT_NAME \
|
||||
- -dit --net=host centos:$CENTOS_RELEASE /sbin/init
|
||||
- # Beautiful workaround for Fedora's version of Docker
|
||||
- sleep 1
|
||||
- $DOCKER_EXEC yum makecache
|
||||
- # Install necessary build/test requirements
|
||||
- $DOCKER_EXEC yum -y upgrade
|
||||
- $DOCKER_EXEC yum -y install "${ADDITIONAL_DEPS[@]}"
|
||||
- $DOCKER_EXEC yum-builddep -y systemd
|
||||
- ;;
|
||||
- RUN)
|
||||
- info "Run phase"
|
||||
- # Build systemd
|
||||
- $DOCKER_EXEC ./autogen.sh
|
||||
- $DOCKER_EXEC ./configure --disable-timesyncd --disable-kdbus --disable-terminal \
|
||||
- --enable-gtk-doc --enable-compat-libs --disable-sysusers \
|
||||
- --disable-ldconfig --enable-lz4 --with-sysvinit-path=/etc/rc.d/init.d
|
||||
- $DOCKER_EXEC make
|
||||
- # Let's install the new systemd and "reboot" the container to avoid
|
||||
- # unexpected fails due to incompatibilities with older systemd
|
||||
- $DOCKER_EXEC make install
|
||||
- docker restart $CONT_NAME
|
||||
- if ! $DOCKER_EXEC make check; then
|
||||
- $DOCKER_EXEC cat test-suite.log
|
||||
- exit 1
|
||||
- fi
|
||||
- ;;
|
||||
- CLEANUP)
|
||||
- info "Cleanup phase"
|
||||
- docker stop $CONT_NAME
|
||||
- docker rm -f $CONT_NAME
|
||||
- ;;
|
||||
- *)
|
||||
- echo >&2 "Unknown phase '$phase'"
|
||||
- exit 1
|
||||
- esac
|
||||
-done
|
||||
diff --git a/ci/travis_wait.bash b/ci/travis_wait.bash
|
||||
deleted file mode 100644
|
||||
index acf6ad15e4..0000000000
|
||||
--- a/ci/travis_wait.bash
|
||||
+++ /dev/null
|
||||
@@ -1,61 +0,0 @@
|
||||
-# This was borrowed from https://github.com/travis-ci/travis-build/tree/master/lib/travis/build/bash
|
||||
-# to get around https://github.com/travis-ci/travis-ci/issues/9979. It should probably be removed
|
||||
-# as soon as Travis CI has started to provide an easy way to export the functions to bash scripts.
|
||||
-
|
||||
-travis_jigger() {
|
||||
- local cmd_pid="${1}"
|
||||
- shift
|
||||
- local timeout="${1}"
|
||||
- shift
|
||||
- local count=0
|
||||
-
|
||||
- echo -e "\\n"
|
||||
-
|
||||
- while [[ "${count}" -lt "${timeout}" ]]; do
|
||||
- count="$((count + 1))"
|
||||
- echo -ne "Still running (${count} of ${timeout}): ${*}\\r"
|
||||
- sleep 60
|
||||
- done
|
||||
-
|
||||
- echo -e "\\n${ANSI_RED}Timeout (${timeout} minutes) reached. Terminating \"${*}\"${ANSI_RESET}\\n"
|
||||
- kill -9 "${cmd_pid}"
|
||||
-}
|
||||
-
|
||||
-travis_wait() {
|
||||
- local timeout="${1}"
|
||||
-
|
||||
- if [[ "${timeout}" =~ ^[0-9]+$ ]]; then
|
||||
- shift
|
||||
- else
|
||||
- timeout=20
|
||||
- fi
|
||||
-
|
||||
- local cmd=("${@}")
|
||||
- local log_file="travis_wait_${$}.log"
|
||||
-
|
||||
- "${cmd[@]}" &>"${log_file}" &
|
||||
- local cmd_pid="${!}"
|
||||
-
|
||||
- travis_jigger "${!}" "${timeout}" "${cmd[@]}" &
|
||||
- local jigger_pid="${!}"
|
||||
- local result
|
||||
-
|
||||
- {
|
||||
- set +e
|
||||
- wait "${cmd_pid}" 2>/dev/null
|
||||
- result="${?}"
|
||||
- ps -p"${jigger_pid}" &>/dev/null && kill "${jigger_pid}"
|
||||
- set -e
|
||||
- }
|
||||
-
|
||||
- if [[ "${result}" -eq 0 ]]; then
|
||||
- echo -e "\\n${ANSI_GREEN}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}"
|
||||
- else
|
||||
- echo -e "\\n${ANSI_RED}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}"
|
||||
- fi
|
||||
-
|
||||
- echo -e "\\n${ANSI_GREEN}Log:${ANSI_RESET}\\n"
|
||||
- cat "${log_file}"
|
||||
-
|
||||
- return "${result}"
|
||||
-}
|
@ -0,0 +1,31 @@
|
||||
From a11334f0eae67b5159a416193e2e37634281000a Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 8 Nov 2018 09:33:31 +0100
|
||||
Subject: [PATCH] unit: make UNIT() cast function deal with NULL pointers
|
||||
|
||||
Fixes: #10681
|
||||
(cherry picked from commit bbf11206230d1b089118971f98a047151cb5c4fa)
|
||||
|
||||
Related: #1871827
|
||||
---
|
||||
src/core/unit.h | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 6e37fd6f5a..ec45b5fb48 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -597,7 +597,12 @@ extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
|
||||
}
|
||||
|
||||
/* For casting the various unit types into a unit */
|
||||
-#define UNIT(u) (&(u)->meta)
|
||||
+#define UNIT(u) \
|
||||
+ ({ \
|
||||
+ typeof(u) _u_ = (u); \
|
||||
+ Unit *_w_ = _u_ ? &(_u_)->meta : NULL; \
|
||||
+ _w_; \
|
||||
+ })
|
||||
|
||||
#define UNIT_HAS_EXEC_CONTEXT(u) (UNIT_VTABLE(u)->exec_context_offset > 0)
|
||||
#define UNIT_HAS_CGROUP_CONTEXT(u) (UNIT_VTABLE(u)->cgroup_context_offset > 0)
|
25
SOURCES/0500-use-link-to-RHEL-8-docs.patch
Normal file
25
SOURCES/0500-use-link-to-RHEL-8-docs.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 6fb6c218fda0d5c3404049243b9392e9b0c7d537 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Fri, 11 Dec 2020 09:34:19 +0100
|
||||
Subject: [PATCH] use link to RHEL-8 docs
|
||||
|
||||
RHEL-only
|
||||
|
||||
Related: #1623116
|
||||
---
|
||||
man/systemctl.xml | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/man/systemctl.xml b/man/systemctl.xml
|
||||
index 56f94d084c..ed60a0739f 100644
|
||||
--- a/man/systemctl.xml
|
||||
+++ b/man/systemctl.xml
|
||||
@@ -2005,7 +2005,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<para>
|
||||
For examples how to use systemctl in comparsion
|
||||
with old service and chkconfig command please see:
|
||||
- <ulink url="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/sect-Managing_Services_with_systemd-Services.html">
|
||||
+ <ulink url="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-services-with-systemd_configuring-basic-system-settings">
|
||||
Managing System Services
|
||||
</ulink>
|
||||
</para>
|
37
SOURCES/0501-cgroup-Also-set-blkio.bfq.weight.patch
Normal file
37
SOURCES/0501-cgroup-Also-set-blkio.bfq.weight.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From af9f03ba48dd75be8c6a923f70da9804b3a3a2c3 Mon Sep 17 00:00:00 2001
|
||||
From: Pavel Hrdina <phrdina@redhat.com>
|
||||
Date: Wed, 25 Nov 2020 09:05:36 +0100
|
||||
Subject: [PATCH] cgroup: Also set blkio.bfq.weight
|
||||
|
||||
Commit [1] added a workaround when unified cgroups are used but missed
|
||||
legacy cgroups where there is the same issue.
|
||||
|
||||
[1] <https://github.com/systemd/systemd/commit/2dbc45aea747f25cc1c3848fded2ec0062f96bcf>
|
||||
|
||||
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
||||
(cherry picked from commit 35e7a62ca32a30169a94693b831e53c832251984)
|
||||
|
||||
Resolves: #1657810
|
||||
---
|
||||
src/core/cgroup.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
|
||||
index f1ce070f9a..71e30fd4db 100644
|
||||
--- a/src/core/cgroup.c
|
||||
+++ b/src/core/cgroup.c
|
||||
@@ -1063,6 +1063,14 @@ static void cgroup_context_apply(
|
||||
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to set blkio.weight: %m");
|
||||
|
||||
+ /* FIXME: drop this when distro kernels properly support BFQ through "blkio.weight"
|
||||
+ * See also: https://github.com/systemd/systemd/pull/13335 */
|
||||
+ xsprintf(buf, "%" PRIu64 "\n", weight);
|
||||
+ r = cg_set_attribute("blkio", path, "blkio.bfq.weight", buf);
|
||||
+ if (r < 0)
|
||||
+ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
+ "Failed to set blkio.bfq.weight: %m");
|
||||
+
|
||||
if (has_io) {
|
||||
CGroupIODeviceWeight *w;
|
||||
|
@ -0,0 +1,37 @@
|
||||
From ea425381a675a2ce4d9519d534fe27c1012ac92e Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Mon, 28 Jan 2019 12:07:37 +0100
|
||||
Subject: [PATCH] units: make sure initrd-cleanup.service terminates before
|
||||
switching to rootfs
|
||||
|
||||
A follow-up for commit a8cb1dc3e0fa81aff.
|
||||
|
||||
Commit a8cb1dc3e0fa81aff made sure that initrd-cleanup.service won't be stopped
|
||||
when initrd-switch-root.target is isolated.
|
||||
|
||||
However even with this change, it might happen that initrd-cleanup.service
|
||||
survives the switch to rootfs (since it has no ordering constraints against
|
||||
initrd-switch-root.target) and is stopped right after when default.target is
|
||||
isolated. This led to initrd-cleanup.service entering in failed state as it
|
||||
happens when oneshot services are stopped.
|
||||
|
||||
This patch along with a8cb1dc3e0fa81aff should fix issue #4343.
|
||||
|
||||
Fixes: #4343
|
||||
(cherry picked from commit e2c7c94ea35fe7e669afb51bfc2251158b522ea5)
|
||||
|
||||
Related: #1657810
|
||||
---
|
||||
units/initrd-switch-root.target | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/units/initrd-switch-root.target b/units/initrd-switch-root.target
|
||||
index ad82245121..ea4f02618f 100644
|
||||
--- a/units/initrd-switch-root.target
|
||||
+++ b/units/initrd-switch-root.target
|
||||
@@ -15,4 +15,4 @@ Requires=initrd-switch-root.service
|
||||
Before=initrd-switch-root.service
|
||||
AllowIsolate=yes
|
||||
Wants=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target systemd-journald.service initrd-cleanup.service
|
||||
-After=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target emergency.service emergency.target
|
||||
+After=initrd-udevadm-cleanup-db.service initrd-root-fs.target initrd-fs.target emergency.service emergency.target initrd-cleanup.service
|
@ -0,0 +1,73 @@
|
||||
From c67be1c7d69a0662ab85720aa0209110c39479f9 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||
Date: Wed, 27 Nov 2019 19:43:47 +0100
|
||||
Subject: [PATCH] core: reload SELinux label cache on daemon-reload
|
||||
|
||||
Reloading the SELinux label cache here enables a light-wight follow-up of a SELinux policy change, e.g. adding a label for a RuntimeDirectory.
|
||||
|
||||
Closes: #13363
|
||||
(cherry picked from commit a9dfac21ec850eb5dcaf1ae9ef729389e4c12802)
|
||||
|
||||
Resolves: #1888912
|
||||
---
|
||||
src/basic/selinux-util.c | 20 ++++++++++++++++++++
|
||||
src/basic/selinux-util.h | 1 +
|
||||
src/core/main.c | 2 ++
|
||||
3 files changed, 23 insertions(+)
|
||||
|
||||
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
|
||||
index e15bd7e1fa..f69d88eb1e 100644
|
||||
--- a/src/basic/selinux-util.c
|
||||
+++ b/src/basic/selinux-util.c
|
||||
@@ -105,6 +105,26 @@ void mac_selinux_finish(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
+void mac_selinux_reload(void) {
|
||||
+
|
||||
+#if HAVE_SELINUX
|
||||
+ struct selabel_handle *backup_label_hnd;
|
||||
+
|
||||
+ if (!label_hnd)
|
||||
+ return;
|
||||
+
|
||||
+ backup_label_hnd = TAKE_PTR(label_hnd);
|
||||
+
|
||||
+ /* try to initialize new handle
|
||||
+ * on success close backup
|
||||
+ * on failure restore backup */
|
||||
+ if (mac_selinux_init() == 0)
|
||||
+ selabel_close(backup_label_hnd);
|
||||
+ else
|
||||
+ label_hnd = backup_label_hnd;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
int mac_selinux_fix(const char *path, LabelFixFlags flags) {
|
||||
|
||||
#if HAVE_SELINUX
|
||||
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
|
||||
index 08314057fb..abcfabe777 100644
|
||||
--- a/src/basic/selinux-util.h
|
||||
+++ b/src/basic/selinux-util.h
|
||||
@@ -13,6 +13,7 @@ void mac_selinux_retest(void);
|
||||
|
||||
int mac_selinux_init(void);
|
||||
void mac_selinux_finish(void);
|
||||
+void mac_selinux_reload(void);
|
||||
|
||||
int mac_selinux_fix(const char *path, LabelFixFlags flags);
|
||||
int mac_selinux_apply(const char *path, const char *label);
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index d897155644..d5c41da0c4 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -1682,6 +1682,8 @@ static int invoke_main_loop(
|
||||
saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
|
||||
saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
|
||||
|
||||
+ mac_selinux_reload();
|
||||
+
|
||||
(void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
|
||||
|
||||
set_manager_defaults(m);
|
@ -0,0 +1,140 @@
|
||||
From 4f4e8bbd9ad46fc146a36f52790bc4920f42ef1f Mon Sep 17 00:00:00 2001
|
||||
From: Franck Bui <fbui@suse.com>
|
||||
Date: Mon, 2 Jul 2018 10:22:56 +0200
|
||||
Subject: [PATCH] selinux: introduce mac_selinux_create_file_prepare_at()
|
||||
|
||||
(cherry picked from commit 7e531a5265687aef5177b070c36ca4ceab42e768)
|
||||
|
||||
Related: #1888912
|
||||
---
|
||||
src/basic/selinux-util.c | 83 ++++++++++++++++++++++++++++++----------
|
||||
src/basic/selinux-util.h | 1 +
|
||||
2 files changed, 63 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
|
||||
index f69d88eb1e..a078ce23ef 100644
|
||||
--- a/src/basic/selinux-util.c
|
||||
+++ b/src/basic/selinux-util.c
|
||||
@@ -336,48 +336,89 @@ char* mac_selinux_free(char *label) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
|
||||
-
|
||||
#if HAVE_SELINUX
|
||||
+static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) {
|
||||
_cleanup_freecon_ char *filecon = NULL;
|
||||
+ _cleanup_free_ char *path = NULL;
|
||||
int r;
|
||||
|
||||
- assert(path);
|
||||
-
|
||||
- if (!label_hnd)
|
||||
- return 0;
|
||||
-
|
||||
- if (path_is_absolute(path))
|
||||
- r = selabel_lookup_raw(label_hnd, &filecon, path, mode);
|
||||
- else {
|
||||
- _cleanup_free_ char *newpath = NULL;
|
||||
-
|
||||
- r = path_make_absolute_cwd(path, &newpath);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode);
|
||||
- }
|
||||
+ assert(abspath);
|
||||
+ assert(path_is_absolute(abspath));
|
||||
|
||||
+ r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
|
||||
if (r < 0) {
|
||||
/* No context specified by the policy? Proceed without setting it. */
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
- log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
|
||||
+ log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
|
||||
} else {
|
||||
if (setfscreatecon_raw(filecon) >= 0)
|
||||
return 0; /* Success! */
|
||||
|
||||
- log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, path);
|
||||
+ log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
|
||||
}
|
||||
|
||||
if (security_getenforce() > 0)
|
||||
return -errno;
|
||||
|
||||
-#endif
|
||||
return 0;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) {
|
||||
+ int r = 0;
|
||||
+
|
||||
+#if HAVE_SELINUX
|
||||
+ _cleanup_free_ char *abspath = NULL;
|
||||
+ _cleanup_close_ int fd = -1;
|
||||
+
|
||||
+ assert(path);
|
||||
+
|
||||
+ if (!label_hnd)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!path_is_absolute(path)) {
|
||||
+ _cleanup_free_ char *p = NULL;
|
||||
+
|
||||
+ if (dirfd == AT_FDCWD)
|
||||
+ r = safe_getcwd(&p);
|
||||
+ else
|
||||
+ r = fd_get_path(dirfd, &p);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ abspath = path_join(NULL, p, path);
|
||||
+ if (!abspath)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ path = abspath;
|
||||
+ }
|
||||
+
|
||||
+ r = selinux_create_file_prepare_abspath(path, mode);
|
||||
+#endif
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
|
||||
+ int r = 0;
|
||||
+
|
||||
+#if HAVE_SELINUX
|
||||
+ _cleanup_free_ char *abspath = NULL;
|
||||
+
|
||||
+ assert(path);
|
||||
+
|
||||
+ if (!label_hnd)
|
||||
+ return 0;
|
||||
+
|
||||
+ r = path_make_absolute_cwd(path, &abspath);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = selinux_create_file_prepare_abspath(abspath, mode);
|
||||
+#endif
|
||||
+ return r;
|
||||
+}
|
||||
|
||||
void mac_selinux_create_file_clear(void) {
|
||||
|
||||
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
|
||||
index abcfabe777..639c35b687 100644
|
||||
--- a/src/basic/selinux-util.h
|
||||
+++ b/src/basic/selinux-util.h
|
||||
@@ -24,6 +24,7 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
|
||||
char* mac_selinux_free(char *label);
|
||||
|
||||
int mac_selinux_create_file_prepare(const char *path, mode_t mode);
|
||||
+int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode);
|
||||
void mac_selinux_create_file_clear(void);
|
||||
|
||||
int mac_selinux_create_socket_prepare(const char *label);
|
@ -0,0 +1,135 @@
|
||||
From 4e48673172b012a06575e4f5b681d3554eded2e2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||
Date: Mon, 6 Jan 2020 15:27:23 +0100
|
||||
Subject: [PATCH] selinux: add trigger for policy reload to refresh internal
|
||||
selabel cache
|
||||
|
||||
Reload the internal selabel cache automatically on SELinux policy reloads so non pid-1 daemons are participating.
|
||||
|
||||
Run the reload function `mac_selinux_reload()` not manually on daemon-reload, but rather pass it as callback to libselinux.
|
||||
Trigger the callback prior usage of the systemd internal selabel cache by depleting the selinux netlink socket via `avc_netlink_check_nb()`.
|
||||
|
||||
Improves: a9dfac21ec85 ("core: reload SELinux label cache on daemon-reload")
|
||||
Improves: #13363
|
||||
(cherry picked from commit 61f3e897f13101f29fb8027e8839498a469ad58e)
|
||||
|
||||
Related: #1888912
|
||||
---
|
||||
src/basic/selinux-util.c | 23 +++++++++++++++++++----
|
||||
src/basic/selinux-util.h | 1 -
|
||||
src/core/main.c | 2 --
|
||||
3 files changed, 19 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c
|
||||
index a078ce23ef..bfe3d015aa 100644
|
||||
--- a/src/basic/selinux-util.c
|
||||
+++ b/src/basic/selinux-util.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <syslog.h>
|
||||
|
||||
#if HAVE_SELINUX
|
||||
+#include <selinux/avc.h>
|
||||
#include <selinux/context.h>
|
||||
#include <selinux/label.h>
|
||||
#include <selinux/selinux.h>
|
||||
@@ -32,6 +33,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
|
||||
#define _cleanup_freecon_ _cleanup_(freeconp)
|
||||
#define _cleanup_context_free_ _cleanup_(context_freep)
|
||||
|
||||
+static int mac_selinux_reload(int seqno);
|
||||
+
|
||||
static int cached_use = -1;
|
||||
static struct selabel_handle *label_hnd = NULL;
|
||||
|
||||
@@ -63,6 +66,8 @@ int mac_selinux_init(void) {
|
||||
usec_t before_timestamp, after_timestamp;
|
||||
struct mallinfo before_mallinfo, after_mallinfo;
|
||||
|
||||
+ selinux_set_callback(SELINUX_CB_POLICYLOAD, (union selinux_callback) mac_selinux_reload);
|
||||
+
|
||||
if (label_hnd)
|
||||
return 0;
|
||||
|
||||
@@ -105,13 +110,12 @@ void mac_selinux_finish(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
-void mac_selinux_reload(void) {
|
||||
-
|
||||
#if HAVE_SELINUX
|
||||
+static int mac_selinux_reload(int seqno) {
|
||||
struct selabel_handle *backup_label_hnd;
|
||||
|
||||
if (!label_hnd)
|
||||
- return;
|
||||
+ return 0;
|
||||
|
||||
backup_label_hnd = TAKE_PTR(label_hnd);
|
||||
|
||||
@@ -122,8 +126,10 @@ void mac_selinux_reload(void) {
|
||||
selabel_close(backup_label_hnd);
|
||||
else
|
||||
label_hnd = backup_label_hnd;
|
||||
-#endif
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
+#endif
|
||||
|
||||
int mac_selinux_fix(const char *path, LabelFixFlags flags) {
|
||||
|
||||
@@ -152,6 +158,9 @@ int mac_selinux_fix(const char *path, LabelFixFlags flags) {
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
+ /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
|
||||
+ (void) avc_netlink_check_nb();
|
||||
+
|
||||
if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) {
|
||||
r = -errno;
|
||||
|
||||
@@ -345,6 +354,9 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
|
||||
assert(abspath);
|
||||
assert(path_is_absolute(abspath));
|
||||
|
||||
+ /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
|
||||
+ (void) avc_netlink_check_nb();
|
||||
+
|
||||
r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
|
||||
if (r < 0) {
|
||||
/* No context specified by the policy? Proceed without setting it. */
|
||||
@@ -496,6 +508,9 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
|
||||
path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));
|
||||
|
||||
+ /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
|
||||
+ (void) avc_netlink_check_nb();
|
||||
+
|
||||
if (path_is_absolute(path))
|
||||
r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
|
||||
else {
|
||||
diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h
|
||||
index 639c35b687..bd5207c318 100644
|
||||
--- a/src/basic/selinux-util.h
|
||||
+++ b/src/basic/selinux-util.h
|
||||
@@ -13,7 +13,6 @@ void mac_selinux_retest(void);
|
||||
|
||||
int mac_selinux_init(void);
|
||||
void mac_selinux_finish(void);
|
||||
-void mac_selinux_reload(void);
|
||||
|
||||
int mac_selinux_fix(const char *path, LabelFixFlags flags);
|
||||
int mac_selinux_apply(const char *path, const char *label);
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index d5c41da0c4..d897155644 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -1682,8 +1682,6 @@ static int invoke_main_loop(
|
||||
saved_log_level = m->log_level_overridden ? log_get_max_level() : -1;
|
||||
saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID;
|
||||
|
||||
- mac_selinux_reload();
|
||||
-
|
||||
(void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock);
|
||||
|
||||
set_manager_defaults(m);
|
@ -0,0 +1,24 @@
|
||||
From fb58a56c6c1c2749ba634abd9ad76f4e718269a1 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Tue, 5 Jan 2021 12:30:15 +0100
|
||||
Subject: [PATCH] udev/net_id: give RHEL-8.4 naming scheme a name
|
||||
|
||||
Follow-up for bb6114af097da0cd9c5081e42db718559130687f
|
||||
|
||||
Related: #1827462
|
||||
---
|
||||
src/udev/udev-builtin-net_id.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index d8c56b62bb..7c153f0aef 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -150,6 +150,7 @@ static const NamingScheme naming_schemes[] = {
|
||||
{ "rhel-8.1", NAMING_RHEL_8_1 },
|
||||
{ "rhel-8.2", NAMING_RHEL_8_2 },
|
||||
{ "rhel-8.3", NAMING_RHEL_8_3 },
|
||||
+ { "rhel-8.4", NAMING_RHEL_8_4 },
|
||||
/* … add more schemes here, as the logic to name devices is updated … */
|
||||
};
|
||||
|
@ -0,0 +1,63 @@
|
||||
From 29c5b8dd6228c4401f034ca0aa85f99ac42cf8dd Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
||||
Date: Thu, 5 Nov 2020 17:55:25 +0100
|
||||
Subject: [PATCH] basic/stat-util: make mtime check stricter and use entire
|
||||
timestamp
|
||||
|
||||
Note that st_mtime member of struct stat is defined as follows,
|
||||
|
||||
#define st_mtime st_mtim.tv_sec
|
||||
|
||||
Hence we omitted checking nanosecond part of the timestamp (struct
|
||||
timespec) and possibly would miss modifications that happened within the
|
||||
same second.
|
||||
|
||||
(cherry picked from commit a59b0a9f768f6e27b25f4f1bab6de08842e78d74)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
src/basic/stat-util.c | 22 ++++++++++++++++++++++
|
||||
src/basic/stat-util.h | 2 ++
|
||||
2 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
|
||||
index 26aee9bad6..c61c4c0517 100644
|
||||
--- a/src/basic/stat-util.c
|
||||
+++ b/src/basic/stat-util.c
|
||||
@@ -287,3 +287,25 @@ int fd_verify_regular(int fd) {
|
||||
|
||||
return stat_verify_regular(&st);
|
||||
}
|
||||
+
|
||||
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
|
||||
+
|
||||
+ /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
|
||||
+ * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file
|
||||
+ * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file
|
||||
+ * size, backing device, inode type and if this refers to a device not the major/minor.
|
||||
+ *
|
||||
+ * Note that we don't care if file attributes such as ownership or access mode change, this here is
|
||||
+ * about contents of the file. The purpose here is to detect file contents changes, and nothing
|
||||
+ * else. */
|
||||
+
|
||||
+ return a && b &&
|
||||
+ (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
|
||||
+ ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
|
||||
+ a->st_mtim.tv_sec == b->st_mtim.tv_sec &&
|
||||
+ a->st_mtim.tv_nsec == b->st_mtim.tv_nsec &&
|
||||
+ (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
|
||||
+ a->st_dev == b->st_dev &&
|
||||
+ a->st_ino == b->st_ino &&
|
||||
+ (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
|
||||
index f8014ed30b..9e1a2b70da 100644
|
||||
--- a/src/basic/stat-util.h
|
||||
+++ b/src/basic/stat-util.h
|
||||
@@ -58,3 +58,5 @@ int path_is_temporary_fs(const char *path);
|
||||
|
||||
int stat_verify_regular(const struct stat *st);
|
||||
int fd_verify_regular(int fd);
|
||||
+
|
||||
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
|
@ -0,0 +1,457 @@
|
||||
From 1d5f966c1758eb620755fcae54abd07a1ac36d3d Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Wed, 6 Jan 2021 11:43:50 +0100
|
||||
Subject: [PATCH] udev: make algorithm that selects highest priority devlink
|
||||
less susceptible to race conditions
|
||||
|
||||
Previously it was very likely, when multiple contenders for the symlink
|
||||
appear in parallel, that algorithm would select wrong symlink (i.e. one
|
||||
with lower-priority).
|
||||
|
||||
Now the algorithm is much more defensive and when we detect change in
|
||||
set of contenders for the symlink we reevaluate the selection. Same
|
||||
happens when new symlink replaces already existing symlink that points
|
||||
to different device node.
|
||||
|
||||
Resolves: #1642728
|
||||
---
|
||||
src/udev/udev-event.c | 71 +++++++-----
|
||||
src/udev/udev-node.c | 244 ++++++++++++++++++++++++++++++------------
|
||||
2 files changed, 216 insertions(+), 99 deletions(-)
|
||||
|
||||
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
|
||||
index fd8406d959..9004634f65 100644
|
||||
--- a/src/udev/udev-event.c
|
||||
+++ b/src/udev/udev-event.c
|
||||
@@ -833,6 +833,41 @@ static int rename_netif(struct udev_event *event) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void update_devnode(struct udev_event *event) {
|
||||
+ struct udev_device *dev = event->dev;
|
||||
+
|
||||
+ if (major(udev_device_get_devnum(dev)) > 0) {
|
||||
+ bool apply;
|
||||
+
|
||||
+ /* remove/update possible left-over symlinks from old database entry */
|
||||
+ if (event->dev_db != NULL)
|
||||
+ udev_node_update_old_links(dev, event->dev_db);
|
||||
+
|
||||
+ if (!event->owner_set)
|
||||
+ event->uid = udev_device_get_devnode_uid(dev);
|
||||
+
|
||||
+ if (!event->group_set)
|
||||
+ event->gid = udev_device_get_devnode_gid(dev);
|
||||
+
|
||||
+ if (!event->mode_set) {
|
||||
+ if (udev_device_get_devnode_mode(dev) > 0) {
|
||||
+ /* kernel supplied value */
|
||||
+ event->mode = udev_device_get_devnode_mode(dev);
|
||||
+ } else if (event->gid > 0) {
|
||||
+ /* default 0660 if a group is assigned */
|
||||
+ event->mode = 0660;
|
||||
+ }
|
||||
+ else {
|
||||
+ /* default 0600 */
|
||||
+ event->mode = 0600;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ apply = streq(udev_device_get_action(dev), "add") || event->owner_set || event->group_set || event->mode_set;
|
||||
+ udev_node_add(dev, apply, event->mode, event->uid, event->gid, &event->seclabel_list);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void udev_event_execute_rules(struct udev_event *event,
|
||||
usec_t timeout_usec, usec_t timeout_warn_usec,
|
||||
struct udev_list *properties_list,
|
||||
@@ -891,35 +926,7 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
}
|
||||
}
|
||||
|
||||
- if (major(udev_device_get_devnum(dev)) > 0) {
|
||||
- bool apply;
|
||||
-
|
||||
- /* remove/update possible left-over symlinks from old database entry */
|
||||
- if (event->dev_db != NULL)
|
||||
- udev_node_update_old_links(dev, event->dev_db);
|
||||
-
|
||||
- if (!event->owner_set)
|
||||
- event->uid = udev_device_get_devnode_uid(dev);
|
||||
-
|
||||
- if (!event->group_set)
|
||||
- event->gid = udev_device_get_devnode_gid(dev);
|
||||
-
|
||||
- if (!event->mode_set) {
|
||||
- if (udev_device_get_devnode_mode(dev) > 0) {
|
||||
- /* kernel supplied value */
|
||||
- event->mode = udev_device_get_devnode_mode(dev);
|
||||
- } else if (event->gid > 0) {
|
||||
- /* default 0660 if a group is assigned */
|
||||
- event->mode = 0660;
|
||||
- } else {
|
||||
- /* default 0600 */
|
||||
- event->mode = 0600;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- apply = streq(udev_device_get_action(dev), "add") || event->owner_set || event->group_set || event->mode_set;
|
||||
- udev_node_add(dev, apply, event->mode, event->uid, event->gid, &event->seclabel_list);
|
||||
- }
|
||||
+ update_devnode(event);
|
||||
|
||||
/* preserve old, or get new initialization timestamp */
|
||||
udev_device_ensure_usec_initialized(event->dev, event->dev_db);
|
||||
@@ -927,6 +934,12 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
/* (re)write database file */
|
||||
udev_device_tag_index(dev, event->dev_db, true);
|
||||
udev_device_update_db(dev);
|
||||
+
|
||||
+ /* Yes, we run update_devnode() twice, because in the first invocation, that is before update of udev database,
|
||||
+ * it could happen that two contenders are replacing each other's symlink. Hence we run it again to make sure
|
||||
+ * symlinks point to devices that claim them with the highest priority. */
|
||||
+ update_devnode(event);
|
||||
+
|
||||
udev_device_set_is_initialized(dev);
|
||||
|
||||
event->dev_db = udev_device_unref(event->dev_db);
|
||||
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
|
||||
index 333dcae6b9..2eeeccdd3a 100644
|
||||
--- a/src/udev/udev-node.c
|
||||
+++ b/src/udev/udev-node.c
|
||||
@@ -13,19 +13,27 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "device-nodes.h"
|
||||
+#include "device-private.h"
|
||||
#include "dirent-util.h"
|
||||
+#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
+#include "sd-device.h"
|
||||
#include "selinux-util.h"
|
||||
#include "smack-util.h"
|
||||
+#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "udev.h"
|
||||
+#include "libudev-device-internal.h"
|
||||
|
||||
-static int node_symlink(struct udev_device *dev, const char *node, const char *slink) {
|
||||
+#define LINK_UPDATE_MAX_RETRIES 128
|
||||
+
|
||||
+static int node_symlink(sd_device *dev, const char *node, const char *slink) {
|
||||
struct stat stats;
|
||||
char target[UTIL_PATH_SIZE];
|
||||
char *s;
|
||||
+ const char *id_filename;
|
||||
size_t l;
|
||||
char slink_tmp[UTIL_PATH_SIZE + 32];
|
||||
int i = 0;
|
||||
@@ -89,7 +97,10 @@ static int node_symlink(struct udev_device *dev, const char *node, const char *s
|
||||
}
|
||||
|
||||
log_debug("atomically replace '%s'", slink);
|
||||
- strscpyl(slink_tmp, sizeof(slink_tmp), slink, ".tmp-", udev_device_get_id_filename(dev), NULL);
|
||||
+ err = device_get_id_filename(dev, &id_filename);
|
||||
+ if (err < 0)
|
||||
+ return log_error_errno(err, "Failed to get id_filename: %m");
|
||||
+ strscpyl(slink_tmp, sizeof(slink_tmp), slink, ".tmp-", id_filename, NULL);
|
||||
unlink(slink_tmp);
|
||||
do {
|
||||
err = mkdir_parents_label(slink_tmp, 0755);
|
||||
@@ -109,104 +120,187 @@ static int node_symlink(struct udev_device *dev, const char *node, const char *s
|
||||
if (err != 0) {
|
||||
log_error_errno(errno, "rename '%s' '%s' failed: %m", slink_tmp, slink);
|
||||
unlink(slink_tmp);
|
||||
- }
|
||||
+ } else
|
||||
+ /* Tell caller that we replaced already existing symlink. */
|
||||
+ return 1;
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* find device node of device with highest priority */
|
||||
-static const char *link_find_prioritized(struct udev_device *dev, bool add, const char *stackdir, char *buf, size_t bufsize) {
|
||||
- struct udev *udev = udev_device_get_udev(dev);
|
||||
- DIR *dir;
|
||||
+static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir, char **ret) {
|
||||
+ _cleanup_closedir_ DIR *dir = NULL;
|
||||
+ _cleanup_free_ char *target = NULL;
|
||||
struct dirent *dent;
|
||||
- int priority = 0;
|
||||
- const char *target = NULL;
|
||||
+ int r, priority = 0;
|
||||
+
|
||||
+ assert(!add || dev);
|
||||
+ assert(stackdir);
|
||||
+ assert(ret);
|
||||
|
||||
if (add) {
|
||||
- priority = udev_device_get_devlink_priority(dev);
|
||||
- strscpy(buf, bufsize, udev_device_get_devnode(dev));
|
||||
- target = buf;
|
||||
+ const char *devnode;
|
||||
+
|
||||
+ r = device_get_devlink_priority(dev, &priority);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_device_get_devname(dev, &devnode);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ target = strdup(devnode);
|
||||
+ if (!target)
|
||||
+ return -ENOMEM;
|
||||
}
|
||||
|
||||
dir = opendir(stackdir);
|
||||
- if (dir == NULL)
|
||||
- return target;
|
||||
+ if (!dir) {
|
||||
+ if (target) {
|
||||
+ *ret = TAKE_PTR(target);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -errno;
|
||||
+ }
|
||||
+
|
||||
FOREACH_DIRENT_ALL(dent, dir, break) {
|
||||
- struct udev_device *dev_db;
|
||||
+ _cleanup_(sd_device_unrefp) sd_device *dev_db = NULL;
|
||||
+ const char *devnode, *id_filename;
|
||||
+ int db_prio = 0;
|
||||
|
||||
if (dent->d_name[0] == '\0')
|
||||
break;
|
||||
if (dent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
- log_debug("found '%s' claiming '%s'", dent->d_name, stackdir);
|
||||
+ log_debug("Found '%s' claiming '%s'", dent->d_name, stackdir);
|
||||
+
|
||||
+ if (device_get_id_filename(dev, &id_filename) < 0)
|
||||
+ continue;
|
||||
|
||||
/* did we find ourself? */
|
||||
- if (streq(dent->d_name, udev_device_get_id_filename(dev)))
|
||||
+ if (streq(dent->d_name, id_filename))
|
||||
continue;
|
||||
|
||||
- dev_db = udev_device_new_from_device_id(udev, dent->d_name);
|
||||
- if (dev_db != NULL) {
|
||||
- const char *devnode;
|
||||
-
|
||||
- devnode = udev_device_get_devnode(dev_db);
|
||||
- if (devnode != NULL) {
|
||||
- if (target == NULL || udev_device_get_devlink_priority(dev_db) > priority) {
|
||||
- log_debug("'%s' claims priority %i for '%s'",
|
||||
- udev_device_get_syspath(dev_db), udev_device_get_devlink_priority(dev_db), stackdir);
|
||||
- priority = udev_device_get_devlink_priority(dev_db);
|
||||
- strscpy(buf, bufsize, devnode);
|
||||
- target = buf;
|
||||
- }
|
||||
- }
|
||||
- udev_device_unref(dev_db);
|
||||
+ if (sd_device_new_from_device_id(&dev_db, dent->d_name) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (sd_device_get_devname(dev_db, &devnode) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (device_get_devlink_priority(dev_db, &db_prio) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (target && db_prio <= priority)
|
||||
+ continue;
|
||||
+
|
||||
+ if (DEBUG_LOGGING) {
|
||||
+ const char *syspath = NULL;
|
||||
+
|
||||
+ (void) sd_device_get_syspath(dev_db, &syspath);
|
||||
+ log_debug("Device '%s' claims priority %i for '%s'", strnull(syspath), db_prio, stackdir);
|
||||
}
|
||||
+
|
||||
+ r = free_and_strdup(&target, devnode);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ priority = db_prio;
|
||||
}
|
||||
- closedir(dir);
|
||||
- return target;
|
||||
+
|
||||
+ if (!target)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ *ret = TAKE_PTR(target);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
+
|
||||
/* manage "stack of names" with possibly specified device priorities */
|
||||
-static void link_update(struct udev_device *dev, const char *slink, bool add) {
|
||||
- char name_enc[UTIL_PATH_SIZE];
|
||||
- char filename[UTIL_PATH_SIZE * 2];
|
||||
- char dirname[UTIL_PATH_SIZE];
|
||||
- const char *target;
|
||||
- char buf[UTIL_PATH_SIZE];
|
||||
+static int link_update(sd_device *dev, const char *slink, bool add) {
|
||||
+ _cleanup_free_ char *filename = NULL, *dirname = NULL;
|
||||
+ char name_enc[PATH_MAX];
|
||||
+ const char *id_filename;
|
||||
+ int i, r, retries;
|
||||
+
|
||||
+ assert(dev);
|
||||
+ assert(slink);
|
||||
+
|
||||
+ r = device_get_id_filename(dev, &id_filename);
|
||||
+ if (r < 0)
|
||||
+ return log_debug_errno(r, "Failed to get id_filename: %m");
|
||||
|
||||
util_path_encode(slink + STRLEN("/dev"), name_enc, sizeof(name_enc));
|
||||
- strscpyl(dirname, sizeof(dirname), "/run/udev/links/", name_enc, NULL);
|
||||
- strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
|
||||
+ dirname = path_join(NULL, "/run/udev/links/", name_enc);
|
||||
+ if (!dirname)
|
||||
+ return log_oom();
|
||||
+ filename = path_join(NULL, dirname, id_filename);
|
||||
+ if (!filename)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ if (!add) {
|
||||
+ if (unlink(filename) == 0)
|
||||
+ (void) rmdir(dirname);
|
||||
+ } else
|
||||
+ for (;;) {
|
||||
+ _cleanup_close_ int fd = -1;
|
||||
+
|
||||
+ r = mkdir_parents(filename, 0755);
|
||||
+ if (!IN_SET(r, 0, -ENOENT))
|
||||
+ return r;
|
||||
|
||||
- if (!add && unlink(filename) == 0)
|
||||
- rmdir(dirname);
|
||||
+ fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444);
|
||||
+ if (fd >= 0)
|
||||
+ break;
|
||||
+ if (errno != ENOENT)
|
||||
+ return -errno;
|
||||
+ }
|
||||
|
||||
- target = link_find_prioritized(dev, add, dirname, buf, sizeof(buf));
|
||||
- if (target == NULL) {
|
||||
- log_debug("no reference left, remove '%s'", slink);
|
||||
- if (unlink(slink) == 0)
|
||||
- rmdir_parents(slink, "/");
|
||||
- } else {
|
||||
- log_debug("creating link '%s' to '%s'", slink, target);
|
||||
- node_symlink(dev, target, slink);
|
||||
- }
|
||||
+ /* If the database entry is not written yet we will just do one iteration and possibly wrong symlink
|
||||
+ * will be fixed in the second invocation. */
|
||||
+ (void) sd_device_get_is_initialized(dev, &r);
|
||||
+ retries = r > 0 ? LINK_UPDATE_MAX_RETRIES : 1;
|
||||
|
||||
- if (add) {
|
||||
- int err;
|
||||
+ for (i = 0; i < retries; i++) {
|
||||
+ _cleanup_free_ char *target = NULL;
|
||||
+ struct stat st1 = {}, st2 = {};
|
||||
|
||||
- do {
|
||||
- int fd;
|
||||
+ r = stat(dirname, &st1);
|
||||
+ if (r < 0 && errno != ENOENT)
|
||||
+ return -errno;
|
||||
|
||||
- err = mkdir_parents(filename, 0755);
|
||||
- if (!IN_SET(err, 0, -ENOENT))
|
||||
+ r = link_find_prioritized(dev, add, dirname, &target);
|
||||
+ if (r == -ENOENT) {
|
||||
+ log_debug("No reference left, removing '%s'", slink);
|
||||
+ if (unlink(slink) == 0)
|
||||
+ (void) rmdir_parents(slink, "/");
|
||||
+
|
||||
+ break;
|
||||
+ } else if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to determine highest priority symlink: %m");
|
||||
+
|
||||
+ r = node_symlink(dev, target, slink);
|
||||
+ if (r < 0) {
|
||||
+ (void) unlink(filename);
|
||||
+ break;
|
||||
+ } else if (r == 1)
|
||||
+ /* We have replaced already existing symlink, possibly there is some other device trying
|
||||
+ * to claim the same symlink. Let's do one more iteration to give us a chance to fix
|
||||
+ * the error if other device actually claims the symlink with higher priority. */
|
||||
+ continue;
|
||||
+
|
||||
+ /* Skip the second stat() if the first failed, stat_inode_unmodified() would return false regardless. */
|
||||
+ if ((st1.st_mode & S_IFMT) != 0) {
|
||||
+ r = stat(dirname, &st2);
|
||||
+ if (r < 0 && errno != ENOENT)
|
||||
+ return -errno;
|
||||
+
|
||||
+ if (stat_inode_unmodified(&st1, &st2))
|
||||
break;
|
||||
- fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444);
|
||||
- if (fd >= 0)
|
||||
- close(fd);
|
||||
- else
|
||||
- err = -errno;
|
||||
- } while (err == -ENOENT);
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP;
|
||||
}
|
||||
|
||||
void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev_old) {
|
||||
@@ -233,7 +327,7 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
|
||||
|
||||
log_debug("update old name, '%s' no longer belonging to '%s'",
|
||||
name, udev_device_get_devpath(dev));
|
||||
- link_update(dev, name, false);
|
||||
+ link_update(dev->device, name, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,11 +432,16 @@ void udev_node_add(struct udev_device *dev, bool apply,
|
||||
xsprintf_dev_num_path(filename,
|
||||
streq(udev_device_get_subsystem(dev), "block") ? "block" : "char",
|
||||
udev_device_get_devnum(dev));
|
||||
- node_symlink(dev, udev_device_get_devnode(dev), filename);
|
||||
+ node_symlink(dev->device, udev_device_get_devnode(dev), filename);
|
||||
|
||||
/* create/update symlinks, add symlinks to name index */
|
||||
- udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev))
|
||||
- link_update(dev, udev_list_entry_get_name(list_entry), true);
|
||||
+ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
|
||||
+ int r;
|
||||
+
|
||||
+ r = link_update(dev->device, udev_list_entry_get_name(list_entry), true);
|
||||
+ if (r < 0)
|
||||
+ log_info_errno(r, "Failed to update device symlinks: %m");
|
||||
+ }
|
||||
}
|
||||
|
||||
void udev_node_remove(struct udev_device *dev) {
|
||||
@@ -350,8 +449,13 @@ void udev_node_remove(struct udev_device *dev) {
|
||||
char filename[DEV_NUM_PATH_MAX];
|
||||
|
||||
/* remove/update symlinks, remove symlinks from name index */
|
||||
- udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev))
|
||||
- link_update(dev, udev_list_entry_get_name(list_entry), false);
|
||||
+ udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(dev)) {
|
||||
+ int r;
|
||||
+
|
||||
+ r = link_update(dev->device, udev_list_entry_get_name(list_entry), false);
|
||||
+ if (r < 0)
|
||||
+ log_info_errno(r, "Failed to update device symlinks: %m");
|
||||
+ }
|
||||
|
||||
/* remove /dev/{block,char}/$major:$minor */
|
||||
xsprintf_dev_num_path(filename,
|
32
SOURCES/0509-test-create-dev-null-in-test-udev.pl.patch
Normal file
32
SOURCES/0509-test-create-dev-null-in-test-udev.pl.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 6a908a38135d050b7c271fdea9c061d7e7ad8ef7 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 23 Oct 2018 07:23:01 +0900
|
||||
Subject: [PATCH] test: create /dev/null in test-udev.pl
|
||||
|
||||
(cherry picked from commit a41ff38b0999fb83464309a29b8f39450b8d4b85)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 0433629c7c..a1c24f49b4 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1537,13 +1537,14 @@ sub udev_setup {
|
||||
system("umount", $udev_tmpfs);
|
||||
rmdir($udev_tmpfs);
|
||||
mkdir($udev_tmpfs) || die "unable to create udev_tmpfs: $udev_tmpfs\n";
|
||||
- system("mount", "-o", "rw,mode=755,nosuid,noexec,nodev", "-t", "tmpfs", "tmpfs", $udev_tmpfs) && die "unable to mount tmpfs";
|
||||
+ system("mount", "-o", "rw,mode=755,nosuid,noexec", "-t", "tmpfs", "tmpfs", $udev_tmpfs) && die "unable to mount tmpfs";
|
||||
|
||||
mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n";
|
||||
# setting group and mode of udev_dev ensures the tests work
|
||||
# even if the parent directory has setgid bit enabled.
|
||||
chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n";
|
||||
chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n";
|
||||
+ system("mknod", $udev_dev . "/null", "c", "1", "3") && "unable to create $udev_dev/null";
|
||||
|
||||
system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys";
|
||||
|
27
SOURCES/0510-test-missing-die.patch
Normal file
27
SOURCES/0510-test-missing-die.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 70bf708d5360372aa541e25ff512609230781dd6 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 7 Nov 2018 14:56:20 +0900
|
||||
Subject: [PATCH] test: missing "die"
|
||||
|
||||
Follow-up for a41ff38b0999fb83464309a29b8f39450b8d4b85.
|
||||
|
||||
(cherry picked from commit 11d93952ea806de2b6e9fb381153115cccc7b5e8)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index a1c24f49b4..61bd3d703a 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1544,7 +1544,7 @@ sub udev_setup {
|
||||
# even if the parent directory has setgid bit enabled.
|
||||
chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n";
|
||||
chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n";
|
||||
- system("mknod", $udev_dev . "/null", "c", "1", "3") && "unable to create $udev_dev/null";
|
||||
+ system("mknod", $udev_dev . "/null", "c", "1", "3") && die "unable to create $udev_dev/null";
|
||||
|
||||
system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys";
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 1b133f2ca15f0a15b05407b2c04521d7de88dfa2 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Fri, 9 Nov 2018 03:14:04 +0100
|
||||
Subject: [PATCH] udev-test: remove a check for whether the test is run in a
|
||||
container
|
||||
|
||||
It's too broad a check that prevents the test from running on Travis CI.
|
||||
|
||||
(cherry picked from commit 881886ef08d50951159633248b0f73977c5d6924)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 61bd3d703a..05b3e17188 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1646,13 +1646,6 @@ if ($? >> 8 == 0) {
|
||||
exit($EXIT_TEST_SKIP);
|
||||
}
|
||||
|
||||
-# skip the test when running in a container
|
||||
-system("systemd-detect-virt", "-c", "-q");
|
||||
-if ($? >> 8 == 0) {
|
||||
- print "Running in a container, skipping the test.\n";
|
||||
- exit($EXIT_TEST_SKIP);
|
||||
-}
|
||||
-
|
||||
udev_setup();
|
||||
|
||||
my $test_num = 1;
|
@ -0,0 +1,94 @@
|
||||
From 8c82f3a4aa2d029dcc303cbf95a71194aa5ac9c3 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Fri, 9 Nov 2018 04:01:15 +0100
|
||||
Subject: [PATCH] udev-test: skip the test only if it can't setup its
|
||||
environment
|
||||
|
||||
This is basically a replacement for 0eb3cc88504b5d8f74.
|
||||
|
||||
(cherry picked from commit 110a13202eab6d92678abcde08372d4afac1cc45)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
src/test/test-udev.c | 8 ++++++++
|
||||
test/udev-test.pl | 24 +++++++++++++++++++++---
|
||||
2 files changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-udev.c b/src/test/test-udev.c
|
||||
index bed51c1270..f098fab721 100644
|
||||
--- a/src/test/test-udev.c
|
||||
+++ b/src/test/test-udev.c
|
||||
@@ -65,6 +65,11 @@ int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
+ if (!IN_SET(argc, 2, 3)) {
|
||||
+ log_error("This program needs one or two arguments, %d given", argc - 1);
|
||||
+ return EXIT_FAILURE;
|
||||
+ }
|
||||
+
|
||||
err = fake_filesystems();
|
||||
if (err < 0)
|
||||
return EXIT_FAILURE;
|
||||
@@ -73,6 +78,9 @@ int main(int argc, char *argv[]) {
|
||||
if (udev == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
+ if (argc == 2)
|
||||
+ return EXIT_SUCCESS;
|
||||
+
|
||||
log_debug("version %s", PACKAGE_VERSION);
|
||||
mac_selinux_init();
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 05b3e17188..aa38bae0b1 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1537,18 +1537,28 @@ sub udev_setup {
|
||||
system("umount", $udev_tmpfs);
|
||||
rmdir($udev_tmpfs);
|
||||
mkdir($udev_tmpfs) || die "unable to create udev_tmpfs: $udev_tmpfs\n";
|
||||
- system("mount", "-o", "rw,mode=755,nosuid,noexec", "-t", "tmpfs", "tmpfs", $udev_tmpfs) && die "unable to mount tmpfs";
|
||||
+
|
||||
+ if (system("mount", "-o", "rw,mode=755,nosuid,noexec", "-t", "tmpfs", "tmpfs", $udev_tmpfs)) {
|
||||
+ warn "unable to mount tmpfs";
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n";
|
||||
# setting group and mode of udev_dev ensures the tests work
|
||||
# even if the parent directory has setgid bit enabled.
|
||||
chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n";
|
||||
chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n";
|
||||
- system("mknod", $udev_dev . "/null", "c", "1", "3") && die "unable to create $udev_dev/null";
|
||||
+
|
||||
+ if (system("mknod", $udev_dev . "/null", "c", "1", "3")) {
|
||||
+ warn "unable to create $udev_dev/null";
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys";
|
||||
|
||||
system("rm", "-rf", "$udev_run");
|
||||
+
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
sub run_test {
|
||||
@@ -1646,7 +1656,15 @@ if ($? >> 8 == 0) {
|
||||
exit($EXIT_TEST_SKIP);
|
||||
}
|
||||
|
||||
-udev_setup();
|
||||
+if (!udev_setup()) {
|
||||
+ warn "Failed to set up the environment, skipping the test";
|
||||
+ exit($EXIT_TEST_SKIP);
|
||||
+}
|
||||
+
|
||||
+if (!system($udev_bin, "check")) {
|
||||
+ warn "$udev_bin failed to set up the environment, skipping the test";
|
||||
+ exit($EXIT_TEST_SKIP);
|
||||
+}
|
||||
|
||||
my $test_num = 1;
|
||||
my @list;
|
33
SOURCES/0513-udev-test-fix-test-skip-condition.patch
Normal file
33
SOURCES/0513-udev-test-fix-test-skip-condition.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From f44fcdde656036f0388fc8244b8960c1873a3a08 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Bogdanenko <alexey@bogdanenko.com>
|
||||
Date: Sat, 8 Dec 2018 11:02:30 +0300
|
||||
Subject: [PATCH] udev-test: fix test skip condition
|
||||
|
||||
When there is a failure to setup the environment, the following happens:
|
||||
|
||||
1. Command "./test-udev check" exits with non-zero code.
|
||||
2. Perl function "system" returns the code.
|
||||
3. The code is evaluated as true by Perl.
|
||||
|
||||
Then we stop the test.
|
||||
|
||||
(cherry picked from commit 7935dae547caf164d807237f1009a9e9fa510337)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index aa38bae0b1..3517feab15 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1661,7 +1661,7 @@ if (!udev_setup()) {
|
||||
exit($EXIT_TEST_SKIP);
|
||||
}
|
||||
|
||||
-if (!system($udev_bin, "check")) {
|
||||
+if (system($udev_bin, "check")) {
|
||||
warn "$udev_bin failed to set up the environment, skipping the test";
|
||||
exit($EXIT_TEST_SKIP);
|
||||
}
|
35
SOURCES/0514-udev-test-fix-missing-directory-test-run.patch
Normal file
35
SOURCES/0514-udev-test-fix-missing-directory-test-run.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 974431a70775d5127cd973c4b4705d2cf8884011 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Bogdanenko <alexey@bogdanenko.com>
|
||||
Date: Sat, 8 Dec 2018 15:35:30 +0300
|
||||
Subject: [PATCH] udev-test: fix missing directory test/run
|
||||
|
||||
Fixes the following error:
|
||||
|
||||
Failed to mount test /run: No such file or directory
|
||||
|
||||
By the time command "./test-udev check" calls function "fake_filesystems",
|
||||
directory "test/run" must be present.
|
||||
|
||||
(cherry picked from commit 1e5548c0e0962424b6ca5fdfd35c866b70760c8f)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 3517feab15..eb76ebd72e 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1558,6 +1558,11 @@ sub udev_setup {
|
||||
|
||||
system("rm", "-rf", "$udev_run");
|
||||
|
||||
+ if (!mkdir($udev_run)) {
|
||||
+ warn "unable to create directory $udev_run";
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 57e9ee0f19098d56995955f6692437affdf94041 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Bogdanenko <alexey@bogdanenko.com>
|
||||
Date: Tue, 11 Dec 2018 16:55:34 +0300
|
||||
Subject: [PATCH] udev-test: check if permitted to create block device nodes
|
||||
|
||||
(cherry picked from commit dbfbc6c4e34366033cb340e8b0c3cbca683ff6f5)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index eb76ebd72e..957cda541c 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1554,6 +1554,14 @@ sub udev_setup {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ # check if we are permitted to create block device nodes
|
||||
+ my $block_device_filename = $udev_dev . "/sda";
|
||||
+ if (system("mknod", $block_device_filename, "b", "8", "0")) {
|
||||
+ warn "unable to create $block_device_filename";
|
||||
+ return 0;
|
||||
+ }
|
||||
+ unlink $block_device_filename;
|
||||
+
|
||||
system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys";
|
||||
|
||||
system("rm", "-rf", "$udev_run");
|
45
SOURCES/0516-test-udev-add-a-testcase-of-too-long-line.patch
Normal file
45
SOURCES/0516-test-udev-add-a-testcase-of-too-long-line.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 527d43064a93fae9a4490e5d152b120e91f5eade Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Mon, 18 Feb 2019 10:38:29 +0900
|
||||
Subject: [PATCH] test-udev: add a testcase of too long line
|
||||
|
||||
(cherry picked from commit 1e797cf596df50a6bdd8cbf8e9b2467a3a934171)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 957cda541c..3a50694fa9 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -39,6 +39,11 @@ for (my $i = 1; $i <= 10000; ++$i) {
|
||||
$rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n";
|
||||
}
|
||||
|
||||
+my $rules_10k_tags_continuation = "";
|
||||
+for (my $i = 1; $i <= 10000; ++$i) {
|
||||
+ $rules_10k_tags_continuation .= 'KERNEL=="sda", TAG+="test' . $i . "\"\\\n";
|
||||
+}
|
||||
+
|
||||
my @tests = (
|
||||
{
|
||||
desc => "no rules",
|
||||
@@ -1444,6 +1449,16 @@ EOF
|
||||
exp_name => "found",
|
||||
rules => $rules_10k_tags . <<EOF
|
||||
TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="found"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "don't crash with lots of tags with continuation",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad" ,
|
||||
+ rules => $rules_10k_tags_continuation . <<EOF
|
||||
+TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="bad"
|
||||
+KERNEL=="sda", SYMLINK+="found"
|
||||
EOF
|
||||
},
|
||||
);
|
@ -0,0 +1,34 @@
|
||||
From 4fb6b699b3d69341093830e92838336c0dbd7ea9 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 19 Feb 2019 09:21:42 +0900
|
||||
Subject: [PATCH] test-udev: use proper semantics for too long line with
|
||||
continuation
|
||||
|
||||
Follow-up for 1e797cf596df50a6bdd8cbf8e9b2467a3a934171.
|
||||
|
||||
(cherry picked from commit e37a5d90b0c624b95f8d0c3400288fec60417ec4)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 3a50694fa9..58b5dc85e1 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -39,10 +39,11 @@ for (my $i = 1; $i <= 10000; ++$i) {
|
||||
$rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n";
|
||||
}
|
||||
|
||||
-my $rules_10k_tags_continuation = "";
|
||||
-for (my $i = 1; $i <= 10000; ++$i) {
|
||||
- $rules_10k_tags_continuation .= 'KERNEL=="sda", TAG+="test' . $i . "\"\\\n";
|
||||
+my $rules_10k_tags_continuation = "KERNEL==\"sda\", \\\n";
|
||||
+for (my $i = 1; $i < 10000; ++$i) {
|
||||
+ $rules_10k_tags_continuation .= 'TAG+="test' . $i . "\",\\\n";
|
||||
}
|
||||
+$rules_10k_tags_continuation .= "TAG+=\"test10000\"\\n";
|
||||
|
||||
my @tests = (
|
||||
{
|
@ -0,0 +1,40 @@
|
||||
From 66c41fbbeb472563993724352b1984aa3e7e47db Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 19 Feb 2019 09:22:45 +0900
|
||||
Subject: [PATCH] test-udev: add more tests for line continuations and comments
|
||||
|
||||
(cherry picked from commit d35976c670b0e5c2d4081b781e5af88c0689ff00)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 58b5dc85e1..a5e1f8cda3 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1453,13 +1453,21 @@ TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test1
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "don't crash with lots of tags with continuation",
|
||||
+ desc => "continuations",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_name => "found",
|
||||
not_exp_name => "bad" ,
|
||||
rules => $rules_10k_tags_continuation . <<EOF
|
||||
TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="bad"
|
||||
-KERNEL=="sda", SYMLINK+="found"
|
||||
+KERNEL=="sda",\\
|
||||
+# comment in continuation
|
||||
+TAG+="hoge1",\\
|
||||
+ # space before comment
|
||||
+TAG+="hoge2",\\
|
||||
+# spaces before and after token are dropped
|
||||
+ TAG+="hoge3", \\
|
||||
+TAG+="hoge4"
|
||||
+TAGS=="hoge1", TAGS=="hoge2", TAGS=="hoge3", TAGS=="hoge4", SYMLINK+="found"
|
||||
EOF
|
||||
},
|
||||
);
|
@ -0,0 +1,59 @@
|
||||
From ac0def8fb2b51a17b7ef256c5c0edf786fffff2a Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Thu, 21 Feb 2019 18:03:32 +0900
|
||||
Subject: [PATCH] test-udev: add more tests for line continuation
|
||||
|
||||
(cherry picked from commit 84a0819c9d89a2ddb195a5d975ae1fd5c62fde3c)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index a5e1f8cda3..002fabd9fd 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1466,8 +1466,42 @@ TAG+="hoge1",\\
|
||||
TAG+="hoge2",\\
|
||||
# spaces before and after token are dropped
|
||||
TAG+="hoge3", \\
|
||||
+\\
|
||||
+ \\
|
||||
TAG+="hoge4"
|
||||
TAGS=="hoge1", TAGS=="hoge2", TAGS=="hoge3", TAGS=="hoge4", SYMLINK+="found"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "continuations with empty line",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+# empty line finishes continuation
|
||||
+KERNEL=="sda", TAG+="foo" \\
|
||||
+
|
||||
+KERNEL=="sdb", TAG+="hoge"
|
||||
+KERNEL=="sda", TAG+="aaa" \\
|
||||
+KERNEL=="sdb", TAG+="bbb"
|
||||
+TAGS=="foo", SYMLINK+="found"
|
||||
+TAGS=="aaa", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "continuations with white only line",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+# space only line finishes continuation
|
||||
+KERNEL=="sda", TAG+="foo" \\
|
||||
+ \t
|
||||
+KERNEL=="sdb", TAG+="hoge"
|
||||
+KERNEL=="sda", TAG+="aaa" \\
|
||||
+KERNEL=="sdb", TAG+="bbb"
|
||||
+TAGS=="foo", SYMLINK+="found"
|
||||
+TAGS=="aaa", SYMLINK+="bad"
|
||||
EOF
|
||||
},
|
||||
);
|
@ -0,0 +1,501 @@
|
||||
From 7898cd7e75f40627651cec134e3ac3a80176759a Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Thu, 21 Feb 2019 18:04:12 +0900
|
||||
Subject: [PATCH] test-udev: fix alignment and drop unnecessary white spaces
|
||||
|
||||
(cherry picked from commit 3dd2d524141d09d57443ae339e1a77d7ce40f847)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 114 +++++++++++++++++++++++-----------------------
|
||||
1 file changed, 57 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 002fabd9fd..122359e377 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -49,7 +49,7 @@ my @tests = (
|
||||
{
|
||||
desc => "no rules",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "sda" ,
|
||||
+ exp_name => "sda",
|
||||
exp_rem_error => "yes",
|
||||
rules => <<EOF
|
||||
#
|
||||
@@ -58,7 +58,7 @@ EOF
|
||||
{
|
||||
desc => "label test of scsi disc",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "boot_disk" ,
|
||||
+ exp_name => "boot_disk",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -67,7 +67,7 @@ EOF
|
||||
{
|
||||
desc => "label test of scsi disc",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "boot_disk" ,
|
||||
+ exp_name => "boot_disk",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -76,7 +76,7 @@ EOF
|
||||
{
|
||||
desc => "label test of scsi disc",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "boot_disk" ,
|
||||
+ exp_name => "boot_disk",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -85,7 +85,7 @@ EOF
|
||||
{
|
||||
desc => "label test of scsi partition",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
- exp_name => "boot_disk1" ,
|
||||
+ exp_name => "boot_disk1",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
|
||||
EOF
|
||||
@@ -93,7 +93,7 @@ EOF
|
||||
{
|
||||
desc => "label test of pattern match",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
- exp_name => "boot_disk1" ,
|
||||
+ exp_name => "boot_disk1",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="?ATA", SYMLINK+="boot_disk%n-1"
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA?", SYMLINK+="boot_disk%n-2"
|
||||
@@ -104,7 +104,7 @@ EOF
|
||||
{
|
||||
desc => "label test of multiple sysfs files",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
- exp_name => "boot_disk1" ,
|
||||
+ exp_name => "boot_disk1",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS X ", SYMLINK+="boot_diskX%n"
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="boot_disk%n"
|
||||
@@ -113,7 +113,7 @@ EOF
|
||||
{
|
||||
desc => "label test of max sysfs files (skip invalid rule)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
- exp_name => "boot_disk1" ,
|
||||
+ exp_name => "boot_disk1",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="32", SYMLINK+="boot_diskXX%n"
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n"
|
||||
@@ -122,7 +122,7 @@ EOF
|
||||
{
|
||||
desc => "catch device by *",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem/0" ,
|
||||
+ exp_name => "modem/0",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM*", SYMLINK+="modem/%n"
|
||||
EOF
|
||||
@@ -130,7 +130,7 @@ EOF
|
||||
{
|
||||
desc => "catch device by * - take 2",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem/0" ,
|
||||
+ exp_name => "modem/0",
|
||||
rules => <<EOF
|
||||
KERNEL=="*ACM1", SYMLINK+="bad"
|
||||
KERNEL=="*ACM0", SYMLINK+="modem/%n"
|
||||
@@ -139,7 +139,7 @@ EOF
|
||||
{
|
||||
desc => "catch device by ?",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem/0" ,
|
||||
+ exp_name => "modem/0",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM??*", SYMLINK+="modem/%n-1"
|
||||
KERNEL=="ttyACM??", SYMLINK+="modem/%n-2"
|
||||
@@ -149,7 +149,7 @@ EOF
|
||||
{
|
||||
desc => "catch device by character class",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem/0" ,
|
||||
+ exp_name => "modem/0",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM[A-Z]*", SYMLINK+="modem/%n-1"
|
||||
KERNEL=="ttyACM?[0-9]", SYMLINK+="modem/%n-2"
|
||||
@@ -159,7 +159,7 @@ EOF
|
||||
{
|
||||
desc => "replace kernel name",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
EOF
|
||||
@@ -167,7 +167,7 @@ EOF
|
||||
{
|
||||
desc => "Handle comment lines in config file (and replace kernel name)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
# this is a comment
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -177,7 +177,7 @@ EOF
|
||||
{
|
||||
desc => "Handle comment lines in config file with whitespace (and replace kernel name)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
# this is a comment with whitespace before the comment
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -187,7 +187,7 @@ EOF
|
||||
{
|
||||
desc => "Handle whitespace only lines (and replace kernel name)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "whitespace" ,
|
||||
+ exp_name => "whitespace",
|
||||
rules => <<EOF
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ EOF
|
||||
{
|
||||
desc => "Handle empty lines in config file (and replace kernel name)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -212,7 +212,7 @@ EOF
|
||||
{
|
||||
desc => "Handle backslashed multi lines in config file (and replace kernel name)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM0", \\
|
||||
SYMLINK+="modem"
|
||||
@@ -230,7 +230,7 @@ EOF
|
||||
{
|
||||
desc => "Handle stupid backslashed multi lines in config file (and replace kernel name)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
|
||||
#
|
||||
@@ -248,7 +248,7 @@ EOF
|
||||
{
|
||||
desc => "subdirectory handling",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "sub/direct/ory/modem" ,
|
||||
+ exp_name => "sub/direct/ory/modem",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM0", SYMLINK+="sub/direct/ory/modem"
|
||||
EOF
|
||||
@@ -256,7 +256,7 @@ EOF
|
||||
{
|
||||
desc => "parent device name match of scsi partition",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "first_disk5" ,
|
||||
+ exp_name => "first_disk5",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="first_disk%n"
|
||||
EOF
|
||||
@@ -264,7 +264,7 @@ EOF
|
||||
{
|
||||
desc => "test substitution chars",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "Major:8:minor:5:kernelnumber:5:id:0:0:0:0" ,
|
||||
+ exp_name => "Major:8:minor:5:kernelnumber:5:id:0:0:0:0",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:%M:minor:%m:kernelnumber:%n:id:%b"
|
||||
EOF
|
||||
@@ -281,7 +281,7 @@ EOF
|
||||
{
|
||||
desc => "sustitution of sysfs value (%s{file})",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "disk-ATA-sda" ,
|
||||
+ exp_name => "disk-ATA-sda",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="disk-%s{vendor}-%k"
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -290,8 +290,8 @@ EOF
|
||||
{
|
||||
desc => "program result substitution",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "special-device-5" ,
|
||||
- not_exp_name => "not" ,
|
||||
+ exp_name => "special-device-5",
|
||||
+ not_exp_name => "not",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="-special-*", SYMLINK+="not"
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="special-*", SYMLINK+="%c-%n"
|
||||
@@ -300,7 +300,7 @@ EOF
|
||||
{
|
||||
desc => "program result substitution (newline removal)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "newline_removed" ,
|
||||
+ exp_name => "newline_removed",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo test", RESULT=="test", SYMLINK+="newline_removed"
|
||||
EOF
|
||||
@@ -308,7 +308,7 @@ EOF
|
||||
{
|
||||
desc => "program result substitution",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "test-0:0:0:0" ,
|
||||
+ exp_name => "test-0:0:0:0",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", SYMLINK+="%c"
|
||||
EOF
|
||||
@@ -316,7 +316,7 @@ EOF
|
||||
{
|
||||
desc => "program with lots of arguments",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "foo9" ,
|
||||
+ exp_name => "foo9",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="%c{7}"
|
||||
EOF
|
||||
@@ -324,7 +324,7 @@ EOF
|
||||
{
|
||||
desc => "program with subshell",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "bar9" ,
|
||||
+ exp_name => "bar9",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed s/foo9/bar9/'", KERNEL=="sda5", SYMLINK+="%c{7}"
|
||||
EOF
|
||||
@@ -332,7 +332,7 @@ EOF
|
||||
{
|
||||
desc => "program arguments combined with apostrophes",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "foo7" ,
|
||||
+ exp_name => "foo7",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4' 'foo5 foo6 foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
|
||||
EOF
|
||||
@@ -340,7 +340,7 @@ EOF
|
||||
{
|
||||
desc => "program arguments combined with escaped double quotes, part 1",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "foo2" ,
|
||||
+ exp_name => "foo2",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf %%s \\\"foo1 foo2\\\" | grep \\\"foo1 foo2\\\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
|
||||
EOF
|
||||
@@ -348,7 +348,7 @@ EOF
|
||||
{
|
||||
desc => "program arguments combined with escaped double quotes, part 2",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "foo2" ,
|
||||
+ exp_name => "foo2",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c \\\"printf %%s 'foo1 foo2' | grep 'foo1 foo2'\\\"", KERNEL=="sda5", SYMLINK+="%c{2}"
|
||||
EOF
|
||||
@@ -356,7 +356,7 @@ EOF
|
||||
{
|
||||
desc => "program arguments combined with escaped double quotes, part 3",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "foo2" ,
|
||||
+ exp_name => "foo2",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf \\\"%%s %%s\\\" \\\"foo1 foo2\\\" \\\"foo3\\\"| grep \\\"foo1 foo2\\\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
|
||||
EOF
|
||||
@@ -364,7 +364,7 @@ EOF
|
||||
{
|
||||
desc => "characters before the %c{N} substitution",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "my-foo9" ,
|
||||
+ exp_name => "my-foo9",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{7}"
|
||||
EOF
|
||||
@@ -372,7 +372,7 @@ EOF
|
||||
{
|
||||
desc => "substitute the second to last argument",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "my-foo8" ,
|
||||
+ exp_name => "my-foo8",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{6}"
|
||||
EOF
|
||||
@@ -396,7 +396,7 @@ EOF
|
||||
{
|
||||
desc => "test substitution by variable name 3",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "850:0:0:05" ,
|
||||
+ exp_name => "850:0:0:05",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="%M%m%b%n"
|
||||
EOF
|
||||
@@ -404,7 +404,7 @@ EOF
|
||||
{
|
||||
desc => "test substitution by variable name 4",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "855" ,
|
||||
+ exp_name => "855",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major\$minor\$number"
|
||||
EOF
|
||||
@@ -412,7 +412,7 @@ EOF
|
||||
{
|
||||
desc => "test substitution by variable name 5",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
|
||||
- exp_name => "8550:0:0:0" ,
|
||||
+ exp_name => "8550:0:0:0",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major%m%n\$id"
|
||||
EOF
|
||||
@@ -429,7 +429,7 @@ EOF
|
||||
{
|
||||
desc => "non matching SUBSYSTEMS",
|
||||
devpath => "/devices/virtual/tty/console",
|
||||
- exp_name => "TTY" ,
|
||||
+ exp_name => "TTY",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="foo", ATTRS{dev}=="5:1", SYMLINK+="foo"
|
||||
KERNEL=="console", SYMLINK+="TTY"
|
||||
@@ -438,7 +438,7 @@ EOF
|
||||
{
|
||||
desc => "ATTRS match",
|
||||
devpath => "/devices/virtual/tty/console",
|
||||
- exp_name => "foo" ,
|
||||
+ exp_name => "foo",
|
||||
rules => <<EOF
|
||||
KERNEL=="console", SYMLINK+="TTY"
|
||||
ATTRS{dev}=="5:1", SYMLINK+="foo"
|
||||
@@ -447,7 +447,7 @@ EOF
|
||||
{
|
||||
desc => "ATTR (empty file)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "empty" ,
|
||||
+ exp_name => "empty",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", ATTR{test_empty_file}=="?*", SYMLINK+="something"
|
||||
KERNEL=="sda", ATTR{test_empty_file}!="", SYMLINK+="not-empty"
|
||||
@@ -458,7 +458,7 @@ EOF
|
||||
{
|
||||
desc => "ATTR (non-existent file)",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "non-existent" ,
|
||||
+ exp_name => "non-existent",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", ATTR{nofile}=="?*", SYMLINK+="something"
|
||||
KERNEL=="sda", ATTR{nofile}!="", SYMLINK+="not-empty"
|
||||
@@ -471,7 +471,7 @@ EOF
|
||||
{
|
||||
desc => "program and bus type match",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "scsi-0:0:0:0" ,
|
||||
+ exp_name => "scsi-0:0:0:0",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="usb", PROGRAM=="/bin/echo -n usb-%b", SYMLINK+="%c"
|
||||
SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", SYMLINK+="%c"
|
||||
@@ -481,7 +481,7 @@ EOF
|
||||
{
|
||||
desc => "sysfs parent hierarchy",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "modem" ,
|
||||
+ exp_name => "modem",
|
||||
rules => <<EOF
|
||||
ATTRS{idProduct}=="007b", SYMLINK+="modem"
|
||||
EOF
|
||||
@@ -489,7 +489,7 @@ EOF
|
||||
{
|
||||
desc => "name test with ! in the name",
|
||||
devpath => "/devices/virtual/block/fake!blockdev0",
|
||||
- exp_name => "is/a/fake/blockdev0" ,
|
||||
+ exp_name => "is/a/fake/blockdev0",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", SYMLINK+="is/not/a/%k"
|
||||
SUBSYSTEM=="block", SYMLINK+="is/a/%k"
|
||||
@@ -499,7 +499,7 @@ EOF
|
||||
{
|
||||
desc => "name test with ! in the name, but no matching rule",
|
||||
devpath => "/devices/virtual/block/fake!blockdev0",
|
||||
- exp_name => "fake/blockdev0" ,
|
||||
+ exp_name => "fake/blockdev0",
|
||||
exp_rem_error => "yes",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
@@ -542,7 +542,7 @@ EOF
|
||||
desc => "KERNELS wildcard partial 2",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_name => "scsi-0:0:0:0",
|
||||
- rules => <<EOF
|
||||
+ rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
|
||||
SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", SYMLINK+="scsi-0:0:0:0"
|
||||
EOF
|
||||
@@ -739,7 +739,7 @@ EOF
|
||||
devpath => "/devices/virtual/misc/misc-fake1",
|
||||
exp_name => "node",
|
||||
exp_majorminor => "4095:1",
|
||||
- rules => <<EOF
|
||||
+ rules => <<EOF
|
||||
KERNEL=="misc-fake1", SYMLINK+="node"
|
||||
EOF
|
||||
},
|
||||
@@ -764,7 +764,7 @@ EOF
|
||||
desc => "multiple symlinks with a lot of s p a c e s",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
exp_name => "one",
|
||||
- not_exp_name => " ",
|
||||
+ not_exp_name => " ",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
|
||||
EOF
|
||||
@@ -860,7 +860,7 @@ EOF
|
||||
{
|
||||
desc => "multiple symlinks",
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "second-0" ,
|
||||
+ exp_name => "second-0",
|
||||
rules => <<EOF
|
||||
KERNEL=="ttyACM0", SYMLINK="first-%n second-%n third-%n"
|
||||
EOF
|
||||
@@ -869,8 +869,8 @@ EOF
|
||||
desc => "symlink name '.'",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_name => ".",
|
||||
- exp_add_error => "yes",
|
||||
- exp_rem_error => "yes",
|
||||
+ exp_add_error => "yes",
|
||||
+ exp_rem_error => "yes",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="."
|
||||
EOF
|
||||
@@ -879,9 +879,9 @@ EOF
|
||||
desc => "symlink node to itself",
|
||||
devpath => "/devices/virtual/tty/tty0",
|
||||
exp_name => "link",
|
||||
- exp_add_error => "yes",
|
||||
- exp_rem_error => "yes",
|
||||
- option => "clean",
|
||||
+ exp_add_error => "yes",
|
||||
+ exp_rem_error => "yes",
|
||||
+ option => "clean",
|
||||
rules => <<EOF
|
||||
KERNEL=="tty0", SYMLINK+="tty0"
|
||||
EOF
|
||||
@@ -1437,7 +1437,7 @@ EOF
|
||||
desc => "add and match tag",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_name => "found",
|
||||
- not_exp_name => "bad" ,
|
||||
+ not_exp_name => "bad",
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", TAG+="green"
|
||||
TAGS=="green", SYMLINK+="found"
|
||||
@@ -1456,7 +1456,7 @@ EOF
|
||||
desc => "continuations",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_name => "found",
|
||||
- not_exp_name => "bad" ,
|
||||
+ not_exp_name => "bad",
|
||||
rules => $rules_10k_tags_continuation . <<EOF
|
||||
TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="bad"
|
||||
KERNEL=="sda",\\
|
@ -0,0 +1,73 @@
|
||||
From dc50d1cc5bf445f1a26dbc646ff52421563e677f Mon Sep 17 00:00:00 2001
|
||||
From: Dan Streetman <ddstreet@canonical.com>
|
||||
Date: Fri, 5 Jul 2019 11:24:55 -0400
|
||||
Subject: [PATCH] test/udev-test.pl: cleanup if skipping test
|
||||
|
||||
In Ubuntu CI, udev-test.pl is run from the debian/test/udev script,
|
||||
in a test dir created for it; but udev-test.pl setup mounts a
|
||||
dir, so if it doesn't cleanup/unmount before exiting, the test dir
|
||||
autopkgtest created for it can't be removed, and autopkgtest
|
||||
aborts the entire test suite, for example this output (from a
|
||||
test run inside an armhf container):
|
||||
|
||||
autopkgtest [12:45:36]: test udev: [-----------------------
|
||||
umount: test/tmpfs: no mount point specified.
|
||||
mknod: test/tmpfs/dev/null: Operation not permitted
|
||||
unable to create test/tmpfs/dev/null at ./udev-test.pl line 1611.
|
||||
Failed to set up the environment, skipping the test at ./udev-test.pl line 1731.
|
||||
autopkgtest [12:45:41]: test udev: -----------------------]
|
||||
autopkgtest [12:45:44]: test udev: - - - - - - - - - - results - - - - - - - - - -
|
||||
udev FAIL non-zero exit status 77
|
||||
rm: cannot remove '/tmp/autopkgtest.ocPFA6/autopkgtest_tmp/test/tmpfs': Device or resource busy
|
||||
autopkgtest [12:46:22]: ERROR: "rm -rf /tmp/autopkgtest.ocPFA6/udev-artifacts /tmp/autopkgtest.ocPFA6/autopkgtest_tmp" failed with stderr "rm:
|
||||
|
||||
(cherry picked from commit abb9cc50afb3949c442849f43301fb33578f3888)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 122359e377..2fea72875b 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1713,6 +1713,12 @@ sub run_test {
|
||||
|
||||
}
|
||||
|
||||
+sub cleanup {
|
||||
+ system("rm", "-rf", "$udev_run");
|
||||
+ system("umount", "$udev_tmpfs");
|
||||
+ rmdir($udev_tmpfs);
|
||||
+}
|
||||
+
|
||||
# only run if we have root permissions
|
||||
# due to mknod restrictions
|
||||
if (!($<==0)) {
|
||||
@@ -1729,11 +1735,13 @@ if ($? >> 8 == 0) {
|
||||
|
||||
if (!udev_setup()) {
|
||||
warn "Failed to set up the environment, skipping the test";
|
||||
+ cleanup();
|
||||
exit($EXIT_TEST_SKIP);
|
||||
}
|
||||
|
||||
if (system($udev_bin, "check")) {
|
||||
warn "$udev_bin failed to set up the environment, skipping the test";
|
||||
+ cleanup();
|
||||
exit($EXIT_TEST_SKIP);
|
||||
}
|
||||
|
||||
@@ -1776,10 +1784,7 @@ if ($list[0]) {
|
||||
|
||||
print "$error errors occurred\n\n";
|
||||
|
||||
-# cleanup
|
||||
-system("rm", "-rf", "$udev_run");
|
||||
-system("umount", "$udev_tmpfs");
|
||||
-rmdir($udev_tmpfs);
|
||||
+cleanup();
|
||||
|
||||
if ($error > 0) {
|
||||
exit(1);
|
@ -0,0 +1,89 @@
|
||||
From 03bc565e6e3249385c4e1ca0ae27670ca2ad9a41 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 11 Sep 2019 09:06:15 +0900
|
||||
Subject: [PATCH] test: add test cases for empty string match
|
||||
|
||||
(cherry picked from commit 48d26c90852c22ec94be961f5fbdcf462bb9a6e8)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 66 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 66 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 2fea72875b..50d978391b 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1256,6 +1256,72 @@ KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
|
||||
KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
|
||||
KERNEL=="all|dontknow|ttyACM0", SYMLINK+="right"
|
||||
KERNEL=="ttyACM0a|nothing", SYMLINK+="wrong3"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 5",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG="foo"
|
||||
+TAGS=="|foo", SYMLINK+="found"
|
||||
+TAGS=="|aaa", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 6",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG=""
|
||||
+TAGS=="|foo", SYMLINK+="found"
|
||||
+TAGS=="aaa|bbb", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 7",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG="foo"
|
||||
+TAGS=="foo||bar", SYMLINK+="found"
|
||||
+TAGS=="aaa||bbb", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 8",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG=""
|
||||
+TAGS=="foo||bar", SYMLINK+="found"
|
||||
+TAGS=="aaa|bbb", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 9",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG="foo"
|
||||
+TAGS=="foo|", SYMLINK+="found"
|
||||
+TAGS=="aaa|", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 10",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG=""
|
||||
+TAGS=="foo|", SYMLINK+="found"
|
||||
+TAGS=="aaa|bbb", SYMLINK+="bad"
|
||||
EOF
|
||||
},
|
||||
{
|
@ -0,0 +1,35 @@
|
||||
From 03b766cc937ffa4dcb7cfb25b2ac20d8a00cb6db Mon Sep 17 00:00:00 2001
|
||||
From: gaoyi <ymuemc@163.com>
|
||||
Date: Sun, 12 Jul 2020 03:27:45 -0400
|
||||
Subject: [PATCH] test: add test case for multi matches when use "||"
|
||||
|
||||
Signed-off-by: gaoyi <ymuemc@163.com>
|
||||
(cherry picked from commit 0d3a8bc7ebd76591e14f7098b4266fd2065ac4db)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 50d978391b..4bf97d82bb 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1322,6 +1322,17 @@ EOF
|
||||
KERNEL=="sda", TAG=""
|
||||
TAGS=="foo|", SYMLINK+="found"
|
||||
TAGS=="aaa|bbb", SYMLINK+="bad"
|
||||
+EOF
|
||||
+ },
|
||||
+ {
|
||||
+ desc => "test multi matches 11",
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_name => "found",
|
||||
+ not_exp_name => "bad",
|
||||
+ rules => <<EOF
|
||||
+KERNEL=="sda", TAG="c"
|
||||
+TAGS=="foo||bar||c", SYMLINK+="found"
|
||||
+TAGS=="aaa||bbb||ccc", SYMLINK+="bad"
|
||||
EOF
|
||||
},
|
||||
{
|
@ -0,0 +1,33 @@
|
||||
From c68da72231d5c502acd4e79791d0810790f3231b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Fri, 4 Sep 2020 18:09:20 +0200
|
||||
Subject: [PATCH] udev-test: do not rely on "mail" group being defined
|
||||
|
||||
"audio" should be there, at least we declare it. "mail" nowadays is less
|
||||
likely to exist than in the past.
|
||||
|
||||
Fixes one of the items in #16942.
|
||||
|
||||
(cherry picked from commit a9030b81c154c3ec92227d04cad6b13cc1125608)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 4bf97d82bb..a4deffacb9 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -629,9 +629,9 @@ EOF
|
||||
desc => "textual user/group id",
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_name => "node",
|
||||
- exp_perms => "root:mail:0660",
|
||||
+ exp_perms => "root:audio:0660",
|
||||
rules => <<EOF
|
||||
-SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="mail"
|
||||
+SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="audio"
|
||||
EOF
|
||||
},
|
||||
{
|
2452
SOURCES/0525-test-udev-test.pl-allow-multiple-devices-per-test.patch
Normal file
2452
SOURCES/0525-test-udev-test.pl-allow-multiple-devices-per-test.patch
Normal file
File diff suppressed because it is too large
Load Diff
61
SOURCES/0526-test-udev-test.pl-create-rules-only-once.patch
Normal file
61
SOURCES/0526-test-udev-test.pl-create-rules-only-once.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 9aa12f2f564c208c4c1eaef613d18d1c0b481a16 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Mon, 23 Apr 2018 21:58:12 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: create rules only once
|
||||
|
||||
It's not necessary to write the rules for every udev run, as we
|
||||
now may have many (rather than just 2) per test.
|
||||
|
||||
(cherry picked from commit af7ee3eae689f9c31b49ea13758ad9c901918ce3)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index bd5401da75..8b5a97ad61 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -2069,14 +2069,18 @@ EOF
|
||||
},
|
||||
);
|
||||
|
||||
-sub udev {
|
||||
- my ($action, $devpath, $rules) = @_;
|
||||
+sub create_rules {
|
||||
+ my ($rules) = @_;
|
||||
|
||||
# create temporary rules
|
||||
system("mkdir", "-p", "$udev_rules_dir");
|
||||
open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
|
||||
print CONF $$rules;
|
||||
close CONF;
|
||||
+}
|
||||
+
|
||||
+sub udev {
|
||||
+ my ($action, $devpath) = @_;
|
||||
|
||||
if ($valgrind > 0) {
|
||||
return system("$udev_bin_valgrind $action $devpath");
|
||||
@@ -2259,9 +2263,10 @@ sub run_test {
|
||||
my @devices = @{$rules->{devices}};
|
||||
|
||||
print "TEST $number: $rules->{desc}\n";
|
||||
+ create_rules(\$rules->{rules});
|
||||
foreach my $dev (@devices) {
|
||||
print "device \'$dev->{devpath}\' expecting node/link \'$dev->{exp_name}\'\n";
|
||||
- $rc = udev("add", $dev->{devpath}, \$rules->{rules});
|
||||
+ $rc = udev("add", $dev->{devpath});
|
||||
if ($rc != 0) {
|
||||
print "$udev_bin add failed with code $rc\n";
|
||||
$error++;
|
||||
@@ -2278,7 +2283,7 @@ sub run_test {
|
||||
}
|
||||
|
||||
foreach my $dev (@devices) {
|
||||
- $rc = udev("remove", $dev->{devpath}, \$rules->{rules});
|
||||
+ $rc = udev("remove", $dev->{devpath});
|
||||
if ($rc != 0) {
|
||||
print "$udev_bin remove failed with code $rc\n";
|
||||
$error++;
|
@ -0,0 +1,169 @@
|
||||
From 618d56c7ac8bd8cd701344a0eaca8373a78dea95 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Mon, 23 Apr 2018 21:59:05 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: allow concurrent additions and removals
|
||||
|
||||
Allow testing cases where multiple devices are added and removed
|
||||
simultaneously. Tests are started as synchronously as possible using a
|
||||
semaphore, in order to test possible race conditions. If this isn't desired,
|
||||
the test parameter "sleep_us" can be set to the number of microseconds to wait
|
||||
between udev invocations.
|
||||
|
||||
(cherry picked from commit 09a4062d70b3a10d022e40066e2adf09df05bbbc)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 90 +++++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 72 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 8b5a97ad61..db25ef13c1 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -18,6 +18,10 @@
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
+use POSIX qw(WIFEXITED WEXITSTATUS);
|
||||
+use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR IPC_CREAT);
|
||||
+use IPC::Semaphore;
|
||||
+use Time::HiRes qw(usleep);
|
||||
|
||||
my $udev_bin = "./test-udev";
|
||||
my $valgrind = 0;
|
||||
@@ -2210,6 +2214,8 @@ sub check_add {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ print "device \'$device->{devpath}\' expecting node/link \'$device->{exp_name}\'\n";
|
||||
if ((-e "$udev_dev/$device->{exp_name}") ||
|
||||
(-l "$udev_dev/$device->{exp_name}")) {
|
||||
|
||||
@@ -2257,21 +2263,72 @@ sub check_remove {
|
||||
}
|
||||
}
|
||||
|
||||
+sub run_udev {
|
||||
+ my ($action, $dev, $sleep_us, $sema) = @_;
|
||||
+
|
||||
+ # Notify main process that this worker has started
|
||||
+ $sema->op(0, 1, 0);
|
||||
+
|
||||
+ # Wait for start
|
||||
+ $sema->op(0, 0, 0);
|
||||
+ usleep($sleep_us) if defined ($sleep_us);
|
||||
+ my $rc = udev($action, $dev->{devpath});
|
||||
+ exit $rc;
|
||||
+}
|
||||
+
|
||||
+sub fork_and_run_udev {
|
||||
+ my ($action, $rules, $sema) = @_;
|
||||
+ my @devices = @{$rules->{devices}};
|
||||
+ my $dev;
|
||||
+ my $k = 0;
|
||||
+
|
||||
+ $sema->setval(0, 1);
|
||||
+ foreach $dev (@devices) {
|
||||
+ my $pid = fork();
|
||||
+
|
||||
+ if (!$pid) {
|
||||
+ run_udev($action, $dev,
|
||||
+ defined($rules->{sleep_us}) ? $k * $rules->{sleep_us} : undef,
|
||||
+ $sema);
|
||||
+ } else {
|
||||
+ $dev->{pid} = $pid;
|
||||
+ }
|
||||
+ $k++;
|
||||
+ }
|
||||
+
|
||||
+ # This operation waits for all workers to become ready, and
|
||||
+ # starts them off when that's the case.
|
||||
+ $sema->op(0, -($#devices + 2), 0);
|
||||
+
|
||||
+ foreach $dev (@devices) {
|
||||
+ my $rc;
|
||||
+ my $pid;
|
||||
+
|
||||
+ $pid = waitpid($dev->{pid}, 0);
|
||||
+ if ($pid == -1) {
|
||||
+ print "error waiting for pid dev->{pid}\n";
|
||||
+ $error += 1;
|
||||
+ }
|
||||
+ if (WIFEXITED($?)) {
|
||||
+ $rc = WEXITSTATUS($?);
|
||||
+
|
||||
+ if ($rc) {
|
||||
+ print "$udev_bin $action for $dev->{devpath} failed with code $rc\n";
|
||||
+ $error += 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
sub run_test {
|
||||
- my ($rules, $number) = @_;
|
||||
+ my ($rules, $number, $sema) = @_;
|
||||
my $rc;
|
||||
my @devices = @{$rules->{devices}};
|
||||
|
||||
print "TEST $number: $rules->{desc}\n";
|
||||
create_rules(\$rules->{rules});
|
||||
- foreach my $dev (@devices) {
|
||||
- print "device \'$dev->{devpath}\' expecting node/link \'$dev->{exp_name}\'\n";
|
||||
- $rc = udev("add", $dev->{devpath});
|
||||
- if ($rc != 0) {
|
||||
- print "$udev_bin add failed with code $rc\n";
|
||||
- $error++;
|
||||
- }
|
||||
- }
|
||||
+
|
||||
+ fork_and_run_udev("add", $rules, $sema);
|
||||
|
||||
foreach my $dev (@devices) {
|
||||
check_add($dev);
|
||||
@@ -2282,13 +2339,8 @@ sub run_test {
|
||||
return;
|
||||
}
|
||||
|
||||
- foreach my $dev (@devices) {
|
||||
- $rc = udev("remove", $dev->{devpath});
|
||||
- if ($rc != 0) {
|
||||
- print "$udev_bin remove failed with code $rc\n";
|
||||
- $error++;
|
||||
- }
|
||||
- }
|
||||
+ fork_and_run_udev("remove", $rules, $sema);
|
||||
+
|
||||
foreach my $dev (@devices) {
|
||||
check_remove($dev);
|
||||
}
|
||||
@@ -2350,12 +2402,13 @@ foreach my $arg (@ARGV) {
|
||||
push(@list, $arg);
|
||||
}
|
||||
}
|
||||
+my $sema = IPC::Semaphore->new(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR | IPC_CREAT);
|
||||
|
||||
if ($list[0]) {
|
||||
foreach my $arg (@list) {
|
||||
if (defined($tests[$arg-1]->{desc})) {
|
||||
print "udev-test will run test number $arg:\n\n";
|
||||
- run_test($tests[$arg-1], $arg);
|
||||
+ run_test($tests[$arg-1], $arg, $sema);
|
||||
} else {
|
||||
print "test does not exist.\n";
|
||||
}
|
||||
@@ -2365,11 +2418,12 @@ if ($list[0]) {
|
||||
print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
|
||||
|
||||
foreach my $rules (@tests) {
|
||||
- run_test($rules, $test_num);
|
||||
+ run_test($rules, $test_num, $sema);
|
||||
$test_num++;
|
||||
}
|
||||
}
|
||||
|
||||
+$sema->remove;
|
||||
print "$error errors occurred\n\n";
|
||||
|
||||
cleanup();
|
260
SOURCES/0528-test-udev-test.pl-use-computed-devnode-name.patch
Normal file
260
SOURCES/0528-test-udev-test.pl-use-computed-devnode-name.patch
Normal file
@ -0,0 +1,260 @@
|
||||
From 5f34ea55a8c6723240eb1641a655db7df3c428a2 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 09:38:26 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: use computed devnode name
|
||||
|
||||
More often than not, the created devnode is the basename of the
|
||||
sysfs entry. The "devnode" device may be used to override the
|
||||
auto-detected node name.
|
||||
|
||||
Permissions and major/minor number are now verified on the devnode
|
||||
itself, not on symlinks.
|
||||
|
||||
For those tests where exp_name is set to the computed devnode name,
|
||||
the explicit "exp_name" can be removed. "exp_name" is only required for
|
||||
symlinks.
|
||||
|
||||
This allows separate testing for devnodes and symlinks an a follow-up
|
||||
patch.
|
||||
|
||||
(cherry picked from commit f0dccf01a7b4e72278e14effd74782ea83d0a73b)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 92 +++++++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 66 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index db25ef13c1..aa9a8dc2ff 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -55,12 +55,10 @@ my @tests = (
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "sda" ,
|
||||
exp_rem_error => "yes",
|
||||
},
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
- exp_name => "sda1" ,
|
||||
exp_rem_error => "yes",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -644,6 +642,7 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/virtual/block/fake!blockdev0",
|
||||
+ devnode => "fake/blockdev0",
|
||||
exp_name => "is/a/fake/blockdev0" ,
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -657,7 +656,7 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/virtual/block/fake!blockdev0",
|
||||
- exp_name => "fake/blockdev0" ,
|
||||
+ devnode => "fake/blockdev0",
|
||||
exp_rem_error => "yes",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -768,7 +767,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/virtual/tty/tty33",
|
||||
- exp_name => "tty33",
|
||||
exp_perms => "0:0:0600",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -864,7 +862,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => "1::",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -876,7 +873,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => ":1:0660",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -888,7 +884,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => "::0060",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -900,7 +895,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => "1:1:0777",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -912,7 +906,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => "1:1:0777",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -926,7 +919,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => "1:1:0777",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -942,7 +934,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_name => "ttyACM0",
|
||||
exp_perms => "1:2:0777",
|
||||
}],
|
||||
rules => <<EOF
|
||||
@@ -1922,7 +1913,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "sda",
|
||||
exp_perms => "0:0:0000",
|
||||
exp_rem_error => "yes",
|
||||
}],
|
||||
@@ -1935,7 +1925,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "sda",
|
||||
exp_perms => "1:1:0400",
|
||||
exp_rem_error => "yes",
|
||||
}],
|
||||
@@ -1949,7 +1938,6 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
- exp_name => "sda",
|
||||
exp_perms => "0:0:0440",
|
||||
exp_rem_error => "yes",
|
||||
}],
|
||||
@@ -2203,6 +2191,44 @@ sub udev_setup {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+sub get_devnode {
|
||||
+ my ($device) = @_;
|
||||
+ my $devnode;
|
||||
+
|
||||
+ if (defined($device->{devnode})) {
|
||||
+ $devnode = "$udev_dev/$device->{devnode}";
|
||||
+ } else {
|
||||
+ $devnode = "$device->{devpath}";
|
||||
+ $devnode =~ s!.*/!$udev_dev/!;
|
||||
+ }
|
||||
+ return $devnode;
|
||||
+}
|
||||
+
|
||||
+sub check_devnode {
|
||||
+ my ($device) = @_;
|
||||
+ my $devnode = get_devnode($device);
|
||||
+
|
||||
+ my @st = lstat("$devnode");
|
||||
+ if (! (-b _ || -c _)) {
|
||||
+ print "add $devnode: error\n";
|
||||
+ system("tree", "$udev_dev");
|
||||
+ $error++;
|
||||
+ return undef;
|
||||
+ }
|
||||
+
|
||||
+ my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
|
||||
+ $atime, $mtime, $ctime, $blksize, $blocks) = @st;
|
||||
+
|
||||
+ if (defined($device->{exp_perms})) {
|
||||
+ permissions_test($device, $uid, $gid, $mode);
|
||||
+ }
|
||||
+ if (defined($device->{exp_majorminor})) {
|
||||
+ major_minor_test($device, $rdev);
|
||||
+ }
|
||||
+ print "add $devnode: ok\n";
|
||||
+ return $devnode;
|
||||
+}
|
||||
+
|
||||
sub check_add {
|
||||
my ($device) = @_;
|
||||
|
||||
@@ -2215,19 +2241,13 @@ sub check_add {
|
||||
}
|
||||
}
|
||||
|
||||
+ my $devnode = check_devnode($device);
|
||||
+
|
||||
print "device \'$device->{devpath}\' expecting node/link \'$device->{exp_name}\'\n";
|
||||
+ return if (!defined($device->{exp_name}));
|
||||
+
|
||||
if ((-e "$udev_dev/$device->{exp_name}") ||
|
||||
(-l "$udev_dev/$device->{exp_name}")) {
|
||||
-
|
||||
- my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
|
||||
- $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$device->{exp_name}");
|
||||
-
|
||||
- if (defined($device->{exp_perms})) {
|
||||
- permissions_test($device, $uid, $gid, $mode);
|
||||
- }
|
||||
- if (defined($device->{exp_majorminor})) {
|
||||
- major_minor_test($device, $rdev);
|
||||
- }
|
||||
print "add $device->{devpath}: ok\n";
|
||||
} else {
|
||||
print "add $device->{devpath}: error";
|
||||
@@ -2243,12 +2263,32 @@ sub check_add {
|
||||
}
|
||||
}
|
||||
|
||||
+sub check_remove_devnode {
|
||||
+ my ($device) = @_;
|
||||
+ my $devnode = get_devnode($device);
|
||||
+
|
||||
+ if (-e "$devnode") {
|
||||
+ print "remove $devnode: error";
|
||||
+ print "\n";
|
||||
+ system("tree", "$udev_dev");
|
||||
+ print "\n";
|
||||
+ $error++;
|
||||
+ sleep(1);
|
||||
+ } else {
|
||||
+ print "remove $devnode: ok\n";
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
sub check_remove {
|
||||
my ($device) = @_;
|
||||
|
||||
+ check_remove_devnode($device);
|
||||
+
|
||||
+ return if (!defined($device->{exp_name}));
|
||||
+
|
||||
if ((-e "$udev_dev/$device->{exp_name}") ||
|
||||
(-l "$udev_dev/$device->{exp_name}")) {
|
||||
- print "remove $device->{devpath}: error";
|
||||
+ print "remove $device->{exp_name}: error";
|
||||
if ($device->{exp_rem_error}) {
|
||||
print " as expected\n";
|
||||
} else {
|
||||
@@ -2259,7 +2299,7 @@ sub check_remove {
|
||||
sleep(1);
|
||||
}
|
||||
} else {
|
||||
- print "remove $device->{devpath}: ok\n";
|
||||
+ print "remove $device->{exp_name}: ok\n";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
From 8ee1cc626f616a2022d641a464fbde9108dd8ad9 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 10:50:24 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: test correctness of symlink targets
|
||||
|
||||
Test if symlinks are created correctly by comparing the symlink
|
||||
targets to the devnode path. This implies (for the symlink) that
|
||||
major/minor numbers and permissions are correct, as we have tested
|
||||
that on the devnode already.
|
||||
|
||||
(cherry picked from commit 997683c8f152e1c139a7ce537de81a0aeae4627f)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 23 ++++++++++++++++++-----
|
||||
1 file changed, 18 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index aa9a8dc2ff..2e3089c5e0 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -22,6 +22,7 @@ use POSIX qw(WIFEXITED WEXITSTATUS);
|
||||
use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR IPC_CREAT);
|
||||
use IPC::Semaphore;
|
||||
use Time::HiRes qw(usleep);
|
||||
+use Cwd qw(getcwd abs_path);
|
||||
|
||||
my $udev_bin = "./test-udev";
|
||||
my $valgrind = 0;
|
||||
@@ -2243,14 +2244,26 @@ sub check_add {
|
||||
|
||||
my $devnode = check_devnode($device);
|
||||
|
||||
- print "device \'$device->{devpath}\' expecting node/link \'$device->{exp_name}\'\n";
|
||||
return if (!defined($device->{exp_name}));
|
||||
|
||||
- if ((-e "$udev_dev/$device->{exp_name}") ||
|
||||
- (-l "$udev_dev/$device->{exp_name}")) {
|
||||
- print "add $device->{devpath}: ok\n";
|
||||
+ my @st = lstat("$udev_dev/$device->{exp_name}");
|
||||
+ if (-l _) {
|
||||
+ my $cwd = getcwd();
|
||||
+ my $dir = "$udev_dev/$device->{exp_name}";
|
||||
+ $dir =~ s!/[^/]*$!!;
|
||||
+ my $tgt = readlink("$udev_dev/$device->{exp_name}");
|
||||
+ $tgt = abs_path("$dir/$tgt");
|
||||
+ $tgt =~ s!^$cwd/!!;
|
||||
+
|
||||
+ if ($tgt ne $devnode) {
|
||||
+ print "symlink $device->{exp_name}: error, found -> $tgt\n";
|
||||
+ $error++;
|
||||
+ system("tree", "$udev_dev");
|
||||
+ } else {
|
||||
+ print "symlink $device->{exp_name}: ok\n";
|
||||
+ }
|
||||
} else {
|
||||
- print "add $device->{devpath}: error";
|
||||
+ print "symlink $device->{exp_name}: error";
|
||||
if ($device->{exp_add_error}) {
|
||||
print " as expected\n";
|
||||
} else {
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,83 @@
|
||||
From 0e0b90ffcf0731865846bfa2754a809cc2b8c53e Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 17:57:47 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: fix wrong test descriptions
|
||||
|
||||
udev hasn't supported renaming device nodes for some time.
|
||||
|
||||
(cherry picked from commit 46bc71b2b73f8a1e27dc5e142730e9877dd05e3e)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index f5edecefd0..d5d0e130e3 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -212,7 +212,7 @@ KERNEL=="ttyACM[0-9]*", SYMLINK+="modem/%n"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "replace kernel name",
|
||||
+ desc => "don't replace kernel name",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
@@ -223,7 +223,7 @@ KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "Handle comment lines in config file (and replace kernel name)",
|
||||
+ desc => "Handle comment lines in config file (and don't replace kernel name)",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
@@ -236,7 +236,7 @@ KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "Handle comment lines in config file with whitespace (and replace kernel name)",
|
||||
+ desc => "Handle comment lines in config file with whitespace (and don't replace kernel name)",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
@@ -249,7 +249,7 @@ KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "Handle whitespace only lines (and replace kernel name)",
|
||||
+ desc => "Handle whitespace only lines (and don't replace kernel name)",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
@@ -267,7 +267,7 @@ KERNEL=="ttyACM0", SYMLINK+="whitespace"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "Handle empty lines in config file (and replace kernel name)",
|
||||
+ desc => "Handle empty lines in config file (and don't replace kernel name)",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
@@ -280,7 +280,7 @@ KERNEL=="ttyACM0", SYMLINK+="modem"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
- desc => "Handle backslashed multi lines in config file (and replace kernel name)",
|
||||
+ desc => "Handle backslashed multi lines in config file (and don't replace kernel name)",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
@@ -303,8 +303,9 @@ EOF
|
||||
KERNEL=="ttyACM0", PROGRAM=="/bin/echo -e \\101", RESULT=="A", SYMLINK+="aaa"
|
||||
EOF
|
||||
},
|
||||
+ # 20
|
||||
{
|
||||
- desc => "Handle stupid backslashed multi lines in config file (and replace kernel name)",
|
||||
+ desc => "Handle stupid backslashed multi lines in config file (and don't replace kernel name)",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
@ -0,0 +1,35 @@
|
||||
From 2d0b828715e67f7accda6f73481deb74febebcb6 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 18:08:18 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: last_rule is unsupported
|
||||
|
||||
the "last_rule" option hasn't been supported for some time.
|
||||
Therefore this test fails if a "not_exp_links" attribute is added,
|
||||
as it should be. Mark it appropriately.
|
||||
|
||||
(cherry picked from commit 17cce031531a5d3f38a27374c99d1bdba5959dbd)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index d5d0e130e3..a9c2dd95f1 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1373,11 +1373,14 @@ SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
+ # This is not supported any more
|
||||
desc => "last_rule option",
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
|
||||
exp_links => ["last"],
|
||||
+ not_exp_links => ["very-last"],
|
||||
+ exp_nodev_error => "yes",
|
||||
}],
|
||||
rules => <<EOF
|
||||
SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="last", OPTIONS="last_rule"
|
@ -0,0 +1,74 @@
|
||||
From 134a415c2d690e57d0f1add23e900e60bcef4627 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 18:09:50 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: Make some tests a little harder
|
||||
|
||||
Add some rules that make it a bit harder to pass, mainly the
|
||||
non-existence checks.
|
||||
|
||||
(cherry picked from commit 06d4d4e24e7d0b51120b165e540d278842e8b1a3)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index a9c2dd95f1..7465b5859e 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1358,7 +1358,7 @@ EOF
|
||||
exp_links => ["sda-part-1"],
|
||||
}],
|
||||
rules => <<EOF
|
||||
-SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-1"
|
||||
+SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-%n"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
@@ -1486,6 +1486,7 @@ SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
|
||||
SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="absolutely-\$env{ASSIGN}"
|
||||
SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
|
||||
SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
|
||||
+SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="true", SYMLINK+="bad"
|
||||
SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="absolutely-true", SYMLINK+="true"
|
||||
EOF
|
||||
},
|
||||
@@ -1497,6 +1498,11 @@ EOF
|
||||
exp_links => ["part"],
|
||||
not_exp_links => ["disk"],
|
||||
},
|
||||
+ {
|
||||
+ devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
+ exp_links => ["disk"],
|
||||
+ not_exp_links => ["part"],
|
||||
+ },
|
||||
],
|
||||
rules => <<EOF
|
||||
SUBSYSTEM=="block", KERNEL=="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false"
|
||||
@@ -1588,7 +1594,7 @@ EOF
|
||||
}],
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", GROUP:="tty"
|
||||
-KERNEL=="sda", GROUP="not-ok", MODE="0640", SYMLINK+="ok"
|
||||
+KERNEL=="sda", GROUP="root", MODE="0640", SYMLINK+="ok"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
@@ -1602,7 +1608,7 @@ EOF
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", GROUP:="tty"
|
||||
SUBSYSTEM=="block", MODE:="640"
|
||||
-KERNEL=="sda", GROUP="not-ok", MODE="0666", SYMLINK+="ok"
|
||||
+KERNEL=="sda", GROUP="root", MODE="0666", SYMLINK+="ok"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
@@ -1983,7 +1989,6 @@ EOF
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
|
||||
exp_perms => "1:1:0400",
|
||||
- exp_rem_error => "yes",
|
||||
}],
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", MODE="666"
|
@ -0,0 +1,28 @@
|
||||
From c63273de445789ffeea961448fda51d21c924f8c Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 18:16:59 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: remove bogus rules from magic subsys test
|
||||
|
||||
These rules have survived from an ancient version of the code
|
||||
and save no purpose any more.
|
||||
|
||||
(cherry picked from commit 86634df43b715f3f77c7de73a3ef6566e5cdf571)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 7465b5859e..6928439d14 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -2017,8 +2017,6 @@ EOF
|
||||
exp_perms => "0:0:0600",
|
||||
}],
|
||||
rules => <<EOF
|
||||
-KERNEL=="sda", PROGRAM="/bin/true create-envp"
|
||||
-KERNEL=="sda", ENV{TESTENV}="change-envp"
|
||||
KERNEL=="sda", SYMLINK+="%k-%s{[dmi/id]product_name}-end"
|
||||
EOF
|
||||
},
|
@ -0,0 +1,57 @@
|
||||
From 7821ecc0b35c422bc8ed26e0e44c841d067f88d7 Mon Sep 17 00:00:00 2001
|
||||
From: Martin Wilck <mwilck@suse.com>
|
||||
Date: Tue, 24 Apr 2018 18:27:25 +0200
|
||||
Subject: [PATCH] test/udev-test.pl: merge "space and var with space" tests
|
||||
|
||||
As we can check multiple links in a single test now, these 3
|
||||
tests can be merged into one.
|
||||
|
||||
(cherry picked from commit 2084fe0d3290c525ecb9faa07d07c3abc2488e59)
|
||||
|
||||
Related: #1642728
|
||||
---
|
||||
test/udev-test.pl | 31 +++----------------------------
|
||||
1 file changed, 3 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/test/udev-test.pl b/test/udev-test.pl
|
||||
index 6928439d14..880a73b10b 100755
|
||||
--- a/test/udev-test.pl
|
||||
+++ b/test/udev-test.pl
|
||||
@@ -1103,34 +1103,9 @@ EOF
|
||||
devices => [
|
||||
{
|
||||
devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_links => ["first"],
|
||||
- not_exp_links => [" "],
|
||||
- }],
|
||||
- rules => <<EOF
|
||||
-ENV{WITH_WS}=" one two three "
|
||||
-SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
|
||||
-EOF
|
||||
- },
|
||||
- {
|
||||
- desc => "symlink with space and var with space, part 2",
|
||||
- devices => [
|
||||
- {
|
||||
- devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_links => ["name-one_two_three-end"],
|
||||
- not_exp_links => [" "],
|
||||
- }],
|
||||
- rules => <<EOF
|
||||
-ENV{WITH_WS}=" one two three "
|
||||
-SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
|
||||
-EOF
|
||||
- },
|
||||
- {
|
||||
- desc => "symlink with space and var with space, part 3",
|
||||
- devices => [
|
||||
- {
|
||||
- devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
|
||||
- exp_links => ["another_symlink"],
|
||||
- not_exp_links => [" "],
|
||||
+ exp_links => ["first", "name-one_two_three-end",
|
||||
+ "another_symlink", "a", "b", "c"],
|
||||
+ not_exp_links => [" "],
|
||||
}],
|
||||
rules => <<EOF
|
||||
ENV{WITH_WS}=" one two three "
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user