import UBI systemd-257-23.el10_2.1

This commit is contained in:
AlmaLinux RelEng Bot 2026-05-19 19:15:00 -04:00
parent 965552652c
commit f5a31dac97
195 changed files with 72897 additions and 1123 deletions

View File

@ -0,0 +1,32 @@
From 68c407e06c533814d9173bbee6bf8585190625bb Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@gmail.com>
Date: Mon, 6 Jan 2025 23:47:45 +0000
Subject: [PATCH] test: add test case for AddDependencyUnitFiles assert
Follow-up for d87dc74e8f1a30d72a0f202e411400bab34ab55a
(cherry picked from commit f2b34ce7f397b89fbf734c05a1440e1541f5751d)
Resolves: RHEL-108257
---
test/units/TEST-07-PID1.issue-35882.sh | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100755 test/units/TEST-07-PID1.issue-35882.sh
diff --git a/test/units/TEST-07-PID1.issue-35882.sh b/test/units/TEST-07-PID1.issue-35882.sh
new file mode 100755
index 0000000000..cf1650cc22
--- /dev/null
+++ b/test/units/TEST-07-PID1.issue-35882.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/util.sh
+. "$(dirname "$0")"/util.sh
+
+(! busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager AddDependencyUnitFiles "asssbb" 0 abracadabra After 1 1)
+
+exit 0

View File

@ -0,0 +1,28 @@
From 5a26d4d52115079e3da7ddffd77d5b87e45a11aa Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 30 Apr 2025 21:07:48 +0900
Subject: [PATCH] TEST-17: drop unnecessary $PATH setting
My local setting was unintentionally inserted by the commit
7cb4508c5af465ab1be1b103e6c2b613eb58e63c.
(cherry picked from commit da9d75e0c6f6ae1e70e2f7efb8adb3851926e220)
Resolves: RHEL-108242
---
test/units/TEST-17-UDEV.11.sh | 2 --
1 file changed, 2 deletions(-)
diff --git a/test/units/TEST-17-UDEV.11.sh b/test/units/TEST-17-UDEV.11.sh
index ac99a80b0f..f0ab20e5c9 100755
--- a/test/units/TEST-17-UDEV.11.sh
+++ b/test/units/TEST-17-UDEV.11.sh
@@ -8,8 +8,6 @@ set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
-PATH=/var/build:$PATH
-
# shellcheck disable=SC2317
cleanup() {
cd /

View File

@ -0,0 +1,58 @@
From d81f351e334d852978277ac716043ad957ec2a85 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 29 Jul 2025 03:25:17 +0900
Subject: [PATCH] chase: check the result is a directory or regular file only
when the resolved path exists
Otherwise, if it is called with CHASE_NONEXISTENT, when we call
stat_verify_directory()/_regular() the struct stat is for one of the
parent directory, rather than for the result path.
With this change, we can safely specify CHASE_MUST_BE_DIRECTORY/REGULAR
with CHASE_NONEXISTENT.
More importantly, chaseat() internally sets CHASE_MUST_BE_DIRECTORY when
the input path ends with "/", "/,", "/..". Hence, without this change,
we cannot specify CHASE_NONEXISTENT safely.
Follow-up for 90b9f7a07e6f57825f416f6ce2db0a9f2086754b.
(cherry picked from commit 1cabb6905b98ecc11bfb1fd8305c8f5c089e5c32)
Resolves: RHEL-108006
---
src/basic/chase.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/src/basic/chase.c b/src/basic/chase.c
index e5a6fb1587..3db1ea7e0e 100644
--- a/src/basic/chase.c
+++ b/src/basic/chase.c
@@ -485,16 +485,18 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
close_and_replace(fd, child);
}
- if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY)) {
- r = stat_verify_directory(&st);
- if (r < 0)
- return r;
- }
+ if (exists) {
+ if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY)) {
+ r = stat_verify_directory(&st);
+ if (r < 0)
+ return r;
+ }
- if (FLAGS_SET(flags, CHASE_MUST_BE_REGULAR)) {
- r = stat_verify_regular(&st);
- if (r < 0)
- return r;
+ if (FLAGS_SET(flags, CHASE_MUST_BE_REGULAR)) {
+ r = stat_verify_regular(&st);
+ if (r < 0)
+ return r;
+ }
}
if (ret_path) {

View File

@ -0,0 +1,64 @@
From 9e239ea80030f6740d900891cf5c1aeb0248cf3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Fri, 14 Feb 2025 09:42:43 +0100
Subject: [PATCH] bootctl: stop printing "Stub/Boot loader set partition
information"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
... and "Stub/Boot loader set network boot URL information".
This reverts 26bfd97216ab55664214d1e0fac7065e5573a36b
('bootctl: also shown whether stub loader partition data was passed'),
and one line from bfcf48b842644c1016583ecf0c4258cb59a102bb
('bootctl: show stub partition data too in "status" too'),
and two lines from e15d18b4c64e13c37a4c676bf61a5ecf8bba04a3
('sd-stub: if we are http booted, query source URL and write to EFI variable').
As discussed in https://github.com/systemd/systemd/pull/36372, those are not
"features", but optional pieces of information that may or may not be set, also
depending on how the boot loader and stub were loaded. We already prominently
show this information right below: either we print the device path or "n/a" or
skip the output. The user already has all the information, and the status
output should be dense, so it doesn't make sense to repeat this twice.
✓ Boot loader set partition information
Partition: /dev/disk/by-partuuid/3f003ec5-5673-5b4f-b9a4-cbac1ca4461a
OR
- Boot loader set partition information
Partition: n/a
✓ Stub loader set partition information
Partition: /dev/disk/by-partuuid/3f003ec5-5673-5b4f-b9a4-cbac1ca4461a
OR
- Stub loader set partition information
Partition: n/a
(cherry picked from commit f25e4e5af0518b4865eff84b65dd339047e429ed)
Resolves: RHEL-108251
---
src/bootctl/bootctl-status.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/bootctl/bootctl-status.c b/src/bootctl/bootctl-status.c
index 6f38b0f793..e130838fb0 100644
--- a/src/bootctl/bootctl-status.c
+++ b/src/bootctl/bootctl-status.c
@@ -478,7 +478,6 @@ int verb_status(int argc, char *argv[], void *userdata) {
sd_id128_t loader_partition_uuid = SD_ID128_NULL;
(void) efi_loader_get_device_part_uuid(&loader_partition_uuid);
- print_yes_no_line(/* first= */ false, !sd_id128_is_null(loader_partition_uuid), "Boot loader set partition information");
if (!sd_id128_is_null(loader_partition_uuid)) {
if (!sd_id128_is_null(esp_uuid) && !sd_id128_equal(esp_uuid, loader_partition_uuid))
@@ -511,7 +510,6 @@ int verb_status(int argc, char *argv[], void *userdata) {
sd_id128_t stub_partition_uuid = SD_ID128_NULL;
(void) efi_stub_get_device_part_uuid(&stub_partition_uuid);
- print_yes_no_line(/* first= */ false, !sd_id128_is_null(stub_partition_uuid), "Stub loader set partition information");
if (!sd_id128_is_null(stub_partition_uuid)) {
if (!(!sd_id128_is_null(esp_uuid) && sd_id128_equal(esp_uuid, stub_partition_uuid)) &&

View File

@ -0,0 +1,32 @@
From ed799d3b50e866d021ab1c4b0acb5b8fd6d19c6d Mon Sep 17 00:00:00 2001
From: Li Tian <94442129+litian1992@users.noreply.github.com>
Date: Tue, 19 Aug 2025 05:43:41 +0800
Subject: [PATCH] ukify: rstrip and escape binary null characters from
'inspect' output (#38607)
SBAT section of UKI may contain \u000 null characters. Rstrip them, and if there's anything left in the middle,
escape them so they are displayed as text.
Fixes #38606
(cherry picked from commit 776991a3f349d9c99fd166a0c87fcd2bc1bf92a5)
Signed-off-by: Li Tian <litian@redhat.com>
Resolves: RHEL-109552
---
src/ukify/ukify.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
index da3ceeed24..a868a5b778 100755
--- a/src/ukify/ukify.py
+++ b/src/ukify/ukify.py
@@ -1468,7 +1468,7 @@ def inspect_section(
if ttype == 'text':
try:
- struct['text'] = data.decode()
+ struct['text'] = data.rstrip(b'\0').replace(b'\0', b'\\0').decode()
except UnicodeDecodeError as e:
print(f'Section {name!r} is not valid text: {e}')
struct['text'] = '(not valid UTF-8)'

View File

@ -0,0 +1,34 @@
From 764786b83c0729765ed529bf1169cf08fb2e9912 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekletar@users.noreply.github.com>
Date: Wed, 20 Aug 2025 12:42:30 +0200
Subject: [PATCH] coredump: drop RestrictSUIDSGID= option (#38640)
systemd-coredump sandbox already has ProtectSystem=strict hence all non
API filesystems are made read-only, thus RestrictSUIDSGID= doesn't buy
us much.
On top of that systemd-coredump's EnterNamespace= feature requires
openat2() to work correctly and that is implicitly blocked by
RestrictSUIDSGID=.
Follow-up for 8f8148cb08bf9f2c0e1f7fe6a5e6eb383115957b
(cherry picked from commit fb56da5b6eb80f4400ea7241fa98d90d245d7fde)
Resolves: RHEL-113920
---
units/systemd-coredump@.service.in | 1 -
1 file changed, 1 deletion(-)
diff --git a/units/systemd-coredump@.service.in b/units/systemd-coredump@.service.in
index c74dc7a5a1..f492c826fe 100644
--- a/units/systemd-coredump@.service.in
+++ b/units/systemd-coredump@.service.in
@@ -36,7 +36,6 @@ ProtectKernelLogs=yes
ProtectSystem=strict
RestrictAddressFamilies=AF_UNIX
RestrictRealtime=yes
-RestrictSUIDSGID=yes
RuntimeMaxSec=5min
StateDirectory=systemd/coredump
SystemCallArchitectures=native

View File

@ -0,0 +1,42 @@
From f604524da21e84048887e36a9e910b25835cb17c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 19 Aug 2025 11:02:44 +0200
Subject: [PATCH] ukify: fix insertion of padding in merged sections
The padding was done to expand the new section contents to the expected size of
the new section. And this then would be used for the content in the existing
section. The new section cannot be larger than the old section, but it can be
smaller. If the new section was smaller, then we'd not write enough padding and
the output file would be corrupted.
This was observed in CI when the .sbat section in the stub was padded to 1k.
The UKI with an .sbat section that was merged and was fairly short would hit
this scenario and be corrupted.
(cherry picked from commit ec1d031f3de02f84beca89e2b402d085fba62be4)
Resolves: RHEL-114414
---
src/ukify/ukify.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/ukify/ukify.py b/src/ukify/ukify.py
index a868a5b778..9205012567 100755
--- a/src/ukify/ukify.py
+++ b/src/ukify/ukify.py
@@ -956,14 +956,13 @@ def pe_add_sections(uki: UKI, output: str) -> None:
if new_section.Misc_VirtualSize > s.SizeOfRawData:
raise PEError(f'Not enough space in existing section {section.name} to append new data.')
- padding = bytes(new_section.SizeOfRawData - new_section.Misc_VirtualSize)
+ padding = bytes(s.SizeOfRawData - new_section.Misc_VirtualSize)
pe.__data__ = (
pe.__data__[: s.PointerToRawData]
+ data
+ padding
+ pe.__data__[pe.sections[i + 1].PointerToRawData :]
)
- s.SizeOfRawData = new_section.SizeOfRawData
s.Misc_VirtualSize = new_section.Misc_VirtualSize
break
else:

View File

@ -0,0 +1,249 @@
From 9a97574845363386036c9f8bc83b271e80844999 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 15 May 2025 12:34:35 +0900
Subject: [PATCH] core: introduce Unit.dependency_generation counter and
restart loop when dependency is updated in the loop
When starting unit A, a dependent unit B may be loaded if it is not
loaded yet, and the dependencies in unit A may be updated.
As Hashmap does not allow a new entry to be added in a loop, we need to
restart loop in such case.
Fixes a bug introduced by cda667722c2218cf1a0185284d2a87f8a25f1b2d.
Fixes #36031.
(cherry picked from commit b7777d08846033859c5b734317fbbbfcca4cafcb)
Resolves: RHEL-112203
---
src/core/transaction.c | 18 +++++++++---------
src/core/unit.c | 10 ++++++++++
src/core/unit.h | 31 ++++++++++++++++++++++++++-----
3 files changed, 45 insertions(+), 14 deletions(-)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index bec96a67af..705ed0c50f 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -894,7 +894,7 @@ void transaction_add_propagate_reload_jobs(
assert(tr);
assert(unit);
- UNIT_FOREACH_DEPENDENCY(dep, unit, UNIT_ATOM_PROPAGATES_RELOAD_TO) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, unit, UNIT_ATOM_PROPAGATES_RELOAD_TO) {
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
nt = job_type_collapse(JOB_TRY_RELOAD, dep);
@@ -1043,7 +1043,7 @@ int transaction_add_job_and_dependencies(
/* Finally, recursively add in all dependencies. */
if (IN_SET(type, JOB_START, JOB_RESTART)) {
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PULL_IN_START) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PULL_IN_START) {
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, TRANSACTION_MATTERS | (flags & TRANSACTION_IGNORE_ORDER), e);
if (r < 0) {
if (r != -EBADR) /* job type not applicable */
@@ -1053,7 +1053,7 @@ int transaction_add_job_and_dependencies(
}
}
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PULL_IN_START_IGNORED) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PULL_IN_START_IGNORED) {
r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, flags & TRANSACTION_IGNORE_ORDER, e);
if (r < 0) {
/* unit masked, job type not applicable and unit not found are not considered
@@ -1066,7 +1066,7 @@ int transaction_add_job_and_dependencies(
}
}
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PULL_IN_VERIFY) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PULL_IN_VERIFY) {
r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, TRANSACTION_MATTERS | (flags & TRANSACTION_IGNORE_ORDER), e);
if (r < 0) {
if (r != -EBADR) /* job type not applicable */
@@ -1076,7 +1076,7 @@ int transaction_add_job_and_dependencies(
}
}
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PULL_IN_STOP) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PULL_IN_STOP) {
r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, TRANSACTION_MATTERS | TRANSACTION_CONFLICTS | (flags & TRANSACTION_IGNORE_ORDER), e);
if (r < 0) {
if (r != -EBADR) /* job type not applicable */
@@ -1086,7 +1086,7 @@ int transaction_add_job_and_dependencies(
}
}
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PULL_IN_STOP_IGNORED) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PULL_IN_STOP_IGNORED) {
r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, flags & TRANSACTION_IGNORE_ORDER, e);
if (r < 0) {
log_unit_warning(dep,
@@ -1100,7 +1100,7 @@ int transaction_add_job_and_dependencies(
if (IN_SET(type, JOB_RESTART, JOB_STOP) || (type == JOB_START && FLAGS_SET(flags, TRANSACTION_PROPAGATE_START_AS_RESTART))) {
bool is_stop = type == JOB_STOP;
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PROPAGATE_STOP) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PROPAGATE_STOP) {
/* We propagate RESTART only as TRY_RESTART, in order not to start dependencies that
* are not around. */
JobType nt;
@@ -1122,7 +1122,7 @@ int transaction_add_job_and_dependencies(
* all other dependencies are processed, i.e. we're the anchor job or already in the recursion
* that handles it. */
if (!by || FLAGS_SET(flags, TRANSACTION_PROCESS_PROPAGATE_STOP_GRACEFUL))
- UNIT_FOREACH_DEPENDENCY(dep, ret->unit, UNIT_ATOM_PROPAGATE_STOP_GRACEFUL) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(dep, ret->unit, UNIT_ATOM_PROPAGATE_STOP_GRACEFUL) {
JobType nt;
Job *j;
@@ -1220,7 +1220,7 @@ int transaction_add_triggering_jobs(Transaction *tr, Unit *u) {
assert(tr);
assert(u);
- UNIT_FOREACH_DEPENDENCY(trigger, u, UNIT_ATOM_TRIGGERED_BY) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(trigger, u, UNIT_ATOM_TRIGGERED_BY) {
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
/* No need to stop inactive jobs */
diff --git a/src/core/unit.c b/src/core/unit.c
index d36f860de9..631fa2f198 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -636,12 +636,14 @@ static void unit_clear_dependencies(Unit *u) {
hashmap_remove(other_deps, u);
unit_add_to_gc_queue(other);
+ other->dependency_generation++;
}
hashmap_free(deps);
}
u->dependencies = hashmap_free(u->dependencies);
+ u->dependency_generation++;
}
static void unit_remove_transient(Unit *u) {
@@ -1092,6 +1094,9 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
}
other->dependencies = hashmap_free(other->dependencies);
+
+ u->dependency_generation++;
+ other->dependency_generation++;
}
int unit_merge(Unit *u, Unit *other) {
@@ -3114,6 +3119,7 @@ static int unit_add_dependency_impl(
return r;
flags = NOTIFY_DEPENDENCY_UPDATE_FROM;
+ u->dependency_generation++;
}
if (other_info.data != other_info_old.data) {
@@ -3130,6 +3136,7 @@ static int unit_add_dependency_impl(
}
flags |= NOTIFY_DEPENDENCY_UPDATE_TO;
+ other->dependency_generation++;
}
return flags;
@@ -5565,6 +5572,9 @@ void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) {
/* The unit 'other' may not be wanted by the unit 'u'. */
unit_submit_to_stop_when_unneeded_queue(other);
+ u->dependency_generation++;
+ other->dependency_generation++;
+
done = false;
break;
}
diff --git a/src/core/unit.h b/src/core/unit.h
index d24658ed9b..b6f47c76d6 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -227,6 +227,7 @@ typedef struct Unit {
* and whose value encodes why the dependency exists, using the UnitDependencyInfo type. i.e. a
* Hashmap(UnitDependency → Hashmap(Unit* → UnitDependencyInfo)) */
Hashmap *dependencies;
+ uint64_t dependency_generation;
/* Similar, for RequiresMountsFor= and WantsMountsFor= path dependencies. The key is the path, the
* value the UnitDependencyInfo type */
@@ -1154,27 +1155,44 @@ CollectMode collect_mode_from_string(const char *s) _pure_;
typedef struct UnitForEachDependencyData {
/* Stores state for the FOREACH macro below for iterating through all deps that have any of the
* specified dependency atom bits set */
+ const Unit *unit;
UnitDependencyAtom match_atom;
Hashmap *by_type, *by_unit;
void *current_type;
Iterator by_type_iterator, by_unit_iterator;
Unit **current_unit;
+ uint64_t generation;
+ unsigned n_restart;
+ bool restart_on_generation_change;
} UnitForEachDependencyData;
+/* Let's not restart the loop infinitely. */
+#define MAX_FOREACH_DEPENDENCY_RESTART 100000
+
/* Iterates through all dependencies that have a specific atom in the dependency type set. This tries to be
* smart: if the atom is unique, we'll directly go to right entry. Otherwise we'll iterate through the
* per-dependency type hashmap and match all dep that have the right atom set. */
-#define _UNIT_FOREACH_DEPENDENCY(other, u, ma, data) \
+#define _UNIT_FOREACH_DEPENDENCY(other, u, ma, restart, data) \
for (UnitForEachDependencyData data = { \
+ .unit = (u), \
.match_atom = (ma), \
- .by_type = (u)->dependencies, \
- .by_type_iterator = ITERATOR_FIRST, \
.current_unit = &(other), \
+ .restart_on_generation_change = (restart), \
}; \
({ \
UnitDependency _dt = _UNIT_DEPENDENCY_INVALID; \
bool _found; \
\
+ if (data.generation == 0 || \
+ (data.restart_on_generation_change && \
+ data.generation != data.unit->dependency_generation)) { \
+ data.generation = data.unit->dependency_generation; \
+ data.by_type = data.unit->dependencies; \
+ data.by_type_iterator = ITERATOR_FIRST; \
+ assert_se(data.n_restart++ < MAX_FOREACH_DEPENDENCY_RESTART); \
+ } else \
+ assert(data.generation == data.unit->dependency_generation); \
+ \
if (data.by_type && ITERATOR_IS_FIRST(data.by_type_iterator)) { \
_dt = unit_dependency_from_unique_atom(data.match_atom); \
if (_dt >= 0) { \
@@ -1187,12 +1205,13 @@ typedef struct UnitForEachDependencyData {
if (_dt < 0) \
_found = hashmap_iterate(data.by_type, \
&data.by_type_iterator, \
- (void**)&(data.by_unit), \
+ (void**) &(data.by_unit), \
(const void**) &(data.current_type)); \
_found; \
}); ) \
if ((unit_dependency_to_atom(UNIT_DEPENDENCY_FROM_PTR(data.current_type)) & data.match_atom) != 0) \
for (data.by_unit_iterator = ITERATOR_FIRST; \
+ data.generation == data.unit->dependency_generation && \
hashmap_iterate(data.by_unit, \
&data.by_unit_iterator, \
NULL, \
@@ -1200,7 +1219,9 @@ typedef struct UnitForEachDependencyData {
/* Note: this matches deps that have *any* of the atoms specified in match_atom set */
#define UNIT_FOREACH_DEPENDENCY(other, u, match_atom) \
- _UNIT_FOREACH_DEPENDENCY(other, u, match_atom, UNIQ_T(data, UNIQ))
+ _UNIT_FOREACH_DEPENDENCY(other, u, match_atom, false, UNIQ_T(data, UNIQ))
+#define UNIT_FOREACH_DEPENDENCY_SAFE(other, u, match_atom) \
+ _UNIT_FOREACH_DEPENDENCY(other, u, match_atom, true, UNIQ_T(data, UNIQ))
#define _LOG_CONTEXT_PUSH_UNIT(unit, u, c) \
const Unit *u = (unit); \

View File

@ -0,0 +1,72 @@
From 41635f7ce09244e8311f31082df0b1b21d117c29 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Fri, 22 Aug 2025 02:06:43 +0900
Subject: [PATCH] core/unit: use UNIT_FOREACH_DEPENDENCY_SAFE() at several more
places
manager_add_job() -> transaction_add_job_and_dependencies() may update
dependencies when a unit is not loaded yet. Hence, we need to restart
dependency loop in that case.
Follow-up for b7777d08846033859c5b734317fbbbfcca4cafcb (#37465).
Fixes #38676.
(cherry picked from commit 64fc4917b9149ffe6defaf5ceaf3236324537a3f)
Resolves: RHEL-112203
---
src/core/unit.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 631fa2f198..01e4d3a64f 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2219,17 +2219,17 @@ static void retroactively_start_dependencies(Unit *u) {
assert(u);
assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));
- UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_START_REPLACE) /* Requires= + BindsTo= */
+ UNIT_FOREACH_DEPENDENCY_SAFE(other, u, UNIT_ATOM_RETROACTIVE_START_REPLACE) /* Requires= + BindsTo= */
if (!unit_has_dependency(u, UNIT_ATOM_AFTER, other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
(void) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, /* error = */ NULL, /* ret = */ NULL);
- UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_START_FAIL) /* Wants= */
+ UNIT_FOREACH_DEPENDENCY_SAFE(other, u, UNIT_ATOM_RETROACTIVE_START_FAIL) /* Wants= */
if (!unit_has_dependency(u, UNIT_ATOM_AFTER, other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
(void) manager_add_job(u->manager, JOB_START, other, JOB_FAIL, /* error = */ NULL, /* ret = */ NULL);
- UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_STOP_ON_START) /* Conflicts= (and inverse) */
+ UNIT_FOREACH_DEPENDENCY_SAFE(other, u, UNIT_ATOM_RETROACTIVE_STOP_ON_START) /* Conflicts= (and inverse) */
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
(void) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, /* error = */ NULL, /* ret = */ NULL);
}
@@ -2241,7 +2241,7 @@ static void retroactively_stop_dependencies(Unit *u) {
assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
/* Pull down units which are bound to us recursively if enabled */
- UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_STOP_ON_STOP) /* BoundBy= */
+ UNIT_FOREACH_DEPENDENCY_SAFE(other, u, UNIT_ATOM_RETROACTIVE_STOP_ON_STOP) /* BoundBy= */
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
(void) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, /* error = */ NULL, /* ret = */ NULL);
}
@@ -2268,7 +2268,7 @@ void unit_start_on_termination_deps(Unit *u, UnitDependencyAtom atom) {
assert(dependency_name);
Unit *other;
- UNIT_FOREACH_DEPENDENCY(other, u, atom) {
+ UNIT_FOREACH_DEPENDENCY_SAFE(other, u, atom) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (n_jobs == 0)
@@ -2291,7 +2291,7 @@ void unit_trigger_notify(Unit *u) {
assert(u);
- UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_TRIGGERED_BY)
+ UNIT_FOREACH_DEPENDENCY_SAFE(other, u, UNIT_ATOM_TRIGGERED_BY)
if (UNIT_VTABLE(other)->trigger_notify)
UNIT_VTABLE(other)->trigger_notify(other, u);
}

View File

@ -0,0 +1,98 @@
From d3f7e897bec268e21b83670c8e1e9c5d11b801de Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 23 Sep 2025 14:28:33 +0200
Subject: [PATCH] test: rename TEST-53-ISSUE-16347 to TEST-53-TIMER
And split the existing test into a separate subtest.
(cherry picked from commit 953c347fb6f293acbd6da009646bfc071b68ddd7)
Related: RHEL-118216
---
.../meson.build | 0
.../mkosi.configure | 0
test/meson.build | 2 +-
...3-ISSUE-16347.sh => TEST-53-TIMER.issue-16347.sh} | 12 ++++--------
test/units/TEST-53-TIMER.sh | 11 +++++++++++
5 files changed, 16 insertions(+), 9 deletions(-)
rename test/{TEST-53-ISSUE-16347 => TEST-53-TIMER}/meson.build (100%)
rename test/{TEST-53-ISSUE-16347 => TEST-53-TIMER}/mkosi.configure (100%)
rename test/units/{TEST-53-ISSUE-16347.sh => TEST-53-TIMER.issue-16347.sh} (82%)
create mode 100755 test/units/TEST-53-TIMER.sh
diff --git a/test/TEST-53-ISSUE-16347/meson.build b/test/TEST-53-TIMER/meson.build
similarity index 100%
rename from test/TEST-53-ISSUE-16347/meson.build
rename to test/TEST-53-TIMER/meson.build
diff --git a/test/TEST-53-ISSUE-16347/mkosi.configure b/test/TEST-53-TIMER/mkosi.configure
similarity index 100%
rename from test/TEST-53-ISSUE-16347/mkosi.configure
rename to test/TEST-53-TIMER/mkosi.configure
diff --git a/test/meson.build b/test/meson.build
index 8775a3a3df..c440bcb722 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -351,7 +351,7 @@ foreach dirname : [
# 'TEST-46-HOMED', # we don't ship systemd-homed
'TEST-50-DISSECT',
'TEST-52-HONORFIRSTSHUTDOWN',
- 'TEST-53-ISSUE-16347',
+ 'TEST-53-TIMER',
'TEST-54-CREDS',
'TEST-55-OOMD',
'TEST-58-REPART',
diff --git a/test/units/TEST-53-ISSUE-16347.sh b/test/units/TEST-53-TIMER.issue-16347.sh
similarity index 82%
rename from test/units/TEST-53-ISSUE-16347.sh
rename to test/units/TEST-53-TIMER.issue-16347.sh
index 84cd66129d..8b266145cd 100755
--- a/test/units/TEST-53-ISSUE-16347.sh
+++ b/test/units/TEST-53-TIMER.issue-16347.sh
@@ -3,10 +3,9 @@
set -eux
set -o pipefail
-: >/failed
-
# Reset host date to current time, 3 days in the past.
date -s "-3 days"
+trap 'date -s "+3 days"' EXIT
# Run a timer for every 15 minutes.
systemd-run --unit test-timer --on-calendar "*:0/15:0" true
@@ -17,15 +16,12 @@ now=$(date +%s)
time_delta=$((next_elapsed - now))
# Check that the timer will elapse in less than 20 minutes.
-((0 < time_delta && time_delta < 1200)) || {
+if [[ "$time_delta" -lt 0 || "$time_delta" -gt 1200 ]]; then
echo 'Timer elapse outside of the expected 20 minute window.'
echo " next_elapsed=${next_elapsed}"
echo " now=${now}"
echo " time_delta=${time_delta}"
- echo ''
-} >>/failed
+ echo
-if test ! -s /failed ; then
- rm -f /failed
- touch /testok
+ exit 1
fi
diff --git a/test/units/TEST-53-TIMER.sh b/test/units/TEST-53-TIMER.sh
new file mode 100755
index 0000000000..9c2a033aa9
--- /dev/null
+++ b/test/units/TEST-53-TIMER.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/test-control.sh
+. "$(dirname "$0")"/test-control.sh
+
+run_subtests
+
+touch /testok

View File

@ -0,0 +1,101 @@
From 4286441a3e2fc82e58ec64ff26aaecb313fd7dec Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 23 Sep 2025 17:42:01 +0200
Subject: [PATCH] test: restarting elapsed timer shouldn't trigger the
corresponding service
Provides coverage for:
- https://github.com/systemd/systemd/issues/31231
- https://github.com/systemd/systemd/issues/35805
(cherry picked from commit 5730a400fd5ee82566fe03eb832121a0d4bc26b6)
Related: RHEL-118216
---
test/units/TEST-53-TIMER.restart-trigger.sh | 77 +++++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100755 test/units/TEST-53-TIMER.restart-trigger.sh
diff --git a/test/units/TEST-53-TIMER.restart-trigger.sh b/test/units/TEST-53-TIMER.restart-trigger.sh
new file mode 100755
index 0000000000..057f379ddc
--- /dev/null
+++ b/test/units/TEST-53-TIMER.restart-trigger.sh
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Restarting an already elapsed timer shouldn't immediately trigger the corresponding service unit.
+#
+# Provides coverage for:
+# - https://github.com/systemd/systemd/issues/31231
+# - https://github.com/systemd/systemd/issues/35805
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/test-control.sh
+. "$(dirname "$0")"/util.sh
+
+UNIT_NAME="timer-restart-$RANDOM"
+TEST_MESSAGE="Hello from timer $RANDOM"
+
+# Setup
+cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
+[Timer]
+OnCalendar=$(date --date="+1 hour" "+%Y-%m-%d %H:%M:%S")
+AccuracySec=1s
+EOF
+
+cat >"/run/systemd/system/$UNIT_NAME.service" <<EOF
+[Service]
+ExecStart=echo "$TEST_MESSAGE"
+EOF
+
+systemctl daemon-reload
+
+JOURNAL_TS="$(date "+%s")"
+# Paranoia check that the test message is not already in the logs
+(! journalctl -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE")
+
+# Restart time timer and move time forward by 2 hours to trigger the timer
+systemctl restart "$UNIT_NAME.timer"
+systemctl status "$UNIT_NAME.timer"
+
+date -s '+2 hours'
+trap 'date -s "-2 hours"' EXIT
+sleep 1
+systemctl status "$UNIT_NAME.timer"
+assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
+
+# Restarting the timer unit shouldn't trigger neither the timer nor the service, so these
+# fields should remain constant through the following tests
+SERVICE_INV_ID="$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
+TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
+
+# Now restart the timer and check if the timer and the service weren't triggered again
+systemctl restart "$UNIT_NAME.timer"
+sleep 5
+assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
+assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
+assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
+
+# Set the timer into the past, restart it, and again check if it wasn't triggered
+TIMER_TS="$(date --date="-1 day" "+%Y-%m-%d %H:%M:%S")"
+mkdir "/run/systemd/system/$UNIT_NAME.timer.d/"
+cat >"/run/systemd/system/$UNIT_NAME.timer.d/99-override.conf" <<EOF
+[Timer]
+OnCalendar=$TIMER_TS
+EOF
+systemctl daemon-reload
+systemctl status "$UNIT_NAME.timer"
+assert_in "OnCalendar=$TIMER_TS" "$(systemctl show -P TimersCalendar "$UNIT_NAME".timer)"
+systemctl restart "$UNIT_NAME.timer"
+sleep 5
+assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
+assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
+assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
+
+# Cleanup
+systemctl stop "$UNIT_NAME".{timer,service}
+rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
+systemctl daemon-reload

View File

@ -0,0 +1,147 @@
From b10337e1343d3f40cce41df530e658389eefbe6b Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 23 Sep 2025 21:04:12 +0200
Subject: [PATCH] test: check the next elapse timer timestamp after
deserialization
When deserializing a serialized timer unit with RandomizedDelaySec= set,
systemd should use the last inactive exit timestamp instead of current
realtime to calculate the new next elapse, so the timer unit actually
runs in the given calendar window.
Provides coverage for:
- https://github.com/systemd/systemd/issues/18678
- https://github.com/systemd/systemd/pull/27752
(cherry picked from commit f4c3c107d9be4e922a080fc292ed3889c4e0f4a5)
Related: RHEL-118216
---
...TEST-53-TIMER.RandomizedDelaySec-reload.sh | 97 +++++++++++++++++++
test/units/util.sh | 9 ++
2 files changed, 106 insertions(+)
create mode 100755 test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
diff --git a/test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh b/test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
new file mode 100755
index 0000000000..08f4f469d6
--- /dev/null
+++ b/test/units/TEST-53-TIMER.RandomizedDelaySec-reload.sh
@@ -0,0 +1,97 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# When deserializing a serialized timer unit with RandomizedDelaySec= set, systemd should use the last
+# inactive exit timestamp instead of current realtime to calculate the new next elapse, so the timer unit
+# actually runs in the given calendar window.
+#
+# Provides coverage for:
+# - https://github.com/systemd/systemd/issues/18678
+# - https://github.com/systemd/systemd/pull/27752
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/test-control.sh
+. "$(dirname "$0")"/util.sh
+
+UNIT_NAME="timer-RandomizedDelaySec-$RANDOM"
+TARGET_TS="$(date --date="tomorrow 00:10")"
+TARGET_TS_S="$(date --date="$TARGET_TS" "+%s")"
+# Maximum possible next elapse timestamp: $TARGET_TS (OnCalendar=) + 22 hours (RandomizedDelaySec=)
+MAX_NEXT_ELAPSE_REALTIME_S="$((TARGET_TS_S + 22 * 60 * 60))"
+MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S")"
+
+# Let's make sure to return the date & time back to the original state once we're done with our time
+# shenigans. One way to do this would be to use hwclock, but the RTC in VMs can be unreliable or slow to
+# respond, causing unexpected test fails/timeouts.
+#
+# Instead, let's save the realtime timestamp before we start with the test together with a current monotonic
+# timestamp, after the test ends take the difference between the current monotonic timestamp and the "start"
+# one, add it to the originally saved realtime timestamp, and finally use that timestamp to set the system
+# time. This should advance the system time by the amount of time the test actually ran, and hence restore it
+# to some sane state after the time jumps performed by the test. It won't be perfect, but it should be close
+# enough for our needs.
+START_REALTIME="$(date "+%s")"
+START_MONOTONIC="$(cut -d . -f 1 /proc/uptime)"
+at_exit() {
+ : "Restore the system date to a sane state"
+ END_MONOTONIC="$(cut -d . -f 1 /proc/uptime)"
+ date --set="@$((START_REALTIME + END_MONOTONIC - START_MONOTONIC))"
+}
+trap at_exit EXIT
+
+# Set some predictable time so we can schedule the first timer elapse in a deterministic-ish way
+date --set="23:00"
+
+# Setup
+cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
+[Timer]
+# Run this timer daily, ten minutes after midnight
+OnCalendar=*-*-* 00:10:00
+RandomizedDelaySec=22h
+AccuracySec=1ms
+EOF
+
+cat >"/run/systemd/system/$UNIT_NAME.service" <<EOF
+[Service]
+ExecStart=echo "Hello world"
+EOF
+
+systemctl daemon-reload
+
+check_elapse_timestamp() {
+ systemctl status "$UNIT_NAME.timer"
+ systemctl show -p InactiveExitTimestamp "$UNIT_NAME.timer"
+
+ NEXT_ELAPSE_REALTIME="$(systemctl show -P NextElapseUSecRealtime "$UNIT_NAME.timer")"
+ NEXT_ELAPSE_REALTIME_S="$(date --date="$NEXT_ELAPSE_REALTIME" "+%s")"
+ : "Next elapse timestamp should be $TARGET_TS <= $NEXT_ELAPSE_REALTIME <= $MAX_NEXT_ELAPSE_REALTIME"
+ assert_ge "$NEXT_ELAPSE_REALTIME_S" "$TARGET_TS_S"
+ assert_le "$NEXT_ELAPSE_REALTIME_S" "$MAX_NEXT_ELAPSE_REALTIME_S"
+}
+
+# Restart the timer unit and check the initial next elapse timestamp
+: "Initial next elapse timestamp"
+systemctl restart "$UNIT_NAME.timer"
+check_elapse_timestamp
+
+# Bump the system date to 1 minute after the original calendar timer would've expired (without any random
+# delay!) - systemd should recalculate the next elapse timestamp with a new randomized delay, but it should
+# use the original inactive exit timestamp as a "base", so the final timestamp should not end up beyond the
+# original calendar timestamp + randomized delay range.
+#
+# Similarly, do the same check after doing daemon-reload, as that also forces systemd to recalculate the next
+# elapse timestamp (this goes through a slightly different codepath that actually contained the original
+# issue).
+: "Next elapse timestamp after time jump"
+date -s "tomorrow 00:11"
+check_elapse_timestamp
+
+: "Next elapse timestamp after daemon-reload"
+systemctl daemon-reload
+check_elapse_timestamp
+
+# Cleanup
+systemctl stop "$UNIT_NAME".{timer,service}
+rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
+systemctl daemon-reload
diff --git a/test/units/util.sh b/test/units/util.sh
index 1f903b3293..cea5c8e62f 100755
--- a/test/units/util.sh
+++ b/test/units/util.sh
@@ -57,6 +57,15 @@ assert_le() {(
fi
)}
+assert_ge() {(
+ set +ex
+
+ if [[ "${1:?}" -lt "${2:?}" ]]; then
+ echo "FAIL: '$1' < '$2'" >&2
+ exit 1
+ fi
+)}
+
assert_in() {(
set +ex

View File

@ -1,25 +0,0 @@
From 40d1437d8aab83c50018decac472608b91f53e49 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: fix 0-passed-as-pointer warning"
This reverts commit 35d4cb60dcfbb65359708a98c3474a8b3827f4a0.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 412411bff7..caec4bb76c 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -217,7 +217,7 @@ static int parse_config(void) {
#if HAVE_DWFL_SET_SYSROOT
{ "Coredump", "EnterNamespace", config_parse_bool, 0, &arg_enter_namespace },
#else
- { "Coredump", "EnterNamespace", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
+ { "Coredump", "EnterNamespace", config_parse_warn_compat, DISABLED_CONFIGURATION, 0 },
#endif
{}
};

View File

@ -0,0 +1,29 @@
From 4de919773f76a7658f034f0713503f965d4fb8c3 Mon Sep 17 00:00:00 2001
From: Lukas Nykryn <lnykryn@redhat.com>
Date: Tue, 9 Sep 2025 15:24:22 +0200
Subject: [PATCH] timer: don't run service immediately after restart of a timer
When a timer is restarted, don't reset the last_trigger field.
This prevents the timer from triggering immediately.
Fixes: #31231
(cherry picked from commit 3fc44a0f68412b649e16f12ff2f97a36c615457d)
Resolves: RHEL-118216
---
src/core/timer.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index b37a67f310..02fdf91c78 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -653,8 +653,6 @@ static int timer_start(Unit *u) {
if (r < 0)
return r;
- t->last_trigger = DUAL_TIMESTAMP_NULL;
-
/* Reenable all timers that depend on unit activation time */
LIST_FOREACH(value, v, t->values)
if (v->base == TIMER_ACTIVE)

View File

@ -1,115 +0,0 @@
From e6fad9f1bcdf98fe8636b1f41da55afd75a0832d Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "Define helper to call PR_SET_DUMPABLE"
This reverts commit 2271674c5776fa8308ad8d425e64246910366d2f.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 3 ++-
src/shared/coredump-util.c | 7 -------
src/shared/coredump-util.h | 2 --
src/shared/elf-util.c | 4 ++--
src/shared/tests.c | 1 -
5 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index caec4bb76c..7bde2f5196 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -3,6 +3,7 @@
#include <errno.h>
#include <stdio.h>
#include <sys/mount.h>
+#include <sys/prctl.h>
#include <sys/statvfs.h>
#include <sys/auxv.h>
#include <sys/xattr.h>
@@ -2015,7 +2016,7 @@ static int run(int argc, char *argv[]) {
log_set_target_and_open(LOG_TARGET_KMSG);
/* Make sure we never enter a loop */
- (void) set_dumpable(SUID_DUMP_DISABLE);
+ (void) prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE);
/* Ignore all parse errors */
(void) parse_config();
diff --git a/src/shared/coredump-util.c b/src/shared/coredump-util.c
index 0050e133c4..805503f366 100644
--- a/src/shared/coredump-util.c
+++ b/src/shared/coredump-util.c
@@ -1,21 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <elf.h>
-#include <sys/prctl.h>
#include "coredump-util.h"
-#include "errno-util.h"
#include "extract-word.h"
#include "fileio.h"
#include "string-table.h"
#include "unaligned.h"
#include "virt.h"
-int set_dumpable(SuidDumpMode mode) {
- /* Cast mode explicitly to long, because prctl wants longs but is varargs. */
- return RET_NERRNO(prctl(PR_SET_DUMPABLE, (long) mode));
-}
-
static const char *const coredump_filter_table[_COREDUMP_FILTER_MAX] = {
[COREDUMP_FILTER_PRIVATE_ANONYMOUS] = "private-anonymous",
[COREDUMP_FILTER_SHARED_ANONYMOUS] = "shared-anonymous",
diff --git a/src/shared/coredump-util.h b/src/shared/coredump-util.h
index b18cb33c84..73c74c98c7 100644
--- a/src/shared/coredump-util.h
+++ b/src/shared/coredump-util.h
@@ -32,8 +32,6 @@ typedef enum SuidDumpMode {
_SUID_DUMP_MODE_MAX,
} SuidDumpMode;
-int set_dumpable(SuidDumpMode mode);
-
const char* coredump_filter_to_string(CoredumpFilter i) _const_;
CoredumpFilter coredump_filter_from_string(const char *s) _pure_;
int coredump_filter_mask_from_string(const char *s, uint64_t *ret);
diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c
index ff8818de27..a3ff1fd3fb 100644
--- a/src/shared/elf-util.c
+++ b/src/shared/elf-util.c
@@ -6,12 +6,12 @@
#include <elfutils/libdwelf.h>
#include <elfutils/libdwfl.h>
#include <libelf.h>
+#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <unistd.h>
#include "alloc-util.h"
-#include "coredump-util.h"
#include "dlfcn-util.h"
#include "elf-util.h"
#include "errno-util.h"
@@ -825,7 +825,7 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
if (r == 0) {
/* We want to avoid loops, given this can be called from systemd-coredump */
if (fork_disable_dump) {
- r = set_dumpable(SUID_DUMP_DISABLE);
+ r = RET_NERRNO(prctl(PR_SET_DUMPABLE, 0));
if (r < 0)
report_errno_and_exit(error_pipe[1], r);
}
diff --git a/src/shared/tests.c b/src/shared/tests.c
index 88031e90d9..50b30ca17d 100644
--- a/src/shared/tests.c
+++ b/src/shared/tests.c
@@ -16,7 +16,6 @@
#include "bus-wait-for-jobs.h"
#include "cgroup-setup.h"
#include "cgroup-util.h"
-#include "coredump-util.h"
#include "env-file.h"
#include "env-util.h"
#include "fd-util.h"

View File

@ -0,0 +1,49 @@
From c2a0cd9a1f46f4c9093b2070ec36466caff3db68 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 29 Sep 2025 16:11:27 +0200
Subject: [PATCH] test: store and compare just the property value
Follow-up for 5730a400fd5ee82566fe03eb832121a0d4bc26b6.
(cherry picked from commit 0cb252d50f35256bff569fa6213784f2d45ad6a1)
Related: RHEL-118216
---
test/units/TEST-53-TIMER.restart-trigger.sh | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/test/units/TEST-53-TIMER.restart-trigger.sh b/test/units/TEST-53-TIMER.restart-trigger.sh
index 057f379ddc..e5cd575d66 100755
--- a/test/units/TEST-53-TIMER.restart-trigger.sh
+++ b/test/units/TEST-53-TIMER.restart-trigger.sh
@@ -45,15 +45,15 @@ assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --
# Restarting the timer unit shouldn't trigger neither the timer nor the service, so these
# fields should remain constant through the following tests
-SERVICE_INV_ID="$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
-TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
+SERVICE_INV_ID="$(systemctl show -P InvocationID "$UNIT_NAME.service")"
+TIMER_LAST_TRIGGER="$(systemctl show -P LastTriggerUSec "$UNIT_NAME.timer")"
# Now restart the timer and check if the timer and the service weren't triggered again
systemctl restart "$UNIT_NAME.timer"
sleep 5
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
-assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
-assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
+assert_eq "$SERVICE_INV_ID" "$(systemctl show -P InvocationID "$UNIT_NAME.service")"
+assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show -P LastTriggerUSec "$UNIT_NAME.timer")"
# Set the timer into the past, restart it, and again check if it wasn't triggered
TIMER_TS="$(date --date="-1 day" "+%Y-%m-%d %H:%M:%S")"
@@ -68,8 +68,8 @@ assert_in "OnCalendar=$TIMER_TS" "$(systemctl show -P TimersCalendar "$UNIT_NAME
systemctl restart "$UNIT_NAME.timer"
sleep 5
assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1"
-assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")"
-assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")"
+assert_eq "$SERVICE_INV_ID" "$(systemctl show -P InvocationID "$UNIT_NAME.service")"
+assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show -P LastTriggerUSec "$UNIT_NAME.timer")"
# Cleanup
systemctl stop "$UNIT_NAME".{timer,service}

View File

@ -1,79 +0,0 @@
From b00298da67577bd432df17ab640ab36b37e03d74 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: introduce an enum to wrap dumpable
constants"
This reverts commit 20b0f1e07885ffc887ac27f9dad164271b07581c.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 10 +++++-----
src/shared/coredump-util.h | 7 -------
2 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 7bde2f5196..67abc20ec5 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -442,7 +442,7 @@ static int grant_user_access(int core_fd, const Context *context) {
/* We allow access if dumpable on the command line was exactly 1, we got all the data,
* at_secure is not set, and the uid/gid match euid/egid. */
bool ret =
- context->dumpable == SUID_DUMP_USER &&
+ context->dumpable == 1 &&
at_secure == 0 &&
uid != UID_INVALID && euid != UID_INVALID && uid == euid &&
gid != GID_INVALID && egid != GID_INVALID && gid == egid;
@@ -1090,13 +1090,13 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
if (r < 0)
log_warning_errno(r, "Failed to parse resource limit \"%s\", ignoring: %m", context->meta[META_ARGV_RLIMIT]);
- /* The value is set to contents of /proc/sys/fs/suid_dumpable, which we set to SUID_DUMP_SAFE (2),
+ /* The value is set to contents of /proc/sys/fs/suid_dumpable, which we set to 2,
* if the process is marked as not dumpable, see PR_SET_DUMPABLE(2const). */
if (context->meta[META_ARGV_DUMPABLE]) {
r = safe_atou(context->meta[META_ARGV_DUMPABLE], &context->dumpable);
if (r < 0)
return log_error_errno(r, "Failed to parse dumpable field \"%s\": %m", context->meta[META_ARGV_DUMPABLE]);
- if (context->dumpable > SUID_DUMP_SAFE)
+ if (context->dumpable > 2)
log_notice("Got unexpected %%d/dumpable value %u.", context->dumpable);
}
@@ -1628,7 +1628,7 @@ static int can_forward_coredump(Context *context, pid_t pid) {
* quickly replaces it with a namespaced process and we forward the coredump to the attacker, into
* the namespace. With %F/pidfd we can reliably check the namespace of the original process, hence we
* can allow forwarding. */
- if (!context->got_pidfd && context->dumpable != SUID_DUMP_USER)
+ if (!context->got_pidfd && context->dumpable != 1)
return false;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
@@ -2016,7 +2016,7 @@ static int run(int argc, char *argv[]) {
log_set_target_and_open(LOG_TARGET_KMSG);
/* Make sure we never enter a loop */
- (void) prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE);
+ (void) prctl(PR_SET_DUMPABLE, 0);
/* Ignore all parse errors */
(void) parse_config();
diff --git a/src/shared/coredump-util.h b/src/shared/coredump-util.h
index 73c74c98c7..4f54bb94c0 100644
--- a/src/shared/coredump-util.h
+++ b/src/shared/coredump-util.h
@@ -25,13 +25,6 @@ typedef enum CoredumpFilter {
/* The kernel doesn't like UINT64_MAX and returns ERANGE, use UINT32_MAX to support future new flags */
#define COREDUMP_FILTER_MASK_ALL UINT32_MAX
-typedef enum SuidDumpMode {
- SUID_DUMP_DISABLE = 0, /* PR_SET_DUMPABLE(2const) */
- SUID_DUMP_USER = 1, /* PR_SET_DUMPABLE(2const) */
- SUID_DUMP_SAFE = 2, /* https://www.kernel.org/doc/html/latest/admin-guide/sysctl/fs.html#suid-dumpable */
- _SUID_DUMP_MODE_MAX,
-} SuidDumpMode;
-
const char* coredump_filter_to_string(CoredumpFilter i) _const_;
CoredumpFilter coredump_filter_from_string(const char *s) _pure_;
int coredump_filter_mask_from_string(const char *s, uint64_t *ret);

View File

@ -0,0 +1,87 @@
From f3a6a5afc55b525dc8796ba34097a4db49b852a0 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 25 Aug 2025 15:09:36 +0200
Subject: [PATCH] pam_systemd: honor session class provided via PAM environment
Replaces #38638
Co-authored-by: Lennart Poettering <lennart@poettering.net>
(cherry picked from commit cf2630acaa87ded5ad99ea30ed4bd895e71ca503)
Resolves: RHEL-109832
---
man/pam_systemd.xml | 13 +++++++++++++
src/login/pam_systemd.c | 13 +++++++++----
2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
index 183b37d676..3cc25bdf5b 100644
--- a/man/pam_systemd.xml
+++ b/man/pam_systemd.xml
@@ -147,6 +147,19 @@
</tgroup>
</table>
+ <para>If no session class is specified via either the PAM module option or via the
+ <varname>$XDG_SESSION_CLASS</varname> environment variable, the class is automatically chosen, depending on
+ various session parameters, such as the session type (if known), whether the session has a TTY or X11
+ display, and the user disposition. Note that various tools allow setting the session class for newly
+ allocated PAM sessions explicitly by means of the <varname>$XDG_SESSION_CLASS</varname> environment variable.
+ For example, classic UNIX cronjobs support environment variable assignments (see
+ <citerefentry project='man-pages'><refentrytitle>crontab</refentrytitle><manvolnum>5</manvolnum></citerefentry>),
+ which may be used to choose between the <constant>background</constant> and
+ <constant>background-light</constant> session class individually per cronjob, or
+ <command>run0 --setenv=XDG_SESSION_CLASS=user-light</command> may be used
+ to choose between <constant>user</constant> and <constant>user-light</constant> for invoked privileged sessions.
+ </para>
+
<xi:include href="version-info.xml" xpointer="v197"/></listitem>
</varlistentry>
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index 7cc64144eb..b3c84a835e 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -997,12 +997,14 @@ _public_ PAM_EXTERN int pam_sm_open_session(
desktop = getenv_harder(handle, "XDG_SESSION_DESKTOP", desktop_pam);
incomplete = getenv_harder_bool(handle, "XDG_SESSION_INCOMPLETE", false);
+ /* The session class can be overridden via the PAM environment, and we try to honor that selection. */
if (streq_ptr(service, "systemd-user")) {
/* If we detect that we are running in the "systemd-user" PAM stack, then let's patch the class to
* 'manager' if not set, simply for robustness reasons. */
type = "unspecified";
- class = IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) ?
- "manager-early" : "manager";
+ if (isempty(class))
+ class = IN_SET(user_record_disposition(ur), USER_INTRINSIC, USER_SYSTEM, USER_DYNAMIC) ?
+ "manager-early" : "manager";
tty = NULL;
} else if (tty && strchr(tty, ':')) {
@@ -1018,20 +1020,23 @@ _public_ PAM_EXTERN int pam_sm_open_session(
* (as they otherwise even try to update it!) — but cron doesn't actually allocate a TTY for its forked
* off processes.) */
type = "unspecified";
- class = "background";
+ if (isempty(class))
+ class = "background";
tty = NULL;
} else if (streq_ptr(tty, "ssh")) {
/* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further
* details look for "PAM_TTY_KLUDGE" in the openssh sources). */
type = "tty";
- class = "user";
+ if (isempty(class))
+ class = "user";
tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though usually
* associated with a pty — won't be tracked by their tty in logind. This is because ssh
* does the PAM session registration early for new connections, and registers a pty only
* much later (this is because it doesn't know yet if it needs one at all, as whether to
* register a pty or not is negotiated much later in the protocol). */
+
} else if (tty)
/* Chop off leading /dev prefix that some clients specify, but others do not. */
tty = skip_dev_prefix(tty);

View File

@ -1,53 +0,0 @@
From dd0b6f16a367e8b1e5fb97233fb1c2099d0c4629 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: when %F/pidfd is used, again allow
forwarding to containers"
This reverts commit 1a01ba0f895a8781908cfebfa1d74f326f6faacb.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 67abc20ec5..940eb44528 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -155,7 +155,6 @@ typedef struct Context {
uint64_t rlimit;
bool is_pid1;
bool is_journald;
- bool got_pidfd;
int mount_tree_fd;
/* These point into external memory, are not owned by this object */
@@ -1404,8 +1403,6 @@ static int gather_pid_metadata_from_argv(
if (r < 0)
return log_error_errno(r, "Failed to initialize pidref from pidfd %d: %m", kernel_fd);
- context->got_pidfd = 1;
-
/* If there are containers involved with different versions of the code they might
* not be using pidfds, so it would be wrong to set the metadata, skip it. */
r = in_same_namespace(/* pid1 = */ 0, context->pidref.pid, NAMESPACE_PID);
@@ -1624,11 +1621,13 @@ static int can_forward_coredump(Context *context, pid_t pid) {
assert(context);
- /* We need to avoid a situation where the attacker crashes a SUID process or a root daemon and
- * quickly replaces it with a namespaced process and we forward the coredump to the attacker, into
- * the namespace. With %F/pidfd we can reliably check the namespace of the original process, hence we
- * can allow forwarding. */
- if (!context->got_pidfd && context->dumpable != 1)
+ /* We don't use %F/pidfd to pin down the crashed process yet. We need to avoid a situation where the
+ * attacker crashes a SUID process or a root daemon and quickly replaces it with a namespaced process
+ * and we forward the initial part of the coredump to the attacker, inside the namespace.
+ *
+ * TODO: relax this check when %F is implemented and used.
+ */
+ if (context->dumpable != 1)
return false;
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);

View File

@ -0,0 +1,58 @@
From 1603dfd95502d68cb47aa14e1c020c39397e1a59 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Wed, 15 Oct 2025 09:02:50 +0200
Subject: [PATCH] udev/net_id: introduce naming scheme for RHEL-10.2
rhel-only: policy
Resolves: RHEL-72813
---
man/systemd.net-naming-scheme.xml | 9 +++++++++
src/shared/netif-naming-scheme.c | 1 +
src/shared/netif-naming-scheme.h | 1 +
3 files changed, 11 insertions(+)
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
index d997b46133..9e7ae58f47 100644
--- a/man/systemd.net-naming-scheme.xml
+++ b/man/systemd.net-naming-scheme.xml
@@ -567,6 +567,15 @@
<xi:include href="version-info.xml" xpointer="rhel-10.1"/>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><constant>rhel-10.2</constant></term>
+
+ <listitem><para>Same as naming scheme <constant>rhel-10.0</constant>.</para>
+
+ <xi:include href="version-info.xml" xpointer="rhel-10.2"/>
+ </listitem>
+ </varlistentry>
</variablelist>
<para>By default <constant>rhel-10.0</constant> is used.</para>
diff --git a/src/shared/netif-naming-scheme.c b/src/shared/netif-naming-scheme.c
index 4929808d4d..7d22bb8831 100644
--- a/src/shared/netif-naming-scheme.c
+++ b/src/shared/netif-naming-scheme.c
@@ -47,6 +47,7 @@ static const NamingScheme naming_schemes[] = {
{ "rhel-10.0-beta", NAMING_RHEL_10_0_BETA },
{ "rhel-10.0", NAMING_RHEL_10_0 },
{ "rhel-10.1", NAMING_RHEL_10_1 },
+ { "rhel-10.2", NAMING_RHEL_10_2 },
/* … add more schemes here, as the logic to name devices is updated … */
EXTRA_NET_NAMING_MAP
diff --git a/src/shared/netif-naming-scheme.h b/src/shared/netif-naming-scheme.h
index e8ea61b6cc..06542c9e20 100644
--- a/src/shared/netif-naming-scheme.h
+++ b/src/shared/netif-naming-scheme.h
@@ -90,6 +90,7 @@ typedef enum NamingSchemeFlags {
NAMING_RHEL_10_0_BETA = NAMING_V255,
NAMING_RHEL_10_0 = NAMING_V257,
NAMING_RHEL_10_1 = NAMING_RHEL_10_0,
+ NAMING_RHEL_10_2 = NAMING_RHEL_10_0,
EXTRA_NET_NAMING_SCHEMES

View File

@ -1,148 +0,0 @@
From 8655b93872dc5d5468042164e71c117813a680e8 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: add support for new %F PIDFD specifier"
This reverts commit 46e24959ecb9390f61403925bb1569c57ca375df.
Reverts: RHEL-104135
---
man/systemd-coredump.xml | 11 -------
src/coredump/coredump.c | 60 ++----------------------------------
sysctl.d/50-coredump.conf.in | 2 +-
3 files changed, 3 insertions(+), 70 deletions(-)
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
index 185497125c..0f5ccf12f9 100644
--- a/man/systemd-coredump.xml
+++ b/man/systemd-coredump.xml
@@ -192,17 +192,6 @@ COREDUMP_FILENAME=/var/lib/systemd/coredump/core.Web….552351.….zst
</listitem>
</varlistentry>
- <varlistentry>
- <term><varname>COREDUMP_BY_PIDFD=</varname></term>
- <listitem><para>If the crashed process was analyzed using a PIDFD provided by the kernel (requires
- kernel v6.16) then this field will be present and set to <literal>1</literal>. If this field is
- not set, then the crashed process was analyzed via a PID, which is known to be subject to race
- conditions.</para>
-
- <xi:include href="version-info.xml" xpointer="v258"/>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term><varname>COREDUMP_TIMESTAMP=</varname></term>
<listitem><para>The time of the crash as reported by the kernel (in μs since the epoch).</para>
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 940eb44528..88cd1c394d 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -109,7 +109,6 @@ typedef enum {
/* The fields below were added to kernel/core_pattern at later points, so they might be missing. */
META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */
META_ARGV_DUMPABLE, /* %d: as set by the kernel */
- META_ARGV_PIDFD, /* %F: pidfd of the process, since v6.16 */
/* If new fields are added, they should be added here, to maintain compatibility
* with callers which don't know about the new fields. */
_META_ARGV_MAX,
@@ -139,7 +138,6 @@ static const char * const meta_field_names[_META_MAX] = {
[META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
[META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
[META_ARGV_DUMPABLE] = "COREDUMP_DUMPABLE=",
- [META_ARGV_PIDFD] = "COREDUMP_BY_PIDFD=",
[META_COMM] = "COREDUMP_COMM=",
[META_EXE] = "COREDUMP_EXE=",
[META_UNIT] = "COREDUMP_UNIT=",
@@ -1343,8 +1341,7 @@ static int gather_pid_metadata_from_argv(
Context *context,
int argc, char **argv) {
- _cleanup_(pidref_done) PidRef local_pidref = PIDREF_NULL;
- int r, kernel_fd = -EBADF;
+ int r;
assert(iovw);
assert(context);
@@ -1376,47 +1373,6 @@ static int gather_pid_metadata_from_argv(
t = buf;
}
- if (i == META_ARGV_PID) {
- /* Store this so that we can check whether the core will be forwarded to a container
- * even when the kernel doesn't provide a pidfd. Can be dropped once baseline is
- * >= v6.16. */
- r = pidref_set_pidstr(&local_pidref, t);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize pidref from pid %s: %m", t);
- }
-
- if (i == META_ARGV_PIDFD) {
- /* If the current kernel doesn't support the %F specifier (which resolves to a
- * pidfd), but we included it in the core_pattern expression, we'll receive an empty
- * string here. Deal with that gracefully. */
- if (isempty(t))
- continue;
-
- assert(!pidref_is_set(&context->pidref));
- assert(kernel_fd < 0);
-
- kernel_fd = parse_fd(t);
- if (kernel_fd < 0)
- return log_error_errno(kernel_fd, "Failed to parse pidfd \"%s\": %m", t);
-
- r = pidref_set_pidfd(&context->pidref, kernel_fd);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize pidref from pidfd %d: %m", kernel_fd);
-
- /* If there are containers involved with different versions of the code they might
- * not be using pidfds, so it would be wrong to set the metadata, skip it. */
- r = in_same_namespace(/* pid1 = */ 0, context->pidref.pid, NAMESPACE_PID);
- if (r < 0)
- log_debug_errno(r, "Failed to check pidns of crashing process, ignoring: %m");
- if (r <= 0)
- continue;
-
- /* We don't print the fd number in the journal as it's meaningless, but we still
- * record that the parsing was done with a kernel-provided fd as it means it's safe
- * from races, which is valuable information to provide in the journal record. */
- t = "1";
- }
-
r = iovw_put_string_field(iovw, meta_field_names[i], t);
if (r < 0)
return r;
@@ -1424,19 +1380,7 @@ static int gather_pid_metadata_from_argv(
/* Cache some of the process metadata we collected so far and that we'll need to
* access soon. */
- r = context_parse_iovw(context, iovw);
- if (r < 0)
- return r;
-
- /* If the kernel didn't give us a PIDFD, then use the one derived from the
- * PID immediately, given we have it. */
- if (!pidref_is_set(&context->pidref))
- context->pidref = TAKE_PIDREF(local_pidref);
-
- /* Close the kernel-provided FD as the last thing after everything else succeeded */
- kernel_fd = safe_close(kernel_fd);
-
- return 0;
+ return context_parse_iovw(context, iovw);
}
static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context *context) {
diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in
index fe8f7670b0..a550c87258 100644
--- a/sysctl.d/50-coredump.conf.in
+++ b/sysctl.d/50-coredump.conf.in
@@ -13,7 +13,7 @@
# the core dump.
#
# See systemd-coredump(8) and core(5).
-kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d %F
+kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d
# Allow 16 coredumps to be dispatched in parallel by the kernel.
# We collect metadata from /proc/%P/, and thus need to make sure the crashed

View File

@ -0,0 +1,59 @@
From ea4962d881846eed9491110fbb69234b667a445c Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Wed, 15 Oct 2025 12:54:52 +0200
Subject: [PATCH] udev/net_id: introduce naming scheme for RHEL-9.8
rhel-only: policy
Resolves: RHEL-72813
---
man/systemd.net-naming-scheme.xml | 10 ++++++++++
src/shared/netif-naming-scheme.c | 1 +
src/shared/netif-naming-scheme.h | 1 +
3 files changed, 12 insertions(+)
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
index 9e7ae58f47..3c4d67cce3 100644
--- a/man/systemd.net-naming-scheme.xml
+++ b/man/systemd.net-naming-scheme.xml
@@ -669,6 +669,16 @@
<xi:include href="version-info.xml" xpointer="rhel-9.7"/>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><constant>rhel-9.8</constant></term>
+
+ <listitem>
+ <para>PCI slot number is now read from <constant>firmware_node/sun</constant> sysfs file.</para>
+
+ <xi:include href="version-info.xml" xpointer="rhel-9.8"/>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect2>
diff --git a/src/shared/netif-naming-scheme.c b/src/shared/netif-naming-scheme.c
index 7d22bb8831..18b012b8c8 100644
--- a/src/shared/netif-naming-scheme.c
+++ b/src/shared/netif-naming-scheme.c
@@ -44,6 +44,7 @@ static const NamingScheme naming_schemes[] = {
{ "rhel-9.5", NAMING_RHEL_9_5 },
{ "rhel-9.6", NAMING_RHEL_9_6 },
{ "rhel-9.7", NAMING_RHEL_9_7 },
+ { "rhel-9.8", NAMING_RHEL_9_8 },
{ "rhel-10.0-beta", NAMING_RHEL_10_0_BETA },
{ "rhel-10.0", NAMING_RHEL_10_0 },
{ "rhel-10.1", NAMING_RHEL_10_1 },
diff --git a/src/shared/netif-naming-scheme.h b/src/shared/netif-naming-scheme.h
index 06542c9e20..eab374fb9a 100644
--- a/src/shared/netif-naming-scheme.h
+++ b/src/shared/netif-naming-scheme.h
@@ -86,6 +86,7 @@ typedef enum NamingSchemeFlags {
NAMING_RHEL_9_5 = NAMING_RHEL_9_4 & ~NAMING_BRIDGE_MULTIFUNCTION_SLOT,
NAMING_RHEL_9_6 = NAMING_RHEL_9_5,
NAMING_RHEL_9_7 = NAMING_RHEL_9_5,
+ NAMING_RHEL_9_8 = NAMING_RHEL_9_5 | NAMING_FIRMWARE_NODE_SUN,
NAMING_RHEL_10_0_BETA = NAMING_V255,
NAMING_RHEL_10_0 = NAMING_V257,

View File

@ -1,24 +0,0 @@
From 41f7b831986b1eda992ea40081ec9d7fe6157e41 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: get rid of a bogus assertion"
This reverts commit cee91ba610d7ae7b80d32e487c79ea10c8fb98bc.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 88cd1c394d..048eb53546 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1027,6 +1027,7 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
assert(context);
assert(iovw);
+ assert(iovw->count >= _META_ARGV_MAX);
/* Converts the data in the iovec array iovw into separate fields. Fills in context->meta[] (for
* which no memory is allocated, it just contains direct pointers into the iovec array memory). */

View File

@ -0,0 +1,423 @@
From 8b14e3ac69bb7f657b103883c0db22d2fdf22ffb Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@gmail.com>
Date: Thu, 21 Nov 2024 09:51:14 +0000
Subject: [PATCH] test: split VM-only subtests from TEST-74-AUX-UTILS to new
VM-only test
TEST-74-AUX-UTILS covers many subtests, as it's a catch-all job, and a few
need a VM to run. The job is thus marked VM-only. But that means in settings
where we can't run VM tests (no KVM available), the entire thing is skipped,
losing tons of coverage that doesn't need skipping.
Move the VM-only subtests to TEST-87-AUX-UTILS-VM that is configured to only
run in VMs under both runners. This way we keep the existing tests as-is, and
we can add new VM-only tests without worrying. This is how the rest of the
tests are organized.
Follow-up for f4faac20730cbb339ae05ed6e20da687a2868e76
(cherry picked from commit 3f9539a97f3b4747ff22a530bac39dec24ac58af)
Resolves: RHEL-112205
---
test/TEST-74-AUX-UTILS/meson.build | 4 +-
test/TEST-87-AUX-UTILS-VM/meson.build | 11 ++
test/meson.build | 1 +
test/units/TEST-74-AUX-UTILS.detect-virt.sh | 4 -
...ctl.sh => TEST-87-AUX-UTILS-VM.bootctl.sh} | 7 +-
...mp.sh => TEST-87-AUX-UTILS-VM.coredump.sh} | 9 +-
.../units/TEST-87-AUX-UTILS-VM.detect-virt.sh | 11 ++
...h => TEST-87-AUX-UTILS-VM.modules-load.sh} | 7 +-
test/units/TEST-87-AUX-UTILS-VM.mount.sh | 182 ++++++++++++++++++
...tore.sh => TEST-87-AUX-UTILS-VM.pstore.sh} | 5 +-
test/units/TEST-87-AUX-UTILS-VM.sh | 11 ++
11 files changed, 225 insertions(+), 27 deletions(-)
create mode 100644 test/TEST-87-AUX-UTILS-VM/meson.build
rename test/units/{TEST-74-AUX-UTILS.bootctl.sh => TEST-87-AUX-UTILS-VM.bootctl.sh} (98%)
rename test/units/{TEST-74-AUX-UTILS.coredump.sh => TEST-87-AUX-UTILS-VM.coredump.sh} (98%)
create mode 100755 test/units/TEST-87-AUX-UTILS-VM.detect-virt.sh
rename test/units/{TEST-74-AUX-UTILS.modules-load.sh => TEST-87-AUX-UTILS-VM.modules-load.sh} (94%)
create mode 100755 test/units/TEST-87-AUX-UTILS-VM.mount.sh
rename test/units/{TEST-74-AUX-UTILS.pstore.sh => TEST-87-AUX-UTILS-VM.pstore.sh} (98%)
create mode 100755 test/units/TEST-87-AUX-UTILS-VM.sh
diff --git a/test/TEST-74-AUX-UTILS/meson.build b/test/TEST-74-AUX-UTILS/meson.build
index ee24cd8f78..698d03b055 100644
--- a/test/TEST-74-AUX-UTILS/meson.build
+++ b/test/TEST-74-AUX-UTILS/meson.build
@@ -1,11 +1,9 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
+# Container-specific auxiliary tests. VM-based ones go in TEST-87-AUX-UTILS-VM.
integration_tests += [
integration_test_template + {
'name' : fs.name(meson.current_source_dir()),
- 'storage': 'persistent',
- 'vm' : true,
- 'coredump-exclude-regex' : '/(test-usr-dump|test-dump|bash)$',
},
]
diff --git a/test/TEST-87-AUX-UTILS-VM/meson.build b/test/TEST-87-AUX-UTILS-VM/meson.build
new file mode 100644
index 0000000000..8490139204
--- /dev/null
+++ b/test/TEST-87-AUX-UTILS-VM/meson.build
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# VM-specific auxiliary tests. Container-based ones go in TEST-74-AUX-UTILS.
+
+integration_tests += [
+ integration_test_template + {
+ 'name' : fs.name(meson.current_source_dir()),
+ 'storage': 'persistent',
+ 'coredump-exclude-regex' : '/(test-usr-dump|test-dump|bash)$',
+ 'vm' : true,
+ },
+]
diff --git a/test/meson.build b/test/meson.build
index c440bcb722..40b2ba2c38 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -381,6 +381,7 @@ foreach dirname : [
# 'TEST-84-STORAGETM', # we don't ship systemd-storagetm
# 'TEST-85-NETWORK', # we don't ship systemd-networkd
'TEST-86-MULTI-PROFILE-UKI',
+ 'TEST-87-AUX-UTILS-VM',
]
subdir(dirname)
endforeach
diff --git a/test/units/TEST-74-AUX-UTILS.detect-virt.sh b/test/units/TEST-74-AUX-UTILS.detect-virt.sh
index a1539d9b44..fe1db4d2aa 100755
--- a/test/units/TEST-74-AUX-UTILS.detect-virt.sh
+++ b/test/units/TEST-74-AUX-UTILS.detect-virt.sh
@@ -5,7 +5,3 @@ set -o pipefail
SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot
(! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot)
-
-if ! systemd-detect-virt -c; then
- unshare --mount-proc --fork --user --pid systemd-detect-virt --container
-fi
diff --git a/test/units/TEST-74-AUX-UTILS.bootctl.sh b/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh
similarity index 98%
rename from test/units/TEST-74-AUX-UTILS.bootctl.sh
rename to test/units/TEST-87-AUX-UTILS-VM.bootctl.sh
index 650c289aca..5a9d8fb27f 100755
--- a/test/units/TEST-74-AUX-UTILS.bootctl.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.bootctl.sh
@@ -3,11 +3,6 @@
set -eux
set -o pipefail
-if systemd-detect-virt --quiet --container; then
- echo "running on container, skipping."
- exit 0
-fi
-
if ! command -v bootctl >/dev/null; then
echo "bootctl not found, skipping."
exit 0
@@ -24,6 +19,8 @@ fi
# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh
+(! systemd-detect-virt -cq)
+
basic_tests() {
bootctl "$@" --help
bootctl "$@" --version
diff --git a/test/units/TEST-74-AUX-UTILS.coredump.sh b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
similarity index 98%
rename from test/units/TEST-74-AUX-UTILS.coredump.sh
rename to test/units/TEST-87-AUX-UTILS-VM.coredump.sh
index 2c084f54d2..7ab6f29d7d 100755
--- a/test/units/TEST-74-AUX-UTILS.coredump.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
@@ -19,12 +19,9 @@ at_exit() {
rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT" "$MAKE_STACKTRACE_DUMP"
}
-trap at_exit EXIT
+(! systemd-detect-virt -cq)
-if systemd-detect-virt -cq; then
- echo "Running in a container, skipping the systemd-coredump test..."
- exit 0
-fi
+trap at_exit EXIT
# To make all coredump entries stored in system.journal.
journalctl --rotate
@@ -81,7 +78,7 @@ timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN |
if cgroupfs_supports_user_xattrs; then
# Make sure we can forward crashes back to containers
- CONTAINER="TEST-74-AUX-UTILS-container"
+ CONTAINER="TEST-87-AUX-UTILS-VM-container"
mkdir -p "/var/lib/machines/$CONTAINER"
mkdir -p "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d"
diff --git a/test/units/TEST-87-AUX-UTILS-VM.detect-virt.sh b/test/units/TEST-87-AUX-UTILS-VM.detect-virt.sh
new file mode 100755
index 0000000000..251a0e8910
--- /dev/null
+++ b/test/units/TEST-87-AUX-UTILS-VM.detect-virt.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+(! systemd-detect-virt -cq)
+
+SYSTEMD_IN_CHROOT=1 systemd-detect-virt --chroot
+(! SYSTEMD_IN_CHROOT=0 systemd-detect-virt --chroot)
+
+unshare --mount-proc --fork --user --pid systemd-detect-virt --container
diff --git a/test/units/TEST-74-AUX-UTILS.modules-load.sh b/test/units/TEST-87-AUX-UTILS-VM.modules-load.sh
similarity index 94%
rename from test/units/TEST-74-AUX-UTILS.modules-load.sh
rename to test/units/TEST-87-AUX-UTILS-VM.modules-load.sh
index ceac8262bf..140f3d5f95 100755
--- a/test/units/TEST-74-AUX-UTILS.modules-load.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.modules-load.sh
@@ -10,12 +10,9 @@ at_exit() {
rm -rfv "${CONFIG_FILE:?}"
}
-trap at_exit EXIT
+(! systemd-detect-virt -cq)
-if systemd-detect-virt -cq; then
- echo "Running in a container, skipping the systemd-modules-load test..."
- exit 0
-fi
+trap at_exit EXIT
ORIG_MODULES_LOAD_CONFIG="$(systemd-analyze cat-config modules-load.d)"
diff --git a/test/units/TEST-87-AUX-UTILS-VM.mount.sh b/test/units/TEST-87-AUX-UTILS-VM.mount.sh
new file mode 100755
index 0000000000..3075d0fe2e
--- /dev/null
+++ b/test/units/TEST-87-AUX-UTILS-VM.mount.sh
@@ -0,0 +1,182 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/util.sh
+. "$(dirname "$0")"/util.sh
+
+at_exit() {
+ set +e
+
+ [[ -n "${LOOP:-}" ]] && losetup -d "$LOOP"
+ [[ -n "${WORK_DIR:-}" ]] && rm -fr "$WORK_DIR"
+}
+
+(! systemd-detect-virt -cq)
+
+trap at_exit EXIT
+
+WORK_DIR="$(mktemp -d)"
+mkdir -p "$WORK_DIR/mnt"
+
+systemd-mount --list
+systemd-mount --list --full
+systemd-mount --list --no-legend
+systemd-mount --list --no-pager
+systemd-mount --list --quiet
+systemd-mount --list --json=pretty
+
+# tmpfs
+mkdir -p "$WORK_DIR/mnt/foo/bar"
+systemd-mount --tmpfs "$WORK_DIR/mnt/foo"
+test ! -d "$WORK_DIR/mnt/foo/bar"
+touch "$WORK_DIR/mnt/foo/baz"
+systemd-umount "$WORK_DIR/mnt/foo"
+test -d "$WORK_DIR/mnt/foo/bar"
+test ! -e "$WORK_DIR/mnt/foo/baz"
+
+# overlay
+systemd-mount --type=overlay --options="lowerdir=/etc,upperdir=$WORK_DIR/upper,workdir=$WORK_DIR/work" /etc "$WORK_DIR/overlay"
+touch "$WORK_DIR/overlay/foo"
+test -e "$WORK_DIR/upper/foo"
+systemd-umount "$WORK_DIR/overlay"
+
+# Set up a simple block device for further tests
+dd if=/dev/zero of="$WORK_DIR/simple.img" bs=1M count=16
+mkfs.ext4 -L sd-mount-test "$WORK_DIR/simple.img"
+LOOP="$(losetup --show --find "$WORK_DIR/simple.img")"
+udevadm wait --timeout 60 --settle "$LOOP"
+# Also wait for the .device unit for the loop device is active. Otherwise, the .device unit activation
+# that is triggered by the .mount unit introduced by systemd-mount below may time out.
+timeout 60 bash -c "until systemctl is-active $LOOP; do sleep 1; done"
+mount "$LOOP" "$WORK_DIR/mnt"
+touch "$WORK_DIR/mnt/foo.bar"
+umount "$LOOP"
+(! mountpoint "$WORK_DIR/mnt")
+# Wait for the mount unit to be unloaded. Otherwise, creation of the transient unit below may fail.
+MOUNT_UNIT=$(systemd-escape --path --suffix=mount "$WORK_DIR/mnt")
+timeout 60 bash -c "while [[ -n \$(systemctl list-units --all --no-legend $MOUNT_UNIT) ]]; do sleep 1; done"
+
+# Mount with both source and destination set
+systemd-mount "$LOOP" "$WORK_DIR/mnt"
+systemctl status "$WORK_DIR/mnt"
+systemd-mount --list --full
+test -e "$WORK_DIR/mnt/foo.bar"
+systemd-umount "$WORK_DIR/mnt"
+# Same thing, but with explicitly specified filesystem and disabled filesystem check
+systemd-mount --type=ext4 --fsck=no --collect "$LOOP" "$WORK_DIR/mnt"
+systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").mount"
+test -e "$WORK_DIR/mnt/foo.bar"
+systemd-mount --umount "$LOOP"
+# Discover additional metadata (unit description should now contain filesystem label)
+systemd-mount --no-ask-password --discover "$LOOP" "$WORK_DIR/mnt"
+test -e "$WORK_DIR/mnt/foo.bar"
+systemctl show -P Description "$WORK_DIR/mnt" | grep -q sd-mount-test
+systemd-umount "$WORK_DIR/mnt"
+# Set a unit description
+systemd-mount --description="Very Important Unit" "$LOOP" "$WORK_DIR/mnt"
+test -e "$WORK_DIR/mnt/foo.bar"
+systemctl show -P Description "$WORK_DIR/mnt" | grep -q "Very Important Unit"
+systemd-umount "$WORK_DIR/mnt"
+# Set a property
+systemd-mount --property="Description=Foo Bar" "$LOOP" "$WORK_DIR/mnt"
+test -e "$WORK_DIR/mnt/foo.bar"
+systemctl show -P Description "$WORK_DIR/mnt" | grep -q "Foo Bar"
+systemd-umount "$WORK_DIR/mnt"
+# Set mount options
+systemd-mount --options=ro,x-foo-bar "$LOOP" "$WORK_DIR/mnt"
+test -e "$WORK_DIR/mnt/foo.bar"
+systemctl show -P Options "$WORK_DIR/mnt" | grep -Eq "(^ro|,ro)"
+systemctl show -P Options "$WORK_DIR/mnt" | grep -q "x-foo-bar"
+systemd-umount "$WORK_DIR/mnt"
+
+# Mount with only source set
+systemd-mount "$LOOP"
+systemctl status /run/media/system/sd-mount-test
+systemd-mount --list --full
+test -e /run/media/system/sd-mount-test/foo.bar
+systemd-umount LABEL=sd-mount-test
+
+# Automount
+systemd-mount --automount=yes "$LOOP" "$WORK_DIR/mnt"
+systemd-mount --list --full
+systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
+[[ "$(systemctl show -P ActiveState "$WORK_DIR/mnt")" == inactive ]]
+test -e "$WORK_DIR/mnt/foo.bar"
+systemctl status "$WORK_DIR/mnt"
+systemd-umount "$WORK_DIR/mnt"
+# Automount + automount-specific property
+systemd-mount -A --automount-property="Description=Bar Baz" "$LOOP" "$WORK_DIR/mnt"
+systemctl show -P Description "$(systemd-escape --path "$WORK_DIR/mnt").automount" | grep -q "Bar Baz"
+test -e "$WORK_DIR/mnt/foo.bar"
+# Call --umount via --machine=, first with a relative path (bad) and then with
+# an absolute one (good)
+(! systemd-umount --machine=.host "$(realpath --relative-to=. "$WORK_DIR/mnt")")
+systemd-umount --machine=.host "$WORK_DIR/mnt"
+
+# ext4 doesn't support uid=/gid=
+(! systemd-mount -t ext4 --owner=testuser "$LOOP" "$WORK_DIR/mnt")
+
+# Automount + --bind-device
+systemd-mount --automount=yes --bind-device --timeout-idle-sec=1 "$LOOP" "$WORK_DIR/mnt"
+systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
+# Trigger the automount
+test -e "$WORK_DIR/mnt/foo.bar"
+# Wait until it's idle again
+sleep 1.5
+# Safety net for slower/overloaded systems
+timeout 10s bash -c "while systemctl is-active -q $WORK_DIR/mnt; do sleep .2; done"
+systemctl status "$(systemd-escape --path "$WORK_DIR/mnt").automount"
+# Disassemble the underlying block device
+losetup -d "$LOOP"
+unset LOOP
+# The automount unit should disappear once the underlying blockdev is gone
+timeout 10s bash -c "while systemctl status '$(systemd-escape --path "$WORK_DIR/mnt".automount)'; do sleep .2; done"
+
+# Mount a disk image
+systemd-mount --discover "$WORK_DIR/simple.img"
+# We can access files in the image even if the loopback block device is not initialized by udevd.
+test -e /run/media/system/simple.img/foo.bar
+# systemd-mount --list and systemd-umount require the loopback block device is initialized by udevd.
+udevadm settle --timeout 30
+assert_in "/dev/loop.* ext4 +sd-mount-test" "$(systemd-mount --list --full)"
+LOOP_AUTO=$(systemd-mount --list --full --no-legend | awk '$7 == "sd-mount-test" { print $1 }')
+LOOP_AUTO_DEVPATH=$(udevadm info --query property --property DEVPATH --value "$LOOP_AUTO")
+systemd-umount "$WORK_DIR/simple.img"
+# Wait for 'change' uevent for the device with DISK_MEDIA_CHANGE=1.
+# After the event, the backing_file attribute should be removed.
+timeout 60 bash -c "while [[ -e /sys/$LOOP_AUTO_DEVPATH/loop/backing_file ]]; do sleep 1; done"
+
+# --owner + vfat
+#
+# Create a vfat image, as ext4 doesn't support uid=/gid= fixating for all
+# files/directories
+dd if=/dev/zero of="$WORK_DIR/owner-vfat.img" bs=1M count=16
+mkfs.vfat -n owner-vfat "$WORK_DIR/owner-vfat.img"
+LOOP="$(losetup --show --find "$WORK_DIR/owner-vfat.img")"
+# If the synthesized uevent triggered by inotify event has been processed earlier than the kernel finishes to
+# attach the backing file, then SYSTEMD_READY=0 is set for the device. As a workaround, monitor sysattr
+# and re-trigger uevent after that.
+LOOP_DEVPATH=$(udevadm info --query property --property DEVPATH --value "$LOOP")
+timeout 60 bash -c "until [[ -e /sys/$LOOP_DEVPATH/loop/backing_file ]]; do sleep 1; done"
+udevadm trigger --settle "$LOOP"
+# Also wait for the .device unit for the loop device is active. Otherwise, the .device unit activation
+# that is triggered by the .mount unit introduced by systemd-mount below may time out.
+if ! timeout 60 bash -c "until systemctl is-active $LOOP; do sleep 1; done"; then
+ # For debugging issue like
+ # https://github.com/systemd/systemd/issues/32680#issuecomment-2120959238
+ # https://github.com/systemd/systemd/issues/32680#issuecomment-2122074805
+ udevadm info "$LOOP"
+ udevadm info --attribute-walk "$LOOP"
+ cat /sys/"$(udevadm info --query property --property DEVPATH --value "$LOOP")"/loop/backing_file || :
+ false
+fi
+# Mount it and check the UID/GID
+[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt")" == "root:root" ]]
+systemd-mount --owner=testuser "$LOOP" "$WORK_DIR/mnt"
+systemctl status "$WORK_DIR/mnt"
+[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt")" == "testuser:testuser" ]]
+touch "$WORK_DIR/mnt/hello"
+[[ "$(stat -c "%U:%G" "$WORK_DIR/mnt/hello")" == "testuser:testuser" ]]
+systemd-umount LABEL=owner-vfat
diff --git a/test/units/TEST-74-AUX-UTILS.pstore.sh b/test/units/TEST-87-AUX-UTILS-VM.pstore.sh
similarity index 98%
rename from test/units/TEST-74-AUX-UTILS.pstore.sh
rename to test/units/TEST-87-AUX-UTILS-VM.pstore.sh
index 9be8066e8e..043d023856 100755
--- a/test/units/TEST-74-AUX-UTILS.pstore.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.pstore.sh
@@ -5,10 +5,7 @@ set -o pipefail
systemctl log-level info
-if systemd-detect-virt -cq; then
- echo "Running in a container, skipping the systemd-pstore test..."
- exit 0
-fi
+(! systemd-detect-virt -cq)
DUMMY_DMESG_0="$(mktemp)"
cat >"$DUMMY_DMESG_0" <<\EOF
diff --git a/test/units/TEST-87-AUX-UTILS-VM.sh b/test/units/TEST-87-AUX-UTILS-VM.sh
new file mode 100755
index 0000000000..9c2a033aa9
--- /dev/null
+++ b/test/units/TEST-87-AUX-UTILS-VM.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/test-control.sh
+. "$(dirname "$0")"/test-control.sh
+
+run_subtests
+
+touch /testok

View File

@ -1,49 +0,0 @@
From 5281235691ff5b64702d9cfb3f704fd069c6169d Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: also stop forwarding non-dumpable
processes"
This reverts commit 69d7d75a872d319b5fda048044238a735dce3834.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 048eb53546..19d4d02437 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1560,21 +1560,10 @@ static int receive_ucred(int transport_fd, struct ucred *ret_ucred) {
return 0;
}
-static int can_forward_coredump(Context *context, pid_t pid) {
+static int can_forward_coredump(pid_t pid) {
_cleanup_free_ char *cgroup = NULL, *path = NULL, *unit = NULL;
int r;
- assert(context);
-
- /* We don't use %F/pidfd to pin down the crashed process yet. We need to avoid a situation where the
- * attacker crashes a SUID process or a root daemon and quickly replaces it with a namespaced process
- * and we forward the initial part of the coredump to the attacker, inside the namespace.
- *
- * TODO: relax this check when %F is implemented and used.
- */
- if (context->dumpable != 1)
- return false;
-
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
if (r < 0)
return r;
@@ -1618,7 +1607,7 @@ static int forward_coredump_to_container(Context *context) {
if (r < 0)
return log_debug_errno(r, "Failed to get namespace leader: %m");
- r = can_forward_coredump(context, leader_pid);
+ r = can_forward_coredump(leader_pid);
if (r < 0)
return log_debug_errno(r, "Failed to check if coredump can be forwarded: %m");
if (r == 0)

View File

@ -0,0 +1,123 @@
From 78ed449353cbe20dcddcbea1f7f6370a5df0c209 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 1 Sep 2025 05:08:45 +0900
Subject: [PATCH] core/transaction: first drop unmergable jobs for anchor jobs
As you can see, something spurious happens in the logs below.
```
initrd-switch-root.target: Trying to enqueue job initrd-switch-root.target/start/isolate
systemd-repart.service: Looking at job systemd-repart.service/stop conflicted_by=no
systemd-repart.service: Looking at job systemd-repart.service/start conflicted_by=no
systemd-repart.service: Fixing conflicting jobs systemd-repart.service/stop,systemd-repart.service/start by deleting job systemd-repart.service/stop
initrd-switch-root.target: Fixing conflicting jobs initrd-switch-root.target/stop,initrd-switch-root.target/start by deleting job initrd-switch-root.target/stop
systemd-repart.service: Deleting job systemd-repart.service/start as dependency of job initrd-switch-root.target/stop
```
The two conflicting jobs for systemd-repart.service are initially queued
as the following:
- initrd-switch-root.target has Wants=initrd-root-fs.target, and
initrd-root-fs.target has Wants=systemd-repart.service (through symlink),
hence starting initrd-switch-root.target tries to start
systemd-repart.service,
- systemd-repart.service has Conflicts=initrd-switch-root.target, hence
starting initrd-switch-root.target tries to stop
systemd-repart.service.
As similar, interestingly(?) starting initrd-switch-root.target tries to
stop initrd-switch-root.target.
So, now there are at least two pairs of conflicting jobs:
- systemd-repart.service: start vs stop,
- initrd-switch-root.target: start vs stop.
As these jobs are induced by starting initrd-switch-root.target, of course
the most important one is the start job for initrd-switch-root.target.
Previously, as you can see in the logs at the beginning, even if
the start job for initrd-switch-root.target is important, we may first
try to resolve the conflict in systemd-repart.service, and may drop the
stop job for systemd-repart.service even if it is relevant to the start
job of initrd-switch-root.target.
This makes first we solve the pair of conflicting jobs for anchor task.
So the stop job for initrd-switch-root.target is dropped first, and the
induced start job for systemd-repart.service is automatically removed,
thus it is not necessary to solve the conflict in systemd-repart.service
anymore.
This is especially important for services that are enabled both in initrd
and after switching root. If a stop job for one of the service is
unexpectedly dropped during switching root, then the service is not stopped
before switching root, and will never start after that.
Fixes #38765.
(cherry picked from commit 811af8d53463fae5a8470b7884158cee0f9acbe4)
Resolves: RHEL-112205
---
src/core/transaction.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 705ed0c50f..eeaf7e8be5 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -14,6 +14,7 @@
#include "terminal-util.h"
#include "transaction.h"
+static bool job_matters_to_anchor(Job *job);
static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) {
@@ -215,17 +216,18 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *job) {
return -EINVAL;
}
-static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
+static int transaction_ensure_mergeable(Transaction *tr, bool matters_to_anchor, sd_bus_error *e) {
Job *j;
int r;
assert(tr);
- /* First step, check whether any of the jobs for one specific
- * task conflict. If so, try to drop one of them. */
HASHMAP_FOREACH(j, tr->jobs) {
JobType t;
+ if (job_matters_to_anchor(j) != matters_to_anchor)
+ continue;
+
t = j->type;
LIST_FOREACH(transaction, k, j->transaction_next) {
if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0)
@@ -252,7 +254,26 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
}
}
- /* Second step, merge the jobs. */
+ return 0;
+}
+
+static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
+ Job *j;
+ int r;
+
+ assert(tr);
+
+ /* First step, try to drop unmergeable jobs for jobs that matter to anchor. */
+ r = transaction_ensure_mergeable(tr, /* matters_to_anchor = */ true, e);
+ if (r < 0)
+ return r;
+
+ /* Second step, do the same for jobs that not matter to anchor. */
+ r = transaction_ensure_mergeable(tr, /* matters_to_anchor = */ false, e);
+ if (r < 0)
+ return r;
+
+ /* Third step, merge the jobs. */
HASHMAP_FOREACH(j, tr->jobs) {
JobType t = j->type;

View File

@ -1,138 +0,0 @@
From cfb8f2d6b759ae93827908afccc18b2b8c3ccc4b Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: use %d in kernel core pattern"
This reverts commit 0ade63d15214fa8e184cc87522bfac9533be441b.
Reverts: RHEL-104135
---
man/systemd-coredump.xml | 12 ------------
src/coredump/coredump.c | 21 +++------------------
sysctl.d/50-coredump.conf.in | 2 +-
test/units/TEST-74-AUX-UTILS.coredump.sh | 5 -----
4 files changed, 4 insertions(+), 36 deletions(-)
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
index 0f5ccf12f9..737b80de9a 100644
--- a/man/systemd-coredump.xml
+++ b/man/systemd-coredump.xml
@@ -292,18 +292,6 @@ COREDUMP_FILENAME=/var/lib/systemd/coredump/core.Web….552351.….zst
</listitem>
</varlistentry>
- <varlistentry>
- <term><varname>COREDUMP_DUMPABLE=</varname></term>
-
- <listitem><para>The <constant>PR_GET_DUMPABLE</constant> field as reported by the kernel, see
- <citerefentry
- project='man-pages'><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
- </para>
-
- <xi:include href="version-info.xml" xpointer="v258"/>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term><varname>COREDUMP_OPEN_FDS=</varname></term>
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 19d4d02437..ac1e1cb9d3 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -108,7 +108,6 @@ typedef enum {
_META_ARGV_REQUIRED,
/* The fields below were added to kernel/core_pattern at later points, so they might be missing. */
META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */
- META_ARGV_DUMPABLE, /* %d: as set by the kernel */
/* If new fields are added, they should be added here, to maintain compatibility
* with callers which don't know about the new fields. */
_META_ARGV_MAX,
@@ -137,7 +136,6 @@ static const char * const meta_field_names[_META_MAX] = {
[META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
[META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
[META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
- [META_ARGV_DUMPABLE] = "COREDUMP_DUMPABLE=",
[META_COMM] = "COREDUMP_COMM=",
[META_EXE] = "COREDUMP_EXE=",
[META_UNIT] = "COREDUMP_UNIT=",
@@ -148,7 +146,6 @@ typedef struct Context {
PidRef pidref;
uid_t uid;
gid_t gid;
- unsigned dumpable;
int signo;
uint64_t rlimit;
bool is_pid1;
@@ -436,16 +433,14 @@ static int grant_user_access(int core_fd, const Context *context) {
if (r < 0)
return r;
- /* We allow access if dumpable on the command line was exactly 1, we got all the data,
- * at_secure is not set, and the uid/gid match euid/egid. */
+ /* We allow access if we got all the data and at_secure is not set and
+ * the uid/gid matches euid/egid. */
bool ret =
- context->dumpable == 1 &&
at_secure == 0 &&
uid != UID_INVALID && euid != UID_INVALID && uid == euid &&
gid != GID_INVALID && egid != GID_INVALID && gid == egid;
- log_debug("Will %s access (dumpable=%u uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)",
+ log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)",
ret ? "permit" : "restrict",
- context->dumpable,
uid, euid, gid, egid, yes_no(at_secure));
return ret;
}
@@ -1088,16 +1083,6 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
if (r < 0)
log_warning_errno(r, "Failed to parse resource limit \"%s\", ignoring: %m", context->meta[META_ARGV_RLIMIT]);
- /* The value is set to contents of /proc/sys/fs/suid_dumpable, which we set to 2,
- * if the process is marked as not dumpable, see PR_SET_DUMPABLE(2const). */
- if (context->meta[META_ARGV_DUMPABLE]) {
- r = safe_atou(context->meta[META_ARGV_DUMPABLE], &context->dumpable);
- if (r < 0)
- return log_error_errno(r, "Failed to parse dumpable field \"%s\": %m", context->meta[META_ARGV_DUMPABLE]);
- if (context->dumpable > 2)
- log_notice("Got unexpected %%d/dumpable value %u.", context->dumpable);
- }
-
unit = context->meta[META_UNIT];
context->is_pid1 = streq(context->meta[META_ARGV_PID], "1") || streq_ptr(unit, SPECIAL_INIT_SCOPE);
context->is_journald = streq_ptr(unit, SPECIAL_JOURNALD_SERVICE);
diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in
index a550c87258..90c080bdfe 100644
--- a/sysctl.d/50-coredump.conf.in
+++ b/sysctl.d/50-coredump.conf.in
@@ -13,7 +13,7 @@
# the core dump.
#
# See systemd-coredump(8) and core(5).
-kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d
+kernel.core_pattern=|{{LIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h
# Allow 16 coredumps to be dispatched in parallel by the kernel.
# We collect metadata from /proc/%P/, and thus need to make sure the crashed
diff --git a/test/units/TEST-74-AUX-UTILS.coredump.sh b/test/units/TEST-74-AUX-UTILS.coredump.sh
index f157f97443..8173a23162 100755
--- a/test/units/TEST-74-AUX-UTILS.coredump.sh
+++ b/test/units/TEST-74-AUX-UTILS.coredump.sh
@@ -201,17 +201,12 @@ journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE
/usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509900 12345
journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
/usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509901 12345 mymachine
-journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
- /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509902 12345 youmachine 1
# Wait a bit for the coredumps to get processed
timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -lt 2 ]]; do sleep 1; done"
coredumpctl info $$
coredumpctl info COREDUMP_TIMESTAMP=1679509900000000
coredumpctl info COREDUMP_TIMESTAMP=1679509901000000
coredumpctl info COREDUMP_HOSTNAME="mymachine"
-coredumpctl info COREDUMP_TIMESTAMP=1679509902000000
-coredumpctl info COREDUMP_HOSTNAME="youmachine"
-coredumpctl info COREDUMP_DUMPABLE="1"
# This used to cause a stack overflow
systemd-run -t --property CoredumpFilter=all ls /tmp

View File

@ -0,0 +1,44 @@
From 44e20b005290dbee4e15b65238f7d87bd51be912 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 4 Sep 2025 00:49:34 +0900
Subject: [PATCH] test: add test case for issue #38765
(cherry picked from commit 5b89cc2a5ad9ecb040dc1fc9b31fb0e24a59e9ae)
Resolves: RHEL-112205
---
src/core/transaction.c | 1 +
test/units/TEST-87-AUX-UTILS-VM.sh | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index eeaf7e8be5..e4b04d0461 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -171,6 +171,7 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *job) {
* another unit in which case we
* rather remove the start. */
+ /* Update test/units/TEST-87-AUX-UTILS-VM.sh when logs below are changed. */
log_unit_debug(j->unit,
"Looking at job %s/%s conflicted_by=%s",
j->unit->id, job_type_to_string(j->type),
diff --git a/test/units/TEST-87-AUX-UTILS-VM.sh b/test/units/TEST-87-AUX-UTILS-VM.sh
index 9c2a033aa9..ecbff290f0 100755
--- a/test/units/TEST-87-AUX-UTILS-VM.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.sh
@@ -3,6 +3,14 @@
set -eux
set -o pipefail
+# For issue #38765
+journalctl --sync
+if journalctl -q -o short-monotonic --grep "Looking at job .*/.* conflicted_by=(yes|no)" >/failed; then
+ echo "Found unexpected unmergeable jobs"
+ cat /failed
+ exit 1
+fi
+
# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh

View File

@ -1,83 +0,0 @@
From 52ec2f34b8313eab2dd6a0eeadec2720d43fa3f1 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: get rid of _META_MANDATORY_MAX"
This reverts commit 6f678c43638caa6b0b349e56f0ded6d9c781a345.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 29 ++++++++---------------------
1 file changed, 8 insertions(+), 21 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index ac1e1cb9d3..c96b59b2f5 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -92,7 +92,7 @@ assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
#define MOUNT_TREE_ROOT "/run/systemd/mount-rootfs"
-typedef enum {
+enum {
/* We use these as array indexes for our process metadata cache.
*
* The first indices of the cache stores the same metadata as the ones passed by the kernel via
@@ -108,9 +108,9 @@ typedef enum {
_META_ARGV_REQUIRED,
/* The fields below were added to kernel/core_pattern at later points, so they might be missing. */
META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */
+ _META_ARGV_MAX,
/* If new fields are added, they should be added here, to maintain compatibility
* with callers which don't know about the new fields. */
- _META_ARGV_MAX,
/* The following indexes are cached for a couple of special fields we use (and
* thereby need to be retrieved quickly) for naming coredump files, and attaching
@@ -118,15 +118,16 @@ typedef enum {
* environment. */
META_COMM = _META_ARGV_MAX,
+ _META_MANDATORY_MAX,
/* The rest are similar to the previous ones except that we won't fail if one of
* them is missing in a message sent over the socket. */
- META_EXE,
+ META_EXE = _META_MANDATORY_MAX,
META_UNIT,
META_PROC_AUXV,
_META_MAX
-} meta_argv_t;
+};
static const char * const meta_field_names[_META_MAX] = {
[META_ARGV_PID] = "COREDUMP_PID=",
@@ -1223,24 +1224,10 @@ static int process_socket(int fd) {
if (r < 0)
return r;
- /* Make sure we received all the expected fields. We support being called by an *older*
- * systemd-coredump from the outside, so we require only the basic set of fields that
- * was being sent when the support for sending to containers over a socket was added
- * in a108c43e36d3ceb6e34efe37c014fc2cda856000. */
- meta_argv_t i;
- FOREACH_ARGUMENT(i,
- META_ARGV_PID,
- META_ARGV_UID,
- META_ARGV_GID,
- META_ARGV_SIGNAL,
- META_ARGV_TIMESTAMP,
- META_ARGV_RLIMIT,
- META_ARGV_HOSTNAME,
- META_COMM)
+ /* Make sure we received at least all fields we need. */
+ for (int i = 0; i < _META_MANDATORY_MAX; i++)
if (!context.meta[i])
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Mandatory argument %s not received on socket, aborting.",
- meta_field_names[i]);
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A mandatory argument (%i) has not been sent, aborting.", i);
return submit_coredump(&context, &iovw, input_fd);
}

View File

@ -0,0 +1,89 @@
From cdb2fd795861211f6e89b9156971677eb5e2ef70 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 20 Jan 2025 10:31:09 +0100
Subject: [PATCH] strv: add strv_equal_ignore_order() helper
(cherry picked from commit 5072f4268b89a71e47e59c434da0222f722c7f0e)
Resolves: RHEL-109902
---
src/basic/strv.c | 20 ++++++++++++++++++++
src/basic/strv.h | 2 ++
src/test/test-strv.c | 22 ++++++++++++++++++++++
3 files changed, 44 insertions(+)
diff --git a/src/basic/strv.c b/src/basic/strv.c
index a92b1234a3..c9c4551cdc 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -861,6 +861,26 @@ int strv_compare(char * const *a, char * const *b) {
return 0;
}
+bool strv_equal_ignore_order(char **a, char **b) {
+
+ /* Just like strv_equal(), but doesn't care about the order of elements or about redundant entries
+ * (i.e. it's even ok if the number of entries in the array differ, as long as the difference just
+ * consists of repititions) */
+
+ if (a == b)
+ return true;
+
+ STRV_FOREACH(i, a)
+ if (!strv_contains(b, *i))
+ return false;
+
+ STRV_FOREACH(i, b)
+ if (!strv_contains(a, *i))
+ return false;
+
+ return true;
+}
+
void strv_print_full(char * const *l, const char *prefix) {
STRV_FOREACH(s, l)
printf("%s%s\n", strempty(prefix), *s);
diff --git a/src/basic/strv.h b/src/basic/strv.h
index 49ef19dcb5..86ba06f835 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -96,6 +96,8 @@ static inline bool strv_equal(char * const *a, char * const *b) {
return strv_compare(a, b) == 0;
}
+bool strv_equal_ignore_order(char **a, char **b);
+
char** strv_new_internal(const char *x, ...) _sentinel_;
char** strv_new_ap(const char *x, va_list ap);
#define strv_new(...) strv_new_internal(__VA_ARGS__, NULL)
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
index d641043c50..b1d30d73a5 100644
--- a/src/test/test-strv.c
+++ b/src/test/test-strv.c
@@ -1255,4 +1255,26 @@ TEST(strv_find_closest) {
ASSERT_NULL(strv_find_closest(l, "sfajosajfosdjaofjdsaf"));
}
+TEST(strv_equal_ignore_order) {
+
+ ASSERT_TRUE(strv_equal_ignore_order(NULL, NULL));
+ ASSERT_TRUE(strv_equal_ignore_order(NULL, STRV_MAKE(NULL)));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE(NULL), NULL));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE(NULL), STRV_MAKE(NULL)));
+
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE("foo"), NULL));
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE("foo"), STRV_MAKE(NULL)));
+ ASSERT_FALSE(strv_equal_ignore_order(NULL, STRV_MAKE("foo")));
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE(NULL), STRV_MAKE("foo")));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE("foo"), STRV_MAKE("foo")));
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE("foo"), STRV_MAKE("foo", "bar")));
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE("foo", "bar"), STRV_MAKE("foo")));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE("foo", "bar"), STRV_MAKE("foo", "bar")));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE("bar", "foo"), STRV_MAKE("foo", "bar")));
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE("bar", "foo"), STRV_MAKE("foo", "bar", "quux")));
+ ASSERT_FALSE(strv_equal_ignore_order(STRV_MAKE("bar", "foo", "quux"), STRV_MAKE("foo", "bar")));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE("bar", "foo", "quux"), STRV_MAKE("quux", "foo", "bar")));
+ ASSERT_TRUE(strv_equal_ignore_order(STRV_MAKE("bar", "foo"), STRV_MAKE("bar", "foo", "bar", "foo", "foo")));
+}
+
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -1,123 +0,0 @@
From 6474cfc2bd0274be6ee9de8cd8cebeee49e3073d Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: wrap long lines, fix grammar in comments"
This reverts commit ad1453257d69a74bf8e47493394c601d733774de.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 34 ++++++++++++++++------------------
1 file changed, 16 insertions(+), 18 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index c96b59b2f5..58bcd4910f 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -95,9 +95,9 @@ assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
enum {
/* We use these as array indexes for our process metadata cache.
*
- * The first indices of the cache stores the same metadata as the ones passed by the kernel via
- * argv[], i.e. the strings specified in our pattern defined in /proc/sys/kernel/core_pattern,
- * see core(5). */
+ * The first indices of the cache stores the same metadata as the ones passed by
+ * the kernel via argv[], ie the strings array passed by the kernel according to
+ * our pattern defined in /proc/sys/kernel/core_pattern (see man:core(5)). */
META_ARGV_PID, /* %P: as seen in the initial pid namespace */
META_ARGV_UID, /* %u: as seen in the initial user namespace */
@@ -274,6 +274,7 @@ static int fix_acl(int fd, uid_t uid, bool allow_user) {
}
static int fix_xattr(int fd, const Context *context) {
+
static const char * const xattrs[_META_MAX] = {
[META_ARGV_PID] = "user.coredump.pid",
[META_ARGV_UID] = "user.coredump.uid",
@@ -1031,9 +1032,9 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
bool have_signal_name = false;
FOREACH_ARRAY(iovec, iovw->iovec, iovw->count) {
for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) {
- /* Note that these strings are NUL-terminated, because we made sure that a
+ /* Note that these strings are NUL terminated, because we made sure that a
* trailing NUL byte is in the buffer, though not included in the iov_len
- * count (see process_socket() and gather_pid_metadata_*()). */
+ * count (see process_socket() and gather_pid_metadata_*()) */
assert(((char*) iovec->iov_base)[iovec->iov_len] == 0);
const char *p = memory_startswith(iovec->iov_base, iovec->iov_len, meta_field_names[i]);
@@ -1048,11 +1049,10 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
memory_startswith(iovec->iov_base, iovec->iov_len, "COREDUMP_SIGNAL_NAME=");
}
- /* The basic fields from argv[] should always be there, refuse early if not. */
+ /* The basic fields from argv[] should always be there, refuse early if not */
for (int i = 0; i < _META_ARGV_REQUIRED; i++)
if (!context->meta[i])
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "A required (%s) has not been sent, aborting.", meta_field_names[i]);
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A required (%s) has not been sent, aborting.", meta_field_names[i]);
pid_t parsed_pid;
r = parse_pid(context->meta[META_ARGV_PID], &parsed_pid);
@@ -1060,8 +1060,7 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
return log_error_errno(r, "Failed to parse PID \"%s\": %m", context->meta[META_ARGV_PID]);
if (pidref_is_set(&context->pidref)) {
if (context->pidref.pid != parsed_pid)
- return log_error_errno(r, "Passed PID " PID_FMT " does not match passed " PID_FMT ": %m",
- parsed_pid, context->pidref.pid);
+ return log_error_errno(r, "Passed PID " PID_FMT " does not match passed " PID_FMT ": %m", parsed_pid, context->pidref.pid);
} else {
r = pidref_set_pid(&context->pidref, parsed_pid);
if (r < 0)
@@ -1159,8 +1158,7 @@ static int process_socket(int fd) {
* that's permissible for the final two fds. Hence let's be strict on the
* first fd, but lenient on the other two. */
- if (!cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, (socklen_t) -1) && state != STATE_PAYLOAD)
- /* No fds, and already got the first fd → we are done. */
+ if (!cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, (socklen_t) -1) && state != STATE_PAYLOAD) /* no fds, and already got the first fd → we are done */
break;
cmsg_close_all(&mh);
@@ -1352,7 +1350,7 @@ static int gather_pid_metadata_from_argv(
}
/* Cache some of the process metadata we collected so far and that we'll need to
- * access soon. */
+ * access soon */
return context_parse_iovw(context, iovw);
}
@@ -1467,12 +1465,12 @@ static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context *
if (get_process_environ(pid, &t) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_ENVIRON=", t);
- /* Now that we have parsed info from /proc/ ensure the pidfd is still valid before continuing. */
+ /* Now that we have parsed info from /proc/ ensure the pidfd is still valid before continuing */
r = pidref_verify(&context->pidref);
if (r < 0)
return log_error_errno(r, "PIDFD validation failed: %m");
- /* We successfully acquired all metadata. */
+ /* we successfully acquired all metadata */
return context_parse_iovw(context, iovw);
}
@@ -1828,12 +1826,12 @@ static int process_kernel(int argc, char* argv[]) {
log_warning_errno(r, "Failed to access the mount tree of a container, ignoring: %m");
}
- /* If this is PID 1, disable coredump collection, we'll unlikely be able to process
+ /* If this is PID 1 disable coredump collection, we'll unlikely be able to process
* it later on.
*
* FIXME: maybe we should disable coredumps generation from the beginning and
- * re-enable it only when we know it's either safe (i.e. we're not running OOM) or
- * it's not PID 1 ? */
+ * re-enable it only when we know it's either safe (ie we're not running OOM) or
+ * it's not pid1 ? */
if (context.is_pid1) {
log_notice("Due to PID 1 having crashed coredump collection will now be turned off.");
disable_coredumps();

View File

@ -0,0 +1,98 @@
From 463c56040bad633e1c7d8883f8d80d5c017f38b7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 14:15:26 +0100
Subject: [PATCH] pam: minor coding style tweaks
(cherry picked from commit 30de5691744781277f992a25afa268518f3fe711)
Resolves: RHEL-109902
---
src/home/pam_systemd_home.c | 7 ++-----
src/login/pam_systemd.c | 13 ++++++-------
2 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index 624f1ced88..0d28e99ba2 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -115,7 +115,6 @@ static int acquire_user_record(
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get user name: @PAMERR@");
-
if (isempty(username))
return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR, "User name not set.");
}
@@ -535,7 +534,6 @@ static int acquire_home(
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get user name: @PAMERR@");
-
if (isempty(username))
return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR, "User name not set.");
@@ -879,7 +877,6 @@ _public_ PAM_EXTERN int pam_sm_close_session(
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get user name: @PAMERR@");
-
if (isempty(username))
return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR, "User name not set.");
@@ -949,7 +946,7 @@ _public_ PAM_EXTERN int pam_sm_acct_mgmt(
if (r != PAM_SUCCESS)
return r;
- r = acquire_user_record(handle, NULL, debug, &ur, NULL);
+ r = acquire_user_record(handle, /* username= */ NULL, debug, &ur, /* bus_data= */ NULL);
if (r != PAM_SUCCESS)
return r;
@@ -1057,7 +1054,7 @@ _public_ PAM_EXTERN int pam_sm_chauthtok(
pam_debug_syslog(handle, debug, "pam-systemd-homed account management");
- r = acquire_user_record(handle, NULL, debug, &ur, NULL);
+ r = acquire_user_record(handle, /* username= */ NULL, debug, &ur, /* bus_data= */ NULL);
if (r != PAM_SUCCESS)
return r;
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index b3c84a835e..cc51daebc1 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -183,7 +183,6 @@ static int acquire_user_record(
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get user name: @PAMERR@");
-
if (isempty(username))
return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR, "User name not valid.");
@@ -220,7 +219,7 @@ static int acquire_user_record(
_cleanup_free_ char *formatted = NULL;
/* Request the record ourselves */
- r = userdb_by_name(username, 0, &ur);
+ r = userdb_by_name(username, /* flags= */ 0, &ur);
if (r < 0) {
pam_syslog_errno(handle, LOG_ERR, r, "Failed to get user record: %m");
return PAM_USER_UNKNOWN;
@@ -1283,12 +1282,12 @@ _public_ PAM_EXTERN int pam_sm_close_session(
if (parse_argv(handle,
argc, argv,
- NULL,
- NULL,
- NULL,
+ /* class= */ NULL,
+ /* type= */ NULL,
+ /* deskop= */ NULL,
&debug,
- NULL,
- NULL) < 0)
+ /* default_capability_bounding_set */ NULL,
+ /* default_capability_ambient_set= */ NULL) < 0)
return PAM_SESSION_ERR;
pam_debug_syslog(handle, debug, "pam-systemd shutting down");

View File

@ -1,102 +0,0 @@
From 1e9bb0d1a4a8c4fba9bb2f9a4282c4f71a8475b7 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: restore compatibility with older patterns"
This reverts commit 942d050f98cc0b6c89dbe30157163a8610cf7f78.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 23 ++++++++---------------
test/units/TEST-74-AUX-UTILS.coredump.sh | 18 +++++++-----------
2 files changed, 15 insertions(+), 26 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 58bcd4910f..db7f76f6c4 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -105,12 +105,8 @@ enum {
META_ARGV_SIGNAL, /* %s: number of signal causing dump */
META_ARGV_TIMESTAMP, /* %t: time of dump, expressed as seconds since the Epoch (we expand this to μs granularity) */
META_ARGV_RLIMIT, /* %c: core file size soft resource limit */
- _META_ARGV_REQUIRED,
- /* The fields below were added to kernel/core_pattern at later points, so they might be missing. */
- META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */
+ META_ARGV_HOSTNAME, /* %h: hostname */
_META_ARGV_MAX,
- /* If new fields are added, they should be added here, to maintain compatibility
- * with callers which don't know about the new fields. */
/* The following indexes are cached for a couple of special fields we use (and
* thereby need to be retrieved quickly) for naming coredump files, and attaching
@@ -121,7 +117,7 @@ enum {
_META_MANDATORY_MAX,
/* The rest are similar to the previous ones except that we won't fail if one of
- * them is missing in a message sent over the socket. */
+ * them is missing. */
META_EXE = _META_MANDATORY_MAX,
META_UNIT,
@@ -1050,7 +1046,7 @@ static int context_parse_iovw(Context *context, struct iovec_wrapper *iovw) {
}
/* The basic fields from argv[] should always be there, refuse early if not */
- for (int i = 0; i < _META_ARGV_REQUIRED; i++)
+ for (int i = 0; i < _META_ARGV_MAX; i++)
if (!context->meta[i])
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A required (%s) has not been sent, aborting.", meta_field_names[i]);
@@ -1318,17 +1314,14 @@ static int gather_pid_metadata_from_argv(
assert(context);
/* We gather all metadata that were passed via argv[] into an array of iovecs that
- * we'll forward to the socket unit.
- *
- * We require at least _META_ARGV_REQUIRED args, but will accept more.
- * We know how to parse _META_ARGV_MAX args. The rest will be ignored. */
+ * we'll forward to the socket unit */
- if (argc < _META_ARGV_REQUIRED)
+ if (argc < _META_ARGV_MAX)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "Not enough arguments passed by the kernel (%i, expected between %i and %i).",
- argc, _META_ARGV_REQUIRED, _META_ARGV_MAX);
+ "Not enough arguments passed by the kernel (%i, expected %i).",
+ argc, _META_ARGV_MAX);
- for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) {
+ for (int i = 0; i < _META_ARGV_MAX; i++) {
_cleanup_free_ char *buf = NULL;
const char *t = argv[i];
diff --git a/test/units/TEST-74-AUX-UTILS.coredump.sh b/test/units/TEST-74-AUX-UTILS.coredump.sh
index 8173a23162..2c084f54d2 100755
--- a/test/units/TEST-74-AUX-UTILS.coredump.sh
+++ b/test/units/TEST-74-AUX-UTILS.coredump.sh
@@ -194,18 +194,14 @@ rm -f /tmp/core.{output,redirected}
(! "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_BIN" >/dev/null)
# --backtrace mode
-# Pass one of the existing journal coredump records to systemd-coredump.
-# Use our PID as the source to be able to create a PIDFD and to make matching easier.
-# systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT [HOSTNAME]
+# Pass one of the existing journal coredump records to systemd-coredump and
+# use our PID as the source to make matching the coredump later easier
+# systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT HOSTNAME
journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
- /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509900 12345
-journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
- /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509901 12345 mymachine
-# Wait a bit for the coredumps to get processed
-timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -lt 2 ]]; do sleep 1; done"
-coredumpctl info $$
-coredumpctl info COREDUMP_TIMESTAMP=1679509900000000
-coredumpctl info COREDUMP_TIMESTAMP=1679509901000000
+ /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509994 12345 mymachine
+# Wait a bit for the coredump to get processed
+timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -eq 0 ]]; do sleep 1; done"
+coredumpctl info "$$"
coredumpctl info COREDUMP_HOSTNAME="mymachine"
# This used to cause a stack overflow

View File

@ -0,0 +1,196 @@
From 941c60137700e5242834459edb4025d96bd52f3d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Jan 2025 17:53:33 +0100
Subject: [PATCH] user-record: add helper that checks if a provided user name
matches a record
This ensures that user names can be specified either in the regular
short syntax or with a realm appended, and both are accepted. (The
latter of course only if the record actually defines a realm)
(cherry picked from commit 8aacf0fee1a8e9503bc071d5557293b0f3af50a4)
Resolves: RHEL-109902
---
src/home/homed-varlink.c | 4 ++--
src/home/pam_systemd_home.c | 2 +-
src/login/pam_systemd.c | 2 +-
src/shared/group-record.c | 13 +++++++++++++
src/shared/group-record.h | 2 ++
src/shared/user-record.c | 13 +++++++++++++
src/shared/user-record.h | 2 ++
src/shared/userdb-dropin.c | 5 +++--
src/userdb/userwork.c | 4 ++--
9 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/src/home/homed-varlink.c b/src/home/homed-varlink.c
index f6dd27594f..cfd46ea51a 100644
--- a/src/home/homed-varlink.c
+++ b/src/home/homed-varlink.c
@@ -62,7 +62,7 @@ static bool home_user_match_lookup_parameters(LookupParameters *p, Home *h) {
assert(p);
assert(h);
- if (p->user_name && !streq(p->user_name, h->user_name))
+ if (p->user_name && !user_record_matches_user_name(h->record, p->user_name))
return false;
if (uid_is_valid(p->uid) && h->uid != p->uid)
@@ -175,7 +175,7 @@ static bool home_group_match_lookup_parameters(LookupParameters *p, Home *h) {
assert(p);
assert(h);
- if (p->group_name && !streq(h->user_name, p->group_name))
+ if (p->group_name && !user_record_matches_user_name(h->record, p->group_name))
return false;
if (gid_is_valid(p->gid) && h->uid != (uid_t) p->gid)
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index 0d28e99ba2..fb61105295 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -220,7 +220,7 @@ static int acquire_user_record(
return pam_syslog_errno(handle, LOG_ERR, r, "Failed to load user record: %m");
/* Safety check if cached record actually matches what we are looking for */
- if (!streq_ptr(username, ur->user_name))
+ if (!user_record_matches_user_name(ur, username))
return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR,
"Acquired user record does not match user name.");
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index cc51daebc1..008bcb28a0 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -212,7 +212,7 @@ static int acquire_user_record(
return pam_syslog_errno(handle, LOG_ERR, r, "Failed to load user record: %m");
/* Safety check if cached record actually matches what we are looking for */
- if (!streq_ptr(username, ur->user_name))
+ if (!user_record_matches_user_name(ur, username))
return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR,
"Acquired user record does not match user name.");
} else {
diff --git a/src/shared/group-record.c b/src/shared/group-record.c
index 7b401bf064..e4a4eca99c 100644
--- a/src/shared/group-record.c
+++ b/src/shared/group-record.c
@@ -327,6 +327,19 @@ int group_record_clone(GroupRecord *h, UserRecordLoadFlags flags, GroupRecord **
return 0;
}
+bool group_record_matches_group_name(const GroupRecord *g, const char *group_name) {
+ assert(g);
+ assert(group_name);
+
+ if (streq_ptr(g->group_name, group_name))
+ return true;
+
+ if (streq_ptr(g->group_name_and_realm_auto, group_name))
+ return true;
+
+ return false;
+}
+
int group_record_match(GroupRecord *h, const UserDBMatch *match) {
assert(h);
assert(match);
diff --git a/src/shared/group-record.h b/src/shared/group-record.h
index a2cef81c8a..5705fe2511 100644
--- a/src/shared/group-record.h
+++ b/src/shared/group-record.h
@@ -47,3 +47,5 @@ int group_record_match(GroupRecord *h, const UserDBMatch *match);
const char* group_record_group_name_and_realm(GroupRecord *h);
UserDisposition group_record_disposition(GroupRecord *h);
+
+bool group_record_matches_group_name(const GroupRecord *g, const char *groupname);
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
index 4557718023..16631ba0ac 100644
--- a/src/shared/user-record.c
+++ b/src/shared/user-record.c
@@ -2621,6 +2621,19 @@ int user_record_is_nobody(const UserRecord *u) {
return u->uid == UID_NOBODY || STRPTR_IN_SET(u->user_name, NOBODY_USER_NAME, "nobody");
}
+bool user_record_matches_user_name(const UserRecord *u, const char *user_name) {
+ assert(u);
+ assert(user_name);
+
+ if (streq_ptr(u->user_name, user_name))
+ return true;
+
+ if (streq_ptr(u->user_name_and_realm_auto, user_name))
+ return true;
+
+ return false;
+}
+
int suitable_blob_filename(const char *name) {
/* Enforces filename requirements as described in docs/USER_RECORD_BULK_DIRS.md */
return filename_is_valid(name) &&
diff --git a/src/shared/user-record.h b/src/shared/user-record.h
index b539b3f55e..b762867c08 100644
--- a/src/shared/user-record.h
+++ b/src/shared/user-record.h
@@ -489,6 +489,8 @@ typedef struct UserDBMatch {
bool user_name_fuzzy_match(const char *names[], size_t n_names, char **matches);
int user_record_match(UserRecord *u, const UserDBMatch *match);
+bool user_record_matches_user_name(const UserRecord *u, const char *username);
+
const char* user_storage_to_string(UserStorage t) _const_;
UserStorage user_storage_from_string(const char *s) _pure_;
diff --git a/src/shared/userdb-dropin.c b/src/shared/userdb-dropin.c
index 9f027d7783..81fd5f3ebc 100644
--- a/src/shared/userdb-dropin.c
+++ b/src/shared/userdb-dropin.c
@@ -4,6 +4,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
+#include "group-record.h"
#include "path-util.h"
#include "stdio-util.h"
#include "user-util.h"
@@ -87,7 +88,7 @@ static int load_user(
if (r < 0)
return r;
- if (name && !streq_ptr(name, u->user_name))
+ if (name && !user_record_matches_user_name(u, name))
return -EINVAL;
if (uid_is_valid(uid) && uid != u->uid)
@@ -231,7 +232,7 @@ static int load_group(
if (r < 0)
return r;
- if (name && !streq_ptr(name, g->group_name))
+ if (name && !group_record_matches_group_name(g, name))
return -EINVAL;
if (gid_is_valid(gid) && gid != g->gid)
diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c
index 1e36face40..dce60e2ebd 100644
--- a/src/userdb/userwork.c
+++ b/src/userdb/userwork.c
@@ -215,7 +215,7 @@ static int vl_method_get_user_record(sd_varlink *link, sd_json_variant *paramete
}
if ((uid_is_valid(p.uid) && hr->uid != p.uid) ||
- (p.user_name && !streq(hr->user_name, p.user_name)))
+ (p.user_name && !user_record_matches_user_name(hr, p.user_name)))
return sd_varlink_error(link, "io.systemd.UserDatabase.ConflictingRecordFound", NULL);
r = build_user_json(link, hr, &v);
@@ -345,7 +345,7 @@ static int vl_method_get_group_record(sd_varlink *link, sd_json_variant *paramet
}
if ((uid_is_valid(p.gid) && g->gid != p.gid) ||
- (p.group_name && !streq(g->group_name, p.group_name)))
+ (p.group_name && !group_record_matches_group_name(g, p.group_name)))
return sd_varlink_error(link, "io.systemd.UserDatabase.ConflictingRecordFound", NULL);
r = build_group_json(link, g, &v);

View File

@ -1,29 +0,0 @@
From 38b2ad72c1926c45790e678ce8c6207b3a93b2e5 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 13 Jan 2026 17:45:45 +0100
Subject: [PATCH] Revert "coredump: verify pidfd after parsing data in usermode
helper"
This reverts commit ae1394abcded51ed5e443d1124059b2e31748baa.
Reverts: RHEL-104135
---
src/coredump/coredump.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index db7f76f6c4..d3a1f7c09d 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1458,11 +1458,6 @@ static int gather_pid_metadata_from_procfs(struct iovec_wrapper *iovw, Context *
if (get_process_environ(pid, &t) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_ENVIRON=", t);
- /* Now that we have parsed info from /proc/ ensure the pidfd is still valid before continuing */
- r = pidref_verify(&context->pidref);
- if (r < 0)
- return log_error_errno(r, "PIDFD validation failed: %m");
-
/* we successfully acquired all metadata */
return context_parse_iovw(context, iovw);
}

View File

@ -0,0 +1,110 @@
From 33c12c3976fa14bf25ca62d8aea3bbc0a11f356f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 14:15:52 +0100
Subject: [PATCH] user-record: add support for alias user names to user record
(cherry picked from commit e2e1f38f5a9d442d0a027986024f4ea75ce97d2f)
Resolves: RHEL-109902
---
docs/USER_RECORD.md | 8 ++++++++
src/shared/user-record-show.c | 7 +++++++
src/shared/user-record.c | 14 +++++++++++++-
src/shared/user-record.h | 1 +
4 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md
index 911fceb03f..5babc70f65 100644
--- a/docs/USER_RECORD.md
+++ b/docs/USER_RECORD.md
@@ -226,6 +226,14 @@ This field is optional, when unset the user should not be considered part of any
A user record with a realm set is never compatible (for the purpose of updates,
see above) with a user record without one set, even if the `userName` field matches.
+`aliases` → An array of strings, each being a valid UNIX user name. If
+specified, a list of additional UNIX user names this record shall be known
+under. These are *alias* names only, the name in `userName` is always the
+primary name. Typically, a user record that carries this field shall be
+retrievable and resolvable under every name listed here, pretty much everywhere
+the primary user name is. If logging in is attempted via an alias name it
+should be normalized to the primary name.
+
`blobDirectory` → The absolute path to a world-readable copy of the user's blob
directory. See [Blob Directories](/USER_RECORD_BLOB_DIRS) for more details.
diff --git a/src/shared/user-record-show.c b/src/shared/user-record-show.c
index 4d8ffe1c35..f47da4b4c7 100644
--- a/src/shared/user-record-show.c
+++ b/src/shared/user-record-show.c
@@ -65,6 +65,13 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
printf(" User name: %s\n",
user_record_user_name_and_realm(hr));
+ if (!strv_isempty(hr->aliases)) {
+ STRV_FOREACH(i, hr->aliases)
+ printf(i == hr->aliases ?
+ " Alias: %s" : ", %s", *i);
+ putchar('\n');
+ }
+
if (hr->state) {
const char *color;
diff --git a/src/shared/user-record.c b/src/shared/user-record.c
index 16631ba0ac..8617c70aef 100644
--- a/src/shared/user-record.c
+++ b/src/shared/user-record.c
@@ -139,6 +139,7 @@ static UserRecord* user_record_free(UserRecord *h) {
free(h->user_name);
free(h->realm);
free(h->user_name_and_realm_auto);
+ strv_free(h->aliases);
free(h->real_name);
free(h->email_address);
erase_and_free(h->password_hint);
@@ -1537,6 +1538,7 @@ int user_record_load(UserRecord *h, sd_json_variant *v, UserRecordLoadFlags load
static const sd_json_dispatch_field user_dispatch_table[] = {
{ "userName", SD_JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(UserRecord, user_name), SD_JSON_RELAX },
+ { "aliases", SD_JSON_VARIANT_ARRAY, json_dispatch_user_group_list, offsetof(UserRecord, aliases), SD_JSON_RELAX },
{ "realm", SD_JSON_VARIANT_STRING, json_dispatch_realm, offsetof(UserRecord, realm), 0 },
{ "blobDirectory", SD_JSON_VARIANT_STRING, json_dispatch_path, offsetof(UserRecord, blob_directory), SD_JSON_STRICT },
{ "blobManifest", SD_JSON_VARIANT_OBJECT, dispatch_blob_manifest, offsetof(UserRecord, blob_manifest), 0 },
@@ -2631,6 +2633,15 @@ bool user_record_matches_user_name(const UserRecord *u, const char *user_name) {
if (streq_ptr(u->user_name_and_realm_auto, user_name))
return true;
+ if (strv_contains(u->aliases, user_name))
+ return true;
+
+ const char *realm = strrchr(user_name, '@');
+ if (realm && streq_ptr(realm+1, u->realm))
+ STRV_FOREACH(a, u->aliases)
+ if (startswith(user_name, *a) == realm)
+ return true;
+
return false;
}
@@ -2700,7 +2711,8 @@ int user_record_match(UserRecord *u, const UserDBMatch *match) {
u->cifs_user_name,
};
- if (!user_name_fuzzy_match(names, ELEMENTSOF(names), match->fuzzy_names))
+ if (!user_name_fuzzy_match(names, ELEMENTSOF(names), match->fuzzy_names) &&
+ !user_name_fuzzy_match((const char**) u->aliases, strv_length(u->aliases), match->fuzzy_names))
return false;
}
diff --git a/src/shared/user-record.h b/src/shared/user-record.h
index b762867c08..f8c7454f21 100644
--- a/src/shared/user-record.h
+++ b/src/shared/user-record.h
@@ -238,6 +238,7 @@ typedef struct UserRecord {
char *user_name;
char *realm;
char *user_name_and_realm_auto; /* the user_name field concatenated with '@' and the realm, if the latter is defined */
+ char **aliases;
char *real_name;
char *email_address;
char *password_hint;

View File

@ -0,0 +1,25 @@
From bc858640e9cba5b7b1a657ad6ab7469b82dfb556 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 14:14:08 +0100
Subject: [PATCH] pam_systemd_home: use right field name in error message
(cherry picked from commit 1fb53bb561db11e72bb695d578f8e94042565822)
Resolves: RHEL-109902
---
src/home/pam_systemd_home.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index fb61105295..794438129e 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -202,7 +202,7 @@ static int acquire_user_record(
r = pam_set_data(handle, generic_field, json_copy, pam_cleanup_free);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r,
- "Failed to set PAM user record data '%s': @PAMERR@", homed_field);
+ "Failed to set PAM user record data '%s': @PAMERR@", generic_field);
TAKE_PTR(json_copy);
}

View File

@ -0,0 +1,181 @@
From 43398a911607928300c76312215eb03447925220 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 14:15:03 +0100
Subject: [PATCH] pam_systemd_home: support login with alias names + user names
with realms
This in particular makes sure that we normalize the user name and update
it in the PAM session, once we acquire it. This means that if you have a
user with name "a" and alias "b", and the user logs in as "b" they end
up properly with "a" as user name set, as intended by the PAM gods.
Moreover, if you have a user "c" in a ralm "d", they may log in by
specifying "c" or "c@d", with equivalent results.
(cherry picked from commit a642f9d2d37945917bf4200a1095a43e6e7b6ea7)
Resolves: RHEL-109902
---
src/home/pam_systemd_home.c | 70 +++++++++++++++++++++++--------------
src/login/pam_systemd.c | 8 ++---
2 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index 794438129e..95f719d912 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -102,11 +102,6 @@ static int acquire_user_record(
UserRecord **ret_record,
PamBusData **bus_data) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
- _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
- _cleanup_free_ char *homed_field = NULL;
- const char *json = NULL;
int r;
assert(handle);
@@ -124,13 +119,19 @@ static int acquire_user_record(
if (STR_IN_SET(username, "root", NOBODY_USER_NAME) || !valid_user_group_name(username, 0))
return PAM_USER_UNKNOWN;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
+ const char *json = NULL;
+ bool fresh_data;
+
/* We cache the user record in the PAM context. We use a field name that includes the username, since
* clients might change the user name associated with a PAM context underneath us. Notably, 'sudo'
* creates a single PAM context and first authenticates it with the user set to the originating user,
* then updates the user for the destination user and issues the session stack with the same PAM
* context. We thus must be prepared that the user record changes between calls and we keep any
* caching separate. */
- homed_field = strjoin("systemd-home-user-record-", username);
+ _cleanup_free_ char *homed_field = strjoin("systemd-home-user-record-", username);
if (!homed_field)
return pam_log_oom(handle);
@@ -143,9 +144,10 @@ static int acquire_user_record(
* negative cache indicator) */
if (json == POINTER_MAX)
return PAM_USER_UNKNOWN;
+
+ fresh_data = false;
} else {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *generic_field = NULL, *json_copy = NULL;
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
r = pam_acquire_bus_connection(handle, "pam-systemd-home", debug, &bus, bus_data);
@@ -177,9 +179,42 @@ static int acquire_user_record(
if (r < 0)
return pam_bus_log_parse_error(handle, r);
+ fresh_data = true;
+ }
+
+ r = sd_json_parse(json, /* flags= */ 0, &v, NULL, NULL);
+ if (r < 0)
+ return pam_syslog_errno(handle, LOG_ERR, r, "Failed to parse JSON user record: %m");
+
+ ur = user_record_new();
+ if (!ur)
+ return pam_log_oom(handle);
+
+ r = user_record_load(ur, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE);
+ if (r < 0)
+ return pam_syslog_errno(handle, LOG_ERR, r, "Failed to load user record: %m");
+
+ /* Safety check if cached record actually matches what we are looking for */
+ if (!user_record_matches_user_name(ur, username))
+ return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR,
+ "Acquired user record does not match user name.");
+
+ /* Update the 'username' pointer to point to our own record now. The pam_set_item() call below is
+ * going to invalidate the old version after all */
+ username = ur->user_name;
+
+ /* We passed all checks. Let's now make sure the rest of the PAM stack continues with the primary,
+ * normalized name of the user record (i.e. not an alias or so). */
+ r = pam_set_item(handle, PAM_USER, ur->user_name);
+ if (r != PAM_SUCCESS)
+ return pam_syslog_pam_error(handle, LOG_ERR, r,
+ "Failed to update username PAM item to '%s': @PAMERR@", ur->user_name);
+
+ /* Everything seems to be good, let's cache this data now */
+ if (fresh_data) {
/* First copy: for the homed-specific data field, i.e. where we know the user record is from
* homed */
- json_copy = strdup(json);
+ _cleanup_free_ char *json_copy = strdup(json);
if (!json_copy)
return pam_log_oom(handle);
@@ -195,7 +230,7 @@ static int acquire_user_record(
if (!json_copy)
return pam_log_oom(handle);
- generic_field = strjoin("systemd-user-record-", username);
+ _cleanup_free_ char *generic_field = strjoin("systemd-user-record-", username);
if (!generic_field)
return pam_log_oom(handle);
@@ -207,23 +242,6 @@ static int acquire_user_record(
TAKE_PTR(json_copy);
}
- r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE, &v, NULL, NULL);
- if (r < 0)
- return pam_syslog_errno(handle, LOG_ERR, r, "Failed to parse JSON user record: %m");
-
- ur = user_record_new();
- if (!ur)
- return pam_log_oom(handle);
-
- r = user_record_load(ur, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_PERMISSIVE);
- if (r < 0)
- return pam_syslog_errno(handle, LOG_ERR, r, "Failed to load user record: %m");
-
- /* Safety check if cached record actually matches what we are looking for */
- if (!user_record_matches_user_name(ur, username))
- return pam_syslog_pam_error(handle, LOG_ERR, PAM_SERVICE_ERR,
- "Acquired user record does not match user name.");
-
if (ret_record)
*ret_record = TAKE_PTR(ur);
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index 008bcb28a0..ab50137e4e 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -173,13 +173,11 @@ static int acquire_user_record(
pam_handle_t *handle,
UserRecord **ret_record) {
- _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
- const char *username = NULL, *json = NULL;
- _cleanup_free_ char *field = NULL;
int r;
assert(handle);
+ const char *username = NULL;
r = pam_get_user(handle, &username, NULL);
if (r != PAM_SUCCESS)
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get user name: @PAMERR@");
@@ -188,10 +186,12 @@ static int acquire_user_record(
/* If pam_systemd_homed (or some other module) already acquired the user record we can reuse it
* here. */
- field = strjoin("systemd-user-record-", username);
+ _cleanup_free_ char *field = strjoin("systemd-user-record-", username);
if (!field)
return pam_log_oom(handle);
+ _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
+ const char *json = NULL;
r = pam_get_data(handle, field, (const void**) &json);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA))
return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get PAM user record data: @PAMERR@");

View File

@ -0,0 +1,503 @@
From d2d21aa57f8c266002c96ea41e811db28b40eeca Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 14:08:51 +0100
Subject: [PATCH] homed: support user record aliases
(cherry picked from commit 40fd0e0423ed9e4ae47d7f1adba83c0487d7decd)
Resolves: RHEL-109902
---
src/home/homectl.c | 12 +-----
src/home/homed-home-bus.c | 7 +++-
src/home/homed-home.c | 28 ++++++++++++-
src/home/homed-home.h | 5 +++
src/home/homed-manager-bus.c | 76 ++++++++++++++++++++++++++----------
src/home/homed-manager.c | 50 +++++++++++++++++++-----
src/home/homed-manager.h | 2 +
src/home/homed-varlink.c | 28 +++++++------
8 files changed, 154 insertions(+), 54 deletions(-)
diff --git a/src/home/homectl.c b/src/home/homectl.c
index 47ca015813..f48b8dc833 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -741,17 +741,9 @@ static int inspect_home(int argc, char *argv[], void *userdata) {
uid_t uid;
r = parse_uid(*i, &uid);
- if (r < 0) {
- if (!valid_user_group_name(*i, 0)) {
- log_error("Invalid user name '%s'.", *i);
- if (ret == 0)
- ret = -EINVAL;
-
- continue;
- }
-
+ if (r < 0)
r = bus_call_method(bus, bus_mgr, "GetUserRecordByName", &error, &reply, "s", *i);
- } else
+ else
r = bus_call_method(bus, bus_mgr, "GetUserRecordByUID", &error, &reply, "u", (uint32_t) uid);
if (r < 0) {
log_error_errno(r, "Failed to inspect home: %s", bus_error_message(&error, r));
diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c
index 80e2773447..a3e6a32162 100644
--- a/src/home/homed-home-bus.c
+++ b/src/home/homed-home-bus.c
@@ -799,8 +799,11 @@ static int bus_home_object_find(
if (parse_uid(e, &uid) >= 0)
h = hashmap_get(m->homes_by_uid, UID_TO_PTR(uid));
- else
- h = hashmap_get(m->homes_by_name, e);
+ else {
+ r = manager_get_home_by_name(m, e, &h);
+ if (r < 0)
+ return r;
+ }
if (!h)
return 0;
diff --git a/src/home/homed-home.c b/src/home/homed-home.c
index 32691e4f81..44e3274c42 100644
--- a/src/home/homed-home.c
+++ b/src/home/homed-home.c
@@ -106,6 +106,7 @@ static int suitable_home_record(UserRecord *hr) {
int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
_cleanup_(home_freep) Home *home = NULL;
_cleanup_free_ char *nm = NULL, *ns = NULL, *blob = NULL;
+ _cleanup_strv_free_ char **aliases = NULL;
int r;
assert(m);
@@ -118,19 +119,29 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
if (hashmap_contains(m->homes_by_name, hr->user_name))
return -EBUSY;
+ STRV_FOREACH(a, hr->aliases)
+ if (hashmap_contains(m->homes_by_name, *a))
+ return -EBUSY;
+
if (hashmap_contains(m->homes_by_uid, UID_TO_PTR(hr->uid)))
return -EBUSY;
if (sysfs && hashmap_contains(m->homes_by_sysfs, sysfs))
return -EBUSY;
- if (hashmap_size(m->homes_by_name) >= HOME_USERS_MAX)
+ if (hashmap_size(m->homes_by_uid) >= HOME_USERS_MAX)
return -EUSERS;
nm = strdup(hr->user_name);
if (!nm)
return -ENOMEM;
+ if (!strv_isempty(hr->aliases)) {
+ aliases = strv_copy(hr->aliases);
+ if (!aliases)
+ return -ENOMEM;
+ }
+
if (sysfs) {
ns = strdup(sysfs);
if (!ns)
@@ -144,6 +155,7 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
*home = (Home) {
.manager = m,
.user_name = TAKE_PTR(nm),
+ .aliases = TAKE_PTR(aliases),
.uid = hr->uid,
.state = _HOME_STATE_INVALID,
.worker_stdout_fd = -EBADF,
@@ -157,6 +169,12 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
if (r < 0)
return r;
+ STRV_FOREACH(a, home->aliases) {
+ r = hashmap_put(m->homes_by_name, *a, home);
+ if (r < 0)
+ return r;
+ }
+
r = hashmap_put(m->homes_by_uid, UID_TO_PTR(home->uid), home);
if (r < 0)
return r;
@@ -202,6 +220,9 @@ Home *home_free(Home *h) {
if (h->user_name)
(void) hashmap_remove_value(h->manager->homes_by_name, h->user_name, h);
+ STRV_FOREACH(a, h->aliases)
+ (void) hashmap_remove_value(h->manager->homes_by_name, *a, h);
+
if (uid_is_valid(h->uid))
(void) hashmap_remove_value(h->manager->homes_by_uid, UID_TO_PTR(h->uid), h);
@@ -223,6 +244,7 @@ Home *home_free(Home *h) {
h->worker_event_source = sd_event_source_disable_unref(h->worker_event_source);
safe_close(h->worker_stdout_fd);
free(h->user_name);
+ strv_free(h->aliases);
free(h->sysfs);
h->ref_event_source_please_suspend = sd_event_source_disable_unref(h->ref_event_source_please_suspend);
@@ -262,6 +284,10 @@ int home_set_record(Home *h, UserRecord *hr) {
if (!user_record_compatible(h->record, hr))
return -EREMCHG;
+ /* For now do not allow changing list of aliases */
+ if (!strv_equal_ignore_order(h->aliases, hr->aliases))
+ return -EREMCHG;
+
if (!FLAGS_SET(hr->mask, USER_RECORD_REGULAR) ||
FLAGS_SET(hr->mask, USER_RECORD_SECRET))
return -EINVAL;
diff --git a/src/home/homed-home.h b/src/home/homed-home.h
index 8c92e39fe5..93689563d3 100644
--- a/src/home/homed-home.h
+++ b/src/home/homed-home.h
@@ -109,7 +109,12 @@ static inline bool HOME_STATE_MAY_RETRY_DEACTIVATE(HomeState state) {
struct Home {
Manager *manager;
+
+ /* The fields this record can be looked up by. This is kinda redundant, as the same information is
+ * available in the .record field, but we keep separate copies of these keys to make memory
+ * management for the hashmaps easier. */
char *user_name;
+ char **aliases;
uid_t uid;
char *sysfs; /* When found via plugged in device, the sysfs path to it */
diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c
index 08c917aee2..a08cc3803c 100644
--- a/src/home/homed-manager-bus.c
+++ b/src/home/homed-manager-bus.c
@@ -37,7 +37,7 @@ static int property_get_auto_login(
if (r < 0)
return r;
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
_cleanup_strv_free_ char **seats = NULL;
_cleanup_free_ char *home_path = NULL;
@@ -97,11 +97,9 @@ static int lookup_user_name(
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_HOME, "Client's UID " UID_FMT " not managed.", uid);
} else {
-
- if (!valid_user_group_name(user_name, 0))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name %s is not valid", user_name);
-
- h = hashmap_get(m->homes_by_name, user_name);
+ r = manager_get_home_by_name(m, user_name, &h);
+ if (r < 0)
+ return r;
if (!h)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_HOME, "No home for user %s known", user_name);
}
@@ -342,6 +340,31 @@ static int method_deactivate_home(sd_bus_message *message, void *userdata, sd_bu
return generic_home_method(userdata, message, bus_home_method_deactivate, error);
}
+static int check_for_conflicts(Manager *m, const char *name, sd_bus_error *error) {
+ int r;
+
+ assert(m);
+ assert(name);
+
+ Home *other = hashmap_get(m->homes_by_name, name);
+ if (other)
+ return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists already, refusing.", name);
+
+ r = getpwnam_malloc(name, /* ret= */ NULL);
+ if (r >= 0)
+ return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists in the NSS user database, refusing.", name);
+ if (r != -ESRCH)
+ return r;
+
+ r = getgrnam_malloc(name, /* ret= */ NULL);
+ if (r >= 0)
+ return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s conflicts with an NSS group by the same name, refusing.", name);
+ if (r != -ESRCH)
+ return r;
+
+ return 0;
+}
+
static int validate_and_allocate_home(Manager *m, UserRecord *hr, Hashmap *blobs, Home **ret, sd_bus_error *error) {
_cleanup_(user_record_unrefp) UserRecord *signed_hr = NULL;
bool signed_locally;
@@ -356,21 +379,32 @@ static int validate_and_allocate_home(Manager *m, UserRecord *hr, Hashmap *blobs
if (r < 0)
return r;
- other = hashmap_get(m->homes_by_name, hr->user_name);
- if (other)
- return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists already, refusing.", hr->user_name);
-
- r = getpwnam_malloc(hr->user_name, /* ret= */ NULL);
- if (r >= 0)
- return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s exists in the NSS user database, refusing.", hr->user_name);
- if (r != -ESRCH)
+ r = check_for_conflicts(m, hr->user_name, error);
+ if (r < 0)
return r;
- r = getgrnam_malloc(hr->user_name, /* ret= */ NULL);
- if (r >= 0)
- return sd_bus_error_setf(error, BUS_ERROR_USER_NAME_EXISTS, "Specified user name %s conflicts with an NSS group by the same name, refusing.", hr->user_name);
- if (r != -ESRCH)
- return r;
+ if (hr->realm) {
+ r = check_for_conflicts(m, user_record_user_name_and_realm(hr), error);
+ if (r < 0)
+ return r;
+ }
+
+ STRV_FOREACH(a, hr->aliases) {
+ r = check_for_conflicts(m, *a, error);
+ if (r < 0)
+ return r;
+
+ if (hr->realm) {
+ _cleanup_free_ char *alias_with_realm = NULL;
+ alias_with_realm = strjoin(*a, "@", hr->realm);
+ if (!alias_with_realm)
+ return -ENOMEM;
+
+ r = check_for_conflicts(m, alias_with_realm, error);
+ if (r < 0)
+ return r;
+ }
+ }
if (blobs) {
const char *failed = NULL;
@@ -637,7 +671,7 @@ static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus
* for every suitable home we have and only when all of them completed we send a reply indicating
* completion. */
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!home_shall_suspend(h))
continue;
@@ -676,7 +710,7 @@ static int method_deactivate_all_homes(sd_bus_message *message, void *userdata,
* systemd-homed.service itself since we want to allow restarting of it without tearing down all home
* directories. */
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!o) {
o = operation_new(OPERATION_DEACTIVATE_ALL, message);
diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c
index de7c3d8dbe..6b9e4fcf11 100644
--- a/src/home/homed-manager.c
+++ b/src/home/homed-manager.c
@@ -75,7 +75,6 @@ static bool uid_is_home(uid_t uid) {
#define UID_CLAMP_INTO_HOME_RANGE(rnd) (((uid_t) (rnd) % (HOME_UID_MAX - HOME_UID_MIN + 1)) + HOME_UID_MIN)
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_uid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_name_hash_ops, char, string_hash_func, string_compare_func, Home, home_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_worker_pid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_sysfs_hash_ops, char, path_hash_func, path_compare, Home, home_free);
@@ -191,7 +190,7 @@ static int on_home_inotify(sd_event_source *s, const struct inotify_event *event
log_debug("%s has been moved away, revalidating.", j);
h = hashmap_get(m->homes_by_name, n);
- if (h) {
+ if (h && streq(h->user_name, n)) {
manager_revalidate_image(m, h);
(void) bus_manager_emit_auto_login_changed(m);
}
@@ -242,7 +241,7 @@ int manager_new(Manager **ret) {
if (!m->homes_by_uid)
return -ENOMEM;
- m->homes_by_name = hashmap_new(&homes_by_name_hash_ops);
+ m->homes_by_name = hashmap_new(&string_hash_ops);
if (!m->homes_by_name)
return -ENOMEM;
@@ -697,6 +696,11 @@ static int manager_add_home_by_image(
if (h) {
bool same;
+ if (!streq(h->user_name, user_name)) {
+ log_debug("Found an image for user %s which already is an alias for another user, skipping.", user_name);
+ return 0; /* Ignore images that would synthesize a user that conflicts with an alias of another user */
+ }
+
if (h->state != HOME_UNFIXATED) {
log_debug("Found an image for user %s which already has a record, skipping.", user_name);
return 0; /* ignore images that synthesize a user we already have a record for */
@@ -1714,7 +1718,7 @@ int manager_gc_images(Manager *m) {
} else {
/* Gc all */
- HASHMAP_FOREACH(h, m->homes_by_name)
+ HASHMAP_FOREACH(h, m->homes_by_uid)
manager_revalidate_image(m, h);
}
@@ -1734,12 +1738,14 @@ static int manager_gc_blob(Manager *m) {
return log_error_errno(errno, "Failed to open %s: %m", home_system_blob_dir());
}
- FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read system blob directory: %m"))
- if (!hashmap_contains(m->homes_by_name, de->d_name)) {
+ FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read system blob directory: %m")) {
+ Home *found = hashmap_get(m->homes_by_name, de->d_name);
+ if (!found || !streq(found->user_name, de->d_name)) {
r = rm_rf_at(dirfd(d), de->d_name, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
if (r < 0)
log_warning_errno(r, "Failed to delete blob dir for missing user '%s', ignoring: %m", de->d_name);
}
+ }
return 0;
}
@@ -1834,7 +1840,7 @@ static bool manager_shall_rebalance(Manager *m) {
if (IN_SET(m->rebalance_state, REBALANCE_PENDING, REBALANCE_SHRINKING, REBALANCE_GROWING))
return true;
- HASHMAP_FOREACH(h, m->homes_by_name)
+ HASHMAP_FOREACH(h, m->homes_by_uid)
if (home_shall_rebalance(h))
return true;
@@ -1880,7 +1886,7 @@ static int manager_rebalance_calculate(Manager *m) {
* (home dirs get 100 by default, i.e. 5x more). This weight
* is not configurable, the per-home weights are. */
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
statfs_f_type_t fstype;
h->rebalance_pending = false; /* First, reset the flag, we only want it to be true for the
* homes that qualify for rebalancing */
@@ -2017,7 +2023,7 @@ static int manager_rebalance_apply(Manager *m) {
assert(m);
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (!h->rebalance_pending)
@@ -2258,3 +2264,29 @@ int manager_reschedule_rebalance(Manager *m) {
return 1;
}
+
+int manager_get_home_by_name(Manager *m, const char *user_name, Home **ret) {
+ assert(m);
+ assert(user_name);
+
+ Home *h = hashmap_get(m->homes_by_name, user_name);
+ if (!h) {
+ /* Also search by username and realm. For that simply chop off realm, then look for the home, and verify it afterwards. */
+ const char *realm = strrchr(user_name, '@');
+ if (realm) {
+ _cleanup_free_ char *prefix = strndup(user_name, realm - user_name);
+ if (!prefix)
+ return -ENOMEM;
+
+ Home *j;
+ j = hashmap_get(m->homes_by_name, prefix);
+ if (j && user_record_matches_user_name(j->record, user_name))
+ h = j;
+ }
+ }
+
+ if (ret)
+ *ret = h;
+
+ return !!h;
+}
diff --git a/src/home/homed-manager.h b/src/home/homed-manager.h
index 3369284e2a..7f9a8a8199 100644
--- a/src/home/homed-manager.h
+++ b/src/home/homed-manager.h
@@ -91,3 +91,5 @@ int manager_acquire_key_pair(Manager *m);
int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus_error *error);
int bus_manager_emit_auto_login_changed(Manager *m);
+
+int manager_get_home_by_name(Manager *m, const char *user_name, Home **ret);
diff --git a/src/home/homed-varlink.c b/src/home/homed-varlink.c
index cfd46ea51a..ef30ea7eaf 100644
--- a/src/home/homed-varlink.c
+++ b/src/home/homed-varlink.c
@@ -100,15 +100,17 @@ int vl_method_get_user_record(sd_varlink *link, sd_json_variant *parameters, sd_
if (uid_is_valid(p.uid))
h = hashmap_get(m->homes_by_uid, UID_TO_PTR(p.uid));
- else if (p.user_name)
- h = hashmap_get(m->homes_by_name, p.user_name);
- else {
+ else if (p.user_name) {
+ r = manager_get_home_by_name(m, p.user_name, &h);
+ if (r < 0)
+ return r;
+ } else {
/* If neither UID nor name was specified, then dump all homes. Do so with varlink_notify()
* for all entries but the last, so that clients can stream the results, and easily process
* them piecemeal. */
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!home_user_match_lookup_parameters(&p, h))
continue;
@@ -212,11 +214,13 @@ int vl_method_get_group_record(sd_varlink *link, sd_json_variant *parameters, sd
if (gid_is_valid(p.gid))
h = hashmap_get(m->homes_by_uid, UID_TO_PTR((uid_t) p.gid));
- else if (p.group_name)
- h = hashmap_get(m->homes_by_name, p.group_name);
- else {
+ else if (p.group_name) {
+ r = manager_get_home_by_name(m, p.group_name, &h);
+ if (r < 0)
+ return r;
+ } else {
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!home_group_match_lookup_parameters(&p, h))
continue;
@@ -279,7 +283,9 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
if (p.user_name) {
const char *last = NULL;
- h = hashmap_get(m->homes_by_name, p.user_name);
+ r = manager_get_home_by_name(m, p.user_name, &h);
+ if (r < 0)
+ return r;
if (!h)
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
@@ -315,7 +321,7 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
} else if (p.group_name) {
const char *last = NULL;
- HASHMAP_FOREACH(h, m->homes_by_name) {
+ HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!strv_contains(h->record->member_of, p.group_name))
continue;
@@ -340,7 +346,7 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
} else {
const char *last_user_name = NULL, *last_group_name = NULL;
- HASHMAP_FOREACH(h, m->homes_by_name)
+ HASHMAP_FOREACH(h, m->homes_by_uid)
STRV_FOREACH(j, h->record->member_of) {
if (last_user_name) {

View File

@ -0,0 +1,116 @@
From 5540ae46fe0f113b4145b49de7dd556d84c98dc7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 14:01:15 +0100
Subject: [PATCH] homectl: add support for creating users with alias names
(cherry picked from commit 5cd7b455e0b2ee5991ff06a885c8bc4fe78c2225)
Resolves: RHEL-109902
---
man/homectl.xml | 10 ++++++++++
src/home/homectl.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+)
diff --git a/man/homectl.xml b/man/homectl.xml
index 927fe939ee..282066c4fa 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -226,6 +226,16 @@
<xi:include href="version-info.xml" xpointer="v245"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--alias=<replaceable>NAME</replaceable><optional>,<replaceable>NAME…</replaceable></optional></option></term>
+
+ <listitem><para>Additional names for the user. Takes one or more valid UNIX user names, separated by
+ commas. May be used multiple times to define multiple aliases. An alias username may be specified
+ wherever the primary user name may be specified, and resolves to the same user record.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--email-address=<replaceable>EMAIL</replaceable></option></term>
diff --git a/src/home/homectl.c b/src/home/homectl.c
index f48b8dc833..08136cda3f 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -2746,6 +2746,7 @@ static int help(int argc, char *argv[], void *userdata) {
"\n%4$sGeneral User Record Properties:%5$s\n"
" -c --real-name=REALNAME Real name for user\n"
" --realm=REALM Realm to create user in\n"
+ " --alias=ALIAS Define alias usernames for this account\n"
" --email-address=EMAIL Email address for user\n"
" --location=LOCATION Set location of user on earth\n"
" --icon-name=NAME Icon name for user\n"
@@ -2890,6 +2891,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_ASK_PASSWORD,
ARG_OFFLINE,
ARG_REALM,
+ ARG_ALIAS,
ARG_EMAIL_ADDRESS,
ARG_DISK_SIZE,
ARG_ACCESS_MODE,
@@ -2981,6 +2983,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "real-name", required_argument, NULL, 'c' },
{ "comment", required_argument, NULL, 'c' }, /* Compat alias to keep thing in sync with useradd(8) */
{ "realm", required_argument, NULL, ARG_REALM },
+ { "alias", required_argument, NULL, ARG_ALIAS },
{ "email-address", required_argument, NULL, ARG_EMAIL_ADDRESS },
{ "location", required_argument, NULL, ARG_LOCATION },
{ "password-hint", required_argument, NULL, ARG_PASSWORD_HINT },
@@ -3136,6 +3139,53 @@ static int parse_argv(int argc, char *argv[]) {
break;
+ case ARG_ALIAS: {
+ if (isempty(optarg)) {
+ r = drop_from_identity("aliases");
+ if (r < 0)
+ return r;
+ break;
+ }
+
+ for (const char *p = optarg;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, ",", 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse alias list: %m");
+ if (r == 0)
+ break;
+
+ if (!valid_user_group_name(word, 0))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid alias user name %s.", word);
+
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *av =
+ sd_json_variant_ref(sd_json_variant_by_key(arg_identity_extra, "aliases"));
+
+ _cleanup_strv_free_ char **list = NULL;
+ r = sd_json_variant_strv(av, &list);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse group list: %m");
+
+ r = strv_extend(&list, word);
+ if (r < 0)
+ return log_oom();
+
+ strv_sort_uniq(list);
+
+ av = sd_json_variant_unref(av);
+ r = sd_json_variant_new_array_strv(&av, list);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create alias list JSON: %m");
+
+ r = sd_json_variant_set_field(&arg_identity_extra, "aliases", av);
+ if (r < 0)
+ return log_error_errno(r, "Failed to update alias list: %m");
+ }
+
+ break;
+ }
+
case 'd': {
_cleanup_free_ char *hd = NULL;

View File

@ -1,40 +0,0 @@
From 9c2aea3a3811a194bb3b9710cf521b68c5809b82 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Tue, 13 Jan 2026 18:26:48 +0100
Subject: [PATCH] ci: pin Packit/mkosi to the latest RHEL 10.1 commit
rhel-only: ci
Related: RHEL-155394
---
.packit.yml | 3 ++-
mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.packit.yml b/.packit.yml
index a5d9aca0e1..0c2b256102 100644
--- a/.packit.yml
+++ b/.packit.yml
@@ -24,7 +24,8 @@ actions:
post-upstream-clone:
# Use the CentOS Stream 10 specfile
- - "git clone -b c10s https://gitlab.com/redhat/centos-stream/rpms/systemd.git .packit_rpm --depth=1"
+ # Pin this to the latest 10.1 version (systemd-257-13)
+ - "git clone https://gitlab.com/redhat/centos-stream/rpms/systemd.git .packit_rpm --depth=1 --revision=8adcfa40b029b11bb2512c8cc7e6301ee3a77df9"
# Drop the "sources" file so rebase-helper doesn't think we're a dist-git
- "rm -fv .packit_rpm/sources"
# Drop all patches, since they're already included in the tarball
diff --git a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf
index 31f03ca120..ea922ec18c 100644
--- a/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf
+++ b/mkosi.images/build/mkosi.conf.d/centos-fedora/mkosi.conf
@@ -8,7 +8,8 @@ Distribution=|fedora
Environment=
GIT_URL=https://gitlab.com/redhat/centos-stream/rpms/systemd/
GIT_BRANCH=c10s
- GIT_COMMIT=c10s
+ # Pin this to the latest 10.1 version (systemd-257-13)
+ GIT_COMMIT=8adcfa40b029b11bb2512c8cc7e6301ee3a77df9
PKG_SUBDIR=fedora
[Content]

View File

@ -0,0 +1,46 @@
From 7938e4205fbd9e35375aa4469cd133251a6dcaa5 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 15:18:45 +0100
Subject: [PATCH] test: add test for homed alias and realm user resolution
(cherry picked from commit 853e9b754a16c58f9fb147376af941ec679e65a6)
Resolves: RHEL-109902
---
test/units/TEST-46-HOMED.sh | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/test/units/TEST-46-HOMED.sh b/test/units/TEST-46-HOMED.sh
index e858b0c297..8de170a1c9 100755
--- a/test/units/TEST-46-HOMED.sh
+++ b/test/units/TEST-46-HOMED.sh
@@ -629,6 +629,29 @@ EOF
wait_for_state homedsshtest inactive
fi
+NEWPASSWORD=hunter4711 homectl create aliastest --storage=directory --alias=aliastest2 --alias=aliastest3 --realm=myrealm
+
+homectl inspect aliastest
+homectl inspect aliastest2
+homectl inspect aliastest3
+homectl inspect aliastest@myrealm
+homectl inspect aliastest2@myrealm
+homectl inspect aliastest3@myrealm
+
+userdbctl user aliastest
+userdbctl user aliastest2
+userdbctl user aliastest3
+userdbctl user aliastest@myrealm
+userdbctl user aliastest2@myrealm
+userdbctl user aliastest3@myrealm
+
+getent passwd aliastest
+getent passwd aliastest2
+getent passwd aliastest3
+getent passwd aliastest@myrealm
+getent passwd aliastest2@myrealm
+getent passwd aliastest3@myrealm
+
systemd-analyze log-level info
touch /testok

41
0468-update-TODO.patch Normal file
View File

@ -0,0 +1,41 @@
From 536eac23913704e258ee8052cd45c0273804b8f9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 16 Jan 2025 13:58:14 +0100
Subject: [PATCH] update TODO
(cherry picked from commit 3d3f27cd9a9d7ba325f0d6acc8526c86b938f09c)
Resolves: RHEL-109902
---
TODO | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/TODO b/TODO
index 99e8f1c723..a20eb2c61e 100644
--- a/TODO
+++ b/TODO
@@ -227,12 +227,6 @@ Features:
suffix the escape sequence with one more decimal digit, because compilers
think you might actually specify a value outside the 8bit range with that.
-* homed: allow login via username + realm on getty/login prompt. Then rewrite
- the user name in the PAM stack
-
-* homed/userdb: add "aliases" field to user record, which can alternatively be
- used for logging in. Rewrite user name in the PAM stack once acquired.
-
* confext/sysext: instead of mounting the overlayfs directly on /etc/ + /usr/,
insert an intermediary bind mount on itself there. This has the benefit that
services where mount propagation from the root fs is off, an still have
@@ -354,11 +348,6 @@ Features:
* Clean up "reboot argument" handling, i.e. set it through some IPC service
instead of directly via /run/, so that it can be sensible set remotely.
-* userdb: add concept for user "aliases", to cover for cases where you can log
- in under the name lennart@somenetworkfsserver, and it would automatically
- generate a local user, and from the one both names can be used to allow
- logins into the same account.
-
* systemd-tpm2-support: add a some logic that detects if system is in DA
lockout mode, and queries the user for TPM recovery PIN then.

View File

@ -0,0 +1,30 @@
From dbe632700253fb0622309a548403cbd097d5c9d5 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue, 14 Oct 2025 11:03:01 +0200
Subject: [PATCH] udev: create symlinks for s390 PTP devices
Similarly to the udev rules handling KVM and Hyper-V PTP devices, create
symlinks for the s390-specific STCKE and Physical clocks (supported
since Linux 6.13) to have some stable names that can be specified in
default configurations of PTP/NTP applications.
(cherry picked from commit 4db925d7da880001b31415354307604dcbe3a4e6)
Resolves: RHEL-120177
---
rules.d/50-udev-default.rules.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in
index 8fa518cd8f..08b2de7047 100644
--- a/rules.d/50-udev-default.rules.in
+++ b/rules.d/50-udev-default.rules.in
@@ -32,6 +32,8 @@ SUBSYSTEM=="net", IMPORT{builtin}="net_driver"
SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK+="ptp_kvm"
SUBSYSTEM=="ptp", ATTR{clock_name}=="hyperv", SYMLINK+="ptp_hyperv"
+SUBSYSTEM=="ptp", ATTR{clock_name}=="s390 Physical Clock", SYMLINK+="ptp_s390_physical"
+SUBSYSTEM=="ptp", ATTR{clock_name}=="s390 STCKE Clock", SYMLINK+="ptp_s390_stcke"
ACTION!="add", GOTO="default_end"

View File

@ -0,0 +1,180 @@
From 46dccb96f595bcaa26db228b4ed5dc7dd553990e Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 9 Oct 2025 23:08:19 +0200
Subject: [PATCH] test: build the crashing test binary outside of the test
So we don't have to pull in gcc and other stuff into it.
Also, make the test itself a bit more robust and debug-able.
(cherry picked from commit 937f609b41b9e27eba69c5ddbab4df2232e5a37b)
Related: RHEL-113920
---
src/test/meson.build | 11 ++++
src/test/test-coredump-stacktrace.c | 29 +++++++++
test/units/TEST-87-AUX-UTILS-VM.coredump.sh | 72 +++++++++++++++------
3 files changed, 93 insertions(+), 19 deletions(-)
create mode 100644 src/test/test-coredump-stacktrace.c
diff --git a/src/test/meson.build b/src/test/meson.build
index 9dae4996f4..d8135c226c 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -261,6 +261,17 @@ executables += [
'sources' : files('test-compress.c'),
'link_with' : [libshared],
},
+ test_template + {
+ 'sources' : files('test-coredump-stacktrace.c'),
+ 'type' : 'manual',
+ # This test intentionally crashes with SIGSEGV by dereferencing a NULL pointer
+ # to generate a coredump with a predictable stack trace. To prevent sanitizers
+ # from catching the error first let's disable them explicitly, and also always
+ # build with minimal optimizations to make the stack trace predictable no matter
+ # what we build the rest of systemd with
+ 'override_options' : ['b_sanitize=none', 'strip=false', 'debug=true'],
+ 'c_args' : ['-fno-sanitize=all', '-fno-optimize-sibling-calls', '-O1'],
+ },
test_template + {
'sources' : files('test-cryptolib.c'),
'dependencies' : lib_openssl_or_gcrypt,
diff --git a/src/test/test-coredump-stacktrace.c b/src/test/test-coredump-stacktrace.c
new file mode 100644
index 0000000000..334a155a9c
--- /dev/null
+++ b/src/test/test-coredump-stacktrace.c
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* This is a test program that intentionally segfaults so we can generate a
+ * predictable-ish stack trace in tests. */
+
+#include <stdlib.h>
+
+__attribute__((noinline))
+static void baz(int *x) {
+ *x = rand();
+}
+
+__attribute__((noinline))
+static void bar(void) {
+ int * volatile x = NULL;
+
+ baz(x);
+}
+
+__attribute__((noinline))
+static void foo(void) {
+ bar();
+}
+
+int main(void) {
+ foo();
+
+ return 0;
+}
diff --git a/test/units/TEST-87-AUX-UTILS-VM.coredump.sh b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
index 7ab6f29d7d..52c9d2fb0a 100755
--- a/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
@@ -8,15 +8,13 @@ set -o pipefail
# Make sure the binary name fits into 15 characters
CORE_TEST_BIN="/tmp/test-dump"
-CORE_STACKTRACE_TEST_BIN="/tmp/test-stacktrace-dump"
-MAKE_STACKTRACE_DUMP="/tmp/make-stacktrace-dump"
CORE_TEST_UNPRIV_BIN="/tmp/test-usr-dump"
MAKE_DUMP_SCRIPT="/tmp/make-dump"
# Unset $PAGER so we don't have to use --no-pager everywhere
export PAGER=
at_exit() {
- rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT" "$MAKE_STACKTRACE_DUMP"
+ rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT"
}
(! systemd-detect-virt -cq)
@@ -226,30 +224,66 @@ systemd-run -t --property CoredumpFilter=default ls /tmp
(! coredumpctl debug --debugger=/bin/true --debugger-arguments='"')
# Test for EnterNamespace= feature
-if pkgconf --atleast-version 0.192 libdw ; then
- # dwfl_set_sysroot() is supported only in libdw-0.192 or newer.
- cat >"$MAKE_STACKTRACE_DUMP" <<END
-#!/bin/bash
-mount -t tmpfs tmpfs /tmp
-gcc -xc -O0 -g -o $CORE_STACKTRACE_TEST_BIN - <<EOF
-void baz(void) { int *x = 0; *x = 42; }
-void bar(void) { baz(); }
-void foo(void) { bar(); }
-int main(void) { foo(); return 0;}
+#
+# dwfl_set_sysroot() is supported only in libdw-0.192 or newer.
+if pkgconf --atleast-version 0.192 libdw; then
+ MAKE_STACKTRACE_DUMP="/tmp/make-stacktrace-dump"
+
+ # Simple script that mounts tmpfs on /tmp/ and copies the crashing test binary there, which in
+ # combination with `unshare --mount` ensures the "outside" systemd-coredump process won't be able to
+ # access the crashed binary (and hence won't be able to symbolize its stacktrace) unless
+ # EnterNamespace=yes is used
+ cat >"$MAKE_STACKTRACE_DUMP" <<\EOF
+#!/usr/bin/bash -eux
+
+TARGET="/tmp/${1:?}"
+EC=0
+
+# "Unhide" debuginfo in the namespace (see the comment below)
+test -d /usr/lib/debug/ && umount /usr/lib/debug/
+
+mount -t tmpfs tmpfs /tmp/
+cp /usr/lib/systemd/tests/unit-tests/manual/test-coredump-stacktrace "$TARGET"
+
+$TARGET || EC=$?
+if [[ $EC -ne 139 ]]; then
+ echo >&2 "$TARGET didn't crash, this shouldn't happen"
+ exit 1
+fi
+
+exit 0
EOF
-$CORE_STACKTRACE_TEST_BIN
-END
chmod +x "$MAKE_STACKTRACE_DUMP"
+ # Since the test-coredump-stacktrace binary is built together with rest of the systemd its debug symbols
+ # might be part of debuginfo packages (if supported & built), and libdw will then use them to symbolize
+ # the stacktrace even if it doesn't have access to the original crashing binary. Let's make the test
+ # simpler and just "hide" the debuginfo data, so libdw is forced to access the target namespace to get
+ # the necessary symbols
+ test -d /usr/lib/debug/ && mount -t tmpfs tmpfs /usr/lib/debug/
+
mkdir -p /run/systemd/coredump.conf.d/
printf '[Coredump]\nEnterNamespace=no' >/run/systemd/coredump.conf.d/99-enter-namespace.conf
- unshare --pid --fork --mount-proc --mount --uts --ipc --net /bin/bash -c "$MAKE_STACKTRACE_DUMP" || :
- timeout 30 bash -c "until coredumpctl -1 info $CORE_STACKTRACE_TEST_BIN | grep -zvqE 'baz.*bar.*foo'; do sleep .2; done"
+ unshare --pid --fork --mount-proc --mount --uts --ipc --net "$MAKE_STACKTRACE_DUMP" "test-stacktrace-not-symbolized"
+ timeout 30 bash -c "until coredumpctl list -q --no-legend /tmp/test-stacktrace-not-symbolized; do sleep .2; done"
+ coredumpctl info /tmp/test-stacktrace-not-symbolized | tee /tmp/not-symbolized.log
+ (! grep -E "#[0-9]+ .* main " /tmp/not-symbolized.log)
+ (! grep -E "#[0-9]+ .* foo " /tmp/not-symbolized.log)
+ (! grep -E "#[0-9]+ .* bar " /tmp/not-symbolized.log)
+ (! grep -E "#[0-9]+ .* baz " /tmp/not-symbolized.log)
printf '[Coredump]\nEnterNamespace=yes' >/run/systemd/coredump.conf.d/99-enter-namespace.conf
- unshare --pid --fork --mount-proc --mount --uts --ipc --net /bin/bash -c "$MAKE_STACKTRACE_DUMP" || :
- timeout 30 bash -c "until coredumpctl -1 info $CORE_STACKTRACE_TEST_BIN | grep -zqE 'baz.*bar.*foo'; do sleep .2; done"
+ unshare --pid --fork --mount-proc --mount --uts --ipc --net "$MAKE_STACKTRACE_DUMP" "test-stacktrace-symbolized"
+ timeout 30 bash -c "until coredumpctl list -q --no-legend /tmp/test-stacktrace-symbolized; do sleep .2; done"
+ coredumpctl info /tmp/test-stacktrace-symbolized | tee /tmp/symbolized.log
+ grep -E "#[0-9]+ .* main " /tmp/symbolized.log
+ grep -E "#[0-9]+ .* foo " /tmp/symbolized.log
+ grep -E "#[0-9]+ .* bar " /tmp/symbolized.log
+ grep -E "#[0-9]+ .* baz " /tmp/symbolized.log
+
+ test -d /usr/lib/debug/ && umount /usr/lib/debug/
+ rm -f "$MAKE_STACKTRACE_DUMP" /run/systemd/coredump.conf.d/99-enter-namespace.conf /tmp/{not-,}symbolized.log
else
echo "libdw doesn't not support setting sysroot, skipping EnterNamespace= test"
fi

View File

@ -0,0 +1,28 @@
From b060529f5a896df4ee443ffc881bf7f61a645f25 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 9 Oct 2025 17:57:25 +0200
Subject: [PATCH] test: exclude test-stacktrace(-not)?-symbolized from the
coredump check
As they are expected coredumps from the EnterNamespace= feature test.
(cherry picked from commit cfb604f8f7c83912648d69bd3ad89c2436b4b8ef)
Related: RHEL-113920
---
test/TEST-87-AUX-UTILS-VM/meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/TEST-87-AUX-UTILS-VM/meson.build b/test/TEST-87-AUX-UTILS-VM/meson.build
index 8490139204..ae9e654032 100644
--- a/test/TEST-87-AUX-UTILS-VM/meson.build
+++ b/test/TEST-87-AUX-UTILS-VM/meson.build
@@ -5,7 +5,7 @@ integration_tests += [
integration_test_template + {
'name' : fs.name(meson.current_source_dir()),
'storage': 'persistent',
- 'coredump-exclude-regex' : '/(test-usr-dump|test-dump|bash)$',
+ 'coredump-exclude-regex' : '/(test-usr-dump|test-dump|test-stacktrace(-not)?-symbolized|bash)$',
'vm' : true,
},
]

View File

@ -0,0 +1,105 @@
From bb285f766c13da97b24194391e111cb0d9701a24 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 9 Oct 2025 17:54:58 +0200
Subject: [PATCH] mkosi: install test dependencies for EnterNamespace= test
The test for the EnterNamespace= feature [0] has been both broken and
disabled since the migration to the mkosi framework, as it's missing the
libdw.pc file for pkg-config, so the test is skipped completely, and
it's also missing gcc to actually build the test binary.
[0] Part of TEST-87-AUX-UTILS-VM.coredump.sh
(cherry picked from commit 4d8e8d44ab3f6f99102faf0dcb53ca4de4d517ae)
Related: RHEL-113920
---
mkosi.conf.d/10-arch/mkosi.conf | 2 ++
mkosi.conf.d/10-centos-fedora/mkosi.conf | 3 +++
mkosi.conf.d/10-debian-ubuntu/mkosi.conf | 3 +++
mkosi.conf.d/10-opensuse/mkosi.conf | 3 +++
4 files changed, 11 insertions(+)
diff --git a/mkosi.conf.d/10-arch/mkosi.conf b/mkosi.conf.d/10-arch/mkosi.conf
index 9ceb6ea6f8..7194edeeac 100644
--- a/mkosi.conf.d/10-arch/mkosi.conf
+++ b/mkosi.conf.d/10-arch/mkosi.conf
@@ -21,6 +21,7 @@ Packages=
dbus-broker
dbus-broker-units
dhcp
+ elfutils
erofs-utils
f2fs-tools
git
@@ -38,6 +39,7 @@ Packages=
openssl
pacman
perf
+ pkgconf
polkit
procps-ng
psmisc
diff --git a/mkosi.conf.d/10-centos-fedora/mkosi.conf b/mkosi.conf.d/10-centos-fedora/mkosi.conf
index 90603bba14..6cd4a056c7 100644
--- a/mkosi.conf.d/10-centos-fedora/mkosi.conf
+++ b/mkosi.conf.d/10-centos-fedora/mkosi.conf
@@ -26,6 +26,8 @@ Packages=
device-mapper-event
device-mapper-multipath
dnf
+ elfutils-devel
+ elfutils-libs
git-core
glibc-langpack-de
glibc-langpack-en
@@ -45,6 +47,7 @@ Packages=
pam
passwd
perf
+ pkgconf
policycoreutils
polkit
procps-ng
diff --git a/mkosi.conf.d/10-debian-ubuntu/mkosi.conf b/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
index c898664f83..85f2af492c 100644
--- a/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
+++ b/mkosi.conf.d/10-debian-ubuntu/mkosi.conf
@@ -54,6 +54,8 @@ Packages=
isc-dhcp-server
knot
libcap-ng-utils
+ libdw-dev
+ libdw1
locales
login
man-db
@@ -64,6 +66,7 @@ Packages=
openssh-server
passwd
polkitd
+ pkgconf
procps
psmisc
python3-pexpect
diff --git a/mkosi.conf.d/10-opensuse/mkosi.conf b/mkosi.conf.d/10-opensuse/mkosi.conf
index 4ee3894c00..d400a85320 100644
--- a/mkosi.conf.d/10-opensuse/mkosi.conf
+++ b/mkosi.conf.d/10-opensuse/mkosi.conf
@@ -52,6 +52,8 @@ Packages=
kernel-default
kmod
knot
+ libdw-devel
+ libdw1
multipath-tools
ncat
open-iscsi
@@ -60,6 +62,7 @@ Packages=
pam
patterns-base-minimal_base
perf
+ pkgconf
procps4
psmisc
python3-pefile

View File

@ -1,4 +1,4 @@
From ae1394abcded51ed5e443d1124059b2e31748baa Mon Sep 17 00:00:00 2001
From c762fb58a253f611d6a6005e0d947b90ad08880a Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@gmail.com>
Date: Fri, 11 Apr 2025 14:44:30 +0100
Subject: [PATCH] coredump: verify pidfd after parsing data in usermode helper

View File

@ -1,4 +1,4 @@
From 942d050f98cc0b6c89dbe30157163a8610cf7f78 Mon Sep 17 00:00:00 2001
From 24cf0dbc7ced71ce472dc0a2a19ee6c2328b6f29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 29 Apr 2025 14:47:59 +0200
Subject: [PATCH] coredump: restore compatibility with older patterns
@ -27,8 +27,8 @@ args.
Related: RHEL-104135
---
src/coredump/coredump.c | 23 +++++++++++++++--------
test/units/TEST-74-AUX-UTILS.coredump.sh | 18 +++++++++++-------
src/coredump/coredump.c | 23 ++++++++++++++-------
test/units/TEST-87-AUX-UTILS-VM.coredump.sh | 18 +++++++++-------
2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
@ -90,11 +90,11 @@ index db7f76f6c4..58bcd4910f 100644
_cleanup_free_ char *buf = NULL;
const char *t = argv[i];
diff --git a/test/units/TEST-74-AUX-UTILS.coredump.sh b/test/units/TEST-74-AUX-UTILS.coredump.sh
index 2c084f54d2..8173a23162 100755
--- a/test/units/TEST-74-AUX-UTILS.coredump.sh
+++ b/test/units/TEST-74-AUX-UTILS.coredump.sh
@@ -194,14 +194,18 @@ rm -f /tmp/core.{output,redirected}
diff --git a/test/units/TEST-87-AUX-UTILS-VM.coredump.sh b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
index 52c9d2fb0a..a170223f37 100755
--- a/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
@@ -189,14 +189,18 @@ rm -f /tmp/core.{output,redirected}
(! "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_BIN" >/dev/null)
# --backtrace mode

View File

@ -1,4 +1,4 @@
From ad1453257d69a74bf8e47493394c601d733774de Mon Sep 17 00:00:00 2001
From 6e3c4832994b9bc6da0a9a0b7a0c55a6fb38cab5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 21 May 2025 22:33:50 +0200
Subject: [PATCH] coredump: wrap long lines, fix grammar in comments

View File

@ -1,4 +1,4 @@
From 6f678c43638caa6b0b349e56f0ded6d9c781a345 Mon Sep 17 00:00:00 2001
From 213ca1ba422418ebf37d4e518704e97b691e8f13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 26 May 2025 12:04:44 +0200
Subject: [PATCH] coredump: get rid of _META_MANDATORY_MAX

View File

@ -1,4 +1,4 @@
From 0ade63d15214fa8e184cc87522bfac9533be441b Mon Sep 17 00:00:00 2001
From ca6244bc21757a799cbc81090cda3a85aa183325 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 29 Apr 2025 14:47:59 +0200
Subject: [PATCH] coredump: use %d in kernel core pattern
@ -24,10 +24,10 @@ Reportedy-by: Qualys Security Advisory <qsa@qualys.com>
Related: RHEL-104135
---
man/systemd-coredump.xml | 12 ++++++++++++
src/coredump/coredump.c | 21 ++++++++++++++++++---
sysctl.d/50-coredump.conf.in | 2 +-
test/units/TEST-74-AUX-UTILS.coredump.sh | 5 +++++
man/systemd-coredump.xml | 12 ++++++++++++
src/coredump/coredump.c | 21 ++++++++++++++++++---
sysctl.d/50-coredump.conf.in | 2 +-
test/units/TEST-87-AUX-UTILS-VM.coredump.sh | 5 +++++
4 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
@ -131,11 +131,11 @@ index 90c080bdfe..a550c87258 100644
# Allow 16 coredumps to be dispatched in parallel by the kernel.
# We collect metadata from /proc/%P/, and thus need to make sure the crashed
diff --git a/test/units/TEST-74-AUX-UTILS.coredump.sh b/test/units/TEST-74-AUX-UTILS.coredump.sh
index 8173a23162..f157f97443 100755
--- a/test/units/TEST-74-AUX-UTILS.coredump.sh
+++ b/test/units/TEST-74-AUX-UTILS.coredump.sh
@@ -201,12 +201,17 @@ journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE
diff --git a/test/units/TEST-87-AUX-UTILS-VM.coredump.sh b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
index a170223f37..0d7bed5609 100755
--- a/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
+++ b/test/units/TEST-87-AUX-UTILS-VM.coredump.sh
@@ -196,12 +196,17 @@ journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE
/usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509900 12345
journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
/usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509901 12345 mymachine

View File

@ -1,4 +1,4 @@
From 69d7d75a872d319b5fda048044238a735dce3834 Mon Sep 17 00:00:00 2001
From c4112c747b8efc7d2704daddedcc1d0816580359 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 5 May 2025 15:48:40 +0200
Subject: [PATCH] coredump: also stop forwarding non-dumpable processes

View File

@ -1,4 +1,4 @@
From cee91ba610d7ae7b80d32e487c79ea10c8fb98bc Mon Sep 17 00:00:00 2001
From 06872611dc55c15942a554b9c2a684ee4979ad00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 26 May 2025 15:24:04 +0200
Subject: [PATCH] coredump: get rid of a bogus assertion

View File

@ -1,4 +1,4 @@
From 46e24959ecb9390f61403925bb1569c57ca375df Mon Sep 17 00:00:00 2001
From bf1c8601385ea5b066557ae8def99f80d876f213 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@gmail.com>
Date: Sun, 13 Apr 2025 22:10:36 +0100
Subject: [PATCH] coredump: add support for new %F PIDFD specifier

View File

@ -1,4 +1,4 @@
From 1a01ba0f895a8781908cfebfa1d74f326f6faacb Mon Sep 17 00:00:00 2001
From 0838984f8cd8959c11fa7ff115510911d0a28890 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 27 May 2025 10:44:32 +0200
Subject: [PATCH] coredump: when %F/pidfd is used, again allow forwarding to

View File

@ -1,4 +1,4 @@
From 20b0f1e07885ffc887ac27f9dad164271b07581c Mon Sep 17 00:00:00 2001
From 7d1e71ab4edfde63ac5516dcbbb972379fae17dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 27 May 2025 20:32:30 +0200
Subject: [PATCH] coredump: introduce an enum to wrap dumpable constants

View File

@ -1,4 +1,4 @@
From 2271674c5776fa8308ad8d425e64246910366d2f Mon Sep 17 00:00:00 2001
From 8973e33905369c319d8db07d9a453fc3c99099ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 28 May 2025 18:31:13 +0200
Subject: [PATCH] Define helper to call PR_SET_DUMPABLE

View File

@ -1,4 +1,4 @@
From 35d4cb60dcfbb65359708a98c3474a8b3827f4a0 Mon Sep 17 00:00:00 2001
From f370e6bdbd9fb01e331ff1850f6e9d5be51a15aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Fri, 6 Jun 2025 17:03:46 +0200
Subject: [PATCH] coredump: fix 0-passed-as-pointer warning

View File

@ -0,0 +1,27 @@
From bf6cdeda171f12b8a9e949de869dd2168ea7ee5f Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 8 Oct 2025 17:23:31 +0200
Subject: [PATCH] man: fix a missing word
Follow-up for 6d48c7cf736ced70c1c2fef1e1f03618911d04bc.
(cherry picked from commit 67111e1bd918f9e1b4b542d1e0fe84f1d571876e)
Resolves: RHEL-120277
---
man/systemd.resource-control.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 5ad9793c7a..e4403e7274 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -583,7 +583,7 @@ CPUWeight=20 DisableControllers=cpu / \
an absolute number of tasks or a percentage value that is taken relative to the configured maximum
number of tasks on the system. If assigned the special value <literal>infinity</literal>, no tasks
limit is applied. This controls the <literal>pids.max</literal> control group attribute. For
- details about this control group attribute, the
+ details about this control group attribute, see the
<ulink url="https://docs.kernel.org/admin-guide/cgroup-v2.html#pid">pids controller
</ulink>.
The effective configuration is reported as <varname>EffectiveTasksMax=</varname>.</para>

View File

@ -0,0 +1,33 @@
From 7eea09ef7498cfe000e6cc4310ae64bb59d5bfa0 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Mon, 17 Mar 2025 12:28:37 +0100
Subject: [PATCH] sd_bus_open_user_machine(): Don't shortcut without necessary
env
Don't shortcut if we don't have the necessary environment variables
set in sd_bus_open_user_machine().
(cherry picked from commit 9e34c34b7b027da24b084a58246c1d88bdbcc817)
Resolves: RHEL-129179
---
src/libsystemd/sd-bus/sd-bus.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 2683959db5..3ea12fc371 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1760,8 +1760,10 @@ _public_ int sd_bus_open_user_machine(sd_bus **ret, const char *user_and_machine
assert_return(user_and_machine, -EINVAL);
assert_return(ret, -EINVAL);
- /* Shortcut things if we'd end up on this host and as the same user. */
- if (user_and_machine_equivalent(user_and_machine))
+ /* Shortcut things if we'd end up on this host and as the same user and have one of the necessary
+ * environment variables set already. */
+ if (user_and_machine_equivalent(user_and_machine) &&
+ (secure_getenv("DBUS_SESSION_BUS_ADDRESS") || secure_getenv("XDG_RUNTIME_DIR")))
return sd_bus_open_user(ret);
r = user_and_machine_valid(user_and_machine);

View File

@ -0,0 +1,90 @@
From 7f38c74a532b536c2f8b2e3a948ab1391387adca Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu, 16 Jan 2025 15:34:47 +0100
Subject: [PATCH] udev: set clock group for PTP and RTC devices
Add a new group for clock devices to enable applications like linuxptp
to open clocks without root privileges.
(cherry picked from commit af96ccfc24bc4803078a46b4ef2cdeb5decdfbcd)
Resolves: RHEL-113051
---
README | 3 ++-
meson.build | 1 +
meson_options.txt | 2 ++
rules.d/50-udev-default.rules.in | 2 ++
sysusers.d/basic.conf.in | 1 +
5 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/README b/README
index 9b84bf7e7a..b9a58389ad 100644
--- a/README
+++ b/README
@@ -351,7 +351,8 @@ USERS AND GROUPS:
need to be resolvable by getgrnam() at any time, even in the very early
boot stages, where no other databases and network are available:
- audio, cdrom, dialout, disk, input, kmem, kvm, lp, render, tape, tty, video
+ audio, cdrom, clock, dialout, disk, input, kmem, kvm, lp, render, tape,
+ tty, video
During runtime, the journal daemon requires the "systemd-journal" system
group to exist. New journal files will be readable by this group (but
diff --git a/meson.build b/meson.build
index cfb202eb30..873d70f8d3 100644
--- a/meson.build
+++ b/meson.build
@@ -950,6 +950,7 @@ static_ugids = []
foreach option : ['adm-gid',
'audio-gid',
'cdrom-gid',
+ 'clock-gid',
'dialout-gid',
'disk-gid',
'input-gid',
diff --git a/meson_options.txt b/meson_options.txt
index f30b3f5238..78b7c5fe30 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -289,6 +289,8 @@ option('audio-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "audio" group')
option('cdrom-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "cdrom" group')
+option('clock-gid', type : 'integer', value : 0,
+ description : 'soft-static allocation for the "clock" group')
option('dialout-gid', type : 'integer', value : 0,
description : 'soft-static allocation for the "dialout" group')
option('disk-gid', type : 'integer', value : 0,
diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in
index 08b2de7047..9264b8e021 100644
--- a/rules.d/50-udev-default.rules.in
+++ b/rules.d/50-udev-default.rules.in
@@ -10,6 +10,7 @@ SUBSYSTEM=="block", KERNEL=="md*", ENV{ID_IGNORE_DISKSEQ}="1"
SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}"
+SUBSYSTEM=="rtc", GROUP="clock", MODE="0660"
# select "system RTC" or just use the first one
SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc"
SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
@@ -30,6 +31,7 @@ SUBSYSTEM=="pci|usb|platform", IMPORT{builtin}="path_id"
SUBSYSTEM=="net", IMPORT{builtin}="net_driver"
+SUBSYSTEM=="ptp", GROUP="clock", MODE="0660"
SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK+="ptp_kvm"
SUBSYSTEM=="ptp", ATTR{clock_name}=="hyperv", SYMLINK+="ptp_hyperv"
SUBSYSTEM=="ptp", ATTR{clock_name}=="s390 Physical Clock", SYMLINK+="ptp_s390_physical"
diff --git a/sysusers.d/basic.conf.in b/sysusers.d/basic.conf.in
index 992af346ca..baf31cb739 100644
--- a/sysusers.d/basic.conf.in
+++ b/sysusers.d/basic.conf.in
@@ -25,6 +25,7 @@ g utmp {{UTMP_GID }} - -
# Physical and virtual hardware access groups
g audio {{AUDIO_GID }} - -
g cdrom {{CDROM_GID }} - -
+g clock {{CLOCK_GID }} - -
g dialout {{DIALOUT_GID}} - -
g disk {{DISK_GID }} - -
g input {{INPUT_GID }} - -

View File

@ -0,0 +1,34 @@
From f8037b1e24bf9fa72611fa1dd1492914ac2af7f9 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Fri, 24 Oct 2025 12:55:20 +0200
Subject: [PATCH] coredump: handle ENOBUFS and EMSGSIZE the same way
Depending on the runtime configuration, e.g. sysctls
net.core.wmem_default= and net.core.rmem_default and on the actual
message size, sendmsg() can fail also with ENOBUFS. E.g. alloc_skb()
failure caused by net.core.[rw]mem_default=64MiB and huge fdinfo list
from process that has 90k opened FDs.
We should handle this case in the same way as EMSGSIZE and drop part of
the message.
(cherry picked from commit 28e62e684b631f928f1d857b04f45f0d34441675)
Resolves: RHEL-126122
---
src/coredump/coredump.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 412411bff7..ea4f8805f4 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -1287,7 +1287,7 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, PidRef *pi
if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0)
break;
- if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) {
+ if (IN_SET(errno, EMSGSIZE, ENOBUFS) && mh.msg_iov[0].iov_len > 0) {
/* This field didn't fit? That's a pity. Given that this is
* just metadata, let's truncate the field at half, and try
* again. We append three dots, in order to show that this is

View File

@ -0,0 +1,84 @@
From 29d63497e76eb54b060ec53614034951d6c7e454 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 28 Jan 2025 08:50:14 +0900
Subject: [PATCH] strv: introduce string_strv_hashmap_remove()
(cherry picked from commit c540875cd3b024f64980966376637ecc284d643c)
Related: RHEL-126937
---
src/basic/strv.c | 17 +++++++++++++++++
src/basic/strv.h | 4 ++++
src/test/test-hashmap-plain.c | 16 ++++++++++++++++
3 files changed, 37 insertions(+)
diff --git a/src/basic/strv.c b/src/basic/strv.c
index c9c4551cdc..bbe0868226 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -1065,6 +1065,23 @@ int fputstrv(FILE *f, char * const *l, const char *separator, bool *space) {
DEFINE_PRIVATE_HASH_OPS_FULL(string_strv_hash_ops, char, string_hash_func, string_compare_func, free, char*, strv_free);
+void string_strv_hashmap_remove(Hashmap *h, const char *key, const char *value) {
+ assert(key);
+
+ if (value) {
+ char **l = hashmap_get(h, key);
+ if (!l)
+ return;
+
+ strv_remove(l, value);
+ if (!strv_isempty(l))
+ return;
+ }
+
+ _unused_ _cleanup_free_ char *key_free = NULL;
+ strv_free(hashmap_remove2(h, key, (void**) &key_free));
+}
+
static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const char *value) {
char **l;
int r;
diff --git a/src/basic/strv.h b/src/basic/strv.h
index 86ba06f835..5cdc801f35 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -258,6 +258,10 @@ int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
#define strv_free_and_replace(a, b) \
free_and_replace_full(a, b, strv_free)
+void string_strv_hashmap_remove(Hashmap *h, const char *key, const char *value);
+static inline void string_strv_ordered_hashmap_remove(OrderedHashmap *h, const char *key, const char *value) {
+ string_strv_hashmap_remove(PLAIN_HASHMAP(h), key, value);
+}
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);
int _string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);
#define string_strv_hashmap_put(h, k, v) _string_strv_hashmap_put(h, k, v HASHMAP_DEBUG_SRC_ARGS)
diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c
index e1485a84d4..0fd4116d8a 100644
--- a/src/test/test-hashmap-plain.c
+++ b/src/test/test-hashmap-plain.c
@@ -992,6 +992,22 @@ TEST(string_strv_hashmap) {
s = hashmap_get(m, "xxx");
assert_se(strv_equal(s, STRV_MAKE("bar", "BAR")));
+
+ string_strv_hashmap_remove(m, "foo", "bar");
+ ASSERT_NOT_NULL(s = hashmap_get(m, "foo"));
+ ASSERT_TRUE(strv_equal(s, STRV_MAKE("BAR")));
+
+ string_strv_hashmap_remove(m, "foo", "BAR");
+ ASSERT_NULL(hashmap_get(m, "foo"));
+
+ string_strv_hashmap_remove(m, "xxx", "BAR");
+ ASSERT_NOT_NULL(s = hashmap_get(m, "xxx"));
+ ASSERT_TRUE(strv_equal(s, STRV_MAKE("bar")));
+
+ string_strv_hashmap_remove(m, "xxx", "bar");
+ ASSERT_NULL(hashmap_get(m, "xxx"));
+
+ ASSERT_TRUE(hashmap_isempty(m));
}
TEST(hashmap_dump_sorted) {

View File

@ -0,0 +1,183 @@
From 08842799a6656ea0de3921842b2e157b032b46b5 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 28 Jan 2025 09:55:12 +0900
Subject: [PATCH] unit-file: introduce unit_file_remove_from_name_map()
(cherry picked from commit d8b34aaef24599917d4e7fa04c78fffac3afe7cf)
Related: RHEL-126937
---
src/shared/unit-file.c | 35 +++++++++++++++++
src/shared/unit-file.h | 8 ++++
src/test/test-unit-file.c | 81 +++++++++++++++++++++++++++++++++++++++
3 files changed, 124 insertions(+)
diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c
index 5bb580285c..01e10c596d 100644
--- a/src/shared/unit-file.c
+++ b/src/shared/unit-file.c
@@ -616,6 +616,41 @@ int unit_file_build_name_map(
return 1;
}
+int unit_file_remove_from_name_map(
+ const LookupPaths *lp,
+ uint64_t *cache_timestamp_hash,
+ Hashmap **unit_ids_map,
+ Hashmap **unit_names_map,
+ Set **path_cache,
+ const char *path) {
+
+ int r;
+
+ assert(path);
+
+ /* This assumes the specified path is already removed, and drops the relevant entries from the maps. */
+
+ /* If one of the lookup paths we are monitoring is already changed, let's rebuild the map. Then, the
+ * new map should not contain entries relevant to the specified path. */
+ r = unit_file_build_name_map(lp, cache_timestamp_hash, unit_ids_map, unit_names_map, path_cache);
+ if (r != 0)
+ return r;
+
+ /* If not, drop the relevant entries. */
+
+ _cleanup_free_ char *name = NULL;
+ r = path_extract_filename(path, &name);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to extract file name from '%s': %m", path);
+
+ _unused_ _cleanup_free_ char *key = NULL;
+ free(hashmap_remove2(*unit_ids_map, name, (void**) &key));
+ string_strv_hashmap_remove(*unit_names_map, name, name);
+ free(set_remove(*path_cache, path));
+
+ return 0;
+}
+
static int add_name(
const char *unit_name,
Set **names,
diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h
index 1c89a92c7d..dd7dc57d15 100644
--- a/src/shared/unit-file.h
+++ b/src/shared/unit-file.h
@@ -68,6 +68,14 @@ int unit_file_build_name_map(
Hashmap **unit_names_map,
Set **path_cache);
+int unit_file_remove_from_name_map(
+ const LookupPaths *lp,
+ uint64_t *cache_timestamp_hash,
+ Hashmap **unit_ids_map,
+ Hashmap **unit_names_map,
+ Set **path_cache,
+ const char *path);
+
int unit_file_find_fragment(
Hashmap *unit_ids_map,
Hashmap *unit_name_map,
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index 63e500003c..a84e6aaf97 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -1,11 +1,16 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include "fileio.h"
#include "initrd-util.h"
#include "path-lookup.h"
+#include "path-util.h"
+#include "random-util.h"
+#include "rm-rf.h"
#include "set.h"
#include "special.h"
#include "strv.h"
#include "tests.h"
+#include "tmpfile-util.h"
#include "unit-file.h"
TEST(unit_validate_alias_symlink_and_warn) {
@@ -86,6 +91,82 @@ TEST(unit_file_build_name_map) {
}
}
+static bool test_unit_file_remove_from_name_map_trail(const LookupPaths *lp, size_t trial) {
+ int r;
+
+ log_debug("/* %s(trial=%zu) */", __func__, trial);
+
+ _cleanup_hashmap_free_ Hashmap *unit_ids = NULL, *unit_names = NULL;
+ _cleanup_set_free_ Set *path_cache = NULL;
+ ASSERT_OK_POSITIVE(unit_file_build_name_map(lp, NULL, &unit_ids, &unit_names, &path_cache));
+
+ _cleanup_free_ char *name = NULL;
+ for (size_t i = 0; i < 100; i++) {
+ ASSERT_OK(asprintf(&name, "test-unit-file-%"PRIx64".service", random_u64()));
+ if (!hashmap_contains(unit_ids, name))
+ break;
+ name = mfree(name);
+ }
+ ASSERT_NOT_NULL(name);
+
+ _cleanup_free_ char *path = path_join(lp->transient, name);
+ ASSERT_NOT_NULL(path);
+ ASSERT_OK(write_string_file(path, "[Unit]\n", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755));
+
+ uint64_t cache_timestamp_hash = 0;
+ ASSERT_OK_POSITIVE(unit_file_build_name_map(lp, &cache_timestamp_hash, &unit_ids, &unit_names, &path_cache));
+
+ ASSERT_STREQ(hashmap_get(unit_ids, name), path);
+ ASSERT_TRUE(strv_equal(hashmap_get(unit_names, name), STRV_MAKE(name)));
+ ASSERT_TRUE(set_contains(path_cache, path));
+
+ ASSERT_OK_ERRNO(unlink(path));
+
+ ASSERT_OK(r = unit_file_remove_from_name_map(lp, &cache_timestamp_hash, &unit_ids, &unit_names, &path_cache, path));
+ if (r > 0)
+ return false; /* someone touches unit files. Retrying. */
+
+ ASSERT_FALSE(hashmap_contains(unit_ids, name));
+ ASSERT_FALSE(hashmap_contains(unit_names, path));
+ ASSERT_FALSE(set_contains(path_cache, path));
+
+ _cleanup_hashmap_free_ Hashmap *unit_ids_2 = NULL, *unit_names_2 = NULL;
+ _cleanup_set_free_ Set *path_cache_2 = NULL;
+ ASSERT_OK_POSITIVE(unit_file_build_name_map(lp, NULL, &unit_ids_2, &unit_names_2, &path_cache_2));
+
+ if (hashmap_size(unit_ids) != hashmap_size(unit_ids_2) ||
+ hashmap_size(unit_names) != hashmap_size(unit_names_2) ||
+ !set_equal(path_cache, path_cache_2))
+ return false;
+
+ const char *k, *v;
+ HASHMAP_FOREACH_KEY(v, k, unit_ids)
+ if (!streq_ptr(hashmap_get(unit_ids_2, k), v))
+ return false;
+
+ char **l;
+ HASHMAP_FOREACH_KEY(l, k, unit_names)
+ if (!strv_equal_ignore_order(hashmap_get(unit_names_2, k), l))
+ return false;
+
+ return true;
+}
+
+
+TEST(unit_file_remove_from_name_map) {
+ _cleanup_(rm_rf_physical_and_freep) char *d = NULL;
+
+ _cleanup_(lookup_paths_done) LookupPaths lp = {};
+ ASSERT_OK(lookup_paths_init(&lp, RUNTIME_SCOPE_SYSTEM, LOOKUP_PATHS_TEMPORARY_GENERATED, NULL));
+ ASSERT_NOT_NULL(d = strdup(lp.temporary_dir));
+
+ for (size_t i = 0; i < 10; i++)
+ if (test_unit_file_remove_from_name_map_trail(&lp, i))
+ return;
+
+ assert_not_reached();
+}
+
TEST(runlevel_to_target) {
in_initrd_force(false);
ASSERT_STREQ(runlevel_to_target(NULL), NULL);

View File

@ -0,0 +1,52 @@
From 551f1d97a7a038538dc1da50c8b6d8f25c6c236b Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 28 Jan 2025 10:09:32 +0900
Subject: [PATCH] core/unit: remove path to transient unit file from unit name
maps on stop
Fixes #35190.
(cherry picked from commit fce94c5c563b8f6ede2b8f7f283d2d2faff4e062)
Resolves: RHEL-126937
---
src/core/unit.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 01e4d3a64f..556ed0eefa 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -648,13 +648,11 @@ static void unit_clear_dependencies(Unit *u) {
static void unit_remove_transient(Unit *u) {
assert(u);
+ assert(u->manager);
if (!u->transient)
return;
- if (u->fragment_path)
- (void) unlink(u->fragment_path);
-
STRV_FOREACH(i, u->dropin_paths) {
_cleanup_free_ char *p = NULL, *pp = NULL;
@@ -671,6 +669,17 @@ static void unit_remove_transient(Unit *u) {
(void) unlink(*i);
(void) rmdir(p);
}
+
+ if (u->fragment_path) {
+ (void) unlink(u->fragment_path);
+ (void) unit_file_remove_from_name_map(
+ &u->manager->lookup_paths,
+ &u->manager->unit_cache_timestamp_hash,
+ &u->manager->unit_id_map,
+ &u->manager->unit_name_map,
+ &u->manager->unit_path_cache,
+ u->fragment_path);
+ }
}
static void unit_free_mounts_for(Unit *u) {

View File

@ -0,0 +1,33 @@
From 77c49a11d4b498b22c582f24b7ce46b2d4c8753f Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 27 Jan 2025 22:24:16 +0900
Subject: [PATCH] TEST-07-PID1: add reprudcer for issue #35190
(cherry picked from commit 448e99251aa47a5986425a1783da44d1200fe733)
Related: RHEL-126937
---
test/units/TEST-07-PID1.transient.sh | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100755 test/units/TEST-07-PID1.transient.sh
diff --git a/test/units/TEST-07-PID1.transient.sh b/test/units/TEST-07-PID1.transient.sh
new file mode 100755
index 0000000000..ae71a38143
--- /dev/null
+++ b/test/units/TEST-07-PID1.transient.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -ex
+set -o pipefail
+
+journalctl --sync
+TS="$(date '+%H:%M:%S')"
+
+systemd-run -u hogehoge.service sleep infinity
+systemctl daemon-reload
+systemctl stop hogehoge.service
+
+journalctl --sync
+[[ -z "$(journalctl -b -q --since "$TS" -u hogehoge.service -p notice)" ]]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
From 0754d389b288f690c2815f1f99859ee03d3ca00b Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Wed, 14 May 2025 20:33:22 +0200
Subject: [PATCH] man: don't duplicate version in History section
(cherry picked from commit 7d71b23304cf8f7d4b4a06f9322847c22c1c5175)
Related: RHEL-128767
---
man/kernel-command-line.xml | 5 ++---
man/systemd-system.conf.xml | 5 ++---
man/systemd.resource-control.xml | 7 +++----
man/systemd.xml | 5 ++---
tools/check-version-history.py | 7 +++++--
tools/command_ignorelist | 4 ++++
6 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml
index 0a4c8cf11b..102015f545 100644
--- a/man/kernel-command-line.xml
+++ b/man/kernel-command-line.xml
@@ -762,11 +762,10 @@
<variablelist>
<varlistentry>
<term>systemd 252</term>
+
<listitem><para>Kernel command-line arguments <varname>systemd.unified_cgroup_hierarchy</varname>
and <varname>systemd.legacy_systemd_cgroup_controller</varname> were deprecated. Please switch to
- the unified cgroup hierarchy.</para>
-
- <xi:include href="version-info.xml" xpointer="v252"/></listitem>
+ the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index 297838eaa4..23d09cfb37 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -754,10 +754,9 @@
<variablelist>
<varlistentry>
<term>systemd 252</term>
- <listitem><para>Option <varname>DefaultBlockIOAccounting=</varname> was deprecated. Please switch
- to the unified cgroup hierarchy.</para>
- <xi:include href="version-info.xml" xpointer="v252"/></listitem>
+ <listitem><para>Option <varname>DefaultBlockIOAccounting=</varname> was deprecated. Please switch
+ to the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index e4403e7274..540db6293f 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -1689,7 +1689,8 @@ DeviceAllow=/dev/loop-control
<variablelist>
<varlistentry>
<term>systemd 252</term>
- <listitem><para> Options for controlling the Legacy Control Group Hierarchy (<ulink
+
+ <listitem><para>Options for controlling the Legacy Control Group Hierarchy (<ulink
url="https://docs.kernel.org/admin-guide/cgroup-v1/index.html">Control Groups version 1</ulink>)
are now fully deprecated:
<varname>CPUShares=<replaceable>weight</replaceable></varname>,
@@ -1703,9 +1704,7 @@ DeviceAllow=/dev/loop-control
<varname>BlockIOReadBandwidth=<replaceable>device</replaceable>
<replaceable>bytes</replaceable></varname>,
<varname>BlockIOWriteBandwidth=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname>.
- Please switch to the unified cgroup hierarchy.</para>
-
- <xi:include href="version-info.xml" xpointer="v252"/></listitem>
+ Please switch to the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemd.xml b/man/systemd.xml
index d11c601a88..afdaf98ac9 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -1563,11 +1563,10 @@
<variablelist>
<varlistentry>
<term>systemd 252</term>
+
<listitem><para>Kernel command-line arguments <varname>systemd.unified_cgroup_hierarchy</varname>
and <varname>systemd.legacy_systemd_cgroup_controller</varname> were deprecated. Please switch to
- the unified cgroup hierarchy.</para>
-
- <xi:include href="version-info.xml" xpointer="v252"/></listitem>
+ the unified cgroup hierarchy.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/tools/check-version-history.py b/tools/check-version-history.py
index efd7023762..dce2b6abd1 100644
--- a/tools/check-version-history.py
+++ b/tools/check-version-history.py
@@ -75,9 +75,12 @@ def find_undocumented_commands(pages, ignorelist):
parent = listitem if listitem is not None else varlistentry
rev = parent.getchildren()[-1]
- if rev.get("href") != "version-info.xml":
- if (filename, path) not in ignorelist:
+ if (
+ rev.get("href") != "version-info.xml" and
+ not path.startswith(tuple(entry[1] for entry in ignorelist if entry[0] == filename))
+ ):
undocumented.append((filename, path))
+
return undocumented
diff --git a/tools/command_ignorelist b/tools/command_ignorelist
index f35f2a3bc1..42076013e4 100644
--- a/tools/command_ignorelist
+++ b/tools/command_ignorelist
@@ -14,6 +14,7 @@ journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Co
journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="RateLimitIntervalSec="]
journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="SystemMaxUse="]
journald.conf.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="ForwardToSyslog="]
+kernel-command-line.xml ./refsect1[title="History"]/
loginctl.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="-p"]
loginctl.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="-a"]
loginctl.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--no-ask-password"]
@@ -123,6 +124,7 @@ systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/var
systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/variablelist/varlistentry[term="suspend"]
systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/variablelist/varlistentry[term="hibernate"]
systemctl.xml ./refsect1[title="Commands"]/refsect2[title="System Commands"]/variablelist/varlistentry[term="switch-root ROOT INIT"]
+systemd.xml ./refsect1[title="History"]/
systemd-ask-password.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--icon="]
systemd-ask-password.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--timeout="]
systemd-ask-password.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--no-tty"]
@@ -169,6 +171,7 @@ systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="Execution Options
systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="System Identity Options"]/variablelist/varlistentry[term="--uuid="]
systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="Networking Options"]/variablelist/varlistentry[term="--private-network"]
systemd-nspawn.xml ./refsect1[title="Options"]/refsect2[title="Image Options"]/variablelist/varlistentry[term="--read-only"]
+systemd-system.conf.xml ./refsect1[title="History"]/
systemd-tmpfiles.xml ./refsect1[title="Commands and options"]/variablelist/varlistentry[term="--create"]
systemd-tmpfiles.xml ./refsect1[title="Commands and options"]/variablelist/varlistentry[term="--clean"]
systemd-tmpfiles.xml ./refsect1[title="Commands and options"]/variablelist/varlistentry[term="--remove"]
@@ -243,6 +246,7 @@ systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Pat
systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Unit="]
systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="MakeDirectory="]
systemd.path.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="DirectoryMode="]
+systemd.resource-control.xml ./refsect1[title="History"]/
systemd.service.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="Type="]
systemd.service.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="RemainAfterExit="]
systemd.service.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="GuessMainPID="]

View File

@ -0,0 +1,35 @@
From f7092782c240db9fe8887c510b231e1dd3c2f284 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Behrmann?= <behrmann@physik.fu-berlin.de>
Date: Wed, 20 Aug 2025 15:47:28 +0200
Subject: [PATCH] tools: ignore root element explicitly in
check-version-history
Currently these messages (broken for length)
2025-08-20T12:04:15.9609277Z
/home/runner/work/systemd/systemd/tools/check-version-history.py:26:
FutureWarning: This search incorrectly ignores the root element, and will be fixed in a future version.
If you rely on the current behaviour, change it to './/funcprototype/funcdef/function'
can be seen in CI output. So let's apply the suggestion.
(cherry picked from commit 1dcbb0b4ca48fe69e2984943d536c3f4252b12b1)
Related: RHEL-128767
---
tools/check-version-history.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/check-version-history.py b/tools/check-version-history.py
index dce2b6abd1..db32b6920a 100644
--- a/tools/check-version-history.py
+++ b/tools/check-version-history.py
@@ -23,7 +23,7 @@ def find_undocumented_functions(pages, ignorelist):
assert pagetree.getroot().tag == "refentry"
hist_section = pagetree.find("refsect1[title='History']")
- for func in pagetree.findall("//funcprototype/funcdef/function"):
+ for func in pagetree.findall(".//funcprototype/funcdef/function"):
path = f"./refsynopsisdiv/funcsynopsis/funcprototype/funcdef/function[.='{func.text}']"
assert pagetree.findall(path) == [func]

View File

@ -0,0 +1,48 @@
From 699c8216cd5cd85c344f6ca475b5adaa8272daa4 Mon Sep 17 00:00:00 2001
From: Masanari Iida <standby24x7@gmail.com>
Date: Tue, 11 Nov 2025 23:20:15 +0900
Subject: [PATCH] systemd-logind: Add signal section in man systemd-logind
This patch adds signal setion in man systemd-logind
(cherry picked from commit 036100d74563edda3cb81e19255ffec5e1b7fc7f)
Resolves: RHEL-128767
---
man/systemd-logind.service.xml | 10 ++++++++++
tools/command_ignorelist | 1 +
2 files changed, 11 insertions(+)
diff --git a/man/systemd-logind.service.xml b/man/systemd-logind.service.xml
index 93bcd6bc8f..34f6330bf7 100644
--- a/man/systemd-logind.service.xml
+++ b/man/systemd-logind.service.xml
@@ -95,6 +95,16 @@
Desktop Environments</ulink>.</para>
</refsect1>
+ <refsect1>
+ <title>Signal</title>
+ <variablelist>
+ <varlistentry>
+ <term><constant>SIGHUP</constant></term>
+ <listitem><para>Reloads the service configuration file.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
diff --git a/tools/command_ignorelist b/tools/command_ignorelist
index 42076013e4..ffbff08867 100644
--- a/tools/command_ignorelist
+++ b/tools/command_ignorelist
@@ -161,6 +161,7 @@ systemd-inhibit.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="
systemd-inhibit.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--why="]
systemd-inhibit.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--mode="]
systemd-inhibit.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--list"]
+systemd-logind.service.xml ./refsect1[title="Signal"]/
systemd-notify.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--ready"]
systemd-notify.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--pid="]
systemd-notify.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--status="]

View File

@ -0,0 +1,131 @@
From aba4e35c7af08fadf1d434f892f0b4b87ee9fafc Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Mon, 13 Oct 2025 17:36:55 +0200
Subject: [PATCH] timer: rebase the next elapse timestamp only if timer didn't
already run
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The test added in f4c3c107d9be4e922a080fc292ed3889c4e0f4a5 uncovered a
corner case while recalculating the next elapse timestamp of a timer unit
that uses RandomizedDelaySec= during deserialization.
If the scheduled time (without RandomizedDelaySec=) already elapsed,
systemd "rebases" the next elapse timestamp to the time when systemd
first started, to make the RandomizedDelaySec= feature work even at
boot. However, since it was done unconditionally, it always overrode the
next elapse timestamp, which could then cause the final next elapse
timestamp to fall out of the expected window.
With a couple of additional debug logs one of the test fail looks like
this:
[ 132.129815] TEST-53-TIMER.sh[384]: + : 'Next elapse timestamp after daemon-reload, try #328'
[ 132.129815] TEST-53-TIMER.sh[384]: + systemctl daemon-reload
[ 132.136352] systemd[1]: Reload requested from client PID 16399 ('systemctl') (unit TEST-53-TIMER.service)...
[ 132.136636] systemd[1]: Reloading...
[ 132.446160] systemd[1]: Rebasing next elapse timestamp
[ 132.446168] systemd[1]: v->next_elapse: Tue 2025-10-14 00:10:00 CEST
[ 132.446170] systemd[1]: rebased: Tue 2025-10-14 00:10:56 CEST
[ 132.446172] systemd[1]: v->next_elapse after rebase: Tue 2025-10-14 00:10:56 CEST
[ 132.447361] systemd[1]: Reloading finished in 310 ms.
[ 132.484041] TEST-53-TIMER.sh[384]: + check_elapse_timestamp
[ 132.484041] TEST-53-TIMER.sh[384]: + systemctl status timer-RandomizedDelaySec-16377.timer
[ 132.533657] TEST-53-TIMER.sh[16440]: ● timer-RandomizedDelaySec-16377.timer
[ 132.533657] TEST-53-TIMER.sh[16440]: Loaded: loaded (/run/systemd/system/timer-RandomizedDelaySec-16377.timer; static)
[ 132.533657] TEST-53-TIMER.sh[16440]: Active: active (waiting) since Mon 2025-10-13 23:00:00 CEST; 1h 13min ago
[ 132.533657] TEST-53-TIMER.sh[16440]: Invocation: 5555d4f060114a5493ff228013830d17
[ 132.533657] TEST-53-TIMER.sh[16440]: Trigger: Tue 2025-10-14 22:10:04 CEST; 21h left
[ 132.533657] TEST-53-TIMER.sh[16440]: Triggers: ● timer-RandomizedDelaySec-16377.service
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 15h 35min 1.230173s random time.
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 15:45:58 CEST.
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 16h 29min 44.084409s random time.
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 16:40:41 CEST.
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 21h 59min 7.955828s random time.
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 22:10:04 CEST.
[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[ 132.535386] TEST-53-TIMER.sh[384]: + systemctl show -p InactiveExitTimestamp timer-RandomizedDelaySec-16377.timer
[ 132.537727] TEST-53-TIMER.sh[16442]: InactiveExitTimestamp=Mon 2025-10-13 23:00:00 CEST
[ 132.540317] TEST-53-TIMER.sh[16444]: ++ systemctl show -P NextElapseUSecRealtime timer-RandomizedDelaySec-16377.timer
[ 132.547745] TEST-53-TIMER.sh[384]: + NEXT_ELAPSE_REALTIME='Tue 2025-10-14 22:10:04 CEST'
[ 132.548020] TEST-53-TIMER.sh[16445]: ++ date '--date=Tue 2025-10-14 22:10:04 CEST' +%s
[ 132.550218] TEST-53-TIMER.sh[384]: + NEXT_ELAPSE_REALTIME_S=1760472604
[ 132.550218] TEST-53-TIMER.sh[384]: + : 'Next elapse timestamp should be Tue 2025-10-14 00:10:00 CEST <= Tue 2025-10-14 22:10:04 CEST <= Tue 2025-10-14 22:10:00 CEST'
[ 132.550218] TEST-53-TIMER.sh[384]: + assert_ge 1760472604 1760393400
[ 132.550555] TEST-53-TIMER.sh[16446]: + set +ex
[ 132.550702] TEST-53-TIMER.sh[384]: + assert_le 1760472604 1760472600
[ 132.550832] TEST-53-TIMER.sh[16447]: + set +ex
[ 132.551091] TEST-53-TIMER.sh[16447]: FAIL: '1760472604' > '1760472600'
Here the original next elapse timestamp was Tue 2025-10-14 00:10:00 CEST
as expected, but it was overridden by the rebased timestamp:
Tue 2025-10-14 00:10:56 CEST. And when a new randomized delay was added
to it (21h 59min 7.955828s) the final next elapse timestamp fell out of
the expected window, i.e. Tue 2025-10-14 00:10:00 (scheduled time) <
Tue 2025-10-14 22:10:04 CEST (rebased elapse timestamp + randomized
delay) < Tue 2025-10-14 22:10:00 CEST (scheduled time + maximum from
RandomizedDelaySec=, i.e. 22h).
By limiting the timestamp rebase only the case where the unit hasn't
already run should prevent this from happening during daemon-reload.
(cherry picked from commit bdb8e584f4509de0daebbe2357d23156160c3a90)
Related: RHEL-118216
---
src/core/timer.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index 02fdf91c78..2fc95d597d 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -391,7 +391,8 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
continue;
if (v->base == TIMER_CALENDAR) {
- usec_t b, rebased;
+ bool rebase_after_boot_time = false;
+ usec_t b;
/* If DeferReactivation= is enabled, schedule the job based on the last time
* the trigger unit entered inactivity. Otherwise, if we know the last time
@@ -409,21 +410,25 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
b = t->last_trigger.realtime;
else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
b = UNIT(t)->inactive_exit_timestamp.realtime;
- else
+ else {
b = ts.realtime;
+ rebase_after_boot_time = true;
+ }
r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
if (r < 0)
continue;
- /* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
- * time has already passed, set the time when systemd first started as the scheduled
- * time. Note that we base this on the monotonic timestamp of the boot, not the
- * realtime one, since the wallclock might have been off during boot. */
- rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
- CLOCK_MONOTONIC, CLOCK_REALTIME);
- if (v->next_elapse < rebased)
- v->next_elapse = rebased;
+ if (rebase_after_boot_time) {
+ /* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
+ * time has already passed, set the time when systemd first started as the scheduled
+ * time. Note that we base this on the monotonic timestamp of the boot, not the
+ * realtime one, since the wallclock might have been off during boot. */
+ usec_t rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
+ CLOCK_MONOTONIC, CLOCK_REALTIME);
+ if (v->next_elapse < rebased)
+ v->next_elapse = rebased;
+ }
if (!found_realtime)
t->next_elapse_realtime = v->next_elapse;

View File

@ -0,0 +1,144 @@
From 974b8e42491ddf150f01f4e0b224d180ab1fe8fa Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 19 Nov 2025 14:44:13 +0100
Subject: [PATCH] timer: rebase last_trigger timestamp if needed
After bdb8e584f4509de0daebbe2357d23156160c3a90 we stopped rebasing the
next elapse timestamp unconditionally and the only case where we'd do
that was when both last trigger and last inactive timestamps were empty.
This covered timer units during boot just fine, since they would have
neither of those timestamps set. However, persistent timers
(Persistent=yes) store their last trigger timestamp on a persistent
storage and load it back after reboot, so the rebasing was skipped in
this case.
To mitigate this, check the last_trigger timestamp is older than the
current machine boot - if so, that means that it came from a stamp file
of a persistent timer unit and we need to rebase it to make
RandomizedDelaySec= work properly.
Follow-up for bdb8e584f4509de0daebbe2357d23156160c3a90.
(cherry picked from commit 3605b3ba87833a9919bfde05952a7d9de10499a2)
Related: RHEL-118216
---
src/core/timer.c | 15 +++--
...-53-TIMER.RandomizedDelaySec-persistent.sh | 67 +++++++++++++++++++
2 files changed, 78 insertions(+), 4 deletions(-)
create mode 100755 test/units/TEST-53-TIMER.RandomizedDelaySec-persistent.sh
diff --git a/src/core/timer.c b/src/core/timer.c
index 2fc95d597d..4158a67b5e 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -393,6 +393,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
if (v->base == TIMER_CALENDAR) {
bool rebase_after_boot_time = false;
usec_t b;
+ usec_t boot_monotonic = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic;
/* If DeferReactivation= is enabled, schedule the job based on the last time
* the trigger unit entered inactivity. Otherwise, if we know the last time
@@ -406,9 +407,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
t->last_trigger.realtime);
else
b = trigger->inactive_enter_timestamp.realtime;
- } else if (dual_timestamp_is_set(&t->last_trigger))
+ } else if (dual_timestamp_is_set(&t->last_trigger)) {
b = t->last_trigger.realtime;
- else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
+
+ /* Check if the last_trigger timestamp is older than the current machine
+ * boot. If so, this means the timestamp came from a stamp file of a
+ * persistent timer and we need to rebase it to make RandomizedDelaySec=
+ * work (see below). */
+ if (t->last_trigger.monotonic < boot_monotonic)
+ rebase_after_boot_time = true;
+ } else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
b = UNIT(t)->inactive_exit_timestamp.realtime;
else {
b = ts.realtime;
@@ -424,8 +432,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
* time has already passed, set the time when systemd first started as the scheduled
* time. Note that we base this on the monotonic timestamp of the boot, not the
* realtime one, since the wallclock might have been off during boot. */
- usec_t rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
- CLOCK_MONOTONIC, CLOCK_REALTIME);
+ usec_t rebased = map_clock_usec(boot_monotonic, CLOCK_MONOTONIC, CLOCK_REALTIME);
if (v->next_elapse < rebased)
v->next_elapse = rebased;
}
diff --git a/test/units/TEST-53-TIMER.RandomizedDelaySec-persistent.sh b/test/units/TEST-53-TIMER.RandomizedDelaySec-persistent.sh
new file mode 100755
index 0000000000..af22daecc7
--- /dev/null
+++ b/test/units/TEST-53-TIMER.RandomizedDelaySec-persistent.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Persistent timers (i.e. timers with Persitent=yes) save their last trigger timestamp to a persistent
+# storage (a stamp file), which is loaded during subsequent boots. As mentioned in the man page, such timers
+# should be still affected by RandomizedDelaySec= during boot even if they already elapsed and would be then
+# triggered immediately.
+#
+# This behavior was, however, broken by [0], which stopped rebasing the to-be next elapse timestamps
+# unconditionally and left that only for timers that have neither last trigger nor inactive exit timestamps
+# set, since rebasing is needed only during boot. This holds for regular timers during boot, but not for
+# persistent ones, since the last trigger timestamp is loaded from a persistent storage.
+#
+# Provides coverage for:
+# - https://github.com/systemd/systemd/issues/39739
+#
+# [0] bdb8e584f4509de0daebbe2357d23156160c3a90
+#
+set -eux
+set -o pipefail
+
+# shellcheck source=test/units/test-control.sh
+. "$(dirname "$0")"/util.sh
+
+UNIT_NAME="timer-RandomizedDelaySec-persistent-$RANDOM"
+STAMP_FILE="/var/lib/systemd/timers/stamp-$UNIT_NAME.timer"
+
+# Setup
+cat >"/run/systemd/system/$UNIT_NAME.timer" <<EOF
+[Timer]
+OnCalendar=daily
+Persistent=true
+RandomizedDelaySec=12h
+EOF
+
+cat >"/run/systemd/system/$UNIT_NAME.service" <<\EOF
+[Service]
+ExecStart=echo "Service ran at $(date)"
+EOF
+
+systemctl daemon-reload
+
+# Create timer's state file with an old-enough timestamp (~2 days ago), so it'd definitely elapse if the next
+# elapse timestamp wouldn't get rebased
+mkdir -p "$(dirname "$STAMP_FILE")"
+touch -d "2 days ago" "$STAMP_FILE"
+stat "$STAMP_FILE"
+SAVED_LAST_TRIGGER_S="$(stat --format="%Y" "$STAMP_FILE")"
+
+# Start the timer and verify that its last trigger timestamp didn't change
+#
+# The last trigger timestamp should get rebased before it gets used as a base for the next elapse timestamp
+# (since it pre-dates the machine boot time). This should then add a RandomizedDelaySec= to the rebased
+# timestamp and the timer unit should not get triggered immediately after starting.
+systemctl start "$UNIT_NAME.timer"
+systemctl status "$UNIT_NAME.timer"
+
+TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec --value "$UNIT_NAME.timer")"
+TIMER_LAST_TRIGGER_S="$(date --date="$TIMER_LAST_TRIGGER" "+%s")"
+: "The timer should not be triggered immediately, hence the last trigger timestamp should not change"
+assert_eq "$SAVED_LAST_TRIGGER_S" "$TIMER_LAST_TRIGGER_S"
+
+# Cleanup
+systemctl stop "$UNIT_NAME".{timer,service}
+systemctl clean --what=state "$UNIT_NAME.timer"
+rm -f "/run/systemd/system/$UNIT_NAME".{timer,service}
+systemctl daemon-reload

View File

@ -0,0 +1,114 @@
From 3ef86b28a4933e2cc4169c3b13143999269e4bf1 Mon Sep 17 00:00:00 2001
From: Jules Lamur <contact@juleslamur.fr>
Date: Mon, 7 Apr 2025 18:49:26 +0200
Subject: [PATCH] fstab-generator: fix options in systemd.mount-extra= arg
Fixes a bug introduced by 55365b0a233ae3024411fd0815ad930e20f6a3d6 (v254).
The arguments `(rd.)systemd.mount-extra` take a value that looks like
`WHAT:WHERE[:FSTYPE[:OPTIONS]]`. The `OPTIONS` were parsed into a nulstr
where a comma-separated c-string was expected. This leads to a bug where
only the first option was taken into account by the generator.
For example, if you passed `systemd.mount-extra=/x:/y:baz:ro,defaults`
to the kernel, `systemd-fstab-generator` would translate that into a
nulstr: `ro\0defaults\0`.
Since methods processing options in the generator expected a
comma-separated c-string, they would only see the first option, `ro` in
this case.
(cherry picked from commit 06fadc4286fee6a7505a88659e5ae2e6f3ee60ba)
Resolves: RHEL-125822
---
src/fstab-generator/fstab-generator.c | 21 ++++---------------
.../hoge-withx20space.mount | 2 +-
.../dev-sdy3.swap | 2 +-
.../dev-sdy3.swap | 0
4 files changed, 6 insertions(+), 19 deletions(-)
rename test/test-fstab-generator/test-20-swap-from-cmdline.expected/{swap.target.requires => swap.target.wants}/dev-sdy3.swap (100%)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 6b7445b201..590042e992 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -109,15 +109,15 @@ static int mount_array_add_internal(
char *in_what,
char *in_where,
const char *in_fstype,
- const char *in_options) {
+ char *in_options) {
_cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL;
- int r;
/* This takes what and where. */
what = ASSERT_PTR(in_what);
where = in_where;
+ options = in_options;
fstype = strdup(isempty(in_fstype) ? "auto" : in_fstype);
if (!fstype)
@@ -126,19 +126,6 @@ static int mount_array_add_internal(
if (streq(fstype, "swap"))
where = mfree(where);
- if (!isempty(in_options)) {
- _cleanup_strv_free_ char **options_strv = NULL;
-
- r = strv_split_full(&options_strv, in_options, ",", 0);
- if (r < 0)
- return r;
-
- r = strv_make_nulstr(options_strv, &options, NULL);
- } else
- r = strv_make_nulstr(STRV_MAKE("defaults"), &options, NULL);
- if (r < 0)
- return r;
-
if (!GREEDY_REALLOC(arg_mounts, arg_n_mounts + 1))
return -ENOMEM;
@@ -168,7 +155,7 @@ static int mount_array_add(bool for_initrd, const char *str) {
if (!isempty(str))
return -EINVAL;
- return mount_array_add_internal(for_initrd, TAKE_PTR(what), TAKE_PTR(where), fstype, options);
+ return mount_array_add_internal(for_initrd, TAKE_PTR(what), TAKE_PTR(where), fstype, TAKE_PTR(options));
}
static int mount_array_add_swap(bool for_initrd, const char *str) {
@@ -186,7 +173,7 @@ static int mount_array_add_swap(bool for_initrd, const char *str) {
if (!isempty(str))
return -EINVAL;
- return mount_array_add_internal(for_initrd, TAKE_PTR(what), NULL, "swap", options);
+ return mount_array_add_internal(for_initrd, TAKE_PTR(what), NULL, "swap", TAKE_PTR(options));
}
static int write_options(FILE *f, const char *options) {
diff --git a/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount b/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount
index e9ffb4bbd9..d3797c9706 100644
--- a/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount
+++ b/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount
@@ -9,4 +9,4 @@ Before=remote-fs.target
What=//foo￾bar
Where=/hoge/with space
Type=cifs
-Options=rw
+Options=rw,seclabel
diff --git a/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap b/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap
index 3b6563d216..1b4b53c9b8 100644
--- a/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap
+++ b/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap
@@ -7,4 +7,4 @@ After=blockdev@dev-sdy3.target
[Swap]
What=/dev/sdy3
-Options=x-systemd.makefs
+Options=x-systemd.makefs,nofail
diff --git a/test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.requires/dev-sdy3.swap b/test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.wants/dev-sdy3.swap
similarity index 100%
rename from test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.requires/dev-sdy3.swap
rename to test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.wants/dev-sdy3.swap

View File

@ -0,0 +1,27 @@
From f925283662c7d00c1686121b13963150dc2acf3c Mon Sep 17 00:00:00 2001
From: Rostislav Lastochkin <remtrik@mail.ru>
Date: Sun, 17 Aug 2025 18:59:25 +0300
Subject: [PATCH] hwdb: Add Accelerometer mount matrix for Irbis TW43
(cherry picked from commit e196be154e9e7fc16b477d6cd09a58010990fb15)
Resolves: RHEL-72702
---
hwdb.d/60-sensor.hwdb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb
index d242025bd2..559fd4151e 100644
--- a/hwdb.d/60-sensor.hwdb
+++ b/hwdb.d/60-sensor.hwdb
@@ -662,6 +662,10 @@ sensor:modalias:acpi:BMA250*:dmi:*:bvritWORKS.G.WI71C.JGBMRB*:*:svnInsyde:pni71c
# Irbis
#########################################
+#TW43
+sensor:modalias:acpi:BMA250E*:dmi:*:svnIRBIS:pnTW43:*
+ ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, -1
+
#TW90
sensor:modalias:acpi:BOSC0200*:dmi:*:svnIRBIS:pnTW90:*
ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1

View File

@ -0,0 +1,30 @@
From e7f97ca0d9ab2843eb05eb42604a37d19c49ada1 Mon Sep 17 00:00:00 2001
From: Alexander Bruy <alexander.bruy@gmail.com>
Date: Tue, 19 Aug 2025 11:05:00 +0100
Subject: [PATCH] hwdb: map FN key on TongFang X4SP4NAL laptops
(cherry picked from commit b15ff659b49eef0d256ac901af625f72febcaee3)
Resolves: RHEL-72702
---
hwdb.d/60-keyboard.hwdb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hwdb.d/60-keyboard.hwdb b/hwdb.d/60-keyboard.hwdb
index 465d527817..20c8662af4 100644
--- a/hwdb.d/60-keyboard.hwdb
+++ b/hwdb.d/60-keyboard.hwdb
@@ -2015,6 +2015,13 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnSystem76*:pnPangolin*:pvrpang15*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnT-bao:pnTbookair:*
KEYBOARD_KEY_76=touchpad_toggle # Touchpad toggle
+###########################################################
+# TongFang
+###########################################################
+# TongFang GX4 (X4SP4NAL)
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAiStone:pnX4SP4NAL:*
+ KEYBOARD_KEY_f8=fn
+
###########################################################
# Toshiba
###########################################################

7022
0502-hwdb-update-rules.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
From 6461bdbc4d147359b1efcc594b00cc25cd384b34 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@gmail.com>
Date: Wed, 20 Aug 2025 13:06:08 +0100
Subject: [PATCH] hwdb: update autosuspend rules
ninja -C build update-hwdb-autosuspend
(cherry picked from commit 26f971909e2e772fb5929495fb1e0bba617aeaf3)
Resolves: RHEL-72702
---
hwdb.d/60-autosuspend-fingerprint-reader.hwdb | 1 +
1 file changed, 1 insertion(+)
diff --git a/hwdb.d/60-autosuspend-fingerprint-reader.hwdb b/hwdb.d/60-autosuspend-fingerprint-reader.hwdb
index eb25c6bd1e..6f1099318a 100644
--- a/hwdb.d/60-autosuspend-fingerprint-reader.hwdb
+++ b/hwdb.d/60-autosuspend-fingerprint-reader.hwdb
@@ -188,6 +188,7 @@ usb:v2808pA78A*
# Supported by libfprint driver fpcmoc
usb:v10A5pFFE0*
usb:v10A5pA305*
+usb:v10A5pA306*
usb:v10A5pDA04*
usb:v10A5pD805*
usb:v10A5pD205*

View File

@ -0,0 +1,36 @@
From 739b86e502b1a34ac260522fee177fc1491b9568 Mon Sep 17 00:00:00 2001
From: Christopher Head <chead@chead.ca>
Date: Wed, 20 Aug 2025 23:52:38 -0700
Subject: [PATCH] Add Razer Cobra mouse to hwdb
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The DPI values are based on the products printed documentation. The
frequency values are based on the endpoint descriptor reported by lsusb
(the mouse is a full-speed USB device and bInterval is 1 at all DPI
settings). Both sets of values are for a mouse that has *not* been
touched by the vendors configuration tool.
(cherry picked from commit bd254d371bcfa5154d67937722984e1a4a0e212a)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index d054aeffe6..da64f4837e 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -833,6 +833,10 @@ mouse:usb:v1532p0042:name:Razer Razer Abyssus:*
mouse:usb:v1532p0029:name:Razer Razer DeathAdder:*
MOUSE_DPI=3500@1000
+# Razer Cobra RZ04-03750300-R3U1
+mouse:usb:v1532p00a3:name:Razer Razer Cobra:*
+ MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000 6400@1000
+
##########################################
# Roccat
##########################################

View File

@ -0,0 +1,27 @@
From cb9e41823e67873669f14030d78408632496be55 Mon Sep 17 00:00:00 2001
From: Jack Wu <wojackbb@gmail.com>
Date: Fri, 22 Aug 2025 17:23:46 +0800
Subject: [PATCH] hwdb: enable autosuspend for Dell DW5826e WWAN modem
(cherry picked from commit 46a688c559886230cc41018348415dda9b59b3cd)
Resolves: RHEL-72702
---
hwdb.d/60-autosuspend.hwdb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hwdb.d/60-autosuspend.hwdb b/hwdb.d/60-autosuspend.hwdb
index f564c6aed9..0e38c0a9a4 100644
--- a/hwdb.d/60-autosuspend.hwdb
+++ b/hwdb.d/60-autosuspend.hwdb
@@ -96,6 +96,10 @@ usb:v2CB7p0007*
ID_AUTOSUSPEND=1
ID_AUTOSUSPEND_DELAY_MS=7000
+# Dell Computer Corp. DW5826e Qualcomm Snapdragon X12 Global LTE-A
+usb:v413Cp8217*
+ ID_AUTOSUSPEND=1
+
#########################################
# Wacom
#########################################

View File

@ -0,0 +1,60 @@
From 01746a1c7368214e3cbaa795bd87f64381cb65c8 Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Mon, 25 Aug 2025 11:14:28 +0200
Subject: [PATCH] hwdb: sort SDR devices by vendor name
(cherry picked from commit e8628ddb787026022c0b91a42dfeb3c782698df3)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index b005309101..61b0428363 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -21,21 +21,6 @@
# Allowed properties are:
# ID_SOFTWARE_RADIO=0|1
-##########################################
-# Nuand
-##########################################
-# bladeRF 1.x
-usb:v2CF0p5246*
- ID_SOFTWARE_RADIO=1
-
-# bladeRF 1.x (legacy)
-usb:v1D50p6066*
- ID_SOFTWARE_RADIO=1
-
-# bladeRF 2.0 micro
-usb:v2CF0p5250*
- ID_SOFTWARE_RADIO=1
-
##########################################
# Analog Devices
##########################################
@@ -67,6 +52,21 @@ usb:v3923p7813*
usb:v3923p7814*
ID_SOFTWARE_RADIO=1
+##########################################
+# Nuand
+##########################################
+# bladeRF 1.x
+usb:v2CF0p5246*
+ ID_SOFTWARE_RADIO=1
+
+# bladeRF 1.x (legacy)
+usb:v1D50p6066*
+ ID_SOFTWARE_RADIO=1
+
+# bladeRF 2.0 micro
+usb:v2CF0p5250*
+ ID_SOFTWARE_RADIO=1
+
##########################################
# RTL-SDR
##########################################

View File

@ -0,0 +1,69 @@
From 9b5f228f5ebd20eed794c527d2e37fcaded8bd09 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20P=C3=A1ral?= <kamil.paral@gmail.com>
Date: Mon, 25 Aug 2025 22:00:47 +0200
Subject: [PATCH] 70-mouse.hwdb: Add Razer Basilisk V3, Asus Cerberus, +2 more
All mice were measured using mouse-dpi-tool, and the measurements match vendors
specs, with the exception of Asus Cerberus (it officially has
500/*1000/1500/2500 DPI, but my measurements were quite different, so I opted
to include the real values).
(cherry picked from commit 2f615ec1d1a597586af15e6e94c0b3503a7da108)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index da64f4837e..dc9be4f915 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -191,6 +191,14 @@ mouse:bluetooth:v256fpc63a:name:*
mouse:bluetooth:v05acp030d:name:*:*
MOUSE_DPI=1300@1000
+##########################################
+# Asus
+##########################################
+
+# Asus Cerberus
+mouse:usb:v04d9pa0d6:name:E-Signal/A-One USB Gaming Mouse:*
+ MOUSE_DPI=800@500 *1350@500 1600@500 2650@500
+
##########################################
# Cherry
##########################################
@@ -388,6 +396,10 @@ mouse:usb:v17efp6045:name:Lenovo USB Laser Mouse:*
mouse:usb:v17efp6044:name:ThinkPad USB Laser Mouse:*
MOUSE_DPI=1200@125
+# Lenovo Essential USB Mouse (SM-8823)
+mouse:usb:v17efp608d:name:PixArt Lenovo USB Optical Mouse:*
+ MOUSE_DPI=1600@125
+
##########################################
# Logitech
##########################################
@@ -675,6 +687,10 @@ mouse:usb:v046dpc517:name:Logitech USB Receiver:*
mouse:usb:v046dpc046:name:Logitech USB Optical Mouse:*
MOUSE_DPI=1000@125
+# Logitech RX1500
+mouse:usb:v046dpc061:name:Logitech USB Laser Mouse:*
+ MOUSE_DPI=1000@125
+
# Logitech M100 Optical Mouse
mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:*
MOUSE_DPI=1000@125
@@ -837,6 +853,10 @@ mouse:usb:v1532p0029:name:Razer Razer DeathAdder:*
mouse:usb:v1532p00a3:name:Razer Razer Cobra:*
MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000 6400@1000
+# Razer Basilisk V3
+mouse:usb:v1532p0099:name:Razer Razer Basilisk V3:*
+ MOUSE_DPI=400@125 800@125 1600@125 3200@125 6400@125 400@500 800@500 1600@500 3200@500 6400@500 400@1000 800@1000 *1600@1000 3200@1000 6400@1000
+
##########################################
# Roccat
##########################################

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
From 6ac255a57fc953a6de35c307b5b120063ab1c704 Mon Sep 17 00:00:00 2001
From: Martin Homuth-Rosemann <Ho-Ro@users.noreply.github.com>
Date: Tue, 9 Sep 2025 17:32:45 +0200
Subject: [PATCH] Add Hantek DSO-6022 oscilloscopes and compatible devices
Signed-off-by: Martin Homuth-Rosemann <Ho-Ro@users.noreply.github.com>
(cherry picked from commit 3efabf88cd8348e76d5f032dd0b4b2ded7c6f06d)
Resolves: RHEL-72702
---
hwdb.d/70-analyzers.hwdb | 55 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/hwdb.d/70-analyzers.hwdb b/hwdb.d/70-analyzers.hwdb
index 821ebcb1ca..f56ee97739 100644
--- a/hwdb.d/70-analyzers.hwdb
+++ b/hwdb.d/70-analyzers.hwdb
@@ -16,6 +16,61 @@
usb:v1209p4D69*
ID_SIGNAL_ANALYZER=1
+###########################################################
+# Hantek DSO-6022 oscilloscopes and compatible devices
+###########################################################
+# Hantek DSO-6022BE w/o FW
+usb:v04B4p6022*
+ ID_SIGNAL_ANALYZER=1
+
+# Hantek DSO-6022BE with FW
+usb:v04B5p6022*
+ ID_SIGNAL_ANALYZER=1
+
+# Hantek DSO-6022BL w/o FW
+usb:v04B4p602A*
+ ID_SIGNAL_ANALYZER=1
+
+# Hantek DSO-6022BL with FW
+usb:v04B5p602A*
+ ID_SIGNAL_ANALYZER=1
+
+# Hantek DSO-6021 w/o FW
+usb:v04B4p6021*
+ ID_SIGNAL_ANALYZER=1
+
+# Hantek DSO-6021 with FW
+usb:v04B5p6021*
+ ID_SIGNAL_ANALYZER=1
+
+# Voltcraft DSO-2020, w/o FW, becomes DSO-6022BE with FW
+usb:v04B4p2020*
+ ID_SIGNAL_ANALYZER=1
+
+# YiXingDianZiKeJi MDSO w/o FW
+usb:vD4A2p5660*
+ ID_SIGNAL_ANALYZER=1
+
+# YiXingDianZiKeJi MDSO with FW
+usb:v1D50p608E*
+ ID_SIGNAL_ANALYZER=1
+
+# BUUDAI DDS120 w/o FW
+usb:v8102p8102*
+ ID_SIGNAL_ANALYZER=1
+
+# BUUDAI DDS120 with FW
+usb:v04B5p0120*
+ ID_SIGNAL_ANALYZER=1
+
+# Instrustar isds-205b w/o FW
+usb:vD4A2p5661*
+ ID_SIGNAL_ANALYZER=1
+
+# Instrustar isds-205b with FW
+usb:v1D50p1D50*
+ ID_SIGNAL_ANALYZER=1
+
###########################################################
# Total Phase
###########################################################

View File

@ -0,0 +1,29 @@
From b69616e750d8d180a24a14caa8714b3dcdc3bbbf Mon Sep 17 00:00:00 2001
From: DeKoile <132840552+DeKoile@users.noreply.github.com>
Date: Wed, 10 Sep 2025 20:22:36 +0200
Subject: [PATCH] Update 60-sensor.hwdb - Add support for Lenovo Legion Go
This adds support for the 3D Accelerometer of the Lenovo Legion Go
(cherry picked from commit 63254ed696d129cc46752e639ae761b758d7b251)
Resolves: RHEL-72702
---
hwdb.d/60-sensor.hwdb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb
index 559fd4151e..9c85bc3357 100644
--- a/hwdb.d/60-sensor.hwdb
+++ b/hwdb.d/60-sensor.hwdb
@@ -778,6 +778,10 @@ sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XE:*
sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80U1:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
+# Legion Go
+sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnLENOVO:pn83E1:*
+ ACCEL_MOUNT_MATRIX=0,1,0;-1,0,0;0,0,1
+
# Yoga 300-11IBR, display sensor
sensor:modalias:acpi:DUAL250E*:dmi:*:svnLENOVO:*:pvrLenovoYoga300-11IBR:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1

View File

@ -0,0 +1,34 @@
From f4ee18b08a7dad5562ba3511f19881ee0cc9c5ca Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Tue, 9 Sep 2025 11:56:18 +0200
Subject: [PATCH] hwdb: add Airspy devices
(cherry picked from commit 8fadcd15d3c50145dec1ad49b742c2eb1a690369)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index 61b0428363..43ea0f2588 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -21,6 +21,17 @@
# Allowed properties are:
# ID_SOFTWARE_RADIO=0|1
+##########################################
+# Airspy
+##########################################
+# Airspy R2
+usb:v1D50p60A1*
+ ID_SOFTWARE_RADIO=1
+
+# Airspy HF+
+usb:v03EBp800C*
+ ID_SOFTWARE_RADIO=1
+
##########################################
# Analog Devices
##########################################

View File

@ -0,0 +1,56 @@
From c4cca5bb8658701f22f3c8d688811231df0e96ae Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Thu, 11 Sep 2025 00:58:46 +0200
Subject: [PATCH] hwdb: add more devices
- FUNcube Dongle Pro
- Great Scott Gadgets HackRF
- Microtelecom Perseus
(cherry picked from commit c61bdd79ef1703fa988d5f156a4bcff25f98bd90)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index 43ea0f2588..7d4138fdc1 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -63,6 +63,35 @@ usb:v3923p7813*
usb:v3923p7814*
ID_SOFTWARE_RADIO=1
+##########################################
+# FUNcube
+##########################################
+# FUNcube Dongle Pro
+usb:v04D8pFB56*
+ ID_SOFTWARE_RADIO=1
+
+# FUNcube Dongle Pro+
+usb:v04D8pFB31*
+ ID_SOFTWARE_RADIO=1
+
+##########################################
+# Great Scott Gadgets
+##########################################
+# HackRF Jawbreaker
+usb:v1D50p604B*
+ ID_SOFTWARE_RADIO=1
+
+# HackRF One
+usb:v1D50p6089*
+ ID_SOFTWARE_RADIO=1
+
+##########################################
+# Microtelecom
+##########################################
+# Perseus
+usb:v04B4p325C*
+ ID_SOFTWARE_RADIO=1
+
##########################################
# Nuand
##########################################

View File

@ -0,0 +1,30 @@
From 08d191a8f240cd5ced65bef1003173e982b055f7 Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Thu, 11 Sep 2025 02:38:06 +0200
Subject: [PATCH] hwdb: add MiriSDR MSi2500 devices
(cherry picked from commit 11c58b6774134fc06fb833ea1720fc0f5ca73453)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index 7d4138fdc1..9ae41601a2 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -92,6 +92,13 @@ usb:v1D50p6089*
usb:v04B4p325C*
ID_SOFTWARE_RADIO=1
+##########################################
+# MiriSDR
+##########################################
+# Mirics MSi2500 default (e.g. VTX3D card)
+usb:v1DF7p2500*
+ ID_SOFTWARE_RADIO=1
+
##########################################
# Nuand
##########################################

View File

@ -0,0 +1,28 @@
From 14a249339749efc21cf6cf468510487c731192ff Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Thu, 11 Sep 2025 16:14:18 +0200
Subject: [PATCH] hwdb: add missing Ettus Research B200 rule
https://github.com/EttusResearch/uhd/blob/master/host/utils/uhd-usrp.rules#L18
Not sure why it was missing.
(cherry picked from commit 69442f94b58dd137e3d163b0ec0187f1a5c0ae13)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 1 +
1 file changed, 1 insertion(+)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index 9ae41601a2..7b885cac0b 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -59,6 +59,7 @@ usb:v2500p0002*
usb:v2500p0020*
usb:v2500p0021*
usb:v2500p0022*
+usb:v2500p0023*
usb:v3923p7813*
usb:v3923p7814*
ID_SOFTWARE_RADIO=1

View File

@ -0,0 +1,30 @@
From ee5a3f14e24c9b9f2594e58deb1e429724d90e8a Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Thu, 11 Sep 2025 21:32:18 +0200
Subject: [PATCH] hwdb: add LimeSDR XTRX devices
(cherry picked from commit 56347fe7f32d0427b371e3c354486241d4e98a20)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index 7b885cac0b..79e91dc5ef 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -86,6 +86,13 @@ usb:v1D50p604B*
usb:v1D50p6089*
ID_SOFTWARE_RADIO=1
+##########################################
+# LimeSDR
+##########################################
+# XTRX (USB3380)
+usb:v0525p3380*
+ ID_SOFTWARE_RADIO=1
+
##########################################
# Microtelecom
##########################################

View File

@ -0,0 +1,30 @@
From e2438bb5f5d8632f6e8f1d8a20e2e52b3c4784dd Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Mon, 15 Sep 2025 02:14:08 +0200
Subject: [PATCH] hwdb: add HydraSDR RFOne
(cherry picked from commit bb4c00001d29151fc44267776c6099711eb4362d)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index 79e91dc5ef..f1723e1fa9 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -86,6 +86,13 @@ usb:v1D50p604B*
usb:v1D50p6089*
ID_SOFTWARE_RADIO=1
+##########################################
+# HydraSDR
+##########################################
+# HydraSDR RFOne
+usb:v38AFp0001*
+ ID_SOFTWARE_RADIO=1
+
##########################################
# LimeSDR
##########################################

View File

@ -0,0 +1,67 @@
From 1592be7d9b8a652c0f680bd3b6bbd8e20f7d1f02 Mon Sep 17 00:00:00 2001
From: AsciiWolf <mail@asciiwolf.com>
Date: Tue, 16 Sep 2025 01:06:18 +0200
Subject: [PATCH] hwdb: add SDRplay devices
Also remove duplicate MiriSDR device that is just a cheap SDRplay RSP1 copy
(cherry picked from commit 0125be8733023fedb4d97c8e79b19717708e7ade)
Resolves: RHEL-72702
---
hwdb.d/70-software-radio.hwdb | 38 ++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/hwdb.d/70-software-radio.hwdb b/hwdb.d/70-software-radio.hwdb
index f1723e1fa9..63af9c77cd 100644
--- a/hwdb.d/70-software-radio.hwdb
+++ b/hwdb.d/70-software-radio.hwdb
@@ -107,13 +107,6 @@ usb:v0525p3380*
usb:v04B4p325C*
ID_SOFTWARE_RADIO=1
-##########################################
-# MiriSDR
-##########################################
-# Mirics MSi2500 default (e.g. VTX3D card)
-usb:v1DF7p2500*
- ID_SOFTWARE_RADIO=1
-
##########################################
# Nuand
##########################################
@@ -299,3 +292,34 @@ usb:v1F4DpD286*
# PROlectrix DV107669 (FC0012)
usb:v1F4DpD803*
ID_SOFTWARE_RADIO=1
+
+##########################################
+# SDRplay
+##########################################
+# RSP1
+usb:v1DF7p2500*
+ ID_SOFTWARE_RADIO=1
+
+# RSP1A
+usb:v1DF7p3000*
+ ID_SOFTWARE_RADIO=1
+
+# RSP2/RSP2pro
+usb:v1DF7p3010*
+ ID_SOFTWARE_RADIO=1
+
+# RSPduo
+usb:v1DF7p3020*
+ ID_SOFTWARE_RADIO=1
+
+# RSPdx
+usb:v1DF7p3030*
+ ID_SOFTWARE_RADIO=1
+
+# RSP1B
+usb:v1DF7p3050*
+ ID_SOFTWARE_RADIO=1
+
+# RSPdxR2
+usb:v1DF7p3060*
+ ID_SOFTWARE_RADIO=1

4390
0518-hwdb-update.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
From d29566a502b9af9ed13a79b1ca1be1bd2e395dd2 Mon Sep 17 00:00:00 2001
From: Lucas Adriano Salles <83602841+luc-salles@users.noreply.github.com>
Date: Thu, 2 Oct 2025 08:50:04 -0500
Subject: [PATCH] hwdb: fix calibrate rotation sensor for Positivo K116J
(#39189)
Fixes #39188.
(cherry picked from commit f8646b9a2ef3b6efd9b9e44919b736c569359299)
Resolves: RHEL-72702
---
hwdb.d/60-sensor.hwdb | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb
index 9c85bc3357..61dc4298c9 100644
--- a/hwdb.d/60-sensor.hwdb
+++ b/hwdb.d/60-sensor.hwdb
@@ -1054,6 +1054,11 @@ sensor:modalias:acpi:KIOX010A*:dmi:bvn*:bvr*:svnPositivoTecnologiaSA:pn*:pvr*:rv
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
ACCEL_LOCATION=display
+# Positivo Duo K116J
+sensor:modalias:acpi:MDA6655*:dmi:bvn*:bvr*:svnPositivoTecnologiaSA:pn*:pvr*:rvnPositivoTecnologiaSA:rnK116J*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+ ACCEL_LOCATION=display
+
########################################
# Predia
#########################################

View File

@ -0,0 +1,36 @@
From b39ab6f5909182def760c7996aad5fe2a0e4d8b9 Mon Sep 17 00:00:00 2001
From: Daniel Brackenbury <daniel.brackenbury@gmail.com>
Date: Tue, 7 Oct 2025 18:00:57 -0400
Subject: [PATCH] Add Nulea M501 trackball to hwdb
(cherry picked from commit 9dde7d9ae850efd3bc35a419ba4acb4427f1d5ad)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index dc9be4f915..98c0149d90 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -821,6 +821,19 @@ mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000:*
mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
MOUSE_DPI=*800@126 1600@126
+
+##########################################
+# Nulea
+##########################################
+
+# Nulea M501 Wireless Trackball (USB Receiver)
+mouse:usb:v25a7pfa61:name:Compx 2.4G Receiver Mouse:*
+ ID_INPUT_TRACKBALL=1
+
+# Nulea M501 Wireless Trackball (Bluetooth)
+mouse:bluetooth:v000ep3412:name:Nulea BT5.0 Mouse:*
+ ID_INPUT_TRACKBALL=1
+
##########################################
# Oklick
##########################################

View File

@ -0,0 +1,26 @@
From 92004bda4c2dd502d7e4ba9a10e754bae2e2d6e9 Mon Sep 17 00:00:00 2001
From: Daniel Brackenbury <daniel.brackenbury@gmail.com>
Date: Tue, 7 Oct 2025 18:04:56 -0400
Subject: [PATCH] add comment to 70-mouse.hwdb regarding generic name for Nulea
M501 USB dongle
(cherry picked from commit 6dfbaa80639d8bbbea6fc7f1976451da575da652)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index 98c0149d90..b0099ece96 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -826,6 +826,8 @@ mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
# Nulea
##########################################
+# Note: it is possible that other devices may use the same wireless dongle,
+# as such this could require revisiting if it causes issues with other mice
# Nulea M501 Wireless Trackball (USB Receiver)
mouse:usb:v25a7pfa61:name:Compx 2.4G Receiver Mouse:*
ID_INPUT_TRACKBALL=1

View File

@ -0,0 +1,31 @@
From 3b3177fd1ab1e93f01362433f75c18a2ef416b73 Mon Sep 17 00:00:00 2001
From: Daniel Brackenbury <daniel.brackenbury@gmail.com>
Date: Tue, 7 Oct 2025 18:55:57 -0400
Subject: [PATCH] remove extra space from new hwdb.d/70-mouse.hwdb entries to
fix failing test
(cherry picked from commit 2dc0e6cd734ac60b21d561bed1edc0cbb8c8d10d)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index b0099ece96..6bee17080a 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -830,11 +830,11 @@ mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
# as such this could require revisiting if it causes issues with other mice
# Nulea M501 Wireless Trackball (USB Receiver)
mouse:usb:v25a7pfa61:name:Compx 2.4G Receiver Mouse:*
- ID_INPUT_TRACKBALL=1
+ ID_INPUT_TRACKBALL=1
# Nulea M501 Wireless Trackball (Bluetooth)
mouse:bluetooth:v000ep3412:name:Nulea BT5.0 Mouse:*
- ID_INPUT_TRACKBALL=1
+ ID_INPUT_TRACKBALL=1
##########################################
# Oklick

View File

@ -0,0 +1,24 @@
From cc8154b3627e812fb5b8e6c7ba26bc4e0ad0bff0 Mon Sep 17 00:00:00 2001
From: helpvisa <daniel.brackenbury@gmail.com>
Date: Wed, 8 Oct 2025 07:18:48 -0400
Subject: [PATCH] remove bonus line
(cherry picked from commit b12cd57f6d8da94073a9cb44eaf753858a6cd5dd)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 1 -
1 file changed, 1 deletion(-)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index 6bee17080a..38e7d9e1d9 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -821,7 +821,6 @@ mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000:*
mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
MOUSE_DPI=*800@126 1600@126
-
##########################################
# Nulea
##########################################

View File

@ -0,0 +1,27 @@
From 31206d6c5d671410e38e946eaf5a589fccf64d74 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Fri, 10 Oct 2025 12:19:04 +0200
Subject: [PATCH] hwdb: drop trailing whitespace
Fixup for 63254ed696d129cc46752e639ae761b758d7b251.
(cherry picked from commit e06b9a1d5265d30061a431cadbdcfce9292c2e15)
Resolves: RHEL-72702
---
hwdb.d/60-sensor.hwdb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb
index 61dc4298c9..c325697151 100644
--- a/hwdb.d/60-sensor.hwdb
+++ b/hwdb.d/60-sensor.hwdb
@@ -779,7 +779,7 @@ sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80U1:*
ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1
# Legion Go
-sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnLENOVO:pn83E1:*
+sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnLENOVO:pn83E1:*
ACCEL_MOUNT_MATRIX=0,1,0;-1,0,0;0,0,1
# Yoga 300-11IBR, display sensor

View File

@ -0,0 +1,34 @@
From cfbb079ee81eaf50bb173909cbc27dc2f8e2faf8 Mon Sep 17 00:00:00 2001
From: Daniel Brackenbury <daniel.brackenbury@gmail.com>
Date: Fri, 10 Oct 2025 00:44:37 -0400
Subject: [PATCH] remove Nulea M501 usb entry from hwdb
conflict with other mice using same generic dongle identified (e.g. Protoarc EM11)
(cherry picked from commit 4cbfaaa5491c8d4b69ffe79b2b09061ec41fca3d)
Resolves: RHEL-72702
---
hwdb.d/70-mouse.hwdb | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb
index 38e7d9e1d9..86470bcfda 100644
--- a/hwdb.d/70-mouse.hwdb
+++ b/hwdb.d/70-mouse.hwdb
@@ -825,12 +825,9 @@ mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX:*
# Nulea
##########################################
-# Note: it is possible that other devices may use the same wireless dongle,
-# as such this could require revisiting if it causes issues with other mice
-# Nulea M501 Wireless Trackball (USB Receiver)
-mouse:usb:v25a7pfa61:name:Compx 2.4G Receiver Mouse:*
- ID_INPUT_TRACKBALL=1
-
+# Note: The Nulea uses a generic USB dongle. Overriding its value would cause
+# other mice to be erroneously registered as trackballs, so only bluetooth
+# detection is added.
# Nulea M501 Wireless Trackball (Bluetooth)
mouse:bluetooth:v000ep3412:name:Nulea BT5.0 Mouse:*
ID_INPUT_TRACKBALL=1

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