systemd-249-8

Resolves: #1973856,#1998509,#2000927,#2003002,#2003031,#2003130,#2005024,#2009237
This commit is contained in:
Jan Macku 2021-10-12 09:54:22 +02:00
parent 654b62f988
commit 09bc8d360a
23 changed files with 1652 additions and 1 deletions

View File

@ -0,0 +1,25 @@
From bdea01b16bedae5fdba3e9a12a864087cfb4b040 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 25 Aug 2021 16:03:04 +0200
Subject: [PATCH] Really don't enable systemd-journald-audit.socket
RHEL-only
Resolves: #1973856
---
units/systemd-journald.service.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in
index d981273b07..f190dff5fb 100644
--- a/units/systemd-journald.service.in
+++ b/units/systemd-journald.service.in
@@ -33,7 +33,7 @@ RestrictRealtime=yes
RestrictSUIDSGID=yes
RuntimeDirectory=systemd/journal
RuntimeDirectoryPreserve=yes
-Sockets=systemd-journald.socket systemd-journald-dev-log.socket systemd-journald-audit.socket
+Sockets=systemd-journald.socket systemd-journald-dev-log.socket
StandardOutput=null
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM

View File

@ -0,0 +1,56 @@
From f583f3db3533bb2b3db1646d6afa74613fca46a6 Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Tue, 12 Feb 2019 16:58:16 +0100
Subject: [PATCH] rules: add elevator= kernel command line parameter
Kernel removed the elevator= option, so let's reintroduce
it for rhel8 via udev rule.
RHEL-only
Resolves: #2003002
---
rules.d/40-elevator.rules | 20 ++++++++++++++++++++
rules.d/meson.build | 1 +
2 files changed, 21 insertions(+)
create mode 100644 rules.d/40-elevator.rules
diff --git a/rules.d/40-elevator.rules b/rules.d/40-elevator.rules
new file mode 100644
index 0000000000..dbe8fc81a4
--- /dev/null
+++ b/rules.d/40-elevator.rules
@@ -0,0 +1,20 @@
+# We aren't adding devices skip the elevator check
+ACTION!="add", GOTO="sched_out"
+
+SUBSYSTEM!="block", GOTO="sched_out"
+ENV{DEVTYPE}!="disk", GOTO="sched_out"
+
+# Technically, dm-multipath can be configured to use an I/O scheduler.
+# However, there are races between the 'add' uevent and the linking in
+# of the queue/scheduler sysfs file. For now, just skip dm- devices.
+KERNEL=="dm-*|md*", GOTO="sched_out"
+
+# Skip bio-based devices, which don't support an I/O scheduler.
+ATTR{queue/scheduler}=="none", GOTO="sched_out"
+
+# If elevator= is specified on the kernel command line, change the
+# scheduler to the one specified.
+IMPORT{cmdline}="elevator"
+ENV{elevator}!="", ATTR{queue/scheduler}="$env{elevator}"
+
+LABEL="sched_out"
\ No newline at end of file
diff --git a/rules.d/meson.build b/rules.d/meson.build
index 72632979fa..b41c50cad3 100644
--- a/rules.d/meson.build
+++ b/rules.d/meson.build
@@ -5,6 +5,7 @@ install_data(
install_dir : udevrulesdir)
rules = files('''
+ 40-elevator.rules
40-redhat.rules
60-autosuspend.rules
60-block.rules

View File

@ -0,0 +1,94 @@
From 9c67a1570d89ff462cb51f4b2a6d2ed0af8e2e9c Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 30 Aug 2021 18:38:09 +0200
Subject: [PATCH] boot: don't build bootctl when -Dgnu-efi=false is set
(cherry picked from commit fbe3a414e1d8f7b05dccf3d24d4fa475eb9c6bc9)
Resolves: #2003130
---
meson.build | 8 +++++---
shell-completion/bash/meson.build | 2 +-
shell-completion/zsh/meson.build | 2 +-
units/meson.build | 2 +-
4 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/meson.build b/meson.build
index 738879eb21..d28f04607a 100644
--- a/meson.build
+++ b/meson.build
@@ -1608,6 +1608,10 @@ else
endif
conf.set10('ENABLE_EFI', have)
+subdir('src/fundamental')
+subdir('src/boot/efi')
+conf.set10('HAVE_GNU_EFI', have_gnu_efi)
+
############################################################
build_bpf_skel_py = find_program('tools/build-bpf-skel.py')
@@ -1660,7 +1664,6 @@ includes = [libsystemd_includes, include_directories('src/shared')]
subdir('po')
subdir('catalog')
-subdir('src/fundamental')
subdir('src/basic')
subdir('src/libsystemd')
subdir('src/shared')
@@ -1751,7 +1754,6 @@ subdir('src/journal')
subdir('src/libsystemd-network')
subdir('src/analyze')
-subdir('src/boot/efi')
subdir('src/busctl')
subdir('src/coredump')
subdir('src/cryptenroll')
@@ -2145,7 +2147,7 @@ if conf.get('HAVE_PAM') == 1
install_dir : rootlibexecdir)
endif
-if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1
+if conf.get('HAVE_BLKID') == 1 and conf.get('HAVE_GNU_EFI') == 1
public_programs += executable(
'bootctl',
'src/boot/bootctl.c',
diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build
index c26b413d92..bfdd2b01f0 100644
--- a/shell-completion/bash/meson.build
+++ b/shell-completion/bash/meson.build
@@ -33,7 +33,7 @@ items = [['busctl', ''],
['systemd-run', ''],
['udevadm', ''],
['kernel-install', ''],
- ['bootctl', 'ENABLE_EFI'],
+ ['bootctl', 'HAVE_GNU_EFI'],
['coredumpctl', 'ENABLE_COREDUMP'],
['homectl', 'ENABLE_HOMED'],
['hostnamectl', 'ENABLE_HOSTNAMED'],
diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build
index f5f9b0f993..3a92f303b8 100644
--- a/shell-completion/zsh/meson.build
+++ b/shell-completion/zsh/meson.build
@@ -28,7 +28,7 @@ items = [['_busctl', ''],
['_sd_outputmodes', ''],
['_sd_unit_files', ''],
['_sd_machines', ''],
- ['_bootctl', 'ENABLE_EFI'],
+ ['_bootctl', 'HAVE_GNU_EFI'],
['_coredumpctl', 'ENABLE_COREDUMP'],
['_hostnamectl', 'ENABLE_HOSTNAMED'],
['_localectl', 'ENABLE_LOCALED'],
diff --git a/units/meson.build b/units/meson.build
index 68be8d0108..27a2b60137 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -102,7 +102,7 @@ units = [
['systemd-ask-password-wall.path', '',
'multi-user.target.wants/'],
['systemd-ask-password-wall.service', ''],
- ['systemd-boot-system-token.service', 'ENABLE_EFI',
+ ['systemd-boot-system-token.service', 'HAVE_GNU_EFI',
'sysinit.target.wants/'],
['systemd-coredump.socket', 'ENABLE_COREDUMP',
'sockets.target.wants/'],

View File

@ -0,0 +1,28 @@
From 8f08b876d44d96b3f255ac5275a1daa3ccf9a801 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 21 Sep 2021 22:47:42 +0200
Subject: [PATCH] unit: install the systemd-bless-boot.service only if we have
gnu-efi
Follow-up to #20591.
(cherry picked from commit 220261ef940a126588b20a1765a2501811473839)
Related: #2003130
---
units/meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/units/meson.build b/units/meson.build
index 27a2b60137..e06d883cd2 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -179,7 +179,7 @@ in_units = [
['systemd-backlight@.service', 'ENABLE_BACKLIGHT'],
['systemd-binfmt.service', 'ENABLE_BINFMT',
'sysinit.target.wants/'],
- ['systemd-bless-boot.service', 'ENABLE_EFI HAVE_BLKID'],
+ ['systemd-bless-boot.service', 'HAVE_GNU_EFI HAVE_BLKID'],
['systemd-boot-check-no-failures.service', ''],
['systemd-coredump@.service', 'ENABLE_COREDUMP'],
['systemd-pstore.service', 'ENABLE_PSTORE'],

View File

@ -0,0 +1,26 @@
From ab1ecca56e5a1cc5ad120958b1bb94c7854f3795 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 22 Sep 2021 14:38:00 +0200
Subject: [PATCH] units: don't enable tmp.mount statically in local-fs.target
RHEL-only
Related: #2000927
---
units/meson.build | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/units/meson.build b/units/meson.build
index e06d883cd2..40487d123e 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -154,8 +154,7 @@ units = [
['time-set.target', ''],
['time-sync.target', ''],
['timers.target', ''],
- ['tmp.mount', '',
- 'local-fs.target.wants/'],
+ ['tmp.mount', ''],
['umount.target', ''],
['usb-gadget.target', ''],
['user.slice', ''],

View File

@ -0,0 +1,59 @@
From 50a744391dbb1130d38b44700ae7e6649fcc9ffb Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Wed, 1 Aug 2018 13:19:39 +0200
Subject: [PATCH] pid1: bump DefaultTasksMax to 80% of the kernel pid.max value
This should be hopefully high enough even for the very big deployments.
RHEL-only
Resolves: #2003031
---
man/systemd-system.conf.xml | 4 ++--
src/core/main.c | 2 +-
src/core/system.conf.in | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index c11dd46143..72c8db5890 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -389,10 +389,10 @@
<listitem><para>Configure the default value for the per-unit <varname>TasksMax=</varname> setting. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. This setting applies to all unit types that support resource control settings, with the exception
- of slice units. Defaults to 15% of the minimum of <varname>kernel.pid_max=</varname>, <varname>kernel.threads-max=</varname>
+ of slice units. Defaults to 80% of the minimum of <varname>kernel.pid_max=</varname>, <varname>kernel.threads-max=</varname>
and root cgroup <varname>pids.max</varname>.
Kernel has a default value for <varname>kernel.pid_max=</varname> and an algorithm of counting in case of more than 32 cores.
- For example with the default <varname>kernel.pid_max=</varname>, <varname>DefaultTasksMax=</varname> defaults to 4915,
+ For example with the default <varname>kernel.pid_max=</varname>, <varname>DefaultTasksMax=</varname> defaults to 26214,
but might be greater in other systems or smaller in OS containers.</para></listitem>
</varlistentry>
diff --git a/src/core/main.c b/src/core/main.c
index da6c50a1c4..f4fe7517fd 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -92,7 +92,7 @@
#include <sanitizer/lsan_interface.h>
#endif
-#define DEFAULT_TASKS_MAX ((TasksMax) { 15U, 100U }) /* 15% */
+#define DEFAULT_TASKS_MAX ((TasksMax) { 80U, 100U }) /* 80% */
static enum {
ACTION_RUN,
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index e88280bd0a..f2c75fcd32 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -54,7 +54,7 @@
#DefaultBlockIOAccounting=no
#DefaultMemoryAccounting={{ 'yes' if MEMORY_ACCOUNTING_DEFAULT else 'no' }}
#DefaultTasksAccounting=yes
-#DefaultTasksMax=15%
+#DefaultTasksMax=80%
#DefaultLimitCPU=
#DefaultLimitFSIZE=
#DefaultLimitDATA=

View File

@ -0,0 +1,43 @@
From 9c46b3e584fbb7be0a9e93471d30f2885bd194c9 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 09:22:15 +0900
Subject: [PATCH] sd-device: introduce device_has_devlink()
(cherry picked from commit b881ce16b9ccae4c3089c82e2ea1781cd9773a4f)
Related: #2005024
---
src/libsystemd/sd-device/device-private.h | 1 +
src/libsystemd/sd-device/sd-device.c | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h
index fe268d7f2f..9bb5eff208 100644
--- a/src/libsystemd/sd-device/device-private.h
+++ b/src/libsystemd/sd-device/device-private.h
@@ -32,6 +32,7 @@ void device_set_db_persist(sd_device *device);
void device_set_devlink_priority(sd_device *device, int priority);
int device_ensure_usec_initialized(sd_device *device, sd_device *device_old);
int device_add_devlink(sd_device *device, const char *devlink);
+bool device_has_devlink(sd_device *device, const char *devlink);
int device_add_property(sd_device *device, const char *property, const char *value);
int device_add_tag(sd_device *device, const char *tag, bool both);
void device_remove_tag(sd_device *device, const char *tag);
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index 388128bf33..8a9e4a33a1 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -1193,6 +1193,13 @@ int device_add_devlink(sd_device *device, const char *devlink) {
return 0;
}
+bool device_has_devlink(sd_device *device, const char *devlink) {
+ assert(device);
+ assert(devlink);
+
+ return set_contains(device->devlinks, devlink);
+}
+
static int device_add_property_internal_from_string(sd_device *device, const char *str) {
_cleanup_free_ char *key = NULL;
char *value;

View File

@ -0,0 +1,305 @@
From a4fba2d79634d660ed2014e18cb85eea090b6413 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 09:24:15 +0900
Subject: [PATCH] udev-node: split out permission handling from udev_node_add()
And then merge udev_node_add() and udev_node_update_old_links().
(cherry picked from commit 2f48561e0db3cd63f65e9311b4d69282b4ac605d)
Related: #2005024
---
src/udev/udev-event.c | 9 +-
src/udev/udev-node.c | 204 +++++++++++++++++++-----------------------
src/udev/udev-node.h | 12 ++-
3 files changed, 106 insertions(+), 119 deletions(-)
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index b28089be71..8b9f8aecfe 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -895,9 +895,6 @@ static int update_devnode(UdevEvent *event) {
if (r < 0)
return log_device_error_errno(dev, r, "Failed to get devnum: %m");
- /* remove/update possible left-over symlinks from old database entry */
- (void) udev_node_update_old_links(dev, event->dev_db_clone);
-
if (!uid_is_valid(event->uid)) {
r = device_get_devnode_uid(dev, &event->uid);
if (r < 0 && r != -ENOENT)
@@ -921,7 +918,11 @@ static int update_devnode(UdevEvent *event) {
bool apply_mac = device_for_action(dev, SD_DEVICE_ADD);
- return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
+ r = udev_node_apply_permissions(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
+ if (r < 0)
+ return log_device_error_errno(dev, r, "Failed to apply devnode permissions: %m");
+
+ return udev_node_update(dev, event->dev_db_clone);
}
static int event_execute_rules_on_remove(
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 9e52906571..7cc9ee3670 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -356,45 +356,117 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP;
}
-int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
- const char *name;
+static int device_get_devpath_by_devnum(sd_device *dev, char **ret) {
+ const char *subsystem;
+ dev_t devnum;
+ int r;
+
+ assert(dev);
+ assert(ret);
+
+ r = sd_device_get_subsystem(dev, &subsystem);
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_devnum(dev, &devnum);
+ if (r < 0)
+ return r;
+
+ return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
+}
+
+int udev_node_update(sd_device *dev, sd_device *dev_old) {
+ _cleanup_free_ char *filename = NULL;
+ const char *devnode, *devlink;
int r;
assert(dev);
assert(dev_old);
- /* update possible left-over symlinks */
- FOREACH_DEVICE_DEVLINK(dev_old, name) {
- const char *name_current;
- bool found = false;
+ r = sd_device_get_devname(dev, &devnode);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
- /* check if old link name still belongs to this device */
- FOREACH_DEVICE_DEVLINK(dev, name_current)
- if (streq(name, name_current)) {
- found = true;
- break;
- }
+ if (DEBUG_LOGGING) {
+ const char *id = NULL;
- if (found)
+ (void) device_get_device_id(dev, &id);
+ log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
+ }
+
+ /* update possible left-over symlinks */
+ FOREACH_DEVICE_DEVLINK(dev_old, devlink) {
+ /* check if old link name still belongs to this device */
+ if (device_has_devlink(dev, devlink))
continue;
log_device_debug(dev,
- "Updating old device symlink '%s', which is no longer belonging to this device.",
- name);
+ "Removing/updating old device symlink '%s', which is no longer belonging to this device.",
+ devlink);
- r = link_update(dev, name, false);
+ r = link_update(dev, devlink, /* add = */ false);
if (r < 0)
log_device_warning_errno(dev, r,
- "Failed to update device symlink '%s', ignoring: %m",
- name);
+ "Failed to remove/update device symlink '%s', ignoring: %m",
+ devlink);
}
+ /* create/update symlinks, add symlinks to name index */
+ FOREACH_DEVICE_DEVLINK(dev, devlink) {
+ r = link_update(dev, devlink, /* add = */ true);
+ if (r < 0)
+ log_device_warning_errno(dev, r,
+ "Failed to create/update device symlink '%s', ignoring: %m",
+ devlink);
+ }
+
+ r = device_get_devpath_by_devnum(dev, &filename);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get device path: %m");
+
+ /* always add /dev/{block,char}/$major:$minor */
+ r = node_symlink(dev, devnode, filename);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to create device symlink '%s': %m", filename);
+
+ return 0;
+}
+
+int udev_node_remove(sd_device *dev) {
+ _cleanup_free_ char *filename = NULL;
+ const char *devlink;
+ int r;
+
+ assert(dev);
+
+ /* remove/update symlinks, remove symlinks from name index */
+ FOREACH_DEVICE_DEVLINK(dev, devlink) {
+ r = link_update(dev, devlink, /* add = */ false);
+ if (r < 0)
+ log_device_warning_errno(dev, r,
+ "Failed to remove/update device symlink '%s', ignoring: %m",
+ devlink);
+ }
+
+ r = device_get_devpath_by_devnum(dev, &filename);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get device path: %m");
+
+ /* remove /dev/{block,char}/$major:$minor */
+ if (unlink(filename) < 0 && errno != ENOENT)
+ return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", filename);
+
return 0;
}
-static int node_permissions_apply(sd_device *dev, bool apply_mac,
- mode_t mode, uid_t uid, gid_t gid,
- OrderedHashmap *seclabel_list) {
+int udev_node_apply_permissions(
+ sd_device *dev,
+ bool apply_mac,
+ mode_t mode,
+ uid_t uid,
+ gid_t gid,
+ OrderedHashmap *seclabel_list) {
+
const char *devnode, *subsystem, *id = NULL;
bool apply_mode, apply_uid, apply_gid;
_cleanup_close_ int node_fd = -1;
@@ -511,95 +583,5 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
if (r < 0)
log_device_debug_errno(dev, r, "Failed to adjust timestamp of node %s: %m", devnode);
- return r;
-}
-
-static int xsprintf_dev_num_path_from_sd_device(sd_device *dev, char **ret) {
- const char *subsystem;
- dev_t devnum;
- int r;
-
- assert(ret);
-
- r = sd_device_get_subsystem(dev, &subsystem);
- if (r < 0)
- return r;
-
- r = sd_device_get_devnum(dev, &devnum);
- if (r < 0)
- return r;
-
- return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
-}
-
-int udev_node_add(sd_device *dev, bool apply,
- mode_t mode, uid_t uid, gid_t gid,
- OrderedHashmap *seclabel_list) {
- const char *devnode, *devlink;
- _cleanup_free_ char *filename = NULL;
- int r;
-
- assert(dev);
-
- r = sd_device_get_devname(dev, &devnode);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
-
- if (DEBUG_LOGGING) {
- const char *id = NULL;
-
- (void) device_get_device_id(dev, &id);
- log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
- }
-
- r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
- if (r < 0)
- return r;
-
- /* create/update symlinks, add symlinks to name index */
- FOREACH_DEVICE_DEVLINK(dev, devlink) {
- r = link_update(dev, devlink, true);
- if (r < 0)
- log_device_warning_errno(dev, r,
- "Failed to update device symlink '%s', ignoring: %m",
- devlink);
- }
-
- r = xsprintf_dev_num_path_from_sd_device(dev, &filename);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to get device path: %m");
-
- /* always add /dev/{block,char}/$major:$minor */
- r = node_symlink(dev, devnode, filename);
- if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to create device symlink '%s': %m", filename);
-
- return 0;
-}
-
-int udev_node_remove(sd_device *dev) {
- _cleanup_free_ char *filename = NULL;
- const char *devlink;
- int r;
-
- assert(dev);
-
- /* remove/update symlinks, remove symlinks from name index */
- FOREACH_DEVICE_DEVLINK(dev, devlink) {
- r = link_update(dev, devlink, false);
- if (r < 0)
- log_device_warning_errno(dev, r,
- "Failed to update device symlink '%s', ignoring: %m",
- devlink);
- }
-
- r = xsprintf_dev_num_path_from_sd_device(dev, &filename);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to get device path: %m");
-
- /* remove /dev/{block,char}/$major:$minor */
- if (unlink(filename) < 0 && errno != ENOENT)
- return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", filename);
-
return 0;
}
diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h
index 2349f9c471..a34af77146 100644
--- a/src/udev/udev-node.h
+++ b/src/udev/udev-node.h
@@ -8,10 +8,14 @@
#include "hashmap.h"
-int udev_node_add(sd_device *dev, bool apply,
- mode_t mode, uid_t uid, gid_t gid,
- OrderedHashmap *seclabel_list);
+int udev_node_apply_permissions(
+ sd_device *dev,
+ bool apply_mac,
+ mode_t mode,
+ uid_t uid,
+ gid_t gid,
+ OrderedHashmap *seclabel_list);
int udev_node_remove(sd_device *dev);
-int udev_node_update_old_links(sd_device *dev, sd_device *dev_old);
+int udev_node_update(sd_device *dev, sd_device *dev_old);
size_t udev_node_escape_path(const char *src, char *dest, size_t size);

View File

@ -0,0 +1,36 @@
From 506dc32b2428936d67e9cf1a034d6b63dbc1cbb0 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 04:14:42 +0900
Subject: [PATCH] udev-node: stack directory must exist when adding device node
symlink
(cherry picked from commit 46070dbf26435ba0def099121f46a6253f3f19b6)
Related: #2005024
---
src/udev/udev-node.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 7cc9ee3670..4496a2bd9b 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -161,12 +161,13 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
dir = opendir(stackdir);
if (!dir) {
- if (errno == ENOENT) {
- *ret = TAKE_PTR(target);
- return !!*ret;
- }
+ if (add) /* The stack directory must exist. */
+ return -errno;
+ if (errno != ENOENT)
+ return -errno;
- return -errno;
+ *ret = NULL;
+ return 0;
}
r = device_get_device_id(dev, &id);

View File

@ -0,0 +1,250 @@
From 065209fc7a53d6f296f7fffd261f0a92fddc4485 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 04:16:21 +0900
Subject: [PATCH] udev-node: save information about device node and priority in
symlink
Previously, we only store device IDs in /run/udev/links, and when
creating/removing device node symlink, we create sd_device object
corresponds to the IDs and read device node and priority from the
object. That requires parsing uevent and udev database files.
This makes link_find_prioritized() get the most prioritzed device node
without parsing the files.
(cherry picked from commit 377a83f0d80376456d9be203796f66f543a8b943)
Related: #2005024
---
src/udev/udev-node.c | 172 ++++++++++++++++++++++++++++++-------------
1 file changed, 121 insertions(+), 51 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 4496a2bd9b..5d6aae0bd4 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -18,6 +18,7 @@
#include "fs-util.h"
#include "hexdecoct.h"
#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
#include "selinux-util.h"
#include "smack-util.h"
@@ -28,9 +29,9 @@
#include "udev-node.h"
#include "user-util.h"
-#define CREATE_LINK_MAX_RETRIES 128
-#define LINK_UPDATE_MAX_RETRIES 128
-#define TOUCH_FILE_MAX_RETRIES 128
+#define CREATE_LINK_MAX_RETRIES 128
+#define LINK_UPDATE_MAX_RETRIES 128
+#define CREATE_STACK_LINK_MAX_RETRIES 128
#define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
static int create_symlink(const char *target, const char *slink) {
@@ -175,39 +176,67 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
return r;
FOREACH_DIRENT_ALL(dent, dir, break) {
- _cleanup_(sd_device_unrefp) sd_device *dev_db = NULL;
- const char *devnode;
- int db_prio = 0;
+ _cleanup_free_ char *path = NULL, *buf = NULL;
+ int tmp_prio;
- if (dent->d_name[0] == '\0')
- break;
if (dent->d_name[0] == '.')
continue;
- log_device_debug(dev, "Found '%s' claiming '%s'", dent->d_name, stackdir);
-
- /* did we find ourself? */
+ /* skip ourself */
if (streq(dent->d_name, id))
continue;
- if (sd_device_new_from_device_id(&dev_db, dent->d_name) < 0)
- continue;
+ path = path_join(stackdir, dent->d_name);
+ if (!path)
+ return -ENOMEM;
- if (sd_device_get_devname(dev_db, &devnode) < 0)
- continue;
+ if (readlink_malloc(path, &buf) >= 0) {
+ char *devnode;
- if (device_get_devlink_priority(dev_db, &db_prio) < 0)
- continue;
+ /* New format. The devnode and priority can be obtained from symlink. */
- if (target && db_prio <= priority)
- continue;
+ devnode = strchr(buf, ':');
+ if (!devnode || devnode == buf)
+ continue;
- log_device_debug(dev_db, "Device claims priority %i for '%s'", db_prio, stackdir);
+ *(devnode++) = '\0';
+ if (!path_startswith(devnode, "/dev"))
+ continue;
- r = free_and_strdup(&target, devnode);
- if (r < 0)
- return r;
- priority = db_prio;
+ if (safe_atoi(buf, &tmp_prio) < 0)
+ continue;
+
+ if (target && tmp_prio <= priority)
+ continue;
+
+ r = free_and_strdup(&target, devnode);
+ if (r < 0)
+ return r;
+ } else {
+ _cleanup_(sd_device_unrefp) sd_device *tmp_dev = NULL;
+ const char *devnode;
+
+ /* Old format. The devnode and priority must be obtained from uevent and
+ * udev database files. */
+
+ if (sd_device_new_from_device_id(&tmp_dev, dent->d_name) < 0)
+ continue;
+
+ if (device_get_devlink_priority(tmp_dev, &tmp_prio) < 0)
+ continue;
+
+ if (target && tmp_prio <= priority)
+ continue;
+
+ if (sd_device_get_devname(tmp_dev, &devnode) < 0)
+ continue;
+
+ r = free_and_strdup(&target, devnode);
+ if (r < 0)
+ return r;
+ }
+
+ priority = tmp_prio;
}
*ret = TAKE_PTR(target);
@@ -256,10 +285,72 @@ toolong:
return size - 1;
}
+static int update_stack_directory(sd_device *dev, const char *dirname, bool add) {
+ _cleanup_free_ char *filename = NULL, *data = NULL, *buf = NULL;
+ const char *devname, *id;
+ int priority, r;
+
+ assert(dev);
+ assert(dirname);
+
+ r = device_get_device_id(dev, &id);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get device id: %m");
+
+ filename = path_join(dirname, id);
+ if (!filename)
+ return log_oom_debug();
+
+ if (!add) {
+ if (unlink(filename) < 0 && errno != ENOENT)
+ log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
+
+ (void) rmdir(dirname);
+ return 0;
+ }
+
+ r = sd_device_get_devname(dev, &devname);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get device node: %m");
+
+ r = device_get_devlink_priority(dev, &priority);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to get priority of device node symlink: %m");
+
+ if (asprintf(&data, "%i:%s", priority, devname) < 0)
+ return log_oom_debug();
+
+ if (readlink_malloc(filename, &buf) >= 0 && streq(buf, data))
+ return 0;
+
+ if (unlink(filename) < 0 && errno != ENOENT)
+ log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
+
+ for (unsigned j = 0; j < CREATE_STACK_LINK_MAX_RETRIES; j++) {
+ /* This may fail with -ENOENT when the parent directory is removed during
+ * creating the file by another udevd worker. */
+ r = mkdir_p(dirname, 0755);
+ if (r == -ENOENT)
+ continue;
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to create directory %s: %m", dirname);
+
+ if (symlink(data, filename) < 0) {
+ if (errno == ENOENT)
+ continue;
+ return log_device_debug_errno(dev, errno, "Failed to create symbolic link %s: %m", filename);
+ }
+
+ return 0;
+ }
+
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ELOOP), "Failed to create symbolic link %s: %m", filename);
+}
+
/* manage "stack of names" with possibly specified device priorities */
static int link_update(sd_device *dev, const char *slink_in, bool add) {
- _cleanup_free_ char *slink = NULL, *filename = NULL, *dirname = NULL;
- const char *slink_name, *id;
+ _cleanup_free_ char *slink = NULL, *dirname = NULL;
+ const char *slink_name;
char name_enc[NAME_MAX+1];
int i, r, retries;
@@ -279,35 +370,14 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL),
"Invalid symbolic link of device node: %s", slink);
- r = device_get_device_id(dev, &id);
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to get device id: %m");
-
(void) udev_node_escape_path(slink_name, name_enc, sizeof(name_enc));
- dirname = path_join("/run/udev/links/", name_enc);
+ dirname = path_join("/run/udev/links", name_enc);
if (!dirname)
return log_oom_debug();
- filename = path_join(dirname, id);
- if (!filename)
- return log_oom_debug();
-
- if (!add) {
- if (unlink(filename) < 0 && errno != ENOENT)
- log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
-
- (void) rmdir(dirname);
- } else {
- for (unsigned j = 0; j < TOUCH_FILE_MAX_RETRIES; j++) {
- /* This may fail with -ENOENT when the parent directory is removed during
- * creating the file by another udevd worker. */
- r = touch_file(filename, /* parents= */ true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
- if (r != -ENOENT)
- break;
- }
- if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to create %s: %m", filename);
- }
+ r = update_stack_directory(dev, dirname, add);
+ if (r < 0)
+ return r;
/* 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. */

View File

@ -0,0 +1,146 @@
From a13bd62f6cb8332864ed3566fdf51eedfe240043 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 12:57:40 +0900
Subject: [PATCH] udev-node: always update timestamp of stack directory
Please see the comments in the code.
(cherry picked from commit 6df797f75fa08bb1a9e657001229bd47903e6174)
Related: #2005024
---
src/udev/udev-node.c | 90 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 87 insertions(+), 3 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 5d6aae0bd4..0de848da19 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -32,6 +32,7 @@
#define CREATE_LINK_MAX_RETRIES 128
#define LINK_UPDATE_MAX_RETRIES 128
#define CREATE_STACK_LINK_MAX_RETRIES 128
+#define UPDATE_TIMESTAMP_MAX_RETRIES 128
#define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
static int create_symlink(const char *target, const char *slink) {
@@ -285,9 +286,60 @@ toolong:
return size - 1;
}
+static int update_timestamp(sd_device *dev, const char *path, struct stat *prev) {
+ assert(path);
+ assert(prev);
+
+ /* Even if a symlink in the stack directory is created/removed, the mtime of the directory may
+ * not be changed. Why? Let's consider the following situation. For simplicity, let's assume
+ * there exist three udev workers (A, B, and C) and all of them calls link_update() for the
+ * same devlink simultaneously.
+ *
+ * 1. B creates/removes a symlink in the stack directory.
+ * 2. A calls the first stat() in the loop of link_update().
+ * 3. A calls link_find_prioritized().
+ * 4. C creates/removes another symlink in the stack directory, so the result of the step 3 is outdated.
+ * 5. B and C finish link_update().
+ * 6. A creates/removes devlink according to the outdated result in the step 3.
+ * 7. A calls the second stat() in the loop of link_update().
+ *
+ * If these 7 steps are processed in this order within a short time period that kernel's timer
+ * does not increase, then even if the contents in the stack directory is changed, the results
+ * of two stat() called by A shows the same timestamp, and A cannot detect the change.
+ *
+ * By calling this function after creating/removing symlinks in the stack directory, the
+ * timestamp of the stack directory is always increased at least in the above step 5, so A can
+ * detect the update. */
+
+ if ((prev->st_mode & S_IFMT) == 0)
+ return 0; /* Does not exist, or previous stat() failed. */
+
+ for (unsigned i = 0; i < UPDATE_TIMESTAMP_MAX_RETRIES; i++) {
+ struct stat st;
+
+ if (stat(path, &st) < 0)
+ return -errno;
+
+ if (!stat_inode_unmodified(prev, &st))
+ return 0;
+
+ log_device_debug(dev,
+ "%s is modified, but its timestamp is not changed, "
+ "updating timestamp after 10ms.",
+ path);
+
+ (void) usleep(10 * USEC_PER_MSEC);
+ if (utimensat(AT_FDCWD, path, NULL, 0) < 0)
+ return -errno;
+ }
+
+ return -ELOOP;
+}
+
static int update_stack_directory(sd_device *dev, const char *dirname, bool add) {
_cleanup_free_ char *filename = NULL, *data = NULL, *buf = NULL;
const char *devname, *id;
+ struct stat st = {};
int priority, r;
assert(dev);
@@ -302,10 +354,31 @@ static int update_stack_directory(sd_device *dev, const char *dirname, bool add)
return log_oom_debug();
if (!add) {
- if (unlink(filename) < 0 && errno != ENOENT)
- log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
+ bool unlink_failed = false;
+
+ if (stat(dirname, &st) < 0) {
+ if (errno == ENOENT)
+ return 0; /* The stack directory is already removed. That's OK. */
+ log_device_debug_errno(dev, errno, "Failed to stat %s, ignoring: %m", dirname);
+ }
+
+ if (unlink(filename) < 0) {
+ unlink_failed = true;
+ if (errno != ENOENT)
+ log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
+ }
+
+ if (rmdir(dirname) >= 0 || errno == ENOENT)
+ return 0;
+
+ if (unlink_failed)
+ return 0; /* If we failed to remove the symlink, there is almost nothing we can do. */
+
+ /* The symlink was removed. Check if the timestamp of directory is changed. */
+ r = update_timestamp(dev, dirname, &st);
+ if (r < 0 && r != -ENOENT)
+ return log_device_debug_errno(dev, r, "Failed to update timestamp of %s: %m", dirname);
- (void) rmdir(dirname);
return 0;
}
@@ -335,12 +408,23 @@ static int update_stack_directory(sd_device *dev, const char *dirname, bool add)
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to create directory %s: %m", dirname);
+ if (stat(dirname, &st) < 0) {
+ if (errno == ENOENT)
+ continue;
+ return log_device_debug_errno(dev, errno, "Failed to stat %s: %m", dirname);
+ }
+
if (symlink(data, filename) < 0) {
if (errno == ENOENT)
continue;
return log_device_debug_errno(dev, errno, "Failed to create symbolic link %s: %m", filename);
}
+ /* The symlink was created. Check if the timestamp of directory is changed. */
+ r = update_timestamp(dev, dirname, &st);
+ if (r < 0)
+ return log_device_debug_errno(dev, r, "Failed to update timestamp of %s: %m", dirname);
+
return 0;
}

View File

@ -0,0 +1,34 @@
From cf49a46c165619a0480d361a0afebb89e998f61c Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 2 Sep 2021 06:58:59 +0900
Subject: [PATCH] udev-node: assume no new claim to a symlink if
/run/udev/links is not updated
During creating a symlink to a device node, if another device node which
requests the same symlink is added/removed, `stat_inode_unmodified()`
should always detects that. We do not need to continue the loop
unconditionally.
(cherry picked from commit 8f27311eb2aec2411d1fb7d62e6c9d75d21ae8df)
Related: #2005024
---
src/udev/udev-node.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 0de848da19..1a34ea8128 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -491,11 +491,6 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
r = node_symlink(dev, target, slink);
if (r < 0)
return r;
- 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) {

View File

@ -0,0 +1,92 @@
From 1561b9e2c9ea779ab611f52fd8b4eef616896e09 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 02:20:33 +0900
Subject: [PATCH] udev-node: always atomically create symlink to device node
By the previous commit, it is not necessary to distinguish if the devlink
already exists. Also, I cannot find any significant advantages of the
previous complecated logic, that is, first try to create directly, and then
fallback to atomically creation. Moreover, such logic increases the chance
of conflicts between multiple udev workers.
This makes devlinks always created atomically. Hopefully, this reduces the
conflicts between the workers.
(cherry picked from commit 242d39ebc1391f4734f6e63ff13764de92bc5f70)
Related: #2005024
---
src/udev/udev-node.c | 42 +++++++++---------------------------------
1 file changed, 9 insertions(+), 33 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 1a34ea8128..46c04fe00b 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -71,6 +71,13 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
assert(node);
assert(slink);
+ if (lstat(slink, &stats) >= 0) {
+ if (!S_ISLNK(stats.st_mode))
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
+ "Conflicting inode '%s' found, link to '%s' will not be created.", slink, node);
+ } else if (errno != ENOENT)
+ return log_device_debug_errno(dev, errno, "Failed to lstat() '%s': %m", slink);
+
r = path_extract_directory(slink, &slink_dirname);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get parent directory of '%s': %m", slink);
@@ -80,41 +87,11 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get relative path from '%s' to '%s': %m", slink, node);
- if (lstat(slink, &stats) >= 0) {
- _cleanup_free_ char *buf = NULL;
-
- if (!S_ISLNK(stats.st_mode))
- return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST),
- "Conflicting inode '%s' found, link to '%s' will not be created.", slink, node);
-
- if (readlink_malloc(slink, &buf) >= 0 &&
- path_equal(target, buf)) {
- /* preserve link with correct target, do not replace node of other device */
- log_device_debug(dev, "Preserve already existing symlink '%s' to '%s'", slink, target);
-
- (void) label_fix(slink, LABEL_IGNORE_ENOENT);
- (void) utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
-
- return 0;
- }
- } else if (errno == ENOENT) {
- log_device_debug(dev, "Creating symlink '%s' to '%s'", slink, target);
-
- r = create_symlink(target, slink);
- if (r >= 0)
- return 0;
-
- log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink);
- } else
- return log_device_debug_errno(dev, errno, "Failed to lstat() '%s': %m", slink);
-
- log_device_debug(dev, "Atomically replace '%s'", slink);
-
r = device_get_device_id(dev, &id);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get device id: %m");
- slink_tmp = strjoina(slink, ".tmp-", id);
+ slink_tmp = strjoina(slink, ".tmp-", id);
(void) unlink(slink_tmp);
r = create_symlink(target, slink_tmp);
@@ -127,8 +104,7 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) {
return r;
}
- /* Tell caller that we replaced already existing symlink. */
- return 1;
+ return 0;
}
static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir, char **ret) {

View File

@ -0,0 +1,44 @@
From a3389b23db9b9ab1ad11f181f036be35aade8c31 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 09:44:26 +0900
Subject: [PATCH] udev-node: check stack directory change even if devlink is
removed
Otherwise, when multiple device additions and removals occur
simultaneously, symlink to unexisting devnode may be created.
Hopefully fixes #19946.
(cherry picked from commit 1cd4e325693007b3628f1a27297f0ab7114b24b8)
Related: #2005024
---
src/udev/udev-node.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 46c04fe00b..28e6e8df94 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -468,15 +468,12 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
if (r < 0)
return r;
- /* 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 log_device_debug_errno(dev, errno, "Failed to stat %s: %m", dirname);
-
- if (stat_inode_unmodified(&st1, &st2))
- break;
- }
+ if (stat(dirname, &st2) < 0 && errno != ENOENT)
+ return log_device_debug_errno(dev, errno, "Failed to stat %s: %m", dirname);
+
+ if (((st1.st_mode & S_IFMT) == 0 && (st2.st_mode & S_IFMT) == 0) ||
+ stat_inode_unmodified(&st1, &st2))
+ return 0;
}
return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP;

View File

@ -0,0 +1,32 @@
From 52938c3ed27ebaadce97060ad8ebdcb351403d90 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 2 Sep 2021 08:23:35 +0900
Subject: [PATCH] udev-node: shorten code a bit and update log message
(cherry picked from commit 8424da2de88ceeed7be8544fb69221f0b0ea84ea)
Related: #2005024
---
src/udev/udev-node.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 28e6e8df94..2e7df899e4 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -447,13 +447,12 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
_cleanup_free_ char *target = NULL;
struct stat st1 = {}, st2 = {};
- r = stat(dirname, &st1);
- if (r < 0 && errno != ENOENT)
+ if (stat(dirname, &st1) < 0 && errno != ENOENT)
return log_device_debug_errno(dev, errno, "Failed to stat %s: %m", dirname);
r = link_find_prioritized(dev, add, dirname, &target);
if (r < 0)
- return log_device_debug_errno(dev, r, "Failed to determine highest priority for symlink '%s': %m", slink);
+ return log_device_debug_errno(dev, r, "Failed to determine device node with the highest priority for '%s': %m", slink);
if (r == 0) {
log_device_debug(dev, "No reference left for '%s', removing", slink);

View File

@ -0,0 +1,59 @@
From 75275ae07233e213fe03a1a33870efe10dbb2b39 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 04:34:48 +0900
Subject: [PATCH] udev-node: add random delay on conflict in updating device
node symlink
To make multiple workers not update the same device node symlink
simultaneously.
(cherry picked from commit 0063fa23a1384dd4385d03b568dc629916b7e72a)
Related: #2005024
---
src/udev/udev-node.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 2e7df899e4..675e6ce313 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -20,12 +20,14 @@
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
+#include "random-util.h"
#include "selinux-util.h"
#include "smack-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strxcpyx.h"
+#include "time-util.h"
#include "udev-node.h"
#include "user-util.h"
@@ -33,6 +35,8 @@
#define LINK_UPDATE_MAX_RETRIES 128
#define CREATE_STACK_LINK_MAX_RETRIES 128
#define UPDATE_TIMESTAMP_MAX_RETRIES 128
+#define MAX_RANDOM_DELAY (250 * USEC_PER_MSEC)
+#define MIN_RANDOM_DELAY ( 50 * USEC_PER_MSEC)
#define UDEV_NODE_HASH_KEY SD_ID128_MAKE(b9,6a,f1,ce,40,31,44,1a,9e,19,ec,8b,ae,f3,e3,2f)
static int create_symlink(const char *target, const char *slink) {
@@ -447,6 +451,14 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
_cleanup_free_ char *target = NULL;
struct stat st1 = {}, st2 = {};
+ if (i > 0) {
+ usec_t delay = MIN_RANDOM_DELAY + random_u64_range(MAX_RANDOM_DELAY - MIN_RANDOM_DELAY);
+
+ log_device_debug(dev, "Directory %s was updated, retrying to update devlink %s after %s.",
+ dirname, slink, FORMAT_TIMESPAN(delay, USEC_PER_MSEC));
+ (void) usleep(delay);
+ }
+
if (stat(dirname, &st1) < 0 && errno != ENOENT)
return log_device_debug_errno(dev, errno, "Failed to stat %s: %m", dirname);

View File

@ -0,0 +1,80 @@
From c715be5f677ab61704ffe358716cf700d662b82d Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 09:29:42 +0900
Subject: [PATCH] udev-node: drop redundant trial of devlink creation
Previously, the devlink was created based on the priority saved in udev
database. So, we needed to reevaluate devlinks after database is saved.
But now the priority is stored in the symlink under /run/udev/links, and
the loop of devlink creation is controlled with the timestamp of the
directory. So, the double evaluation is not necessary anymore.
(cherry picked from commit 7920d0a135fb6a08aa0bfc31e9d0a3f589fe7a1f)
Related: #2005024
---
src/udev/udev-event.c | 5 +----
src/udev/udev-node.c | 12 ++++--------
2 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 8b9f8aecfe..c77f55c67e 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -1060,10 +1060,7 @@ int udev_event_execute_rules(
device_set_is_initialized(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. */
- return update_devnode(event);
+ return 0;
}
void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal) {
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 675e6ce313..bb551d86b0 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -416,7 +416,7 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
_cleanup_free_ char *slink = NULL, *dirname = NULL;
const char *slink_name;
char name_enc[NAME_MAX+1];
- int i, r, retries;
+ int r;
assert(dev);
assert(slink_in);
@@ -443,11 +443,7 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
if (r < 0)
return r;
- /* 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. */
- retries = sd_device_get_is_initialized(dev) > 0 ? LINK_UPDATE_MAX_RETRIES : 1;
-
- for (i = 0; i < retries; i++) {
+ for (unsigned i = 0; i < LINK_UPDATE_MAX_RETRIES; i++) {
_cleanup_free_ char *target = NULL;
struct stat st1 = {}, st2 = {};
@@ -472,7 +468,7 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
log_device_debug_errno(dev, errno, "Failed to remove '%s', ignoring: %m", slink);
(void) rmdir_parents(slink, "/dev");
- break;
+ return 0;
}
r = node_symlink(dev, target, slink);
@@ -487,7 +483,7 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
return 0;
}
- return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP;
+ return -ELOOP;
}
static int device_get_devpath_by_devnum(sd_device *dev, char **ret) {

View File

@ -0,0 +1,36 @@
From 13293ddc7822025cb9f785262655f928634395f6 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 12 Sep 2021 16:05:51 +0900
Subject: [PATCH] udev-node: simplify the example of race
(cherry picked from commit 3df566a66723490914ef3bae0ca8046044b70dce)
Related: #2005024
---
src/udev/udev-node.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index bb551d86b0..61cb9a449b 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -272,14 +272,14 @@ static int update_timestamp(sd_device *dev, const char *path, struct stat *prev)
/* Even if a symlink in the stack directory is created/removed, the mtime of the directory may
* not be changed. Why? Let's consider the following situation. For simplicity, let's assume
- * there exist three udev workers (A, B, and C) and all of them calls link_update() for the
- * same devlink simultaneously.
+ * there exist two udev workers (A and B) and all of them calls link_update() for the same
+ * devlink simultaneously.
*
- * 1. B creates/removes a symlink in the stack directory.
+ * 1. A creates/removes a symlink in the stack directory.
* 2. A calls the first stat() in the loop of link_update().
* 3. A calls link_find_prioritized().
- * 4. C creates/removes another symlink in the stack directory, so the result of the step 3 is outdated.
- * 5. B and C finish link_update().
+ * 4. B creates/removes another symlink in the stack directory, so the result of the step 3 is outdated.
+ * 5. B finishes link_update().
* 6. A creates/removes devlink according to the outdated result in the step 3.
* 7. A calls the second stat() in the loop of link_update().
*

View File

@ -0,0 +1,59 @@
From 969b05b3f1dc644e821756205450b06a30c79d7f Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sun, 12 Sep 2021 16:14:27 +0900
Subject: [PATCH] udev-node: do not ignore unexpected errors on removing
symlink in stack directory
Only acceptable error here is -ENOENT.
(cherry picked from commit 0706cdf4ec92d6bd40391da0e81a30d9bf851663)
Related: #2005024
---
src/udev/udev-node.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 61cb9a449b..e1fb387cb9 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -334,25 +334,30 @@ static int update_stack_directory(sd_device *dev, const char *dirname, bool add)
return log_oom_debug();
if (!add) {
- bool unlink_failed = false;
+ int unlink_error = 0, stat_error = 0;
if (stat(dirname, &st) < 0) {
if (errno == ENOENT)
return 0; /* The stack directory is already removed. That's OK. */
- log_device_debug_errno(dev, errno, "Failed to stat %s, ignoring: %m", dirname);
+ stat_error = -errno;
}
- if (unlink(filename) < 0) {
- unlink_failed = true;
- if (errno != ENOENT)
- log_device_debug_errno(dev, errno, "Failed to remove %s, ignoring: %m", filename);
- }
+ if (unlink(filename) < 0)
+ unlink_error = -errno;
if (rmdir(dirname) >= 0 || errno == ENOENT)
return 0;
- if (unlink_failed)
- return 0; /* If we failed to remove the symlink, there is almost nothing we can do. */
+ if (unlink_error < 0) {
+ if (unlink_error == -ENOENT)
+ return 0;
+
+ /* If we failed to remove the symlink, then there is almost nothing we can do. */
+ return log_device_debug_errno(dev, unlink_error, "Failed to remove %s: %m", filename);
+ }
+
+ if (stat_error < 0)
+ return log_device_debug_errno(dev, stat_error, "Failed to stat %s: %m", dirname);
/* The symlink was removed. Check if the timestamp of directory is changed. */
r = update_timestamp(dev, dirname, &st);

View File

@ -0,0 +1,25 @@
From 1cbcfc6f69e50d309698b6aa16a48b7f282913f5 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Tue, 21 Sep 2021 09:28:29 +0200
Subject: [PATCH] basic/time-util: introduce FORMAT_TIMESPAN
This is cherry-pick of the relevant part from the tree-wide change in
5291f26d4a6.
Related: #2005024
---
src/basic/time-util.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
index 2bd947d6a8..8254913930 100644
--- a/src/basic/time-util.h
+++ b/src/basic/time-util.h
@@ -67,6 +67,7 @@ typedef enum TimestampStyle {
#define FORMAT_TIMESTAMP_WIDTH 28U /* when outputting, assume this width */
#define FORMAT_TIMESTAMP_RELATIVE_MAX 256U
#define FORMAT_TIMESPAN_MAX 64U
+#define FORMAT_TIMESPAN(t, accuracy) format_timespan((char[FORMAT_TIMESPAN_MAX]){}, FORMAT_TIMESPAN_MAX, t, accuracy)
#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)

View File

@ -0,0 +1,51 @@
From 59bad0f7db6d56c359816bc048341b38b824e460 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Tue, 21 Sep 2021 15:01:19 +0200
Subject: [PATCH] udev/net-setup-link: change the default MACAddressPolicy to
"none"
While stable MAC address for interface types that don't have the
address provided by HW could be useful it also breaks LACP based bonds.
Let's err on the side of caution and don't change the MAC address from
udev.
Resolves: #2009237
---
man/systemd.link.xml | 2 +-
network/99-default.link | 2 +-
test/fuzz/fuzz-link-parser/99-default.link | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/man/systemd.link.xml b/man/systemd.link.xml
index 1093e2e0b8..095d8b4873 100644
--- a/man/systemd.link.xml
+++ b/man/systemd.link.xml
@@ -816,7 +816,7 @@
<programlisting>[Link]
NamePolicy=kernel database onboard slot path
-MACAddressPolicy=persistent</programlisting>
+MACAddressPolicy=none</programlisting>
</example>
<example>
diff --git a/network/99-default.link b/network/99-default.link
index bca660ac28..31aee37e75 100644
--- a/network/99-default.link
+++ b/network/99-default.link
@@ -13,4 +13,4 @@ OriginalName=*
[Link]
NamePolicy=keep kernel database onboard slot path
AlternativeNamesPolicy=database onboard slot path
-MACAddressPolicy=persistent
+MACAddressPolicy=none
diff --git a/test/fuzz/fuzz-link-parser/99-default.link b/test/fuzz/fuzz-link-parser/99-default.link
index feb5b1fbb0..3d755898b4 100644
--- a/test/fuzz/fuzz-link-parser/99-default.link
+++ b/test/fuzz/fuzz-link-parser/99-default.link
@@ -9,4 +9,4 @@
[Link]
NamePolicy=keep kernel database onboard slot path
-MACAddressPolicy=persistent
+MACAddressPolicy=none

View File

@ -0,0 +1,25 @@
From 2edaafdfacc14088d7b6f04eec578bd048057103 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Mon, 25 Jan 2021 16:19:56 +0100
Subject: [PATCH] set core ulimit to 0 like on RHEL-7
RHEL-only
Resolves: #1998509
---
src/core/system.conf.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index f2c75fcd32..c290b14b8b 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -59,7 +59,7 @@
#DefaultLimitFSIZE=
#DefaultLimitDATA=
#DefaultLimitSTACK=
-#DefaultLimitCORE=
+DefaultLimitCORE=0:infinity
#DefaultLimitRSS=
#DefaultLimitNOFILE=1024:{{HIGH_RLIMIT_NOFILE}}
#DefaultLimitAS=

View File

@ -21,7 +21,7 @@
Name: systemd
Url: https://www.freedesktop.org/wiki/Software/systemd
Version: 249
Release: 4%{?dist}
Release: 8%{?dist}
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -95,6 +95,28 @@ Patch0014: 0014-random-util-increase-random-seed-size-to-1024.patch
Patch0015: 0015-journal-don-t-enable-systemd-journald-audit.socket-b.patch
Patch0016: 0016-journald.conf-don-t-touch-current-audit-settings.patch
Patch0017: 0017-Revert-udev-remove-WAIT_FOR-key.patch
Patch0018: 0018-Really-don-t-enable-systemd-journald-audit.socket.patch
Patch0019: 0019-rules-add-elevator-kernel-command-line-parameter.patch
Patch0020: 0020-boot-don-t-build-bootctl-when-Dgnu-efi-false-is-set.patch
Patch0021: 0021-unit-install-the-systemd-bless-boot.service-only-if-.patch
Patch0022: 0022-units-don-t-enable-tmp.mount-statically-in-local-fs..patch
Patch0023: 0023-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch
Patch0024: 0024-sd-device-introduce-device_has_devlink.patch
Patch0025: 0025-udev-node-split-out-permission-handling-from-udev_no.patch
Patch0026: 0026-udev-node-stack-directory-must-exist-when-adding-dev.patch
Patch0027: 0027-udev-node-save-information-about-device-node-and-pri.patch
Patch0028: 0028-udev-node-always-update-timestamp-of-stack-directory.patch
Patch0029: 0029-udev-node-assume-no-new-claim-to-a-symlink-if-run-ud.patch
Patch0030: 0030-udev-node-always-atomically-create-symlink-to-device.patch
Patch0031: 0031-udev-node-check-stack-directory-change-even-if-devli.patch
Patch0032: 0032-udev-node-shorten-code-a-bit-and-update-log-message.patch
Patch0033: 0033-udev-node-add-random-delay-on-conflict-in-updating-d.patch
Patch0034: 0034-udev-node-drop-redundant-trial-of-devlink-creation.patch
Patch0035: 0035-udev-node-simplify-the-example-of-race.patch
Patch0036: 0036-udev-node-do-not-ignore-unexpected-errors-on-removin.patch
Patch0037: 0037-basic-time-util-introduce-FORMAT_TIMESPAN.patch
Patch0038: 0038-udev-net-setup-link-change-the-default-MACAddressPol.patch
Patch0039: 0039-set-core-ulimit-to-0-like-on-RHEL-7.patch
# Downstream-only patches (90009999)
# https://github.com/systemd/systemd/pull/17050
@ -861,6 +883,30 @@ getent passwd systemd-oom &>/dev/null || useradd -r -l -g systemd-oom -d / -s /s
%files standalone-sysusers -f .file-list-standalone-sysusers
%changelog
* Tue Oct 12 2021 systemd maintenance team <systemd-maint@redhat.com> - 249-8
- Really don't enable systemd-journald-audit.socket (#1973856)
- rules: add elevator= kernel command line parameter (#2003002)
- boot: don't build bootctl when -Dgnu-efi=false is set (#2003130)
- unit: install the systemd-bless-boot.service only if we have gnu-efi (#2003130)
- units: don't enable tmp.mount statically in local-fs.target (#2000927)
- pid1: bump DefaultTasksMax to 80% of the kernel pid.max value (#2003031)
- sd-device: introduce device_has_devlink() (#2005024)
- udev-node: split out permission handling from udev_node_add() (#2005024)
- udev-node: stack directory must exist when adding device node symlink (#2005024)
- udev-node: save information about device node and priority in symlink (#2005024)
- udev-node: always update timestamp of stack directory (#2005024)
- udev-node: assume no new claim to a symlink if /run/udev/links is not updated (#2005024)
- udev-node: always atomically create symlink to device node (#2005024)
- udev-node: check stack directory change even if devlink is removed (#2005024)
- udev-node: shorten code a bit and update log message (#2005024)
- udev-node: add random delay on conflict in updating device node symlink (#2005024)
- udev-node: drop redundant trial of devlink creation (#2005024)
- udev-node: simplify the example of race (#2005024)
- udev-node: do not ignore unexpected errors on removing symlink in stack directory (#2005024)
- basic/time-util: introduce FORMAT_TIMESPAN (#2005024)
- udev/net-setup-link: change the default MACAddressPolicy to "none" (#2009237)
- set core ulimit to 0 like on RHEL-7 (#1998509)
* Fri Aug 20 2021 systemd maintenance team <systemd-maint@redhat.com> - 249-4
- Revert "udev: remove WAIT_FOR key" (#1982666)