import CS systemd-252-67.el9
This commit is contained in:
parent
b0cdb78193
commit
7a1189d5b7
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
SOURCES/rhel-net-naming-sysattrs-v0.5.tar.gz
|
||||
SOURCES/net-naming-sysattrs-v0.5.tar.gz
|
||||
SOURCES/systemd-252.tar.gz
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
9ce6834429dbb9cb049de1bdf77bc8c84763709c SOURCES/rhel-net-naming-sysattrs-v0.5.tar.gz
|
||||
1f16c2c8705497c3068559321b2183f0f1e20b7b SOURCES/net-naming-sysattrs-v0.5.tar.gz
|
||||
7c961dc6e8bb950825b85129f59dc80f4536cabb SOURCES/systemd-252.tar.gz
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
From 3d54c58e3d4c720a9a95a39879b795e7154f0209 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Fri, 23 Dec 2022 14:14:53 +0100
|
||||
Subject: [PATCH] Revert "boot: Use EFI_BOOT_MANAGER_POLICY_PROTOCOL to connect
|
||||
console devices"
|
||||
|
||||
This reverts commit b99bf5811850afdb2502ba37251c48348da63c82.
|
||||
|
||||
It seems that using this protocol on some firmwares to forcibly
|
||||
initialize console devices may break handles (already opened file
|
||||
handles and the device handle itself) that we rely on to access the
|
||||
boot filesystem, making it impossible to load the selected entry.
|
||||
|
||||
It might be possible to get a new handle by querying for the device
|
||||
handle by using its device path after calling into this protocol, but
|
||||
this is untested. The firmware might also be so buggy that accessing
|
||||
devices after using this protocol is impossible.
|
||||
|
||||
It seems prudent to revert this for now until some reliable way is found
|
||||
to initialize console devices without introducing huge boot delays. Any
|
||||
users on firmware where console devices cannot be accessed would have to
|
||||
rely on disabling fastboot.
|
||||
|
||||
Fixes: #25737, #25846
|
||||
(cherry picked from commit f151abb0e5fa4f820109eb0541bfdcba319d2b92)
|
||||
|
||||
Resolves: RHEL-108596
|
||||
---
|
||||
src/boot/efi/console.c | 16 ----------------
|
||||
src/boot/efi/missing_efi.h | 19 -------------------
|
||||
2 files changed, 35 deletions(-)
|
||||
|
||||
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
|
||||
index 85a76e6e68..3b8b6b2e41 100644
|
||||
--- a/src/boot/efi/console.c
|
||||
+++ b/src/boot/efi/console.c
|
||||
@@ -12,20 +12,6 @@
|
||||
#define VERTICAL_MAX_OK 1080
|
||||
#define VIEWPORT_RATIO 10
|
||||
|
||||
-static EFI_STATUS console_connect(void) {
|
||||
- EFI_BOOT_MANAGER_POLICY_PROTOCOL *boot_policy;
|
||||
- EFI_STATUS err;
|
||||
-
|
||||
- /* This should make console devices appear/fully initialize on fastboot firmware. */
|
||||
-
|
||||
- err = BS->LocateProtocol(
|
||||
- &(EFI_GUID) EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID, NULL, (void **) &boot_policy);
|
||||
- if (err != EFI_SUCCESS)
|
||||
- return err;
|
||||
-
|
||||
- return boot_policy->ConnectDeviceClass(boot_policy, &(EFI_GUID) EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID);
|
||||
-}
|
||||
-
|
||||
static inline void event_closep(EFI_EVENT *event) {
|
||||
if (!*event)
|
||||
return;
|
||||
@@ -61,8 +47,6 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) {
|
||||
assert(key);
|
||||
|
||||
if (!checked) {
|
||||
- console_connect();
|
||||
-
|
||||
/* Get the *first* TextInputEx device.*/
|
||||
err = BS->LocateProtocol(
|
||||
MAKE_GUID_PTR(EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL), NULL, (void **) &extraInEx);
|
||||
diff --git a/src/boot/efi/missing_efi.h b/src/boot/efi/missing_efi.h
|
||||
index d34dfc3379..3c35a85e46 100644
|
||||
--- a/src/boot/efi/missing_efi.h
|
||||
+++ b/src/boot/efi/missing_efi.h
|
||||
@@ -399,25 +399,6 @@ typedef struct {
|
||||
} EFI_SHELL_PARAMETERS_PROTOCOL;
|
||||
#endif
|
||||
|
||||
-#ifndef EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID
|
||||
-#define EFI_BOOT_MANAGER_POLICY_PROTOCOL_GUID \
|
||||
- { 0xFEDF8E0C, 0xE147, 0x11E3, { 0x99, 0x03, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } }
|
||||
-#define EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID \
|
||||
- { 0xCAB0E94C, 0xE15F, 0x11E3, { 0x91, 0x8D, 0xB8, 0xE8, 0x56, 0x2C, 0xBA, 0xFA } }
|
||||
-
|
||||
-typedef struct EFI_BOOT_MANAGER_POLICY_PROTOCOL EFI_BOOT_MANAGER_POLICY_PROTOCOL;
|
||||
-struct EFI_BOOT_MANAGER_POLICY_PROTOCOL {
|
||||
- UINT64 Revision;
|
||||
- EFI_STATUS (EFIAPI *ConnectDevicePath)(
|
||||
- EFI_BOOT_MANAGER_POLICY_PROTOCOL *This,
|
||||
- EFI_DEVICE_PATH *DevicePath,
|
||||
- BOOLEAN Recursive);
|
||||
- EFI_STATUS (EFIAPI *ConnectDeviceClass)(
|
||||
- EFI_BOOT_MANAGER_POLICY_PROTOCOL *This,
|
||||
- EFI_GUID *Class);
|
||||
-};
|
||||
-#endif
|
||||
-
|
||||
#ifndef EFI_WARN_UNKNOWN_GLYPH
|
||||
# define EFI_WARN_UNKNOWN_GLYPH 1
|
||||
#endif
|
||||
@ -0,0 +1,38 @@
|
||||
From bcb456e590fd6994a6b38e9b2d89e3ef0417d402 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Janssen <medhefgo@web.de>
|
||||
Date: Tue, 2 May 2023 19:41:58 +0200
|
||||
Subject: [PATCH] boot: Use correct memory type for allocations
|
||||
|
||||
We were using the wrong memory type when allocating pool memory. This
|
||||
does not seem to cause a problem on x86, but the kernel will fail to
|
||||
boot at least on ARM in QEMU.
|
||||
|
||||
This is caused by mixing different allocation types which ended up
|
||||
breaking the kernel or EDK2 during boot services exit. Commit
|
||||
2f3c3b0bee5534f2338439f04b0aa517479f8b76 appears to fix this boot
|
||||
failure because it was replacing the gnu-efi xpool_print with xasprintf
|
||||
thereby unifying the allocation type.
|
||||
But this same issue can also happen without this fix somehow when the
|
||||
random-seed logic is in use.
|
||||
|
||||
Fixes: #27371
|
||||
(cherry picked from commit ec232e4abd7aebfec06b4814b30129532b2bcefd)
|
||||
|
||||
Resolves: RHEL-108555
|
||||
---
|
||||
src/boot/efi/util.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
|
||||
index f7452e3cf5..16c9fcc3e1 100644
|
||||
--- a/src/boot/efi/util.h
|
||||
+++ b/src/boot/efi/util.h
|
||||
@@ -47,7 +47,7 @@ static inline void freep(void *p) {
|
||||
_malloc_ _alloc_(1) _returns_nonnull_ _warn_unused_result_
|
||||
static inline void *xmalloc(size_t size) {
|
||||
void *p;
|
||||
- assert_se(BS->AllocatePool(EfiBootServicesData, size, &p) == EFI_SUCCESS);
|
||||
+ assert_se(BS->AllocatePool(EfiLoaderData, size, &p) == EFI_SUCCESS);
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
From 7ee5909a539f7a4a65c35e86404ceecb499c54c5 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Thu, 2 Nov 2023 14:20:11 +0900
|
||||
Subject: [PATCH] meson: /etc/systemd/network is also used by udevd
|
||||
|
||||
(cherry picked from commit 6256c65aad2a719ac9054961561bb26e497208ce)
|
||||
|
||||
Resolves: RHEL-109096
|
||||
---
|
||||
network/meson.build | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/network/meson.build b/network/meson.build
|
||||
index 4c6de20515..499ea61086 100644
|
||||
--- a/network/meson.build
|
||||
+++ b/network/meson.build
|
||||
@@ -12,11 +12,12 @@ if conf.get('ENABLE_NETWORKD') == 1
|
||||
'80-wifi-station.network.example',
|
||||
install_dir : networkdir)
|
||||
|
||||
- if install_sysconfdir
|
||||
- meson.add_install_script('sh', '-c',
|
||||
- mkdir_p.format(sysconfdir / 'systemd/network'))
|
||||
- endif
|
||||
endif
|
||||
|
||||
install_data('99-default.link',
|
||||
install_dir : networkdir)
|
||||
+
|
||||
+if install_sysconfdir
|
||||
+ meson.add_install_script('sh', '-c',
|
||||
+ mkdir_p.format(sysconfdir / 'systemd/network'))
|
||||
+endif
|
||||
207
SOURCES/1213-sd-bus-make-bus_add_match_full-accept-timeout.patch
Normal file
207
SOURCES/1213-sd-bus-make-bus_add_match_full-accept-timeout.patch
Normal file
@ -0,0 +1,207 @@
|
||||
From 3b49b68593cbca6ee4e08a34a780fd5b5c3ab9fb Mon Sep 17 00:00:00 2001
|
||||
From: licunlong <licunlong1@huawei.com>
|
||||
Date: Thu, 15 Jun 2023 16:28:28 +0800
|
||||
Subject: [PATCH] sd-bus: make bus_add_match_full accept timeout
|
||||
|
||||
(cherry picked from commit bb30e58f644689feaa87d8136d1686b6c3a6f42a)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-control.c | 48 +++++++++++++++++++++-------
|
||||
src/libsystemd/sd-bus/bus-control.h | 4 +--
|
||||
src/libsystemd/sd-bus/bus-internal.h | 10 ++++++
|
||||
src/libsystemd/sd-bus/sd-bus.c | 17 ++++++----
|
||||
4 files changed, 59 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
|
||||
index d96b7256a1..762656fa74 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-control.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-control.c
|
||||
@@ -803,9 +803,10 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
|
||||
int bus_add_match_internal(
|
||||
sd_bus *bus,
|
||||
const char *match,
|
||||
+ uint64_t timeout_usec,
|
||||
uint64_t *ret_counter) {
|
||||
|
||||
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
@@ -816,16 +817,26 @@ int bus_add_match_internal(
|
||||
|
||||
e = append_eavesdrop(bus, match);
|
||||
|
||||
- r = sd_bus_call_method(
|
||||
+ r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
+ &m,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
- "AddMatch",
|
||||
+ "AddMatch");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_bus_message_append(m, "s", e);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_bus_call(
|
||||
+ bus,
|
||||
+ m,
|
||||
+ timeout_usec,
|
||||
NULL,
|
||||
- &reply,
|
||||
- "s",
|
||||
- e);
|
||||
+ &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -841,9 +852,12 @@ int bus_add_match_internal_async(
|
||||
sd_bus_slot **ret_slot,
|
||||
const char *match,
|
||||
sd_bus_message_handler_t callback,
|
||||
- void *userdata) {
|
||||
+ void *userdata,
|
||||
+ uint64_t timeout_usec) {
|
||||
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
const char *e;
|
||||
+ int r;
|
||||
|
||||
assert(bus);
|
||||
|
||||
@@ -852,17 +866,27 @@ int bus_add_match_internal_async(
|
||||
|
||||
e = append_eavesdrop(bus, match);
|
||||
|
||||
- return sd_bus_call_method_async(
|
||||
+ r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
- ret_slot,
|
||||
+ &m,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
- "AddMatch",
|
||||
+ "AddMatch");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_bus_message_append(m, "s", e);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return sd_bus_call_async(
|
||||
+ bus,
|
||||
+ ret_slot,
|
||||
+ m,
|
||||
callback,
|
||||
userdata,
|
||||
- "s",
|
||||
- e);
|
||||
+ timeout_usec);
|
||||
}
|
||||
|
||||
int bus_remove_match_internal(
|
||||
diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h
|
||||
index 8182b9cd63..1cd4fb88d9 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-control.h
|
||||
+++ b/src/libsystemd/sd-bus/bus-control.h
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
-int bus_add_match_internal(sd_bus *bus, const char *match, uint64_t *ret_counter);
|
||||
-int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata);
|
||||
+int bus_add_match_internal(sd_bus *bus, const char *match, uint64_t timeout_usec, uint64_t *ret_counter);
|
||||
+int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata, uint64_t timeout_usec);
|
||||
|
||||
int bus_remove_match_internal(sd_bus *bus, const char *match);
|
||||
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
|
||||
index 51673ad1c5..603a53fb10 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-internal.h
|
||||
+++ b/src/libsystemd/sd-bus/bus-internal.h
|
||||
@@ -386,6 +386,16 @@ int bus_attach_inotify_event(sd_bus *b);
|
||||
void bus_close_inotify_fd(sd_bus *b);
|
||||
void bus_close_io_fds(sd_bus *b);
|
||||
|
||||
+int bus_add_match_full(
|
||||
+ sd_bus *bus,
|
||||
+ sd_bus_slot **slot,
|
||||
+ bool asynchronous,
|
||||
+ const char *match,
|
||||
+ sd_bus_message_handler_t callback,
|
||||
+ sd_bus_message_handler_t install_callback,
|
||||
+ void *userdata,
|
||||
+ uint64_t timeout_usec);
|
||||
+
|
||||
#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \
|
||||
for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \
|
||||
_slash && ((_slash[(_slash) == (prefix)] = 0), true); \
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index 10efe53a25..b8406f154b 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -3486,14 +3486,15 @@ static int add_match_callback(
|
||||
return r;
|
||||
}
|
||||
|
||||
-static int bus_add_match_full(
|
||||
+int bus_add_match_full(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **slot,
|
||||
bool asynchronous,
|
||||
const char *match,
|
||||
sd_bus_message_handler_t callback,
|
||||
sd_bus_message_handler_t install_callback,
|
||||
- void *userdata) {
|
||||
+ void *userdata,
|
||||
+ uint64_t timeout_usec) {
|
||||
|
||||
struct bus_match_component *components = NULL;
|
||||
unsigned n_components = 0;
|
||||
@@ -3539,7 +3540,8 @@ static int bus_add_match_full(
|
||||
&s->match_callback.install_slot,
|
||||
s->match_callback.match_string,
|
||||
add_match_callback,
|
||||
- s);
|
||||
+ s,
|
||||
+ timeout_usec);
|
||||
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3549,7 +3551,10 @@ static int bus_add_match_full(
|
||||
* then make it floating. */
|
||||
r = sd_bus_slot_set_floating(s->match_callback.install_slot, true);
|
||||
} else
|
||||
- r = bus_add_match_internal(bus, s->match_callback.match_string, &s->match_callback.after);
|
||||
+ r = bus_add_match_internal(bus,
|
||||
+ s->match_callback.match_string,
|
||||
+ timeout_usec,
|
||||
+ &s->match_callback.after);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@@ -3580,7 +3585,7 @@ _public_ int sd_bus_add_match(
|
||||
sd_bus_message_handler_t callback,
|
||||
void *userdata) {
|
||||
|
||||
- return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata);
|
||||
+ return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata, 0);
|
||||
}
|
||||
|
||||
_public_ int sd_bus_add_match_async(
|
||||
@@ -3591,7 +3596,7 @@ _public_ int sd_bus_add_match_async(
|
||||
sd_bus_message_handler_t install_callback,
|
||||
void *userdata) {
|
||||
|
||||
- return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata);
|
||||
+ return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata, 0);
|
||||
}
|
||||
|
||||
bool bus_pid_changed(sd_bus *bus) {
|
||||
@ -0,0 +1,52 @@
|
||||
From 1a5720577ae6791ae64795486c5902b7c5aceb6b Mon Sep 17 00:00:00 2001
|
||||
From: licunlong <licunlong1@huawei.com>
|
||||
Date: Thu, 15 Jun 2023 10:47:32 +0800
|
||||
Subject: [PATCH] core/unit: add get_timeout_start_usec in UnitVTable and
|
||||
define it for service
|
||||
|
||||
(cherry picked from commit f5a9d2ee2a849aca1f2d15485d020142ff33cc30)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/service.c | 6 ++++++
|
||||
src/core/unit.h | 3 +++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 433df0afe3..305f3b7170 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -4383,6 +4383,11 @@ static int service_get_timeout(Unit *u, usec_t *timeout) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static usec_t service_get_timeout_start_usec(Unit *u) {
|
||||
+ Service *s = SERVICE(ASSERT_PTR(u));
|
||||
+ return s->timeout_start_usec;
|
||||
+}
|
||||
+
|
||||
static bool pick_up_pid_from_bus_name(Service *s) {
|
||||
assert(s);
|
||||
|
||||
@@ -4870,6 +4875,7 @@ const UnitVTable service_vtable = {
|
||||
.bus_commit_properties = bus_service_commit_properties,
|
||||
|
||||
.get_timeout = service_get_timeout,
|
||||
+ .get_timeout_start_usec = service_get_timeout_start_usec,
|
||||
.needs_console = service_needs_console,
|
||||
.exit_status = service_exit_status,
|
||||
.status_text = service_status_text,
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 4bb85b55be..fdea76458d 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -713,6 +713,9 @@ typedef struct UnitVTable {
|
||||
/* Returns the next timeout of a unit */
|
||||
int (*get_timeout)(Unit *u, usec_t *timeout);
|
||||
|
||||
+ /* Returns the start timeout of a unit */
|
||||
+ usec_t (*get_timeout_start_usec)(Unit *u);
|
||||
+
|
||||
/* Returns the main PID if there is any defined, or 0. */
|
||||
pid_t (*main_pid)(Unit *u);
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
From 6b2f0e500e6688d1b2d9ad8b9947e03bd58f27a2 Mon Sep 17 00:00:00 2001
|
||||
From: licunlong <licunlong1@huawei.com>
|
||||
Date: Wed, 24 May 2023 11:45:31 +0800
|
||||
Subject: [PATCH] core/unit: increase the NameOwnerChanged/GetNameOwner timeout
|
||||
to the unit's start timeout
|
||||
|
||||
When dbus is overloaded, these messages are easily timedout,
|
||||
systemd may kill dbus-type service by mistake. This PR
|
||||
mitigates this problem by increasing the timeout to the
|
||||
unit's start timeout.
|
||||
|
||||
(cherry picked from commit 8df433d7cd268ae96cfe795feaa59f4d3e87b85c)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/unit.c | 39 ++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 34 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 0d65880ac7..dddaeb96f6 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "bpf-foreign.h"
|
||||
#include "bpf-socket-bind.h"
|
||||
#include "bus-common-errors.h"
|
||||
+#include "bus-internal.h"
|
||||
#include "bus-util.h"
|
||||
#include "cgroup-setup.h"
|
||||
#include "cgroup-util.h"
|
||||
@@ -3539,7 +3540,9 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu
|
||||
}
|
||||
|
||||
int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
const char *match;
|
||||
+ usec_t timeout_usec = 0;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
@@ -3549,6 +3552,12 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||
if (u->match_bus_slot || u->get_name_owner_slot)
|
||||
return -EBUSY;
|
||||
|
||||
+ /* NameOwnerChanged and GetNameOwner is used to detect when a service finished starting up. The dbus
|
||||
+ * call timeout shouldn't be earlier than that. If we couldn't get the start timeout, use the default
|
||||
+ * value defined above. */
|
||||
+ if (UNIT_VTABLE(u)->get_timeout_start_usec)
|
||||
+ timeout_usec = UNIT_VTABLE(u)->get_timeout_start_usec(u);
|
||||
+
|
||||
match = strjoina("type='signal',"
|
||||
"sender='org.freedesktop.DBus',"
|
||||
"path='/org/freedesktop/DBus',"
|
||||
@@ -3556,20 +3565,40 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||
"member='NameOwnerChanged',"
|
||||
"arg0='", name, "'");
|
||||
|
||||
- r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u);
|
||||
+ r = bus_add_match_full(
|
||||
+ bus,
|
||||
+ &u->match_bus_slot,
|
||||
+ true,
|
||||
+ match,
|
||||
+ signal_name_owner_changed,
|
||||
+ NULL,
|
||||
+ u,
|
||||
+ timeout_usec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- r = sd_bus_call_method_async(
|
||||
+ r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
- &u->get_name_owner_slot,
|
||||
+ &m,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
- "GetNameOwner",
|
||||
+ "GetNameOwner");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_bus_message_append(m, "s", name);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = sd_bus_call_async(
|
||||
+ bus,
|
||||
+ &u->get_name_owner_slot,
|
||||
+ m,
|
||||
get_name_owner_handler,
|
||||
u,
|
||||
- "s", name);
|
||||
+ timeout_usec);
|
||||
+
|
||||
if (r < 0) {
|
||||
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
||||
return r;
|
||||
@ -0,0 +1,38 @@
|
||||
From 14c6c9a0a58a99d66f541cec50a5cc860303ae7e Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 29 Dec 2024 15:10:53 +0900
|
||||
Subject: [PATCH] core,sd-bus: drop empty lines between function call and error
|
||||
check
|
||||
|
||||
(cherry picked from commit 7baf4d234a70f136014f9e92f00c078a55c7adba)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/unit.c | 1 -
|
||||
src/libsystemd/sd-bus/sd-bus.c | 1 -
|
||||
2 files changed, 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index dddaeb96f6..5a091b3bc4 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -3598,7 +3598,6 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||
get_name_owner_handler,
|
||||
u,
|
||||
timeout_usec);
|
||||
-
|
||||
if (r < 0) {
|
||||
u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
||||
return r;
|
||||
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
||||
index b8406f154b..c2dded43ad 100644
|
||||
--- a/src/libsystemd/sd-bus/sd-bus.c
|
||||
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
||||
@@ -3542,7 +3542,6 @@ int bus_add_match_full(
|
||||
add_match_callback,
|
||||
s,
|
||||
timeout_usec);
|
||||
-
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
From 899e94d72119c5e5f3d0ae75f39abd376bc28b0e Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 29 Dec 2024 15:50:43 +0900
|
||||
Subject: [PATCH] core: do not disconnect from bus when failed to install
|
||||
signal match
|
||||
|
||||
If bus_add_match_full() is called without install callback and we failed
|
||||
to install the signal match e.g. by timeout, then add_match_callback()
|
||||
will disconnect from the bus.
|
||||
Let's use a custom install handler and handle failures gracefully.
|
||||
|
||||
This does not *solve* the root cause of issue #30573, but should improve
|
||||
the situation when the issue is triggered.
|
||||
|
||||
(cherry picked from commit db6b214f95aa42f9a9fa3d94a3c6492cc57b58fb)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/unit.c | 30 ++++++++++++++++++++++++++++--
|
||||
1 file changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 5a091b3bc4..9e349402ff 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -3486,6 +3486,32 @@ int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int signal_name_owner_changed_install_handler(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
+ Unit *u = ASSERT_PTR(userdata);
|
||||
+ const sd_bus_error *e;
|
||||
+ int r;
|
||||
+
|
||||
+ e = sd_bus_message_get_error(message);
|
||||
+ if (!e) {
|
||||
+ log_unit_trace(u, "Successfully installed NameOwnerChanged signal match.");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = sd_bus_error_get_errno(e);
|
||||
+ log_unit_error_errno(u, r,
|
||||
+ "Unexpected error response on installing NameOwnerChanged signal match: %s",
|
||||
+ bus_error_message(e, r));
|
||||
+
|
||||
+ /* If we failed to install NameOwnerChanged signal, also unref the bus slot of GetNameOwner(). */
|
||||
+ u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
|
||||
+ u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot);
|
||||
+
|
||||
+ if (UNIT_VTABLE(u)->bus_name_owner_change)
|
||||
+ UNIT_VTABLE(u)->bus_name_owner_change(u, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
const char *new_owner;
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
@@ -3568,10 +3594,10 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||
r = bus_add_match_full(
|
||||
bus,
|
||||
&u->match_bus_slot,
|
||||
- true,
|
||||
+ /* asynchronous = */ true,
|
||||
match,
|
||||
signal_name_owner_changed,
|
||||
- NULL,
|
||||
+ signal_name_owner_changed_install_handler,
|
||||
u,
|
||||
timeout_usec);
|
||||
if (r < 0)
|
||||
@ -0,0 +1,180 @@
|
||||
From 5917dd6d4667ed4f97b63baaa3b35e2c1410f3c0 Mon Sep 17 00:00:00 2001
|
||||
From: Ronan Pigott <ronan@rjp.ie>
|
||||
Date: Thu, 28 Nov 2024 12:53:32 -0700
|
||||
Subject: [PATCH] dbus: stash the subscriber list when we disconenct from the
|
||||
bus
|
||||
|
||||
If we unexpectly disconnect from the bus, systemd would end up dropping
|
||||
the list of subscribers, which breaks the ability of clients like logind
|
||||
to monitor the state of units.
|
||||
|
||||
Stash the list of subscribers into the deserialized state in the event
|
||||
of a disconnect so that when we recover we can renew the broken
|
||||
subscriptions.
|
||||
|
||||
(cherry picked from commit 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/dbus.c | 21 +++++++++++++++------
|
||||
src/core/dbus.h | 2 +-
|
||||
src/core/manager.c | 8 ++++----
|
||||
src/shared/bus-util.c | 22 ++++++++++++++++++++++
|
||||
src/shared/bus-util.h | 1 +
|
||||
5 files changed, 43 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/core/dbus.c b/src/core/dbus.c
|
||||
index 1431e079c2..12a6f2fa27 100644
|
||||
--- a/src/core/dbus.c
|
||||
+++ b/src/core/dbus.c
|
||||
@@ -834,6 +834,8 @@ int bus_init_api(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up API bus: %m");
|
||||
|
||||
+ (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->deserialized_subscribed);
|
||||
+ m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
m->api_bus = TAKE_PTR(bus);
|
||||
|
||||
return 0;
|
||||
@@ -986,8 +988,17 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
|
||||
}
|
||||
|
||||
/* Get rid of tracked clients on this bus */
|
||||
- if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
|
||||
+ if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) {
|
||||
+ _cleanup_strv_free_ char **subscribed = NULL;
|
||||
+ int r;
|
||||
+
|
||||
+ r = bus_track_to_strv(m->subscribed, &subscribed);
|
||||
+ if (r < 0)
|
||||
+ log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m");
|
||||
+ strv_free_and_replace(m->deserialized_subscribed, subscribed);
|
||||
+
|
||||
m->subscribed = sd_bus_track_unref(m->subscribed);
|
||||
+ }
|
||||
|
||||
HASHMAP_FOREACH(j, m->jobs)
|
||||
if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
|
||||
@@ -1046,7 +1057,6 @@ void bus_done(Manager *m) {
|
||||
|
||||
assert(!m->subscribed);
|
||||
|
||||
- m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
bus_verify_polkit_async_registry_free(m->polkit_registry);
|
||||
}
|
||||
|
||||
@@ -1137,20 +1147,19 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
|
||||
}
|
||||
}
|
||||
|
||||
-int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) {
|
||||
+int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l) {
|
||||
int r;
|
||||
|
||||
- assert(m);
|
||||
assert(t);
|
||||
|
||||
if (strv_isempty(l))
|
||||
return 0;
|
||||
|
||||
- if (!m->api_bus)
|
||||
+ if (!bus)
|
||||
return 0;
|
||||
|
||||
if (!*t) {
|
||||
- r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
|
||||
+ r = sd_bus_track_new(bus, t, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
diff --git a/src/core/dbus.h b/src/core/dbus.h
|
||||
index 50e7bb400e..3f0d902c89 100644
|
||||
--- a/src/core/dbus.h
|
||||
+++ b/src/core/dbus.h
|
||||
@@ -19,7 +19,7 @@ void bus_done(Manager *m);
|
||||
int bus_fdset_add_all(Manager *m, FDSet *fds);
|
||||
|
||||
void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix);
|
||||
-int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l);
|
||||
+int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l);
|
||||
|
||||
int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index daeaa641d7..6c67780c99 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1560,6 +1560,9 @@ Manager* manager_free(Manager *m) {
|
||||
free(m->switch_root);
|
||||
free(m->switch_root_init);
|
||||
|
||||
+ sd_bus_track_unref(m->subscribed);
|
||||
+ strv_free(m->deserialized_subscribed);
|
||||
+
|
||||
free(m->default_smack_process_label);
|
||||
|
||||
rlimit_free_all(m->rlimit);
|
||||
@@ -1862,7 +1865,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
|
||||
manager_setup_bus(m);
|
||||
|
||||
/* Now that we are connected to all possible buses, let's deserialize who is tracking us. */
|
||||
- r = bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed);
|
||||
+ r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->deserialized_subscribed);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m");
|
||||
m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
@@ -3412,9 +3415,6 @@ int manager_reload(Manager *m) {
|
||||
/* Clean up runtime objects no longer referenced */
|
||||
manager_vacuum(m);
|
||||
|
||||
- /* Clean up deserialized tracked clients */
|
||||
- m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
-
|
||||
/* Consider the reload process complete now. */
|
||||
assert(m->n_reloading > 0);
|
||||
m->n_reloading--;
|
||||
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
|
||||
index d09ec5148d..9293f10fdc 100644
|
||||
--- a/src/shared/bus-util.c
|
||||
+++ b/src/shared/bus-util.c
|
||||
@@ -495,6 +495,28 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
|
||||
return r;
|
||||
}
|
||||
|
||||
+int bus_track_to_strv(sd_bus_track *t, char ***ret) {
|
||||
+ _cleanup_strv_free_ char **subscribed = NULL;
|
||||
+ int r = 0;
|
||||
+
|
||||
+ assert(ret);
|
||||
+
|
||||
+ for (const char *n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
|
||||
+ r = sd_bus_track_count_name(t, n);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ for (int j = 0; j < r; j++) {
|
||||
+ r = strv_extend(&subscribed, n);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ *ret = TAKE_PTR(subscribed);
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
|
||||
_cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
|
||||
const char *e;
|
||||
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
|
||||
index 955cdcb57c..e1fdf2ef48 100644
|
||||
--- a/src/shared/bus-util.h
|
||||
+++ b/src/shared/bus-util.h
|
||||
@@ -52,6 +52,7 @@ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id,
|
||||
int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external);
|
||||
|
||||
int bus_track_add_name_many(sd_bus_track *t, char **l);
|
||||
+int bus_track_to_strv(sd_bus_track *t, char ***ret);
|
||||
|
||||
int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description);
|
||||
static inline int bus_open_system_watch_bind(sd_bus **ret) {
|
||||
@ -0,0 +1,94 @@
|
||||
From 435d53448b8c427dc1b61b4d27342fb593185acf Mon Sep 17 00:00:00 2001
|
||||
From: Ronan Pigott <ronan@rjp.ie>
|
||||
Date: Wed, 11 Dec 2024 12:47:10 -0700
|
||||
Subject: [PATCH] manager: s/deserialized_subscribed/subscribed_as_strv
|
||||
|
||||
Now that this field may get populated at runtime, the deserialized name
|
||||
is misleading. Change the name to reflect its updated purpose.
|
||||
|
||||
(cherry picked from commit e1315a621ae26473fcc9cd0d6013836f5f498d40)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/dbus.c | 6 +++---
|
||||
src/core/manager-serialize.c | 2 +-
|
||||
src/core/manager.c | 6 +++---
|
||||
src/core/manager.h | 2 +-
|
||||
4 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/core/dbus.c b/src/core/dbus.c
|
||||
index 12a6f2fa27..7655427f38 100644
|
||||
--- a/src/core/dbus.c
|
||||
+++ b/src/core/dbus.c
|
||||
@@ -834,8 +834,8 @@ int bus_init_api(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up API bus: %m");
|
||||
|
||||
- (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->deserialized_subscribed);
|
||||
- m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
+ (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->subscribed_as_strv);
|
||||
+ m->subscribed_as_strv = strv_free(m->subscribed_as_strv);
|
||||
m->api_bus = TAKE_PTR(bus);
|
||||
|
||||
return 0;
|
||||
@@ -995,7 +995,7 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
|
||||
r = bus_track_to_strv(m->subscribed, &subscribed);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m");
|
||||
- strv_free_and_replace(m->deserialized_subscribed, subscribed);
|
||||
+ strv_free_and_replace(m->subscribed_as_strv, subscribed);
|
||||
|
||||
m->subscribed = sd_bus_track_unref(m->subscribed);
|
||||
}
|
||||
diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c
|
||||
index f3b2d7ee16..a87d490219 100644
|
||||
--- a/src/core/manager-serialize.c
|
||||
+++ b/src/core/manager-serialize.c
|
||||
@@ -529,7 +529,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
||||
(void) exec_runtime_deserialize_one(m, val, fds);
|
||||
else if ((val = startswith(l, "subscribed="))) {
|
||||
|
||||
- if (strv_extend(&m->deserialized_subscribed, val) < 0)
|
||||
+ if (strv_extend(&m->subscribed_as_strv, val) < 0)
|
||||
return -ENOMEM;
|
||||
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
|
||||
if (!m->varlink_server && MANAGER_IS_SYSTEM(m)) {
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 6c67780c99..45676d3def 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1561,7 +1561,7 @@ Manager* manager_free(Manager *m) {
|
||||
free(m->switch_root_init);
|
||||
|
||||
sd_bus_track_unref(m->subscribed);
|
||||
- strv_free(m->deserialized_subscribed);
|
||||
+ strv_free(m->subscribed_as_strv);
|
||||
|
||||
free(m->default_smack_process_label);
|
||||
|
||||
@@ -1865,10 +1865,10 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
|
||||
manager_setup_bus(m);
|
||||
|
||||
/* Now that we are connected to all possible buses, let's deserialize who is tracking us. */
|
||||
- r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->deserialized_subscribed);
|
||||
+ r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->subscribed_as_strv);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m");
|
||||
- m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
+ m->subscribed_as_strv = strv_free(m->subscribed_as_strv);
|
||||
|
||||
r = manager_varlink_init(m);
|
||||
if (r < 0)
|
||||
diff --git a/src/core/manager.h b/src/core/manager.h
|
||||
index 86e7e40989..a96ba7bf9d 100644
|
||||
--- a/src/core/manager.h
|
||||
+++ b/src/core/manager.h
|
||||
@@ -276,7 +276,7 @@ struct Manager {
|
||||
considered subscribes, since they last for very short only,
|
||||
and it is much simpler that way. */
|
||||
sd_bus_track *subscribed;
|
||||
- char **deserialized_subscribed;
|
||||
+ char **subscribed_as_strv;
|
||||
|
||||
/* This is used during reloading: before the reload we queue
|
||||
* the reply message here, and afterwards we send it */
|
||||
@ -0,0 +1,55 @@
|
||||
From da904dede254800cdbac51905db9423f8f88fefa Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Sat, 11 Jan 2025 16:26:55 +0100
|
||||
Subject: [PATCH] bus-util: do not reset the count returned by
|
||||
sd_bus_track_count_name()
|
||||
|
||||
Follow-up for 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98
|
||||
|
||||
While at it, turn the retval check for sd_bus_track_count_name()
|
||||
into assertion, given we're working with already established tracks
|
||||
(service_name_is_valid() should never yield false in this case).
|
||||
|
||||
Addresses https://github.com/systemd/systemd/pull/35406#discussion_r1912066774
|
||||
|
||||
(cherry picked from commit 33eeea4128f31df7ab4bd8866b582062d70114ae)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/shared/bus-util.c | 11 +++++------
|
||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
|
||||
index 9293f10fdc..5e6d17d201 100644
|
||||
--- a/src/shared/bus-util.c
|
||||
+++ b/src/shared/bus-util.c
|
||||
@@ -497,16 +497,15 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
|
||||
|
||||
int bus_track_to_strv(sd_bus_track *t, char ***ret) {
|
||||
_cleanup_strv_free_ char **subscribed = NULL;
|
||||
- int r = 0;
|
||||
+ int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
for (const char *n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
|
||||
- r = sd_bus_track_count_name(t, n);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ int c = sd_bus_track_count_name(t, n);
|
||||
+ assert(c >= 0);
|
||||
|
||||
- for (int j = 0; j < r; j++) {
|
||||
+ for (int j = 0; j < c; j++) {
|
||||
r = strv_extend(&subscribed, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -514,7 +513,7 @@ int bus_track_to_strv(sd_bus_track *t, char ***ret) {
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(subscribed);
|
||||
- return r;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
|
||||
@ -0,0 +1,31 @@
|
||||
From 02e5c4076ce3981fb2b0c7830197b2f13e225efe Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Mon, 13 Jan 2025 17:30:51 +0100
|
||||
Subject: [PATCH] core/manager: restore bus track deserialization cleanup in
|
||||
manager_reload()
|
||||
|
||||
There's zero explanation why it got (spuriously) removed in
|
||||
8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98...
|
||||
|
||||
(cherry picked from commit 34f4b817f67b002eae7e2c09b19bf4b66c4791b6)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/manager.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 45676d3def..92f283d33d 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -3409,6 +3409,10 @@ int manager_reload(Manager *m) {
|
||||
(void) manager_setup_cgroups_agent(m);
|
||||
(void) manager_setup_user_lookup_fd(m);
|
||||
|
||||
+ /* Clean up deserialized bus track information. They're never consumed during reload (as opposed to
|
||||
+ * reexec) since we do not disconnect from the bus. */
|
||||
+ m->subscribed_as_strv = strv_free(m->subscribed_as_strv);
|
||||
+
|
||||
/* Third, fire things up! */
|
||||
manager_coldplug(m);
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From 8e451eebfe6f37bacb02543d9a38c4ddaa6f8400 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Sat, 11 Jan 2025 18:38:49 +0100
|
||||
Subject: [PATCH] core/manager: drop duplicate bus track deserialization
|
||||
|
||||
bus_init_api() now does this internally
|
||||
(after 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98).
|
||||
|
||||
(cherry picked from commit af0e10354e567bfd0b9521376b2aad55f12a4e3d)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/core/manager.c | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 92f283d33d..653b0c2d22 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1864,12 +1864,6 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
|
||||
/* Connect to the bus if we are good for it */
|
||||
manager_setup_bus(m);
|
||||
|
||||
- /* Now that we are connected to all possible buses, let's deserialize who is tracking us. */
|
||||
- r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->subscribed_as_strv);
|
||||
- if (r < 0)
|
||||
- log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m");
|
||||
- m->subscribed_as_strv = strv_free(m->subscribed_as_strv);
|
||||
-
|
||||
r = manager_varlink_init(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to set up Varlink, ignoring: %m");
|
||||
@ -0,0 +1,102 @@
|
||||
From f18c7dd568ba87c6aa9a045878c0a9ef7c23208e Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Thu, 31 Jul 2025 18:26:09 +0200
|
||||
Subject: [PATCH] sd-bus/bus-track: use install_callback in
|
||||
sd_bus_track_add_name()
|
||||
|
||||
Previously we didn't provide any install_callback to
|
||||
sd_bus_add_match_async() so in case AddMatch() method call timed out we
|
||||
destroyed the bus connection. This seems overly aggressive and simply
|
||||
updating the sd_bus_track object accordingly should be enough.
|
||||
|
||||
Follow-up for 37ce3fd2b7dd8f81f6f4bca2003961a92b2963dc.
|
||||
|
||||
Fixes #32381
|
||||
|
||||
(cherry picked from commit dcf42d1ee21222ee698e5e0ab3ecf3411b63da40)
|
||||
|
||||
Related: RHEL-31756
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-track.c | 32 +++++++++++++++++++++++++++----
|
||||
1 file changed, 28 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
|
||||
index f9c59a1007..276e177d2b 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-track.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-track.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
+#include "bus-error.h"
|
||||
#include "bus-internal.h"
|
||||
#include "bus-track.h"
|
||||
#include "string-util.h"
|
||||
@@ -11,6 +12,7 @@ struct track_item {
|
||||
unsigned n_ref;
|
||||
char *name;
|
||||
sd_bus_slot *slot;
|
||||
+ sd_bus_track *track;
|
||||
};
|
||||
|
||||
struct sd_bus_track {
|
||||
@@ -163,18 +165,39 @@ static sd_bus_track *track_free(sd_bus_track *track) {
|
||||
|
||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_track, sd_bus_track, track_free);
|
||||
|
||||
-static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
- sd_bus_track *track = ASSERT_PTR(userdata);
|
||||
+static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *reterr_error) {
|
||||
+ struct track_item *item = ASSERT_PTR(userdata);
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
+ assert(item->track);
|
||||
|
||||
r = sd_bus_message_read(message, "sss", &name, NULL, NULL);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
- bus_track_remove_name_fully(track, name);
|
||||
+ bus_track_remove_name_fully(item->track, name);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int name_owner_changed_install_callback(sd_bus_message *message, void *userdata, sd_bus_error *reterr_error) {
|
||||
+ struct track_item *item = ASSERT_PTR(userdata);
|
||||
+ const sd_bus_error *e;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(message);
|
||||
+ assert(item->track);
|
||||
+ assert(item->name);
|
||||
+
|
||||
+ e = sd_bus_message_get_error(message);
|
||||
+ if (!e)
|
||||
+ return 0;
|
||||
+
|
||||
+ r = sd_bus_error_get_errno(e);
|
||||
+ log_debug_errno(r, "Failed to install match for tracking name '%s': %s", item->name, bus_error_message(e, r));
|
||||
+
|
||||
+ bus_track_remove_name_fully(item->track, item->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -216,6 +239,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
|
||||
|
||||
*n = (struct track_item) {
|
||||
.n_ref = 1,
|
||||
+ .track = track,
|
||||
};
|
||||
|
||||
n->name = strdup(name);
|
||||
@@ -227,7 +251,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
|
||||
|
||||
bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
|
||||
|
||||
- r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL, track);
|
||||
+ r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, name_owner_changed_install_callback, n);
|
||||
if (r < 0) {
|
||||
bus_track_add_to_queue(track);
|
||||
return r;
|
||||
@ -0,0 +1,38 @@
|
||||
From 9f940102616443911fff789aae63546c1da3138e Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <luca.boccassi@gmail.com>
|
||||
Date: Tue, 18 Feb 2025 21:15:08 +0000
|
||||
Subject: [PATCH] shell completion: add kernel-identify/inspect verbs for
|
||||
bootctl
|
||||
|
||||
Follow-up for a05255981ba5b04f1cf54ea656fbce1dfd9c3a68
|
||||
Follow-up for 3e0a3a0259324b4c40a9a62c8506fe683cd0273b
|
||||
|
||||
(cherry picked from commit 6a6d4c3f3c123a1cbb6770f1cae8c130a48333e1)
|
||||
|
||||
Resolves: RHEL-108576
|
||||
---
|
||||
shell-completion/bash/bootctl | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/shell-completion/bash/bootctl b/shell-completion/bash/bootctl
|
||||
index 0b7cef7871..328289e0cf 100644
|
||||
--- a/shell-completion/bash/bootctl
|
||||
+++ b/shell-completion/bash/bootctl
|
||||
@@ -70,6 +70,7 @@ _bootctl() {
|
||||
[STANDALONE]='help status install update remove is-installed random-seed systemd-efi-options list set-timeout set-timeout-oneshot'
|
||||
[BOOTENTRY]='set-default set-oneshot'
|
||||
[BOOLEAN]='reboot-to-firmware'
|
||||
+ [FILE]='kernel-identify kernel-inspect'
|
||||
)
|
||||
|
||||
for ((i=0; i < COMP_CWORD; i++)); do
|
||||
@@ -100,6 +101,9 @@ _bootctl() {
|
||||
fi
|
||||
elif __contains_word "$verb" ${VERBS[BOOLEAN]}; then
|
||||
comps="yes no"
|
||||
+ elif __contains_word "$verb" ${VERBS[FILE]}; then
|
||||
+ comps=$( compgen -A file -- "$cur" )
|
||||
+ compopt -o filenames
|
||||
fi
|
||||
|
||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||
@ -0,0 +1,444 @@
|
||||
From 05b4623cb23c6f083a5bee9769e5cd22d8ff4e16 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 12 Feb 2023 05:30:49 +0900
|
||||
Subject: [PATCH] test: add tests for format_timestamp() and parse_timestamp()
|
||||
with various timezone
|
||||
|
||||
(cherry picked from commit 8b51c41fd0796b1299f3b7f2f11eaf4efae8c2db)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 378 ++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 366 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 6b546fb9f5..3fbf7bf3d0 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -1,6 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
+#include "dirent-util.h"
|
||||
#include "env-util.h"
|
||||
+#include "fd-util.h"
|
||||
+#include "fileio.h"
|
||||
#include "random-util.h"
|
||||
#include "serialize.h"
|
||||
#include "string-util.h"
|
||||
@@ -8,6 +11,8 @@
|
||||
#include "tests.h"
|
||||
#include "time-util.h"
|
||||
|
||||
+#define TRIAL 100u
|
||||
+
|
||||
TEST(parse_sec) {
|
||||
usec_t u;
|
||||
|
||||
@@ -334,11 +339,11 @@ TEST(usec_sub_signed) {
|
||||
}
|
||||
|
||||
TEST(format_timestamp) {
|
||||
- for (unsigned i = 0; i < 100; i++) {
|
||||
+ for (unsigned i = 0; i < TRIAL; i++) {
|
||||
char buf[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
|
||||
usec_t x, y;
|
||||
|
||||
- x = random_u64_range(2147483600 * USEC_PER_SEC) + 1;
|
||||
+ x = random_u64_range(USEC_TIMESTAMP_FORMATTABLE_MAX - USEC_PER_SEC) + USEC_PER_SEC;
|
||||
|
||||
assert_se(format_timestamp(buf, sizeof(buf), x));
|
||||
log_debug("%s", buf);
|
||||
@@ -377,20 +382,91 @@ TEST(format_timestamp) {
|
||||
}
|
||||
}
|
||||
|
||||
+static void test_format_timestamp_impl(usec_t x) {
|
||||
+ bool success;
|
||||
+ const char *xx, *yy;
|
||||
+ usec_t y;
|
||||
+
|
||||
+ xx = FORMAT_TIMESTAMP(x);
|
||||
+ assert_se(xx);
|
||||
+ assert_se(parse_timestamp(xx, &y) >= 0);
|
||||
+ yy = FORMAT_TIMESTAMP(y);
|
||||
+ assert_se(yy);
|
||||
+
|
||||
+ success = (x / USEC_PER_SEC == y / USEC_PER_SEC) && streq(xx, yy);
|
||||
+ log_full(success ? LOG_DEBUG : LOG_ERR, "@" USEC_FMT " → %s → @" USEC_FMT " → %s", x, xx, y, yy);
|
||||
+ assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
||||
+ assert_se(streq(xx, yy));
|
||||
+}
|
||||
+
|
||||
+static void test_format_timestamp_loop(void) {
|
||||
+ test_format_timestamp_impl(USEC_PER_SEC);
|
||||
+
|
||||
+ for (unsigned i = 0; i < TRIAL; i++) {
|
||||
+ usec_t x;
|
||||
+
|
||||
+ x = random_u64_range(USEC_TIMESTAMP_FORMATTABLE_MAX - USEC_PER_SEC) + USEC_PER_SEC;
|
||||
+ test_format_timestamp_impl(x);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
TEST(FORMAT_TIMESTAMP) {
|
||||
- for (unsigned i = 0; i < 100; i++) {
|
||||
- _cleanup_free_ char *buf;
|
||||
- usec_t x, y;
|
||||
+ test_format_timestamp_loop();
|
||||
+}
|
||||
|
||||
- x = random_u64_range(2147483600 * USEC_PER_SEC) + 1;
|
||||
+static void test_format_timestamp_with_tz_one(const char *name1, const char *name2) {
|
||||
+ _cleanup_free_ char *buf = NULL, *tz = NULL;
|
||||
+ const char *name, *saved_tz;
|
||||
|
||||
- /* strbuf() is to test the macro in an argument to a function call. */
|
||||
- assert_se(buf = strdup(FORMAT_TIMESTAMP(x)));
|
||||
- log_debug("%s", buf);
|
||||
- assert_se(parse_timestamp(buf, &y) >= 0);
|
||||
- assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
||||
+ if (name2)
|
||||
+ assert_se(buf = path_join(name1, name2));
|
||||
+ name = buf ?: name1;
|
||||
+
|
||||
+ if (!timezone_is_valid(name, LOG_DEBUG))
|
||||
+ return;
|
||||
|
||||
- assert_se(streq(FORMAT_TIMESTAMP(x), buf));
|
||||
+ log_info("/* %s(%s) */", __func__, name);
|
||||
+
|
||||
+ saved_tz = getenv("TZ");
|
||||
+
|
||||
+ assert_se(tz = strjoin(":", name));
|
||||
+ assert_se(setenv("TZ", tz, 1) >= 0);
|
||||
+ tzset();
|
||||
+ log_debug("%s: tzname[0]=%s, tzname[1]=%s", tz, strempty(tzname[0]), strempty(tzname[1]));
|
||||
+
|
||||
+ test_format_timestamp_loop();
|
||||
+
|
||||
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
+ tzset();
|
||||
+}
|
||||
+
|
||||
+TEST(FORMAT_TIMESTAMP_with_tz) {
|
||||
+ if (!slow_tests_enabled())
|
||||
+ return (void) log_tests_skipped("slow tests are disabled");
|
||||
+
|
||||
+ _cleanup_closedir_ DIR *dir = opendir("/usr/share/zoneinfo");
|
||||
+ if (!dir)
|
||||
+ return (void) log_tests_skipped_errno(errno, "Failed to open /usr/share/zoneinfo");
|
||||
+
|
||||
+ FOREACH_DIRENT(de, dir, break) {
|
||||
+ if (de->d_type == DT_REG)
|
||||
+ test_format_timestamp_with_tz_one(de->d_name, NULL);
|
||||
+
|
||||
+ else if (de->d_type == DT_DIR) {
|
||||
+ if (streq(de->d_name, "right"))
|
||||
+ /* The test does not support timezone with leap second info. */
|
||||
+ continue;
|
||||
+
|
||||
+ _cleanup_closedir_ DIR *subdir = xopendirat(dirfd(dir), de->d_name, 0);
|
||||
+ if (!subdir) {
|
||||
+ log_notice_errno(errno, "Failed to open /usr/share/zoneinfo/%s, ignoring: %m", de->d_name);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ FOREACH_DIRENT(subde, subdir, break)
|
||||
+ if (subde->d_type == DT_REG)
|
||||
+ test_format_timestamp_with_tz_one(de->d_name, subde->d_name);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,6 +566,219 @@ TEST(format_timestamp_utc) {
|
||||
test_format_timestamp_utc_one(USEC_INFINITY, NULL);
|
||||
}
|
||||
|
||||
+static void test_parse_timestamp_one(const char *str, usec_t max_diff, usec_t expected) {
|
||||
+ usec_t usec;
|
||||
+
|
||||
+ log_debug("/* %s(%s) */", __func__, str);
|
||||
+ assert_se(parse_timestamp(str, &usec) >= 0);
|
||||
+ assert_se(usec >= expected);
|
||||
+ assert_se(usec_sub_unsigned(usec, expected) <= max_diff);
|
||||
+}
|
||||
+
|
||||
+TEST(parse_timestamp) {
|
||||
+ usec_t today, now_usec;
|
||||
+
|
||||
+ /* UTC */
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1970-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1970-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1970-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1970-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("70-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("70-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("70-01-01 00:00:01.001 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("70-01-01 00:00:01.0010 UTC", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ if (timezone_is_valid("Asia/Tokyo", LOG_DEBUG)) {
|
||||
+ /* Asia/Tokyo (+0900) */
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1970-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1970-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1970-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1970-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("70-01-01 09:01 Asia/Tokyo", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("70-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("70-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("70-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ const char *saved_tz = getenv("TZ");
|
||||
+ assert_se(setenv("TZ", ":Asia/Tokyo", 1) >= 0);
|
||||
+
|
||||
+ /* JST (+0900) */
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Thu 1970-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Thu 70-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1970-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1970-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1970-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1970-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("70-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("70-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("70-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("70-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
+ }
|
||||
+
|
||||
+ if (timezone_is_valid("America/New_York", LOG_DEBUG)) {
|
||||
+ /* America/New_York (-0500) */
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1969-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1969-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1969-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1969-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("69-12-31 19:01 America/New_York", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("69-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("69-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("69-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ const char *saved_tz = getenv("TZ");
|
||||
+ assert_se(setenv("TZ", ":America/New_York", 1) >= 0);
|
||||
+
|
||||
+ /* EST (-0500) */
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1969-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1969-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1969-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1969-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("69-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("69-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("69-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("69-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
+ }
|
||||
+
|
||||
+ /* -06 */
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1969-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("69-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01.001 -06", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01.0010 -06", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ /* -0600 */
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1969-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("69-12-31 18:01 -0600", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01 -0600", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01.001 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01.0010 -0600", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ /* -06:00 */
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 1969-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("Wed 69-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("1969-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("1969-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ test_parse_timestamp_one("69-12-31 18:01 -06:00", 0, USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("69-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ /* without date */
|
||||
+ assert_se(parse_timestamp("today", &today) == 0);
|
||||
+ test_parse_timestamp_one("00:01", 0, today + USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("00:00:01", 0, today + USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("00:00:01.001", 0, today + USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("00:00:01.0010", 0, today + USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("tomorrow", 0, today + USEC_PER_DAY);
|
||||
+ test_parse_timestamp_one("yesterday", 0, today - USEC_PER_DAY);
|
||||
+
|
||||
+ /* relative */
|
||||
+ assert_se(parse_timestamp("now", &now_usec) == 0);
|
||||
+ test_parse_timestamp_one("+5hours", USEC_PER_MINUTE, now_usec + 5 * USEC_PER_HOUR);
|
||||
+ if (now_usec >= 10 * USEC_PER_DAY)
|
||||
+ test_parse_timestamp_one("-10days", USEC_PER_MINUTE, now_usec - 10 * USEC_PER_DAY);
|
||||
+ test_parse_timestamp_one("2weeks left", USEC_PER_MINUTE, now_usec + 2 * USEC_PER_WEEK);
|
||||
+ if (now_usec >= 30 * USEC_PER_MINUTE)
|
||||
+ test_parse_timestamp_one("30minutes ago", USEC_PER_MINUTE, now_usec - 30 * USEC_PER_MINUTE);
|
||||
+}
|
||||
+
|
||||
TEST(deserialize_dual_timestamp) {
|
||||
int r;
|
||||
dual_timestamp t;
|
||||
@@ -613,6 +902,71 @@ TEST(map_clock_usec) {
|
||||
}
|
||||
}
|
||||
|
||||
+static void test_timezone_offset_change_one(const char *utc, const char *pretty) {
|
||||
+ usec_t x, y, z;
|
||||
+ char *s;
|
||||
+
|
||||
+ assert_se(parse_timestamp(utc, &x) >= 0);
|
||||
+
|
||||
+ s = FORMAT_TIMESTAMP_STYLE(x, TIMESTAMP_UTC);
|
||||
+ assert_se(parse_timestamp(s, &y) >= 0);
|
||||
+ log_debug("%s -> " USEC_FMT " -> %s -> " USEC_FMT, utc, x, s, y);
|
||||
+ assert_se(streq(s, utc));
|
||||
+ assert_se(x == y);
|
||||
+
|
||||
+ assert_se(parse_timestamp(pretty, &y) >= 0);
|
||||
+ s = FORMAT_TIMESTAMP_STYLE(y, TIMESTAMP_PRETTY);
|
||||
+ assert_se(parse_timestamp(s, &z) >= 0);
|
||||
+ log_debug("%s -> " USEC_FMT " -> %s -> " USEC_FMT, pretty, y, s, z);
|
||||
+ assert_se(streq(s, pretty));
|
||||
+ assert_se(x == y);
|
||||
+ assert_se(x == z);
|
||||
+}
|
||||
+
|
||||
+TEST(timezone_offset_change) {
|
||||
+ const char *tz = getenv("TZ");
|
||||
+
|
||||
+ /* See issue #26370. */
|
||||
+
|
||||
+ if (timezone_is_valid("Africa/Casablanca", LOG_DEBUG)) {
|
||||
+ assert_se(setenv("TZ", ":Africa/Casablanca", 1) >= 0);
|
||||
+ tzset();
|
||||
+ log_debug("Africa/Casablanca: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
|
||||
+
|
||||
+ test_timezone_offset_change_one("Sun 2015-10-25 01:59:59 UTC", "Sun 2015-10-25 02:59:59 +01");
|
||||
+ test_timezone_offset_change_one("Sun 2015-10-25 02:00:00 UTC", "Sun 2015-10-25 02:00:00 +00");
|
||||
+ test_timezone_offset_change_one("Sun 2018-06-17 01:59:59 UTC", "Sun 2018-06-17 01:59:59 +00");
|
||||
+ test_timezone_offset_change_one("Sun 2018-06-17 02:00:00 UTC", "Sun 2018-06-17 03:00:00 +01");
|
||||
+ test_timezone_offset_change_one("Sun 2018-10-28 01:59:59 UTC", "Sun 2018-10-28 02:59:59 +01");
|
||||
+ test_timezone_offset_change_one("Sun 2018-10-28 02:00:00 UTC", "Sun 2018-10-28 03:00:00 +01");
|
||||
+ }
|
||||
+
|
||||
+ if (timezone_is_valid("Asia/Atyrau", LOG_DEBUG)) {
|
||||
+ assert_se(setenv("TZ", ":Asia/Atyrau", 1) >= 0);
|
||||
+ tzset();
|
||||
+ log_debug("Asia/Atyrau: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
|
||||
+
|
||||
+ test_timezone_offset_change_one("Sat 2004-03-27 21:59:59 UTC", "Sun 2004-03-28 01:59:59 +04");
|
||||
+ test_timezone_offset_change_one("Sat 2004-03-27 22:00:00 UTC", "Sun 2004-03-28 03:00:00 +05");
|
||||
+ test_timezone_offset_change_one("Sat 2004-10-30 21:59:59 UTC", "Sun 2004-10-31 02:59:59 +05");
|
||||
+ test_timezone_offset_change_one("Sat 2004-10-30 22:00:00 UTC", "Sun 2004-10-31 03:00:00 +05");
|
||||
+ }
|
||||
+
|
||||
+ if (timezone_is_valid("Chile/EasterIsland", LOG_DEBUG)) {
|
||||
+ assert_se(setenv("TZ", ":Chile/EasterIsland", 1) >= 0);
|
||||
+ tzset();
|
||||
+ log_debug("Chile/EasterIsland: tzname[0]=%s, tzname[1]=%s", strempty(tzname[0]), strempty(tzname[1]));
|
||||
+
|
||||
+ test_timezone_offset_change_one("Sun 1981-10-11 03:59:59 UTC", "Sat 1981-10-10 20:59:59 -07");
|
||||
+ test_timezone_offset_change_one("Sun 1981-10-11 04:00:00 UTC", "Sat 1981-10-10 22:00:00 -06");
|
||||
+ test_timezone_offset_change_one("Sun 1982-03-14 02:59:59 UTC", "Sat 1982-03-13 20:59:59 -06");
|
||||
+ test_timezone_offset_change_one("Sun 1982-03-14 03:00:00 UTC", "Sat 1982-03-13 21:00:00 -06");
|
||||
+ }
|
||||
+
|
||||
+ assert_se(set_unset_env("TZ", tz, true) == 0);
|
||||
+ tzset();
|
||||
+}
|
||||
+
|
||||
static int intro(void) {
|
||||
log_info("realtime=" USEC_FMT "\n"
|
||||
"monotonic=" USEC_FMT "\n"
|
||||
52
SOURCES/1226-test-time-util-disable-failing-tests.patch
Normal file
52
SOURCES/1226-test-time-util-disable-failing-tests.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From c7a62e108ffbe41ccf1bb5fba4b5a37daf317939 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Fri, 15 Aug 2025 15:12:14 +0200
|
||||
Subject: [PATCH] test-time-util: disable failing tests
|
||||
|
||||
Presumably they depend on fixes that we don't have yet. And I don't want
|
||||
to backport stuff not relevant to the "--when" feature as a part of this
|
||||
PR.
|
||||
|
||||
RHEL-only: ci
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 3fbf7bf3d0..f2acb6159a 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -697,6 +697,7 @@ TEST(parse_timestamp) {
|
||||
assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
}
|
||||
|
||||
+#if 0
|
||||
/* -06 */
|
||||
test_parse_timestamp_one("Wed 1969-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
||||
@@ -759,6 +760,7 @@ TEST(parse_timestamp) {
|
||||
test_parse_timestamp_one("69-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
||||
test_parse_timestamp_one("69-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("69-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
+#endif
|
||||
|
||||
/* without date */
|
||||
assert_se(parse_timestamp("today", &today) == 0);
|
||||
@@ -941,6 +943,7 @@ TEST(timezone_offset_change) {
|
||||
test_timezone_offset_change_one("Sun 2018-10-28 02:00:00 UTC", "Sun 2018-10-28 03:00:00 +01");
|
||||
}
|
||||
|
||||
+#if 0
|
||||
if (timezone_is_valid("Asia/Atyrau", LOG_DEBUG)) {
|
||||
assert_se(setenv("TZ", ":Asia/Atyrau", 1) >= 0);
|
||||
tzset();
|
||||
@@ -962,6 +965,7 @@ TEST(timezone_offset_change) {
|
||||
test_timezone_offset_change_one("Sun 1982-03-14 02:59:59 UTC", "Sat 1982-03-13 20:59:59 -06");
|
||||
test_timezone_offset_change_one("Sun 1982-03-14 03:00:00 UTC", "Sat 1982-03-13 21:00:00 -06");
|
||||
}
|
||||
+#endif
|
||||
|
||||
assert_se(set_unset_env("TZ", tz, true) == 0);
|
||||
tzset();
|
||||
122
SOURCES/1227-test-test-parse_timestamp-in-various-timezone.patch
Normal file
122
SOURCES/1227-test-test-parse_timestamp-in-various-timezone.patch
Normal file
@ -0,0 +1,122 @@
|
||||
From 9010f2b16067fbe974cd1922b596bcd526de07bc Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 3 Mar 2023 12:09:59 +0900
|
||||
Subject: [PATCH] test: test parse_timestamp() in various timezone
|
||||
|
||||
(cherry picked from commit d8f3ad627c9a857d46d442f8ab722c1efab30d5c)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 57 +++++++++++++++++++++++++++++----------
|
||||
1 file changed, 43 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index f2acb6159a..ee861135c2 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -567,15 +567,17 @@ TEST(format_timestamp_utc) {
|
||||
}
|
||||
|
||||
static void test_parse_timestamp_one(const char *str, usec_t max_diff, usec_t expected) {
|
||||
- usec_t usec;
|
||||
+ usec_t usec = USEC_INFINITY;
|
||||
+ int r;
|
||||
|
||||
- log_debug("/* %s(%s) */", __func__, str);
|
||||
- assert_se(parse_timestamp(str, &usec) >= 0);
|
||||
+ r = parse_timestamp(str, &usec);
|
||||
+ log_debug("/* %s(%s): max_diff="USEC_FMT", expected="USEC_FMT", result="USEC_FMT"*/", __func__, str, max_diff, expected, usec);
|
||||
+ assert_se(r >= 0);
|
||||
assert_se(usec >= expected);
|
||||
assert_se(usec_sub_unsigned(usec, expected) <= max_diff);
|
||||
}
|
||||
|
||||
-TEST(parse_timestamp) {
|
||||
+static void test_parse_timestamp_impl(const char *tz) {
|
||||
usec_t today, now_usec;
|
||||
|
||||
/* UTC */
|
||||
@@ -620,10 +622,9 @@ TEST(parse_timestamp) {
|
||||
test_parse_timestamp_one("70-01-01 09:00:01 Asia/Tokyo", 0, USEC_PER_SEC);
|
||||
test_parse_timestamp_one("70-01-01 09:00:01.001 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("70-01-01 09:00:01.0010 Asia/Tokyo", 0, USEC_PER_SEC + 1000);
|
||||
+ }
|
||||
|
||||
- const char *saved_tz = getenv("TZ");
|
||||
- assert_se(setenv("TZ", ":Asia/Tokyo", 1) >= 0);
|
||||
-
|
||||
+ if (streq_ptr(tz, "Asia/Tokyo")) {
|
||||
/* JST (+0900) */
|
||||
test_parse_timestamp_one("Thu 1970-01-01 09:01 JST", 0, USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("Thu 1970-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
||||
@@ -644,8 +645,6 @@ TEST(parse_timestamp) {
|
||||
test_parse_timestamp_one("70-01-01 09:00:01 JST", 0, USEC_PER_SEC);
|
||||
test_parse_timestamp_one("70-01-01 09:00:01.001 JST", 0, USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("70-01-01 09:00:01.0010 JST", 0, USEC_PER_SEC + 1000);
|
||||
-
|
||||
- assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
}
|
||||
|
||||
if (timezone_is_valid("America/New_York", LOG_DEBUG)) {
|
||||
@@ -669,10 +668,9 @@ TEST(parse_timestamp) {
|
||||
test_parse_timestamp_one("69-12-31 19:00:01 America/New_York", 0, USEC_PER_SEC);
|
||||
test_parse_timestamp_one("69-12-31 19:00:01.001 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("69-12-31 19:00:01.0010 America/New_York", 0, USEC_PER_SEC + 1000);
|
||||
+ }
|
||||
|
||||
- const char *saved_tz = getenv("TZ");
|
||||
- assert_se(setenv("TZ", ":America/New_York", 1) >= 0);
|
||||
-
|
||||
+ if (streq_ptr(tz, "America/New_York")) {
|
||||
/* EST (-0500) */
|
||||
test_parse_timestamp_one("Wed 1969-12-31 19:01 EST", 0, USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("Wed 1969-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
||||
@@ -693,8 +691,6 @@ TEST(parse_timestamp) {
|
||||
test_parse_timestamp_one("69-12-31 19:00:01 EST", 0, USEC_PER_SEC);
|
||||
test_parse_timestamp_one("69-12-31 19:00:01.001 EST", 0, USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("69-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
||||
-
|
||||
- assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -781,6 +777,39 @@ TEST(parse_timestamp) {
|
||||
test_parse_timestamp_one("30minutes ago", USEC_PER_MINUTE, now_usec - 30 * USEC_PER_MINUTE);
|
||||
}
|
||||
|
||||
+TEST(parse_timestamp) {
|
||||
+ test_parse_timestamp_impl(NULL);
|
||||
+}
|
||||
+
|
||||
+static void test_parse_timestamp_with_tz_one(const char *tz) {
|
||||
+ const char *saved_tz, *colon_tz;
|
||||
+
|
||||
+ if (!timezone_is_valid(tz, LOG_DEBUG))
|
||||
+ return;
|
||||
+
|
||||
+ log_info("/* %s(%s) */", __func__, tz);
|
||||
+
|
||||
+ saved_tz = getenv("TZ");
|
||||
+
|
||||
+ assert_se(colon_tz = strjoina(":", tz));
|
||||
+ assert_se(setenv("TZ", colon_tz, 1) >= 0);
|
||||
+ tzset();
|
||||
+ log_debug("%s: tzname[0]=%s, tzname[1]=%s", tz, strempty(tzname[0]), strempty(tzname[1]));
|
||||
+
|
||||
+ test_parse_timestamp_impl(tz);
|
||||
+
|
||||
+ assert_se(set_unset_env("TZ", saved_tz, true) == 0);
|
||||
+ tzset();
|
||||
+}
|
||||
+
|
||||
+TEST(parse_timestamp_with_tz) {
|
||||
+ _cleanup_strv_free_ char **timezones = NULL;
|
||||
+
|
||||
+ assert_se(get_timezones(&timezones) >= 0);
|
||||
+ STRV_FOREACH(tz, timezones)
|
||||
+ test_parse_timestamp_with_tz_one(*tz);
|
||||
+}
|
||||
+
|
||||
TEST(deserialize_dual_timestamp) {
|
||||
int r;
|
||||
dual_timestamp t;
|
||||
47
SOURCES/1228-systemctl-logind-add-missing-asserts.patch
Normal file
47
SOURCES/1228-systemctl-logind-add-missing-asserts.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From 41b7fedf9ed75f6dfa9fec03a70964b897fbf9ba Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Tue, 14 Mar 2023 06:56:17 +0800
|
||||
Subject: [PATCH] systemctl: logind: add missing asserts
|
||||
|
||||
(cherry picked from commit 9071eea01bd26d838bfd793db497efd849ad44da)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/systemctl/systemctl-logind.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c
|
||||
index 1c3b68f09f..f910fe6675 100644
|
||||
--- a/src/systemctl/systemctl-logind.c
|
||||
+++ b/src/systemctl/systemctl-logind.c
|
||||
@@ -21,6 +21,8 @@ static int logind_set_wall_message(sd_bus *bus) {
|
||||
_cleanup_free_ char *m = NULL;
|
||||
int r;
|
||||
|
||||
+ assert(bus);
|
||||
+
|
||||
m = strv_join(arg_wall, " ");
|
||||
if (!m)
|
||||
return log_oom();
|
||||
@@ -55,7 +57,10 @@ int logind_reboot(enum action a) {
|
||||
sd_bus *bus;
|
||||
int r;
|
||||
|
||||
- if (a < 0 || a >= _ACTION_MAX || !actions[a])
|
||||
+ assert(a >= 0);
|
||||
+ assert(a < _ACTION_MAX);
|
||||
+
|
||||
+ if (!actions[a])
|
||||
return -EINVAL;
|
||||
|
||||
r = acquire_bus(BUS_FULL, &bus);
|
||||
@@ -106,6 +111,9 @@ int logind_check_inhibitors(enum action a) {
|
||||
unsigned c = 0;
|
||||
int r;
|
||||
|
||||
+ assert(a >= 0);
|
||||
+ assert(a < _ACTION_MAX);
|
||||
+
|
||||
if (arg_check_inhibitors == 0 || arg_force > 0)
|
||||
return 0;
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
From 5085c1c72a52d6c4e8b47d91a6cd08ceec9c49cc Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Sun, 5 Mar 2023 23:11:48 +0800
|
||||
Subject: [PATCH] systemctl: logind: make logind_schedule_shutdown accept
|
||||
action as param
|
||||
|
||||
(cherry picked from commit 92b00e867844948bdf559758739343c4308570c0)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/systemctl/systemctl-compat-halt.c | 2 +-
|
||||
src/systemctl/systemctl-logind.c | 8 +++++---
|
||||
src/systemctl/systemctl-logind.h | 2 +-
|
||||
3 files changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/systemctl/systemctl-compat-halt.c b/src/systemctl/systemctl-compat-halt.c
|
||||
index 8a0e4e6294..b9164c27ab 100644
|
||||
--- a/src/systemctl/systemctl-compat-halt.c
|
||||
+++ b/src/systemctl/systemctl-compat-halt.c
|
||||
@@ -149,7 +149,7 @@ int halt_main(void) {
|
||||
if (arg_force == 0) {
|
||||
/* always try logind first */
|
||||
if (arg_when > 0)
|
||||
- r = logind_schedule_shutdown();
|
||||
+ r = logind_schedule_shutdown(arg_action);
|
||||
else {
|
||||
r = logind_check_inhibitors(arg_action);
|
||||
if (r < 0)
|
||||
diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c
|
||||
index f910fe6675..068f54e18b 100644
|
||||
--- a/src/systemctl/systemctl-logind.c
|
||||
+++ b/src/systemctl/systemctl-logind.c
|
||||
@@ -291,19 +291,21 @@ int prepare_boot_loader_entry(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
-int logind_schedule_shutdown(void) {
|
||||
-
|
||||
+int logind_schedule_shutdown(enum action a) {
|
||||
#if ENABLE_LOGIND
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
const char *action;
|
||||
sd_bus *bus;
|
||||
int r;
|
||||
|
||||
+ assert(a >= 0);
|
||||
+ assert(a < _ACTION_MAX);
|
||||
+
|
||||
r = acquire_bus(BUS_FULL, &bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- action = action_table[arg_action].verb;
|
||||
+ action = action_table[a].verb;
|
||||
if (!action)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Scheduling not supported for this action.");
|
||||
|
||||
diff --git a/src/systemctl/systemctl-logind.h b/src/systemctl/systemctl-logind.h
|
||||
index 925f4559c1..516f74952f 100644
|
||||
--- a/src/systemctl/systemctl-logind.h
|
||||
+++ b/src/systemctl/systemctl-logind.h
|
||||
@@ -10,7 +10,7 @@ int prepare_firmware_setup(void);
|
||||
int prepare_boot_loader_menu(void);
|
||||
int prepare_boot_loader_entry(void);
|
||||
|
||||
-int logind_schedule_shutdown(void);
|
||||
+int logind_schedule_shutdown(enum action a);
|
||||
int logind_cancel_shutdown(void);
|
||||
int logind_show_shutdown(void);
|
||||
|
||||
@ -0,0 +1,262 @@
|
||||
From 87f8db36eb01b805e7000aeb69ebfaf1c8c323b8 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Sun, 5 Mar 2023 23:27:44 +0800
|
||||
Subject: [PATCH] systemctl: add option --when for scheduled shutdown
|
||||
|
||||
Pass an empty string or "cancel" will cancel the action.
|
||||
Pass "show" will show the scheduled actions.
|
||||
|
||||
Replaces #17258
|
||||
|
||||
(cherry picked from commit 1433e1f998465b7acf472c73d58c14e7e2eb3f13)
|
||||
|
||||
Resolves: RHEL-109488
|
||||
---
|
||||
man/systemctl.xml | 41 ++++++++++++++-----------
|
||||
src/systemctl/systemctl-logind.c | 26 ++++++++++------
|
||||
src/systemctl/systemctl-start-special.c | 33 +++++++++++++-------
|
||||
src/systemctl/systemctl.c | 28 +++++++++++++++++
|
||||
4 files changed, 89 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/man/systemctl.xml b/man/systemctl.xml
|
||||
index 1df0b158bd..cea6192224 100644
|
||||
--- a/man/systemctl.xml
|
||||
+++ b/man/systemctl.xml
|
||||
@@ -1448,6 +1448,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<option>--force</option> is specified twice the halt operation is executed by <command>systemctl</command>
|
||||
itself, and the system manager is not contacted. This means the command should succeed even when the system
|
||||
manager has crashed.</para>
|
||||
+
|
||||
+ <para>If combined with <option>--when=</option>, shutdown will be scheduled after the given timestamp.
|
||||
+ And <option>--when=cancel</option> will cancel the shutdown.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@@ -1459,13 +1462,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
users. This command is asynchronous; it will return after the power-off operation is enqueued, without
|
||||
waiting for it to complete.</para>
|
||||
|
||||
- <para>If combined with <option>--force</option>, shutdown of all running services is skipped, however all
|
||||
- processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the
|
||||
- powering off. If <option>--force</option> is specified twice, the operation is immediately executed without
|
||||
- terminating any processes or unmounting any file systems. This may result in data loss. Note that when
|
||||
- <option>--force</option> is specified twice the power-off operation is executed by
|
||||
- <command>systemctl</command> itself, and the system manager is not contacted. This means the command should
|
||||
- succeed even when the system manager has crashed.</para>
|
||||
+ <para>This command honors <option>--force</option> and <option>--when=</option> in a similar way
|
||||
+ as <command>halt</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@@ -1479,14 +1477,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
users. This command is asynchronous; it will return after the reboot operation is enqueued,
|
||||
without waiting for it to complete.</para>
|
||||
|
||||
- <para>If combined with <option>--force</option>, shutdown of all running services is skipped, however all
|
||||
- processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the
|
||||
- reboot. If <option>--force</option> is specified twice, the operation is immediately executed without
|
||||
- terminating any processes or unmounting any file systems. This may result in data loss. Note that when
|
||||
- <option>--force</option> is specified twice the reboot operation is executed by
|
||||
- <command>systemctl</command> itself, and the system manager is not contacted. This means the command should
|
||||
- succeed even when the system manager has crashed.</para>
|
||||
-
|
||||
<para>If the switch <option>--reboot-argument=</option> is given, it will be passed as the optional
|
||||
argument to the <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
system call.</para>
|
||||
@@ -1494,6 +1484,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<para>Options <option>--boot-loader-entry=</option>, <option>--boot-loader-menu=</option>, and
|
||||
<option>--firmware-setup</option> can be used to select what to do <emphasis>after</emphasis> the
|
||||
reboot. See the descriptions of those options for details.</para>
|
||||
+
|
||||
+ <para>This command honors <option>--force</option> and <option>--when=</option> in a similar way
|
||||
+ as <command>halt</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -1506,9 +1499,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
asynchronous; it will return after the reboot operation is enqueued, without waiting for it to
|
||||
complete.</para>
|
||||
|
||||
- <para>If combined with <option>--force</option>, shutdown of all running services is skipped, however all
|
||||
- processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the
|
||||
- reboot.</para>
|
||||
+ <para>This command honors <option>--force</option> and <option>--when=</option> in a similar way
|
||||
+ as <command>halt</command>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -2420,6 +2412,19 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<listitem><para>When used with <command>bind</command>, creates a read-only bind mount.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><option>--when=</option></term>
|
||||
+
|
||||
+ <listitem>
|
||||
+ <para>When used with <command>halt</command>, <command>poweroff</command>, <command>reboot</command>
|
||||
+ or <command>kexec</command>, schedule the action to be performed at the given timestamp,
|
||||
+ which should adhere to the syntax documented in <citerefentry
|
||||
+ project='man-pages'><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
+ section "PARSING TIMESTAMPS". Specially, if <literal>show</literal> is given, the currently scheduled
|
||||
+ action will be shown, which can be canceled by passing an empty string or <literal>cancel</literal>.</para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<xi:include href="user-system-options.xml" xpointer="host" />
|
||||
<xi:include href="user-system-options.xml" xpointer="machine" />
|
||||
|
||||
diff --git a/src/systemctl/systemctl-logind.c b/src/systemctl/systemctl-logind.c
|
||||
index 068f54e18b..fd8ca09de8 100644
|
||||
--- a/src/systemctl/systemctl-logind.c
|
||||
+++ b/src/systemctl/systemctl-logind.c
|
||||
@@ -356,7 +356,7 @@ int logind_show_shutdown(void) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
sd_bus *bus;
|
||||
- const char *action = NULL;
|
||||
+ const char *action, *pretty_action;
|
||||
uint64_t elapse;
|
||||
int r;
|
||||
|
||||
@@ -376,17 +376,23 @@ int logind_show_shutdown(void) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No scheduled shutdown.");
|
||||
|
||||
if (STR_IN_SET(action, "halt", "poweroff", "exit"))
|
||||
- action = "Shutdown";
|
||||
+ pretty_action = "Shutdown";
|
||||
else if (streq(action, "kexec"))
|
||||
- action = "Reboot via kexec";
|
||||
+ pretty_action = "Reboot via kexec";
|
||||
else if (streq(action, "reboot"))
|
||||
- action = "Reboot";
|
||||
-
|
||||
- /* If we don't recognize the action string, we'll show it as-is */
|
||||
-
|
||||
- log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
|
||||
- action,
|
||||
- FORMAT_TIMESTAMP_STYLE(elapse, arg_timestamp_style));
|
||||
+ pretty_action = "Reboot";
|
||||
+ else /* If we don't recognize the action string, we'll show it as-is */
|
||||
+ pretty_action = action;
|
||||
+
|
||||
+ if (arg_action == ACTION_SYSTEMCTL)
|
||||
+ log_info("%s scheduled for %s, use 'systemctl %s --when=cancel' to cancel.",
|
||||
+ pretty_action,
|
||||
+ FORMAT_TIMESTAMP_STYLE(elapse, arg_timestamp_style),
|
||||
+ action);
|
||||
+ else
|
||||
+ log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
|
||||
+ pretty_action,
|
||||
+ FORMAT_TIMESTAMP_STYLE(elapse, arg_timestamp_style));
|
||||
|
||||
return 0;
|
||||
#else
|
||||
diff --git a/src/systemctl/systemctl-start-special.c b/src/systemctl/systemctl-start-special.c
|
||||
index 9363764cd7..4dee3028b0 100644
|
||||
--- a/src/systemctl/systemctl-start-special.c
|
||||
+++ b/src/systemctl/systemctl-start-special.c
|
||||
@@ -208,22 +208,33 @@ int verb_start_special(int argc, char *argv[], void *userdata) {
|
||||
ACTION_POWEROFF,
|
||||
ACTION_REBOOT,
|
||||
ACTION_KEXEC,
|
||||
- ACTION_HALT,
|
||||
- ACTION_SUSPEND,
|
||||
- ACTION_HIBERNATE,
|
||||
- ACTION_HYBRID_SLEEP,
|
||||
- ACTION_SUSPEND_THEN_HIBERNATE)) {
|
||||
-
|
||||
- r = logind_reboot(a);
|
||||
- if (r >= 0)
|
||||
- return r;
|
||||
- if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
|
||||
- /* Requested operation requires auth, is not supported or already in progress */
|
||||
+ ACTION_HALT)) {
|
||||
+
|
||||
+ if (arg_when == 0)
|
||||
+ r = logind_reboot(a);
|
||||
+ else if (arg_when != USEC_INFINITY)
|
||||
+ r = logind_schedule_shutdown(a);
|
||||
+ else /* arg_when == USEC_INFINITY */
|
||||
+ r = logind_cancel_shutdown();
|
||||
+ if (r >= 0 || IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
|
||||
+ /* The latter indicates that the requested operation requires auth,
|
||||
+ * is not supported or already in progress, in which cases we ignore the error. */
|
||||
return r;
|
||||
|
||||
/* On all other errors, try low-level operation. In order to minimize the difference
|
||||
* between operation with and without logind, we explicitly enable non-blocking mode
|
||||
* for this, as logind's shutdown operations are always non-blocking. */
|
||||
+ arg_no_block = true;
|
||||
+
|
||||
+ } else if (IN_SET(a,
|
||||
+ ACTION_SUSPEND,
|
||||
+ ACTION_HIBERNATE,
|
||||
+ ACTION_HYBRID_SLEEP,
|
||||
+ ACTION_SUSPEND_THEN_HIBERNATE)) {
|
||||
+
|
||||
+ r = logind_reboot(a);
|
||||
+ if (r >= 0 || IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
|
||||
+ return r;
|
||||
|
||||
arg_no_block = true;
|
||||
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index 883a5b75f4..9dfde28426 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -313,6 +313,8 @@ static int systemctl_help(void) {
|
||||
" --read-only Create read-only bind mount\n"
|
||||
" --mkdir Create directory before mounting, if missing\n"
|
||||
" --marked Restart/reload previously marked units\n"
|
||||
+ " --when=TIME Schedule halt/power-off/reboot/kexec action after\n"
|
||||
+ " a certain timestamp\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
@@ -435,6 +437,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
ARG_MKDIR,
|
||||
ARG_MARKED,
|
||||
ARG_NO_WARN,
|
||||
+ ARG_WHEN,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -497,6 +500,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
|
||||
{ "mkdir", no_argument, NULL, ARG_MKDIR },
|
||||
{ "marked", no_argument, NULL, ARG_MARKED },
|
||||
+ { "when", required_argument, NULL, ARG_WHEN },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -933,6 +937,30 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
arg_no_warn = true;
|
||||
break;
|
||||
|
||||
+ case ARG_WHEN:
|
||||
+ if (streq(optarg, "show")) {
|
||||
+ r = logind_show_shutdown();
|
||||
+ if (r < 0 && r != -ENODATA)
|
||||
+ return r;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (STR_IN_SET(optarg, "", "cancel")) {
|
||||
+ arg_when = USEC_INFINITY;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ r = parse_timestamp(optarg, &arg_when);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to parse --when= argument '%s': %m", optarg);
|
||||
+
|
||||
+ if (!timestamp_is_set(arg_when))
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
+ "Invalid timestamp '%s' specified for --when=.", optarg);
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
case '.':
|
||||
/* Output an error mimicking getopt, and print a hint afterwards */
|
||||
log_error("%s: invalid option -- '.'", program_invocation_name);
|
||||
@ -0,0 +1,31 @@
|
||||
From e8f66d4c6570765fd60111ec7e3b5dbdb7d14c69 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Tue, 14 Mar 2023 07:16:18 +0800
|
||||
Subject: [PATCH] test-time-util: add test cases to invalidate "show" and
|
||||
"cancel"
|
||||
|
||||
Ensure that systemctl reboot --when=show and --when=cancel will not result in ambiguities
|
||||
|
||||
(cherry picked from commit 165655cb1de2e79d954d9165459143140e52c53b)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index ee861135c2..379f55ff2f 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -580,6 +580,11 @@ static void test_parse_timestamp_one(const char *str, usec_t max_diff, usec_t ex
|
||||
static void test_parse_timestamp_impl(const char *tz) {
|
||||
usec_t today, now_usec;
|
||||
|
||||
+ /* Invalid: Ensure that systemctl reboot --when=show and --when=cancel
|
||||
+ * will not result in ambiguities */
|
||||
+ assert_se(parse_timestamp("show", NULL) == -EINVAL);
|
||||
+ assert_se(parse_timestamp("cancel", NULL) == -EINVAL);
|
||||
+
|
||||
/* UTC */
|
||||
test_parse_timestamp_one("Thu 1970-01-01 00:01 UTC", 0, USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("Thu 1970-01-01 00:00:01 UTC", 0, USEC_PER_SEC);
|
||||
128
SOURCES/1232-Introduce-RET_GATHER-and-use-it-in-src-shared.patch
Normal file
128
SOURCES/1232-Introduce-RET_GATHER-and-use-it-in-src-shared.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From 5bec9826a14483e7e612879fe2630f1b517e37be Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Sun, 9 Jul 2023 13:25:42 -0600
|
||||
Subject: [PATCH] Introduce RET_GATHER and use it in src/shared/
|
||||
|
||||
The idea is to make it easier to implement the common pattern of
|
||||
accumulating errors (negative values) in an accumulator to return
|
||||
the first error.
|
||||
|
||||
(cherry picked from commit 809c3a84e1a572ccaaa7eca5394c0b842118c22f)
|
||||
|
||||
Resolves: RHEL-108598
|
||||
---
|
||||
src/basic/errno-util.h | 10 ++++++++++
|
||||
src/shared/bus-util.c | 10 ++--------
|
||||
src/shared/devnode-acl.c | 4 ++--
|
||||
src/shared/nscd-flush.c | 16 +++++-----------
|
||||
src/test/test-errno-util.c | 11 +++++++++++
|
||||
5 files changed, 30 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h
|
||||
index b10dd755c9..27804e6382 100644
|
||||
--- a/src/basic/errno-util.h
|
||||
+++ b/src/basic/errno-util.h
|
||||
@@ -74,6 +74,16 @@ static inline int RET_NERRNO(int ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* Collect possible errors in <acc>, so that the first error can be returned.
|
||||
+ * Returns (possibly updated) <acc>. */
|
||||
+#define RET_GATHER(acc, err) \
|
||||
+ ({ \
|
||||
+ int *__a = &(acc), __e = (err); \
|
||||
+ if (*__a >= 0 && __e < 0) \
|
||||
+ *__a = __e; \
|
||||
+ *__a; \
|
||||
+ })
|
||||
+
|
||||
static inline int errno_or_else(int fallback) {
|
||||
/* To be used when invoking library calls where errno handling is not defined clearly: we return
|
||||
* errno if it is set, and the specified error otherwise. The idea is that the caller initializes
|
||||
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
|
||||
index 5e6d17d201..7c8d2aa6f5 100644
|
||||
--- a/src/shared/bus-util.c
|
||||
+++ b/src/shared/bus-util.c
|
||||
@@ -484,14 +484,8 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
|
||||
|
||||
/* Continues adding after failure, and returns the first failure. */
|
||||
|
||||
- STRV_FOREACH(i, l) {
|
||||
- int k;
|
||||
-
|
||||
- k = sd_bus_track_add_name(t, *i);
|
||||
- if (k < 0 && r >= 0)
|
||||
- r = k;
|
||||
- }
|
||||
-
|
||||
+ STRV_FOREACH(i, l)
|
||||
+ RET_GATHER(r, sd_bus_track_add_name(t, *i));
|
||||
return r;
|
||||
}
|
||||
|
||||
diff --git a/src/shared/devnode-acl.c b/src/shared/devnode-acl.c
|
||||
index 66e3a40f2f..8c961061cf 100644
|
||||
--- a/src/shared/devnode-acl.c
|
||||
+++ b/src/shared/devnode-acl.c
|
||||
@@ -220,8 +220,8 @@ int devnode_acl_all(const char *seat,
|
||||
k = devnode_acl(n, flush, del, old_uid, add, new_uid);
|
||||
if (k == -ENOENT)
|
||||
log_debug("Device %s disappeared while setting ACLs", n);
|
||||
- else if (k < 0 && r == 0)
|
||||
- r = k;
|
||||
+ else
|
||||
+ RET_GATHER(r, k);
|
||||
}
|
||||
|
||||
return r;
|
||||
diff --git a/src/shared/nscd-flush.c b/src/shared/nscd-flush.c
|
||||
index 9b0ba2d67a..d2b41f2b4d 100644
|
||||
--- a/src/shared/nscd-flush.c
|
||||
+++ b/src/shared/nscd-flush.c
|
||||
@@ -128,21 +128,15 @@ static int nscd_flush_cache_one(const char *database, usec_t end) {
|
||||
}
|
||||
|
||||
int nscd_flush_cache(char **databases) {
|
||||
- usec_t end;
|
||||
int r = 0;
|
||||
|
||||
- /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout, so that we
|
||||
- * don't block indefinitely on another service. */
|
||||
+ /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s timeout,
|
||||
+ * so that we don't block indefinitely on another service. */
|
||||
|
||||
- end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
|
||||
+ usec_t end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC);
|
||||
|
||||
- STRV_FOREACH(i, databases) {
|
||||
- int k;
|
||||
-
|
||||
- k = nscd_flush_cache_one(*i, end);
|
||||
- if (k < 0 && r >= 0)
|
||||
- r = k;
|
||||
- }
|
||||
+ STRV_FOREACH(i, databases)
|
||||
+ RET_GATHER(r, nscd_flush_cache_one(*i, end));
|
||||
|
||||
return r;
|
||||
}
|
||||
diff --git a/src/test/test-errno-util.c b/src/test/test-errno-util.c
|
||||
index cac0d5402b..77fb7d0011 100644
|
||||
--- a/src/test/test-errno-util.c
|
||||
+++ b/src/test/test-errno-util.c
|
||||
@@ -67,4 +67,15 @@ TEST(ERRNO_IS_TRANSIENT) {
|
||||
assert_se(!ERRNO_IS_NEG_TRANSIENT(INTMAX_MIN));
|
||||
}
|
||||
|
||||
+TEST(RET_GATHER) {
|
||||
+ int x = 0, y = 2;
|
||||
+
|
||||
+ assert_se(RET_GATHER(x, 5) == 0);
|
||||
+ assert_se(RET_GATHER(x, -5) == -5);
|
||||
+ assert_se(RET_GATHER(x, -1) == -5);
|
||||
+
|
||||
+ assert_se(RET_GATHER(x, y++) == -5);
|
||||
+ assert_se(y == 3);
|
||||
+}
|
||||
+
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
@ -0,0 +1,50 @@
|
||||
From c2dc44abd4014f13a40dde350af92e2d74201359 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Fri, 29 Dec 2023 17:57:59 +0800
|
||||
Subject: [PATCH] fd-util: don't eat up errors in fd_cloexec_many
|
||||
|
||||
Follow-up for ed18c22c989495aab36512f03449222cfcf79aa7
|
||||
|
||||
Before this commit, a successful fd_cloexec() call would
|
||||
discard all previously gathered errors.
|
||||
|
||||
(cherry picked from commit 6b9cac874c33f4fa27aa4b4b5b980f60c28ee043)
|
||||
|
||||
Resolves: RHEL-108598
|
||||
---
|
||||
src/basic/fd-util.c | 13 ++++++-------
|
||||
1 file changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
|
||||
index 66bb7569bb..932c5a8d80 100644
|
||||
--- a/src/basic/fd-util.c
|
||||
+++ b/src/basic/fd-util.c
|
||||
@@ -175,7 +175,7 @@ int fd_cloexec(int fd, bool cloexec) {
|
||||
}
|
||||
|
||||
int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec) {
|
||||
- int ret = 0, r;
|
||||
+ int r = 0;
|
||||
|
||||
assert(n_fds == 0 || fds);
|
||||
|
||||
@@ -183,14 +183,13 @@ int fd_cloexec_many(const int fds[], size_t n_fds, bool cloexec) {
|
||||
if (fds[i] < 0) /* Skip gracefully over already invalidated fds */
|
||||
continue;
|
||||
|
||||
- r = fd_cloexec(fds[i], cloexec);
|
||||
- if (r < 0 && ret >= 0) /* Continue going, but return first error */
|
||||
- ret = r;
|
||||
- else
|
||||
- ret = 1; /* report if we did anything */
|
||||
+ RET_GATHER(r, fd_cloexec(fds[i], cloexec));
|
||||
+
|
||||
+ if (r >= 0)
|
||||
+ r = 1; /* report if we did anything */
|
||||
}
|
||||
|
||||
- return ret;
|
||||
+ return r;
|
||||
}
|
||||
|
||||
_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) {
|
||||
@ -0,0 +1,52 @@
|
||||
From 762a8dc0c328e256847b111249bbff8e70f98942 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 19 May 2023 04:33:39 +0900
|
||||
Subject: [PATCH] sd-bus: refuse to send messages with an invalid string
|
||||
|
||||
Prompted by aaf7b0e41105d7b7cf30912cdac32820f011a219 and
|
||||
4804da58536ab7ad46178a03f4d2da49fd8e4ba2.
|
||||
|
||||
(cherry picked from commit 26a9dd6f55bb757e0033995cbb16bca12986b7cd)
|
||||
|
||||
Resolves: RHEL-108584
|
||||
---
|
||||
src/libsystemd/sd-bus/bus-message.c | 14 +++++++++++++-
|
||||
1 file changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
|
||||
index 213b276e33..c51af56dda 100644
|
||||
--- a/src/libsystemd/sd-bus/bus-message.c
|
||||
+++ b/src/libsystemd/sd-bus/bus-message.c
|
||||
@@ -1324,12 +1324,21 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
|
||||
* into the empty string */
|
||||
p = strempty(p);
|
||||
|
||||
- _fallthrough_;
|
||||
+ if (!utf8_is_valid(p))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ align = 4;
|
||||
+ sz = 4 + strlen(p) + 1;
|
||||
+ break;
|
||||
+
|
||||
case SD_BUS_TYPE_OBJECT_PATH:
|
||||
|
||||
if (!p)
|
||||
return -EINVAL;
|
||||
|
||||
+ if (!object_path_is_valid(p))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
align = 4;
|
||||
sz = 4 + strlen(p) + 1;
|
||||
break;
|
||||
@@ -1338,6 +1347,9 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
|
||||
|
||||
p = strempty(p);
|
||||
|
||||
+ if (!signature_is_valid(p, /* allow_dict_entry = */ true))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
align = 1;
|
||||
sz = 1 + strlen(p) + 1;
|
||||
break;
|
||||
@ -0,0 +1,92 @@
|
||||
From f3f939b236636fdca38e89ca564a669f0da4fd4d Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Fri, 19 May 2023 18:42:36 +0200
|
||||
Subject: [PATCH] test: check if we correctly handle invalid UTF-8 in mount
|
||||
stuff
|
||||
|
||||
Provides coverage for #27611.
|
||||
|
||||
(cherry picked from commit b74df879fc81d4668ce14532a76c23b85e651170)
|
||||
|
||||
Resolves: RHEL-108584
|
||||
---
|
||||
.../units/testsuite-07.mount-invalid-chars.sh | 70 +++++++++++++++++++
|
||||
1 file changed, 70 insertions(+)
|
||||
create mode 100755 test/units/testsuite-07.mount-invalid-chars.sh
|
||||
|
||||
diff --git a/test/units/testsuite-07.mount-invalid-chars.sh b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
new file mode 100755
|
||||
index 0000000000..617ea697c8
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
@@ -0,0 +1,70 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+# Don't send invalid characters over dbus if a mount contains them
|
||||
+
|
||||
+at_exit() {
|
||||
+ mountpoint -q /proc/1/mountinfo && umount /proc/1/mountinfo
|
||||
+ [[ -e /tmp/fstab.bak ]] && mv -f /tmp/fstab /etc/fstab
|
||||
+ rm -f /run/systemd/system/foo-*.mount
|
||||
+ systemctl daemon-reload
|
||||
+}
|
||||
+
|
||||
+trap at_exit EXIT
|
||||
+
|
||||
+# Check invalid characters directly in /proc/mountinfo
|
||||
+#
|
||||
+# This is a bit tricky (and hacky), since we have to temporarily replace
|
||||
+# PID 1's /proc/mountinfo, but we have to keep the original mounts intact,
|
||||
+# otherwise systemd would unmount them on reload
|
||||
+TMP_MOUNTINFO="$(mktemp)"
|
||||
+
|
||||
+cp /proc/1/mountinfo "$TMP_MOUNTINFO"
|
||||
+# Add a mount entry with a "Unicode non-character" in it
|
||||
+echo -ne '69 1 252:2 / /foo/mountinfo rw,relatime shared:1 - cifs //foo\ufffebar rw,seclabel\n' >>"$TMP_MOUNTINFO"
|
||||
+mount --bind "$TMP_MOUNTINFO" /proc/1/mountinfo
|
||||
+systemctl daemon-reload
|
||||
+# On affected versions this would throw an error:
|
||||
+# Failed to get properties: Bad message
|
||||
+systemctl status foo-mountinfo.mount
|
||||
+
|
||||
+umount /proc/1/mountinfo
|
||||
+systemctl daemon-reload
|
||||
+rm -f "$TMP_MOUNTINFO"
|
||||
+
|
||||
+# Check invalid characters in a mount unit
|
||||
+#
|
||||
+# systemd already handles this and refuses to load the invalid string, e.g.:
|
||||
+# foo-fstab.mount:9: String is not UTF-8 clean, ignoring assignment: What=//localhost/foo<6F><6F><EFBFBD>bar
|
||||
+#
|
||||
+# a) Unit generated from /etc/fstab
|
||||
+[[ -e /etc/fstab ]] && cp -f /etc/fstab /tmp/fstab.bak
|
||||
+
|
||||
+echo -ne '//localhost/foo\ufffebar /foo/fstab cifs defaults 0 0\n' >/etc/fstab
|
||||
+systemctl daemon-reload
|
||||
+[[ "$(systemctl show -P UnitFileState foo-fstab.mount)" == bad ]]
|
||||
+
|
||||
+# b) Unit generated from /etc/fstab (but the invalid character is in options)
|
||||
+echo -ne '//localhost/foobar /foo/fstab/opt cifs nosuid,a\ufffeb,noexec 0 0\n' >/etc/fstab
|
||||
+systemctl daemon-reload
|
||||
+[[ "$(systemctl show -P UnitFileState foo-fstab-opt.mount)" == bad ]]
|
||||
+rm -f /etc/fstab
|
||||
+
|
||||
+[[ -e /tmp/fstab.bak ]] && mv -f /tmp/fstab /etc/fstab
|
||||
+systemctl daemon-reload
|
||||
+
|
||||
+# c) Mount unit
|
||||
+mkdir -p /run/systemd/system
|
||||
+echo -ne '[Mount]\nWhat=//localhost/foo\ufffebar\nWhere=/foo/unit\nType=cifs\nOptions=noexec\n' >/run/systemd/system/foo-unit.mount
|
||||
+systemctl daemon-reload
|
||||
+[[ "$(systemctl show -P UnitFileState foo-unit.mount)" == bad ]]
|
||||
+rm -f /run/systemd/system/foo-unit.mount
|
||||
+
|
||||
+# d) Mount unit (but the invalid character is in Options=)
|
||||
+mkdir -p /run/systemd/system
|
||||
+echo -ne '[Mount]\nWhat=//localhost/foobar\nWhere=/foo/unit/opt\nType=cifs\nOptions=noexec,a\ufffeb,nosuid\n' >/run/systemd/system/foo-unit-opt.mount
|
||||
+systemctl daemon-reload
|
||||
+[[ "$(systemctl show -P UnitFileState foo-unit-opt.mount)" == bad ]]
|
||||
+rm -f /run/systemd/system/foo-unit-opt.mount
|
||||
25
SOURCES/1236-test-fix-a-typo-in-the-cleanup-stuff.patch
Normal file
25
SOURCES/1236-test-fix-a-typo-in-the-cleanup-stuff.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From e882eabc5c9115413db1e6d83f4542ad618fec23 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Mon, 22 May 2023 12:06:16 +0200
|
||||
Subject: [PATCH] test: fix a typo in the cleanup stuff
|
||||
|
||||
(cherry picked from commit 7942811255f3d6973b246ebf6b26b690bbceab37)
|
||||
|
||||
Resolves: RHEL-108584
|
||||
---
|
||||
test/units/testsuite-07.mount-invalid-chars.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/units/testsuite-07.mount-invalid-chars.sh b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
index 617ea697c8..b70e621126 100755
|
||||
--- a/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
+++ b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
@@ -7,7 +7,7 @@ set -o pipefail
|
||||
|
||||
at_exit() {
|
||||
mountpoint -q /proc/1/mountinfo && umount /proc/1/mountinfo
|
||||
- [[ -e /tmp/fstab.bak ]] && mv -f /tmp/fstab /etc/fstab
|
||||
+ [[ -e /tmp/fstab.bak ]] && mv -f /tmp/fstab.bak /etc/fstab
|
||||
rm -f /run/systemd/system/foo-*.mount
|
||||
systemctl daemon-reload
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
From 78641d8a552eb95dd85cad9686d829af48478727 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Mon, 14 Aug 2023 20:09:31 +0200
|
||||
Subject: [PATCH] test: explicitly specify a UTF-8 locale for UTF-8 shenanigans
|
||||
|
||||
As things don't work well without it:
|
||||
|
||||
$ LANG=C printf "\ufffe\n"
|
||||
\uFFFE
|
||||
|
||||
(cherry picked from commit 01febfcdce0326aa1888d085c1009c9399f6a930)
|
||||
|
||||
Resolves: RHEL-108584
|
||||
---
|
||||
test/units/testsuite-07.mount-invalid-chars.sh | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/test/units/testsuite-07.mount-invalid-chars.sh b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
index b70e621126..5a07d14d04 100755
|
||||
--- a/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
+++ b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
@@ -23,7 +23,7 @@ TMP_MOUNTINFO="$(mktemp)"
|
||||
|
||||
cp /proc/1/mountinfo "$TMP_MOUNTINFO"
|
||||
# Add a mount entry with a "Unicode non-character" in it
|
||||
-echo -ne '69 1 252:2 / /foo/mountinfo rw,relatime shared:1 - cifs //foo\ufffebar rw,seclabel\n' >>"$TMP_MOUNTINFO"
|
||||
+LANG="C.UTF-8" printf '69 1 252:2 / /foo/mountinfo rw,relatime shared:1 - cifs //foo\ufffebar rw,seclabel\n' >>"$TMP_MOUNTINFO"
|
||||
mount --bind "$TMP_MOUNTINFO" /proc/1/mountinfo
|
||||
systemctl daemon-reload
|
||||
# On affected versions this would throw an error:
|
||||
@@ -42,12 +42,12 @@ rm -f "$TMP_MOUNTINFO"
|
||||
# a) Unit generated from /etc/fstab
|
||||
[[ -e /etc/fstab ]] && cp -f /etc/fstab /tmp/fstab.bak
|
||||
|
||||
-echo -ne '//localhost/foo\ufffebar /foo/fstab cifs defaults 0 0\n' >/etc/fstab
|
||||
+LANG="C.UTF-8" printf '//localhost/foo\ufffebar /foo/fstab cifs defaults 0 0\n' >/etc/fstab
|
||||
systemctl daemon-reload
|
||||
[[ "$(systemctl show -P UnitFileState foo-fstab.mount)" == bad ]]
|
||||
|
||||
# b) Unit generated from /etc/fstab (but the invalid character is in options)
|
||||
-echo -ne '//localhost/foobar /foo/fstab/opt cifs nosuid,a\ufffeb,noexec 0 0\n' >/etc/fstab
|
||||
+LANG="C.UTF-8" printf '//localhost/foobar /foo/fstab/opt cifs nosuid,a\ufffeb,noexec 0 0\n' >/etc/fstab
|
||||
systemctl daemon-reload
|
||||
[[ "$(systemctl show -P UnitFileState foo-fstab-opt.mount)" == bad ]]
|
||||
rm -f /etc/fstab
|
||||
@@ -57,14 +57,14 @@ systemctl daemon-reload
|
||||
|
||||
# c) Mount unit
|
||||
mkdir -p /run/systemd/system
|
||||
-echo -ne '[Mount]\nWhat=//localhost/foo\ufffebar\nWhere=/foo/unit\nType=cifs\nOptions=noexec\n' >/run/systemd/system/foo-unit.mount
|
||||
+LANG="C.UTF-8" printf '[Mount]\nWhat=//localhost/foo\ufffebar\nWhere=/foo/unit\nType=cifs\nOptions=noexec\n' >/run/systemd/system/foo-unit.mount
|
||||
systemctl daemon-reload
|
||||
[[ "$(systemctl show -P UnitFileState foo-unit.mount)" == bad ]]
|
||||
rm -f /run/systemd/system/foo-unit.mount
|
||||
|
||||
# d) Mount unit (but the invalid character is in Options=)
|
||||
mkdir -p /run/systemd/system
|
||||
-echo -ne '[Mount]\nWhat=//localhost/foobar\nWhere=/foo/unit/opt\nType=cifs\nOptions=noexec,a\ufffeb,nosuid\n' >/run/systemd/system/foo-unit-opt.mount
|
||||
+LANG="C.UTF-8" printf '[Mount]\nWhat=//localhost/foobar\nWhere=/foo/unit/opt\nType=cifs\nOptions=noexec,a\ufffeb,nosuid\n' >/run/systemd/system/foo-unit-opt.mount
|
||||
systemctl daemon-reload
|
||||
[[ "$(systemctl show -P UnitFileState foo-unit-opt.mount)" == bad ]]
|
||||
rm -f /run/systemd/system/foo-unit-opt.mount
|
||||
@ -0,0 +1,26 @@
|
||||
From 15ad0f0a0145640ee290d805030338f8c01051f4 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Wed, 23 Aug 2023 15:10:23 +0200
|
||||
Subject: [PATCH] test: use the correct file name when restoring the original
|
||||
fstab
|
||||
|
||||
(cherry picked from commit 9541addff028b56724df79fcf5b88e1544403957)
|
||||
|
||||
Resolves: RHEL-108584
|
||||
---
|
||||
test/units/testsuite-07.mount-invalid-chars.sh | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/units/testsuite-07.mount-invalid-chars.sh b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
index 5a07d14d04..a879334869 100755
|
||||
--- a/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
+++ b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
@@ -52,7 +52,7 @@ systemctl daemon-reload
|
||||
[[ "$(systemctl show -P UnitFileState foo-fstab-opt.mount)" == bad ]]
|
||||
rm -f /etc/fstab
|
||||
|
||||
-[[ -e /tmp/fstab.bak ]] && mv -f /tmp/fstab /etc/fstab
|
||||
+[[ -e /tmp/fstab.bak ]] && mv -f /tmp/fstab.bak /etc/fstab
|
||||
systemctl daemon-reload
|
||||
|
||||
# c) Mount unit
|
||||
@ -0,0 +1,134 @@
|
||||
From b280191167ddc52a77da5b4047297d288f9ce73b Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Fri, 20 Jun 2025 13:16:10 +0200
|
||||
Subject: [PATCH] core: escape UTF-8 in mount unit Where field before sending
|
||||
to clients
|
||||
|
||||
Followup for: 4804da58536ab7ad46178a03f4d2da49fd8e4ba2 #27541
|
||||
|
||||
Fixes: #36206
|
||||
(cherry picked from commit 222b0b05ce9ac29283cd89cf98444c4da3373568)
|
||||
|
||||
Resolves: RHEL-108584
|
||||
---
|
||||
src/core/dbus-mount.c | 23 ++++++++++++++++++-
|
||||
src/core/mount.c | 16 ++++++++++++-
|
||||
src/core/mount.h | 2 ++
|
||||
.../units/testsuite-07.mount-invalid-chars.sh | 5 ++--
|
||||
4 files changed, 42 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
|
||||
index 55ad4f2c98..7006ebbbba 100644
|
||||
--- a/src/core/dbus-mount.c
|
||||
+++ b/src/core/dbus-mount.c
|
||||
@@ -11,6 +11,27 @@
|
||||
#include "unit.h"
|
||||
#include "utf8.h"
|
||||
|
||||
+static int property_get_where(
|
||||
+ sd_bus *bus,
|
||||
+ const char *path,
|
||||
+ const char *interface,
|
||||
+ const char *property,
|
||||
+ sd_bus_message *reply,
|
||||
+ void *userdata,
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ Mount *m = ASSERT_PTR(userdata);
|
||||
+
|
||||
+ assert(bus);
|
||||
+ assert(reply);
|
||||
+
|
||||
+ _cleanup_free_ char *escaped = mount_get_where_escaped(m);
|
||||
+ if (!escaped)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ return sd_bus_message_append_basic(reply, 's', escaped);
|
||||
+}
|
||||
+
|
||||
static int property_get_what(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
@@ -84,7 +105,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResu
|
||||
|
||||
const sd_bus_vtable bus_mount_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
- SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Mount, where), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("Where", "s", property_get_where, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("What", "s", property_get_what, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Options","s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Type", "s", property_get_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index cfe3f40302..79772fb6f1 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "strv.h"
|
||||
#include "unit-name.h"
|
||||
#include "unit.h"
|
||||
+#include "utf8.h"
|
||||
|
||||
#define RETRY_UMOUNT_MAX 32
|
||||
|
||||
@@ -657,7 +658,11 @@ static int mount_add_extras(Mount *m) {
|
||||
path_simplify(m->where);
|
||||
|
||||
if (!u->description) {
|
||||
- r = unit_set_description(u, m->where);
|
||||
+ _cleanup_free_ char *w = mount_get_where_escaped(m);
|
||||
+ if (!w)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ r = unit_set_description(u, w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -2207,6 +2212,15 @@ static int mount_can_start(Unit *u) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+char* mount_get_where_escaped(const Mount *m) {
|
||||
+ assert(m);
|
||||
+
|
||||
+ if (!m->where)
|
||||
+ return strdup("");
|
||||
+
|
||||
+ return utf8_escape_invalid(m->where);
|
||||
+}
|
||||
+
|
||||
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
|
||||
[MOUNT_EXEC_MOUNT] = "ExecMount",
|
||||
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
|
||||
diff --git a/src/core/mount.h b/src/core/mount.h
|
||||
index 1a0d9fc5e5..db4a915202 100644
|
||||
--- a/src/core/mount.h
|
||||
+++ b/src/core/mount.h
|
||||
@@ -93,6 +93,8 @@ extern const UnitVTable mount_vtable;
|
||||
|
||||
void mount_fd_event(Manager *m, int events);
|
||||
|
||||
+char* mount_get_where_escaped(const Mount *m);
|
||||
+
|
||||
const char* mount_exec_command_to_string(MountExecCommand i) _const_;
|
||||
MountExecCommand mount_exec_command_from_string(const char *s) _pure_;
|
||||
|
||||
diff --git a/test/units/testsuite-07.mount-invalid-chars.sh b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
index a879334869..cd2ca78fdf 100755
|
||||
--- a/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
+++ b/test/units/testsuite-07.mount-invalid-chars.sh
|
||||
@@ -23,12 +23,13 @@ TMP_MOUNTINFO="$(mktemp)"
|
||||
|
||||
cp /proc/1/mountinfo "$TMP_MOUNTINFO"
|
||||
# Add a mount entry with a "Unicode non-character" in it
|
||||
-LANG="C.UTF-8" printf '69 1 252:2 / /foo/mountinfo rw,relatime shared:1 - cifs //foo\ufffebar rw,seclabel\n' >>"$TMP_MOUNTINFO"
|
||||
+LANG="C.UTF-8" printf '69 1 252:2 / /foo/mount\ufffeinfo rw,relatime shared:1 - cifs //foo\ufffebar rw,seclabel\n' >>"$TMP_MOUNTINFO"
|
||||
mount --bind "$TMP_MOUNTINFO" /proc/1/mountinfo
|
||||
systemctl daemon-reload
|
||||
# On affected versions this would throw an error:
|
||||
# Failed to get properties: Bad message
|
||||
-systemctl status foo-mountinfo.mount
|
||||
+systemctl list-units -t mount
|
||||
+systemctl status foo-mount\\xef\\xbf\\xbeinfo.mount
|
||||
|
||||
umount /proc/1/mountinfo
|
||||
systemctl daemon-reload
|
||||
@ -0,0 +1,51 @@
|
||||
From 4d4f5e617bb467be81274dc32b7066fc5ce52b75 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <fsumsal@redhat.com>
|
||||
Date: Wed, 3 Sep 2025 13:55:00 +0200
|
||||
Subject: [PATCH] Revert "test-time-util: disable failing tests"
|
||||
|
||||
This won't be needed anymore.
|
||||
|
||||
This reverts commit c7a62e108ffbe41ccf1bb5fba4b5a37daf317939.
|
||||
|
||||
rhel-only: ci
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 379f55ff2f..56a71ecfba 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -698,7 +698,6 @@ static void test_parse_timestamp_impl(const char *tz) {
|
||||
test_parse_timestamp_one("69-12-31 19:00:01.0010 EST", 0, USEC_PER_SEC + 1000);
|
||||
}
|
||||
|
||||
-#if 0
|
||||
/* -06 */
|
||||
test_parse_timestamp_one("Wed 1969-12-31 18:01 -06", 0, USEC_PER_MINUTE);
|
||||
test_parse_timestamp_one("Wed 1969-12-31 18:00:01 -06", 0, USEC_PER_SEC);
|
||||
@@ -761,7 +760,6 @@ static void test_parse_timestamp_impl(const char *tz) {
|
||||
test_parse_timestamp_one("69-12-31 18:00:01 -06:00", 0, USEC_PER_SEC);
|
||||
test_parse_timestamp_one("69-12-31 18:00:01.001 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
test_parse_timestamp_one("69-12-31 18:00:01.0010 -06:00", 0, USEC_PER_SEC + 1000);
|
||||
-#endif
|
||||
|
||||
/* without date */
|
||||
assert_se(parse_timestamp("today", &today) == 0);
|
||||
@@ -977,7 +975,6 @@ TEST(timezone_offset_change) {
|
||||
test_timezone_offset_change_one("Sun 2018-10-28 02:00:00 UTC", "Sun 2018-10-28 03:00:00 +01");
|
||||
}
|
||||
|
||||
-#if 0
|
||||
if (timezone_is_valid("Asia/Atyrau", LOG_DEBUG)) {
|
||||
assert_se(setenv("TZ", ":Asia/Atyrau", 1) >= 0);
|
||||
tzset();
|
||||
@@ -999,7 +996,6 @@ TEST(timezone_offset_change) {
|
||||
test_timezone_offset_change_one("Sun 1982-03-14 02:59:59 UTC", "Sat 1982-03-13 20:59:59 -06");
|
||||
test_timezone_offset_change_one("Sun 1982-03-14 03:00:00 UTC", "Sat 1982-03-13 21:00:00 -06");
|
||||
}
|
||||
-#endif
|
||||
|
||||
assert_se(set_unset_env("TZ", tz, true) == 0);
|
||||
tzset();
|
||||
@ -0,0 +1,92 @@
|
||||
From 03dff755efde1a311969636e11fe95c398b7d878 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 3 Mar 2023 19:40:40 +0900
|
||||
Subject: [PATCH] test: use get_timezones() to iterate all known timezones
|
||||
|
||||
(cherry picked from commit 0b20d70d1c7c190fb943dd4d1f28e6f456d2193e)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 50 +++++++++------------------------------
|
||||
1 file changed, 11 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 56a71ecfba..eb8cc538c0 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
-#include "dirent-util.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@@ -414,23 +413,18 @@ TEST(FORMAT_TIMESTAMP) {
|
||||
test_format_timestamp_loop();
|
||||
}
|
||||
|
||||
-static void test_format_timestamp_with_tz_one(const char *name1, const char *name2) {
|
||||
- _cleanup_free_ char *buf = NULL, *tz = NULL;
|
||||
- const char *name, *saved_tz;
|
||||
-
|
||||
- if (name2)
|
||||
- assert_se(buf = path_join(name1, name2));
|
||||
- name = buf ?: name1;
|
||||
+static void test_format_timestamp_with_tz_one(const char *tz) {
|
||||
+ const char *saved_tz, *colon_tz;
|
||||
|
||||
- if (!timezone_is_valid(name, LOG_DEBUG))
|
||||
+ if (!timezone_is_valid(tz, LOG_DEBUG))
|
||||
return;
|
||||
|
||||
- log_info("/* %s(%s) */", __func__, name);
|
||||
+ log_info("/* %s(%s) */", __func__, tz);
|
||||
|
||||
saved_tz = getenv("TZ");
|
||||
|
||||
- assert_se(tz = strjoin(":", name));
|
||||
- assert_se(setenv("TZ", tz, 1) >= 0);
|
||||
+ assert_se(colon_tz = strjoina(":", tz));
|
||||
+ assert_se(setenv("TZ", colon_tz, 1) >= 0);
|
||||
tzset();
|
||||
log_debug("%s: tzname[0]=%s, tzname[1]=%s", tz, strempty(tzname[0]), strempty(tzname[1]));
|
||||
|
||||
@@ -441,33 +435,11 @@ static void test_format_timestamp_with_tz_one(const char *name1, const char *nam
|
||||
}
|
||||
|
||||
TEST(FORMAT_TIMESTAMP_with_tz) {
|
||||
- if (!slow_tests_enabled())
|
||||
- return (void) log_tests_skipped("slow tests are disabled");
|
||||
-
|
||||
- _cleanup_closedir_ DIR *dir = opendir("/usr/share/zoneinfo");
|
||||
- if (!dir)
|
||||
- return (void) log_tests_skipped_errno(errno, "Failed to open /usr/share/zoneinfo");
|
||||
-
|
||||
- FOREACH_DIRENT(de, dir, break) {
|
||||
- if (de->d_type == DT_REG)
|
||||
- test_format_timestamp_with_tz_one(de->d_name, NULL);
|
||||
-
|
||||
- else if (de->d_type == DT_DIR) {
|
||||
- if (streq(de->d_name, "right"))
|
||||
- /* The test does not support timezone with leap second info. */
|
||||
- continue;
|
||||
-
|
||||
- _cleanup_closedir_ DIR *subdir = xopendirat(dirfd(dir), de->d_name, 0);
|
||||
- if (!subdir) {
|
||||
- log_notice_errno(errno, "Failed to open /usr/share/zoneinfo/%s, ignoring: %m", de->d_name);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- FOREACH_DIRENT(subde, subdir, break)
|
||||
- if (subde->d_type == DT_REG)
|
||||
- test_format_timestamp_with_tz_one(de->d_name, subde->d_name);
|
||||
- }
|
||||
- }
|
||||
+ _cleanup_strv_free_ char **timezones = NULL;
|
||||
+
|
||||
+ assert_se(get_timezones(&timezones) >= 0);
|
||||
+ STRV_FOREACH(tz, timezones)
|
||||
+ test_format_timestamp_with_tz_one(*tz);
|
||||
}
|
||||
|
||||
TEST(format_timestamp_relative) {
|
||||
72
SOURCES/1242-test-time-util-do-not-fail-on-DST-change.patch
Normal file
72
SOURCES/1242-test-time-util-do-not-fail-on-DST-change.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From c1e4badeadf75e75b6059a6d644d28414013c102 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Mon, 13 Mar 2023 03:47:45 +0900
|
||||
Subject: [PATCH] test-time-util: do not fail on DST change
|
||||
|
||||
(cherry picked from commit cfacd245e798282fcb9b3231bd6e857abfe124fc)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 37 ++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 30 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index eb8cc538c0..775e6bb84a 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -543,12 +543,30 @@ static void test_parse_timestamp_one(const char *str, usec_t max_diff, usec_t ex
|
||||
int r;
|
||||
|
||||
r = parse_timestamp(str, &usec);
|
||||
- log_debug("/* %s(%s): max_diff="USEC_FMT", expected="USEC_FMT", result="USEC_FMT"*/", __func__, str, max_diff, expected, usec);
|
||||
+ log_debug("/* %s(%s): max_diff="USEC_FMT", expected="USEC_FMT", result="USEC_FMT" */", __func__, str, max_diff, expected, usec);
|
||||
assert_se(r >= 0);
|
||||
assert_se(usec >= expected);
|
||||
assert_se(usec_sub_unsigned(usec, expected) <= max_diff);
|
||||
}
|
||||
|
||||
+static bool time_is_zero(usec_t usec) {
|
||||
+ const char *s;
|
||||
+
|
||||
+ s = FORMAT_TIMESTAMP(usec);
|
||||
+ return strstr(s, " 00:00:00 ");
|
||||
+}
|
||||
+
|
||||
+static bool timezone_equal(usec_t today, usec_t target) {
|
||||
+ const char *s, *t, *sz, *tz;
|
||||
+
|
||||
+ s = FORMAT_TIMESTAMP(today);
|
||||
+ t = FORMAT_TIMESTAMP(target);
|
||||
+ assert_se(sz = strrchr(s, ' '));
|
||||
+ assert_se(tz = strrchr(t, ' '));
|
||||
+ log_debug("%s("USEC_FMT", "USEC_FMT") -> %s, %s", __func__, today, target, s, t);
|
||||
+ return streq(sz, tz);
|
||||
+}
|
||||
+
|
||||
static void test_parse_timestamp_impl(const char *tz) {
|
||||
usec_t today, now_usec;
|
||||
|
||||
@@ -735,12 +753,17 @@ static void test_parse_timestamp_impl(const char *tz) {
|
||||
|
||||
/* without date */
|
||||
assert_se(parse_timestamp("today", &today) == 0);
|
||||
- test_parse_timestamp_one("00:01", 0, today + USEC_PER_MINUTE);
|
||||
- test_parse_timestamp_one("00:00:01", 0, today + USEC_PER_SEC);
|
||||
- test_parse_timestamp_one("00:00:01.001", 0, today + USEC_PER_SEC + 1000);
|
||||
- test_parse_timestamp_one("00:00:01.0010", 0, today + USEC_PER_SEC + 1000);
|
||||
- test_parse_timestamp_one("tomorrow", 0, today + USEC_PER_DAY);
|
||||
- test_parse_timestamp_one("yesterday", 0, today - USEC_PER_DAY);
|
||||
+ if (time_is_zero(today)) {
|
||||
+ test_parse_timestamp_one("00:01", 0, today + USEC_PER_MINUTE);
|
||||
+ test_parse_timestamp_one("00:00:01", 0, today + USEC_PER_SEC);
|
||||
+ test_parse_timestamp_one("00:00:01.001", 0, today + USEC_PER_SEC + 1000);
|
||||
+ test_parse_timestamp_one("00:00:01.0010", 0, today + USEC_PER_SEC + 1000);
|
||||
+
|
||||
+ if (timezone_equal(today, today + USEC_PER_DAY) && time_is_zero(today + USEC_PER_DAY))
|
||||
+ test_parse_timestamp_one("tomorrow", 0, today + USEC_PER_DAY);
|
||||
+ if (timezone_equal(today, today - USEC_PER_DAY) && time_is_zero(today - USEC_PER_DAY))
|
||||
+ test_parse_timestamp_one("yesterday", 0, today - USEC_PER_DAY);
|
||||
+ }
|
||||
|
||||
/* relative */
|
||||
assert_se(parse_timestamp("now", &now_usec) == 0);
|
||||
@ -0,0 +1,82 @@
|
||||
From 8e8569467616ee982df2cc73ac39240482c92d36 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Sun, 26 Nov 2023 20:58:43 +0100
|
||||
Subject: [PATCH] test-time-util: suppress timestamp conversion failures for
|
||||
Africa/Khartoum timezone
|
||||
|
||||
Our timestamp conversion roundtrip test was failing. But I think that this
|
||||
is not our bug:
|
||||
|
||||
$ TZ='Africa/Khartoum' date --date='@1509482094'
|
||||
Tue Oct 31 23:34:54 EAT 2017
|
||||
$ TZ='Africa/Khartoum' date --date='Tue Oct 31 23:34:54 EAT 2017' +%s
|
||||
1509485694
|
||||
$ TZ='Africa/Khartoum' date --date='@1509485694'
|
||||
Tue Oct 31 23:34:54 CAT 2017
|
||||
$ echo $[1509485694 - 1509482094]
|
||||
3600
|
||||
|
||||
This is essentially the same as what happens in our test. After a round-trip, we
|
||||
end up one hour ahead.
|
||||
|
||||
> For 1509482094632752, from the change log of tzdata:
|
||||
>
|
||||
> Release 2017c - 2017-10-20 14:49:34 -0700
|
||||
>
|
||||
> Changes to future timestamps
|
||||
> Sudan will switch from +03 to +02 on 2017-11-01.
|
||||
|
||||
Fixes https://github.com/systemd/systemd/issues/28472.
|
||||
|
||||
(cherry picked from commit 78b95ccad864e1f993fe0776841dd8f39856581b)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 22 ++++++++++++++++++----
|
||||
1 file changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 775e6bb84a..2550ffdba2 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -382,7 +382,7 @@ TEST(format_timestamp) {
|
||||
}
|
||||
|
||||
static void test_format_timestamp_impl(usec_t x) {
|
||||
- bool success;
|
||||
+ bool success, override;
|
||||
const char *xx, *yy;
|
||||
usec_t y;
|
||||
|
||||
@@ -393,14 +393,28 @@ static void test_format_timestamp_impl(usec_t x) {
|
||||
assert_se(yy);
|
||||
|
||||
success = (x / USEC_PER_SEC == y / USEC_PER_SEC) && streq(xx, yy);
|
||||
- log_full(success ? LOG_DEBUG : LOG_ERR, "@" USEC_FMT " → %s → @" USEC_FMT " → %s", x, xx, y, yy);
|
||||
- assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
||||
- assert_se(streq(xx, yy));
|
||||
+ /* Workaround for https://github.com/systemd/systemd/issues/28472 */
|
||||
+ override = !success &&
|
||||
+ (STRPTR_IN_SET(tzname[0], "CAT", "EAT") ||
|
||||
+ STRPTR_IN_SET(tzname[1], "CAT", "EAT")) &&
|
||||
+ DIV_ROUND_UP(y - x, USEC_PER_SEC) == 3600; /* 1 hour, ignore fractional second */
|
||||
+ log_full(success ? LOG_DEBUG : override ? LOG_WARNING : LOG_ERR,
|
||||
+ "@" USEC_FMT " → %s → @" USEC_FMT " → %s%s",
|
||||
+ x, xx, y, yy,
|
||||
+ override ? ", ignoring." : "");
|
||||
+ if (!override) {
|
||||
+ assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
||||
+ assert_se(streq(xx, yy));
|
||||
+ }
|
||||
}
|
||||
|
||||
static void test_format_timestamp_loop(void) {
|
||||
test_format_timestamp_impl(USEC_PER_SEC);
|
||||
|
||||
+ /* Two cases which trigger https://github.com/systemd/systemd/issues/28472 */
|
||||
+ test_format_timestamp_impl(1504938962980066);
|
||||
+ test_format_timestamp_impl(1509482094632752);
|
||||
+
|
||||
for (unsigned i = 0; i < TRIAL; i++) {
|
||||
usec_t x;
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
From 846cb844c3e8b5621745798f62bfbfb4275735f1 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Thu, 5 Dec 2024 13:32:19 +0100
|
||||
Subject: [PATCH] test-time-util: do more suppression of time zone checks
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The issue is directly triggered by tzdata-2024b, where the setting of timezone
|
||||
started to fail and the tests stopped passing. But those timestamps in 1/1/1970
|
||||
appear to have some problems already before:
|
||||
|
||||
$ sudo date -s 'Thu 1970-01-01 13:00:01 WET'
|
||||
Thu Jan 1 03:00:01 PM EET 1970
|
||||
$ sudo date -s 'Thu 1970-01-01 12:00:01 WET'
|
||||
date: cannot set date: Invalid argument
|
||||
Thu Jan 1 02:00:01 PM EET 1970
|
||||
$ rpm -q tzdata
|
||||
tzdata-2024a-9.fc41.noarch
|
||||
|
||||
The same issue appears with other timezones. So move the first timestamp one
|
||||
day forward to avoid the issue.
|
||||
|
||||
After the previous problem is solved, we also get the problem already seen
|
||||
previously where the roundtrip returns a time that is off by one hour:
|
||||
|
||||
@86401000000 → Fri 1970-01-02 00:00:01 WET → @82801000000 → Thu 1970-01-01 23:00:01 WET
|
||||
Assertion 'x / USEC_PER_SEC == y / USEC_PER_SEC' failed at src/test/test-time-util.c:415, function test_format_timestamp_impl(). Aborting.
|
||||
|
||||
Extend the override to suppress this.
|
||||
|
||||
(cherry picked from commit 3cf362f6f57b7d0b5f6b86a49316303b0dda7599)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 2550ffdba2..45d7541415 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -393,11 +393,12 @@ static void test_format_timestamp_impl(usec_t x) {
|
||||
assert_se(yy);
|
||||
|
||||
success = (x / USEC_PER_SEC == y / USEC_PER_SEC) && streq(xx, yy);
|
||||
- /* Workaround for https://github.com/systemd/systemd/issues/28472 */
|
||||
+ /* Workaround for https://github.com/systemd/systemd/issues/28472
|
||||
+ * and https://github.com/systemd/systemd/pull/35471. */
|
||||
override = !success &&
|
||||
- (STRPTR_IN_SET(tzname[0], "CAT", "EAT") ||
|
||||
- STRPTR_IN_SET(tzname[1], "CAT", "EAT")) &&
|
||||
- DIV_ROUND_UP(y - x, USEC_PER_SEC) == 3600; /* 1 hour, ignore fractional second */
|
||||
+ (STRPTR_IN_SET(tzname[0], "CAT", "EAT", "WET") ||
|
||||
+ STRPTR_IN_SET(tzname[1], "CAT", "EAT", "WET")) &&
|
||||
+ DIV_ROUND_UP(x > y ? x - y : y - x, USEC_PER_SEC) == 3600; /* 1 hour, ignore fractional second */
|
||||
log_full(success ? LOG_DEBUG : override ? LOG_WARNING : LOG_ERR,
|
||||
"@" USEC_FMT " → %s → @" USEC_FMT " → %s%s",
|
||||
x, xx, y, yy,
|
||||
@@ -409,7 +410,7 @@ static void test_format_timestamp_impl(usec_t x) {
|
||||
}
|
||||
|
||||
static void test_format_timestamp_loop(void) {
|
||||
- test_format_timestamp_impl(USEC_PER_SEC);
|
||||
+ test_format_timestamp_impl(USEC_PER_DAY + USEC_PER_SEC);
|
||||
|
||||
/* Two cases which trigger https://github.com/systemd/systemd/issues/28472 */
|
||||
test_format_timestamp_impl(1504938962980066);
|
||||
@ -0,0 +1,61 @@
|
||||
From cb442eb90085aae9db3bdf0cd7a4730912dba3ef Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sat, 14 Dec 2024 16:49:54 +0900
|
||||
Subject: [PATCH] test-time-util: fix truncation of usec to sec
|
||||
|
||||
Also
|
||||
- use ASSERT_XYZ() macros,
|
||||
- log tzname[] on failure.
|
||||
|
||||
(cherry picked from commit 3f1d499964abb6a4c0141d7ea8f852829880adff)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-time-util.c | 20 ++++++++++++--------
|
||||
1 file changed, 12 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 45d7541415..a5443ad7d7 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -384,28 +384,32 @@ TEST(format_timestamp) {
|
||||
static void test_format_timestamp_impl(usec_t x) {
|
||||
bool success, override;
|
||||
const char *xx, *yy;
|
||||
- usec_t y;
|
||||
+ usec_t y, x_sec, y_sec;
|
||||
|
||||
xx = FORMAT_TIMESTAMP(x);
|
||||
- assert_se(xx);
|
||||
- assert_se(parse_timestamp(xx, &y) >= 0);
|
||||
+ ASSERT_NOT_NULL(xx);
|
||||
+ ASSERT_OK(parse_timestamp(xx, &y));
|
||||
yy = FORMAT_TIMESTAMP(y);
|
||||
- assert_se(yy);
|
||||
+ ASSERT_NOT_NULL(yy);
|
||||
|
||||
- success = (x / USEC_PER_SEC == y / USEC_PER_SEC) && streq(xx, yy);
|
||||
+ x_sec = x / USEC_PER_SEC;
|
||||
+ y_sec = y / USEC_PER_SEC;
|
||||
+ success = (x_sec == y_sec) && streq(xx, yy);
|
||||
/* Workaround for https://github.com/systemd/systemd/issues/28472
|
||||
* and https://github.com/systemd/systemd/pull/35471. */
|
||||
override = !success &&
|
||||
(STRPTR_IN_SET(tzname[0], "CAT", "EAT", "WET") ||
|
||||
STRPTR_IN_SET(tzname[1], "CAT", "EAT", "WET")) &&
|
||||
- DIV_ROUND_UP(x > y ? x - y : y - x, USEC_PER_SEC) == 3600; /* 1 hour, ignore fractional second */
|
||||
+ (x_sec > y_sec ? x_sec - y_sec : y_sec - x_sec) == 3600; /* 1 hour, ignore fractional second */
|
||||
log_full(success ? LOG_DEBUG : override ? LOG_WARNING : LOG_ERR,
|
||||
"@" USEC_FMT " → %s → @" USEC_FMT " → %s%s",
|
||||
x, xx, y, yy,
|
||||
override ? ", ignoring." : "");
|
||||
if (!override) {
|
||||
- assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
|
||||
- assert_se(streq(xx, yy));
|
||||
+ if (!success)
|
||||
+ log_warning("tzname[0]=\"%s\", tzname[1]=\"%s\"", tzname[0], tzname[1]);
|
||||
+ ASSERT_EQ(x_sec, y_sec);
|
||||
+ ASSERT_STREQ(xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
From e0ac4a4632c99750ad63476c3ae62a1988b2883b Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Fri, 26 Jan 2024 00:22:38 +0000
|
||||
Subject: [PATCH] test: unset TZ before timezone-sensitive unit tests are run
|
||||
|
||||
Some tests have hard-coded results that need to match, and change if
|
||||
the caller has a timezone set via the TZ= environment variable, as it
|
||||
is the case during reproducible build tests. Unset it.
|
||||
|
||||
(cherry picked from commit 1e902c3463024bb328bf0d01a5d58a69e1ccf739)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/test-calendarspec.c | 9 ++++++++-
|
||||
src/test/test-date.c | 3 +++
|
||||
src/test/test-time-util.c | 3 +++
|
||||
3 files changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
|
||||
index 564983b699..4699991535 100644
|
||||
--- a/src/test/test-calendarspec.c
|
||||
+++ b/src/test/test-calendarspec.c
|
||||
@@ -260,4 +260,11 @@ TEST(calendar_spec_from_string) {
|
||||
assert_se(calendar_spec_from_string("*:4,30:*\n", &c) == -EINVAL);
|
||||
}
|
||||
|
||||
-DEFINE_TEST_MAIN(LOG_INFO);
|
||||
+static int intro(void) {
|
||||
+ /* Tests have hard-coded results that do not expect a specific timezone to be set by the caller */
|
||||
+ assert_se(unsetenv("TZ") >= 0);
|
||||
+
|
||||
+ return EXIT_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
|
||||
diff --git a/src/test/test-date.c b/src/test/test-date.c
|
||||
index 097066b61a..cc11bd999e 100644
|
||||
--- a/src/test/test-date.c
|
||||
+++ b/src/test/test-date.c
|
||||
@@ -62,6 +62,9 @@ static void test_one_noutc(const char *p) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
+ /* Tests have hard-coded results that do not expect a specific timezone to be set by the caller */
|
||||
+ assert_se(unsetenv("TZ") >= 0);
|
||||
+
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_one("17:41");
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index a5443ad7d7..21b05a3010 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -1016,6 +1016,9 @@ TEST(timezone_offset_change) {
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
+ /* Tests have hard-coded results that do not expect a specific timezone to be set by the caller */
|
||||
+ assert_se(unsetenv("TZ") >= 0);
|
||||
+
|
||||
log_info("realtime=" USEC_FMT "\n"
|
||||
"monotonic=" USEC_FMT "\n"
|
||||
"boottime=" USEC_FMT "\n",
|
||||
30
SOURCES/1247-meson-extend-timeout-for-test-time-util.patch
Normal file
30
SOURCES/1247-meson-extend-timeout-for-test-time-util.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From bef180f6ddc06bc6e669024b5d1fb9b97a1e3f4d Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <fsumsal@redhat.com>
|
||||
Date: Tue, 2 Sep 2025 17:33:35 +0200
|
||||
Subject: [PATCH] meson: extend timeout for test-time-util
|
||||
|
||||
As it runs through many timezones and hits the default timeout when
|
||||
running under sanitizers.
|
||||
|
||||
Based on upstream's b66b3c409900a77b3da7b366ae5a0179abacea99.
|
||||
|
||||
rhel-only: ci
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/test/meson.build | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/test/meson.build b/src/test/meson.build
|
||||
index 5547271ee7..9de487ced5 100644
|
||||
--- a/src/test/meson.build
|
||||
+++ b/src/test/meson.build
|
||||
@@ -459,7 +459,8 @@ tests += [
|
||||
|
||||
[files('test-fileio.c')],
|
||||
|
||||
- [files('test-time-util.c')],
|
||||
+ [files('test-time-util.c'),
|
||||
+ [], [], [], '', 'timeout=120'],
|
||||
|
||||
[files('test-clock.c')],
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
From c5bdf8c148fc9ab18d3412756ada7317caece6fe Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 01:40:56 +0900
|
||||
Subject: [PATCH] time-util: use DEFINE_STRING_TABLE_LOOKUP_TO_STRING() macro
|
||||
|
||||
(cherry picked from commit d227a42aadf04c23c668ac3089bc7b4a9baaf7e1)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index f5e10bba1a..6eee8a48a7 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -1616,7 +1616,7 @@ static const char* const timestamp_style_table[_TIMESTAMP_STYLE_MAX] = {
|
||||
};
|
||||
|
||||
/* Use the macro for enum → string to allow for aliases */
|
||||
-_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(timestamp_style, TimestampStyle,);
|
||||
+DEFINE_STRING_TABLE_LOOKUP_TO_STRING(timestamp_style, TimestampStyle);
|
||||
|
||||
/* For the string → enum mapping we use the generic implementation, but also support two aliases */
|
||||
TimestampStyle timestamp_style_from_string(const char *s) {
|
||||
30
SOURCES/1249-time-util-align-string-table.patch
Normal file
30
SOURCES/1249-time-util-align-string-table.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 243ecafd63c2c0f8cbdecee770626143bf4def62 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 01:41:38 +0900
|
||||
Subject: [PATCH] time-util: align string table
|
||||
|
||||
(cherry picked from commit e01a8fdd2645c06cdb9057bd5b8a45ab02c0d6ee)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 6eee8a48a7..404fde01db 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -1609,10 +1609,10 @@ int time_change_fd(void) {
|
||||
|
||||
static const char* const timestamp_style_table[_TIMESTAMP_STYLE_MAX] = {
|
||||
[TIMESTAMP_PRETTY] = "pretty",
|
||||
- [TIMESTAMP_US] = "us",
|
||||
- [TIMESTAMP_UTC] = "utc",
|
||||
+ [TIMESTAMP_US] = "us",
|
||||
+ [TIMESTAMP_UTC] = "utc",
|
||||
[TIMESTAMP_US_UTC] = "us+utc",
|
||||
- [TIMESTAMP_UNIX] = "unix",
|
||||
+ [TIMESTAMP_UNIX] = "unix",
|
||||
};
|
||||
|
||||
/* Use the macro for enum → string to allow for aliases */
|
||||
316
SOURCES/1250-time-util-rename-variables.patch
Normal file
316
SOURCES/1250-time-util-rename-variables.patch
Normal file
@ -0,0 +1,316 @@
|
||||
From 753dd2e5f28a9b5a552efda75bcbec20ad501e69 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 02:04:31 +0900
|
||||
Subject: [PATCH] time-util: rename variables
|
||||
|
||||
(cherry picked from commit cf98b66d1ad0ff0e9ee0444861069ebade038dbb)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 86 +++++++++++++++++++++----------------------
|
||||
src/basic/time-util.h | 16 ++++----
|
||||
2 files changed, 51 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 404fde01db..7dbd3af20a 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -604,7 +604,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
-static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
+static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
static const struct {
|
||||
const char *name;
|
||||
const int nr;
|
||||
@@ -628,7 +628,7 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
const char *k, *utc = NULL, *tzn = NULL;
|
||||
struct tm tm, copy;
|
||||
time_t x;
|
||||
- usec_t x_usec, plus = 0, minus = 0, ret;
|
||||
+ usec_t usec, x_usec, plus = 0, minus = 0;
|
||||
int r, weekday = -1, dst = -1;
|
||||
size_t i;
|
||||
|
||||
@@ -651,9 +651,9 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
assert(t);
|
||||
|
||||
if (t[0] == '@' && !with_tz)
|
||||
- return parse_sec(t + 1, usec);
|
||||
+ return parse_sec(t + 1, ret);
|
||||
|
||||
- ret = now(CLOCK_REALTIME);
|
||||
+ usec = now(CLOCK_REALTIME);
|
||||
|
||||
if (!with_tz) {
|
||||
if (streq(t, "now"))
|
||||
@@ -734,7 +734,7 @@ static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) {
|
||||
}
|
||||
}
|
||||
|
||||
- x = (time_t) (ret / USEC_PER_SEC);
|
||||
+ x = (time_t) (usec / USEC_PER_SEC);
|
||||
x_usec = 0;
|
||||
|
||||
if (!localtime_or_gmtime_r(&x, &tm, utc))
|
||||
@@ -871,24 +871,24 @@ from_tm:
|
||||
if (x < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- ret = (usec_t) x * USEC_PER_SEC + x_usec;
|
||||
- if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
+ usec = (usec_t) x * USEC_PER_SEC + x_usec;
|
||||
+ if (usec > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
finish:
|
||||
- if (ret + plus < ret) /* overflow? */
|
||||
+ if (usec + plus < usec) /* overflow? */
|
||||
return -EINVAL;
|
||||
- ret += plus;
|
||||
- if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
+ usec += plus;
|
||||
+ if (usec > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
- if (ret >= minus)
|
||||
- ret -= minus;
|
||||
+ if (usec >= minus)
|
||||
+ usec -= minus;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
- if (usec)
|
||||
- *usec = ret;
|
||||
+ if (ret)
|
||||
+ *ret = usec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -897,7 +897,7 @@ typedef struct ParseTimestampResult {
|
||||
int return_value;
|
||||
} ParseTimestampResult;
|
||||
|
||||
-int parse_timestamp(const char *t, usec_t *usec) {
|
||||
+int parse_timestamp(const char *t, usec_t *ret) {
|
||||
char *last_space, *tz = NULL;
|
||||
ParseTimestampResult *shared, tmp;
|
||||
int r;
|
||||
@@ -907,7 +907,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
||||
tz = last_space + 1;
|
||||
|
||||
if (!tz || endswith_no_case(t, " UTC"))
|
||||
- return parse_timestamp_impl(t, usec, false);
|
||||
+ return parse_timestamp_impl(t, ret, false);
|
||||
|
||||
shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
|
||||
if (shared == MAP_FAILED)
|
||||
@@ -949,13 +949,13 @@ int parse_timestamp(const char *t, usec_t *usec) {
|
||||
if (munmap(shared, sizeof *shared) != 0)
|
||||
return negative_errno();
|
||||
|
||||
- if (tmp.return_value == 0 && usec)
|
||||
- *usec = tmp.usec;
|
||||
+ if (tmp.return_value == 0 && ret)
|
||||
+ *ret = tmp.usec;
|
||||
|
||||
return tmp.return_value;
|
||||
}
|
||||
|
||||
-static const char* extract_multiplier(const char *p, usec_t *multiplier) {
|
||||
+static const char* extract_multiplier(const char *p, usec_t *ret) {
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
usec_t usec;
|
||||
@@ -996,7 +996,7 @@ static const char* extract_multiplier(const char *p, usec_t *multiplier) {
|
||||
|
||||
e = startswith(p, table[i].suffix);
|
||||
if (e) {
|
||||
- *multiplier = table[i].usec;
|
||||
+ *ret = table[i].usec;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -1004,9 +1004,9 @@ static const char* extract_multiplier(const char *p, usec_t *multiplier) {
|
||||
return p;
|
||||
}
|
||||
|
||||
-int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
+int parse_time(const char *t, usec_t *ret, usec_t default_unit) {
|
||||
const char *p, *s;
|
||||
- usec_t r = 0;
|
||||
+ usec_t usec = 0;
|
||||
bool something = false;
|
||||
|
||||
assert(t);
|
||||
@@ -1021,8 +1021,8 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
if (*s != 0)
|
||||
return -EINVAL;
|
||||
|
||||
- if (usec)
|
||||
- *usec = USEC_INFINITY;
|
||||
+ if (ret)
|
||||
+ *ret = USEC_INFINITY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1069,10 +1069,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
return -ERANGE;
|
||||
|
||||
k = (usec_t) l * multiplier;
|
||||
- if (k >= USEC_INFINITY - r)
|
||||
+ if (k >= USEC_INFINITY - usec)
|
||||
return -ERANGE;
|
||||
|
||||
- r += k;
|
||||
+ usec += k;
|
||||
|
||||
something = true;
|
||||
|
||||
@@ -1082,10 +1082,10 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
|
||||
for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) {
|
||||
k = (usec_t) (*b - '0') * m;
|
||||
- if (k >= USEC_INFINITY - r)
|
||||
+ if (k >= USEC_INFINITY - usec)
|
||||
return -ERANGE;
|
||||
|
||||
- r += k;
|
||||
+ usec += k;
|
||||
}
|
||||
|
||||
/* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge" */
|
||||
@@ -1094,13 +1094,13 @@ int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
|
||||
}
|
||||
}
|
||||
|
||||
- if (usec)
|
||||
- *usec = r;
|
||||
+ if (ret)
|
||||
+ *ret = usec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int parse_sec(const char *t, usec_t *usec) {
|
||||
- return parse_time(t, usec, USEC_PER_SEC);
|
||||
+int parse_sec(const char *t, usec_t *ret) {
|
||||
+ return parse_time(t, ret, USEC_PER_SEC);
|
||||
}
|
||||
|
||||
int parse_sec_fix_0(const char *t, usec_t *ret) {
|
||||
@@ -1127,7 +1127,7 @@ int parse_sec_def_infinity(const char *t, usec_t *ret) {
|
||||
return parse_sec(t, ret);
|
||||
}
|
||||
|
||||
-static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) {
|
||||
+static const char* extract_nsec_multiplier(const char *p, nsec_t *ret) {
|
||||
static const struct {
|
||||
const char *suffix;
|
||||
nsec_t nsec;
|
||||
@@ -1172,7 +1172,7 @@ static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) {
|
||||
|
||||
e = startswith(p, table[i].suffix);
|
||||
if (e) {
|
||||
- *multiplier = table[i].nsec;
|
||||
+ *ret = table[i].nsec;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -1180,13 +1180,13 @@ static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) {
|
||||
return p;
|
||||
}
|
||||
|
||||
-int parse_nsec(const char *t, nsec_t *nsec) {
|
||||
+int parse_nsec(const char *t, nsec_t *ret) {
|
||||
const char *p, *s;
|
||||
- nsec_t r = 0;
|
||||
+ nsec_t nsec = 0;
|
||||
bool something = false;
|
||||
|
||||
assert(t);
|
||||
- assert(nsec);
|
||||
+ assert(ret);
|
||||
|
||||
p = t;
|
||||
|
||||
@@ -1197,7 +1197,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
|
||||
if (*s != 0)
|
||||
return -EINVAL;
|
||||
|
||||
- *nsec = NSEC_INFINITY;
|
||||
+ *ret = NSEC_INFINITY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1244,10 +1244,10 @@ int parse_nsec(const char *t, nsec_t *nsec) {
|
||||
return -ERANGE;
|
||||
|
||||
k = (nsec_t) l * multiplier;
|
||||
- if (k >= NSEC_INFINITY - r)
|
||||
+ if (k >= NSEC_INFINITY - nsec)
|
||||
return -ERANGE;
|
||||
|
||||
- r += k;
|
||||
+ nsec += k;
|
||||
|
||||
something = true;
|
||||
|
||||
@@ -1257,10 +1257,10 @@ int parse_nsec(const char *t, nsec_t *nsec) {
|
||||
|
||||
for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) {
|
||||
k = (nsec_t) (*b - '0') * m;
|
||||
- if (k >= NSEC_INFINITY - r)
|
||||
+ if (k >= NSEC_INFINITY - nsec)
|
||||
return -ERANGE;
|
||||
|
||||
- r += k;
|
||||
+ nsec += k;
|
||||
}
|
||||
|
||||
/* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge" */
|
||||
@@ -1269,7 +1269,7 @@ int parse_nsec(const char *t, nsec_t *nsec) {
|
||||
}
|
||||
}
|
||||
|
||||
- *nsec = r;
|
||||
+ *ret = nsec;
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
|
||||
index c98f95a530..9d44cac747 100644
|
||||
--- a/src/basic/time-util.h
|
||||
+++ b/src/basic/time-util.h
|
||||
@@ -141,15 +141,15 @@ static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
|
||||
#define FORMAT_TIMESTAMP_STYLE(t, style) \
|
||||
format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t, style)
|
||||
|
||||
-int parse_timestamp(const char *t, usec_t *usec);
|
||||
+int parse_timestamp(const char *t, usec_t *ret);
|
||||
|
||||
-int parse_sec(const char *t, usec_t *usec);
|
||||
-int parse_sec_fix_0(const char *t, usec_t *usec);
|
||||
-int parse_sec_def_infinity(const char *t, usec_t *usec);
|
||||
-int parse_time(const char *t, usec_t *usec, usec_t default_unit);
|
||||
-int parse_nsec(const char *t, nsec_t *nsec);
|
||||
+int parse_sec(const char *t, usec_t *ret);
|
||||
+int parse_sec_fix_0(const char *t, usec_t *ret);
|
||||
+int parse_sec_def_infinity(const char *t, usec_t *ret);
|
||||
+int parse_time(const char *t, usec_t *ret, usec_t default_unit);
|
||||
+int parse_nsec(const char *t, nsec_t *ret);
|
||||
|
||||
-int get_timezones(char ***l);
|
||||
+int get_timezones(char ***ret);
|
||||
int verify_timezone(const char *name, int log_level);
|
||||
static inline bool timezone_is_valid(const char *name, int log_level) {
|
||||
return verify_timezone(name, log_level) >= 0;
|
||||
@@ -159,7 +159,7 @@ bool clock_supported(clockid_t clock);
|
||||
|
||||
usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to);
|
||||
|
||||
-int get_timezone(char **timezone);
|
||||
+int get_timezone(char **ret);
|
||||
|
||||
time_t mktime_or_timegm(struct tm *tm, bool utc);
|
||||
struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc);
|
||||
115
SOURCES/1251-time-util-add-assertions.patch
Normal file
115
SOURCES/1251-time-util-add-assertions.patch
Normal file
@ -0,0 +1,115 @@
|
||||
From 23f6608ffa05ce80ebfbca9a28369ff858e9d42e Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 02:06:13 +0900
|
||||
Subject: [PATCH] time-util: add assertions
|
||||
|
||||
(cherry picked from commit dff3bddc5416834d42cc682cb544732a4b91db3b)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 25 +++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 7dbd3af20a..ac28dc9be6 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -172,6 +172,8 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
|
||||
dual_timestamp* dual_timestamp_from_boottime(dual_timestamp *ts, usec_t u) {
|
||||
usec_t nowm;
|
||||
|
||||
+ assert(ts);
|
||||
+
|
||||
if (u == USEC_INFINITY) {
|
||||
ts->realtime = ts->monotonic = USEC_INFINITY;
|
||||
return ts;
|
||||
@@ -184,6 +186,7 @@ dual_timestamp* dual_timestamp_from_boottime(dual_timestamp *ts, usec_t u) {
|
||||
}
|
||||
|
||||
usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
|
||||
+ assert(ts);
|
||||
|
||||
switch (clock) {
|
||||
|
||||
@@ -421,6 +424,8 @@ char *format_timestamp_relative(char *buf, size_t l, usec_t t) {
|
||||
const char *s;
|
||||
usec_t n, d;
|
||||
|
||||
+ assert(buf);
|
||||
+
|
||||
if (!timestamp_is_set(t))
|
||||
return NULL;
|
||||
|
||||
@@ -902,6 +907,8 @@ int parse_timestamp(const char *t, usec_t *ret) {
|
||||
ParseTimestampResult *shared, tmp;
|
||||
int r;
|
||||
|
||||
+ assert(t);
|
||||
+
|
||||
last_space = strrchr(t, ' ');
|
||||
if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
|
||||
tz = last_space + 1;
|
||||
@@ -991,6 +998,9 @@ static const char* extract_multiplier(const char *p, usec_t *ret) {
|
||||
{ "µs", 1ULL },
|
||||
};
|
||||
|
||||
+ assert(p);
|
||||
+ assert(ret);
|
||||
+
|
||||
for (size_t i = 0; i < ELEMENTSOF(table); i++) {
|
||||
char *e;
|
||||
|
||||
@@ -1119,6 +1129,9 @@ int parse_sec_fix_0(const char *t, usec_t *ret) {
|
||||
}
|
||||
|
||||
int parse_sec_def_infinity(const char *t, usec_t *ret) {
|
||||
+ assert(t);
|
||||
+ assert(ret);
|
||||
+
|
||||
t += strspn(t, WHITESPACE);
|
||||
if (isempty(t)) {
|
||||
*ret = USEC_INFINITY;
|
||||
@@ -1167,6 +1180,9 @@ static const char* extract_nsec_multiplier(const char *p, nsec_t *ret) {
|
||||
};
|
||||
size_t i;
|
||||
|
||||
+ assert(p);
|
||||
+ assert(ret);
|
||||
+
|
||||
for (i = 0; i < ELEMENTSOF(table); i++) {
|
||||
char *e;
|
||||
|
||||
@@ -1320,6 +1336,8 @@ static int get_timezones_from_tzdata_zi(char ***ret) {
|
||||
_cleanup_strv_free_ char **zones = NULL;
|
||||
int r;
|
||||
|
||||
+ assert(ret);
|
||||
+
|
||||
f = fopen("/usr/share/zoneinfo/tzdata.zi", "re");
|
||||
if (!f)
|
||||
return -errno;
|
||||
@@ -1477,6 +1495,8 @@ int get_timezone(char **ret) {
|
||||
char *z;
|
||||
int r;
|
||||
|
||||
+ assert(ret);
|
||||
+
|
||||
r = readlink_malloc("/etc/localtime", &t);
|
||||
if (r == -ENOENT) {
|
||||
/* If the symlink does not exist, assume "UTC", like glibc does */
|
||||
@@ -1506,10 +1526,15 @@ int get_timezone(char **ret) {
|
||||
}
|
||||
|
||||
time_t mktime_or_timegm(struct tm *tm, bool utc) {
|
||||
+ assert(tm);
|
||||
+
|
||||
return utc ? timegm(tm) : mktime(tm);
|
||||
}
|
||||
|
||||
struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) {
|
||||
+ assert(t);
|
||||
+ assert(tm);
|
||||
+
|
||||
return utc ? gmtime_r(t, tm) : localtime_r(t, tm);
|
||||
}
|
||||
|
||||
54
SOURCES/1252-time-util-drop-redundant-else.patch
Normal file
54
SOURCES/1252-time-util-drop-redundant-else.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From a3c08667c9abaf60793ed35e93123bc5f89981f3 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 03:43:58 +0900
|
||||
Subject: [PATCH] time-util: drop redundant else
|
||||
|
||||
(cherry picked from commit 17d1ebfc43c3b971d20ff2806acc634ee153eef6)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index ac28dc9be6..c5b91fde66 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -664,21 +664,23 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
if (streq(t, "now"))
|
||||
goto finish;
|
||||
|
||||
- else if (t[0] == '+') {
|
||||
+ if (t[0] == '+') {
|
||||
r = parse_sec(t+1, &plus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
goto finish;
|
||||
+ }
|
||||
|
||||
- } else if (t[0] == '-') {
|
||||
+ if (t[0] == '-') {
|
||||
r = parse_sec(t+1, &minus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
goto finish;
|
||||
+ }
|
||||
|
||||
- } else if ((k = endswith(t, " ago"))) {
|
||||
+ if ((k = endswith(t, " ago"))) {
|
||||
t = strndupa_safe(t, k - t);
|
||||
|
||||
r = parse_sec(t, &minus);
|
||||
@@ -686,8 +688,9 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
return r;
|
||||
|
||||
goto finish;
|
||||
+ }
|
||||
|
||||
- } else if ((k = endswith(t, " left"))) {
|
||||
+ if ((k = endswith(t, " left"))) {
|
||||
t = strndupa_safe(t, k - t);
|
||||
|
||||
r = parse_sec(t, &plus);
|
||||
50
SOURCES/1253-time-util-do-not-use-strdupa.patch
Normal file
50
SOURCES/1253-time-util-do-not-use-strdupa.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 50a7d58a24a381e265436c14303e7bb368a4b147 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 03:41:26 +0900
|
||||
Subject: [PATCH] time-util: do not use strdupa()
|
||||
|
||||
The input string may come from command line, config files.
|
||||
|
||||
(cherry picked from commit 804537bdc420bb82e54b455b7a10d542c8f029dd)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index c5b91fde66..64cdcea594 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -681,9 +681,13 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
}
|
||||
|
||||
if ((k = endswith(t, " ago"))) {
|
||||
- t = strndupa_safe(t, k - t);
|
||||
+ _cleanup_free_ char *buf = NULL;
|
||||
|
||||
- r = parse_sec(t, &minus);
|
||||
+ buf = strndup(t, k - t);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ r = parse_sec(buf, &minus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -691,9 +695,13 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
}
|
||||
|
||||
if ((k = endswith(t, " left"))) {
|
||||
- t = strndupa_safe(t, k - t);
|
||||
+ _cleanup_free_ char *buf = NULL;
|
||||
+
|
||||
+ buf = strndup(t, k - t);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
|
||||
- r = parse_sec(t, &plus);
|
||||
+ r = parse_sec(buf, &plus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
From eabf4db441c885a78d5726838004bbb9436dbf91 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 04:14:24 +0900
|
||||
Subject: [PATCH] time-util: use result from startswith_no_case()
|
||||
|
||||
No functional change, just refactoring.
|
||||
|
||||
(cherry picked from commit f2ecfd8bc1e6d09173e9f98c5ac1b19b755a3c25)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 14 ++++----------
|
||||
1 file changed, 4 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 64cdcea594..047dad0fec 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -635,7 +635,6 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
time_t x;
|
||||
usec_t usec, x_usec, plus = 0, minus = 0;
|
||||
int r, weekday = -1, dst = -1;
|
||||
- size_t i;
|
||||
|
||||
/* Allowed syntaxes:
|
||||
*
|
||||
@@ -775,18 +774,13 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
goto from_tm;
|
||||
}
|
||||
|
||||
- for (i = 0; i < ELEMENTSOF(day_nr); i++) {
|
||||
- size_t skip;
|
||||
-
|
||||
- if (!startswith_no_case(t, day_nr[i].name))
|
||||
- continue;
|
||||
-
|
||||
- skip = strlen(day_nr[i].name);
|
||||
- if (t[skip] != ' ')
|
||||
+ for (size_t i = 0; i < ELEMENTSOF(day_nr); i++) {
|
||||
+ k = startswith_no_case(t, day_nr[i].name);
|
||||
+ if (!k || *k != ' ')
|
||||
continue;
|
||||
|
||||
weekday = day_nr[i].nr;
|
||||
- t += skip + 1;
|
||||
+ t = k + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
From 9f7d490b1c16f0444987dab7ce70287b59d98cf9 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 04:27:27 +0900
|
||||
Subject: [PATCH] time-util: use usec_add() and usec_sub_unsigned()
|
||||
|
||||
And move the check with USEC_TIMESTAMP_FORMATTABLE_MAX at the end,
|
||||
as usec_add() can handle overflow correctly.
|
||||
|
||||
(cherry picked from commit db43717e982e1361eee4bdcd92167d6c47eb627c)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 17 +++++++----------
|
||||
1 file changed, 7 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 047dad0fec..ba5e17bd9d 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -881,20 +881,17 @@ from_tm:
|
||||
if (x < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- usec = (usec_t) x * USEC_PER_SEC + x_usec;
|
||||
- if (usec > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
- return -EINVAL;
|
||||
+ usec = usec_add(x * USEC_PER_SEC, x_usec);
|
||||
|
||||
finish:
|
||||
- if (usec + plus < usec) /* overflow? */
|
||||
- return -EINVAL;
|
||||
- usec += plus;
|
||||
- if (usec > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
+ usec = usec_add(usec, plus);
|
||||
+
|
||||
+ if (usec < minus)
|
||||
return -EINVAL;
|
||||
|
||||
- if (usec >= minus)
|
||||
- usec -= minus;
|
||||
- else
|
||||
+ usec = usec_sub_unsigned(usec, minus);
|
||||
+
|
||||
+ if (usec > USEC_TIMESTAMP_FORMATTABLE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (ret)
|
||||
72
SOURCES/1256-time-util-shorten-code-a-bit.patch
Normal file
72
SOURCES/1256-time-util-shorten-code-a-bit.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From 2dafd8e6be624f93c757ca9c739d502ed73d79c0 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 04:27:52 +0900
|
||||
Subject: [PATCH] time-util: shorten code a bit
|
||||
|
||||
No functional change, just refactoring.
|
||||
|
||||
(cherry picked from commit 1d2c42c5dc765c57b4fba6b7c629093aa20685a8)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 25 +++++++++----------------
|
||||
1 file changed, 9 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index ba5e17bd9d..6e1b34b025 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -633,8 +633,9 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
const char *k, *utc = NULL, *tzn = NULL;
|
||||
struct tm tm, copy;
|
||||
time_t x;
|
||||
- usec_t usec, x_usec, plus = 0, minus = 0;
|
||||
+ usec_t usec, plus = 0, minus = 0;
|
||||
int r, weekday = -1, dst = -1;
|
||||
+ unsigned fractional = 0;
|
||||
|
||||
/* Allowed syntaxes:
|
||||
*
|
||||
@@ -750,7 +751,6 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
}
|
||||
|
||||
x = (time_t) (usec / USEC_PER_SEC);
|
||||
- x_usec = 0;
|
||||
|
||||
if (!localtime_or_gmtime_r(&x, &tm, utc))
|
||||
return -EINVAL;
|
||||
@@ -859,19 +859,12 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
return -EINVAL;
|
||||
|
||||
parse_usec:
|
||||
- {
|
||||
- unsigned add;
|
||||
-
|
||||
- k++;
|
||||
- r = parse_fractional_part_u(&k, 6, &add);
|
||||
- if (r < 0)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- if (*k)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- x_usec = add;
|
||||
- }
|
||||
+ k++;
|
||||
+ r = parse_fractional_part_u(&k, 6, &fractional);
|
||||
+ if (r < 0)
|
||||
+ return -EINVAL;
|
||||
+ if (*k != '\0')
|
||||
+ return -EINVAL;
|
||||
|
||||
from_tm:
|
||||
if (weekday >= 0 && tm.tm_wday != weekday)
|
||||
@@ -881,7 +874,7 @@ from_tm:
|
||||
if (x < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- usec = usec_add(x * USEC_PER_SEC, x_usec);
|
||||
+ usec = usec_add(x * USEC_PER_SEC, fractional);
|
||||
|
||||
finish:
|
||||
usec = usec_add(usec, plus);
|
||||
69
SOURCES/1257-time-util-rename-variables.patch
Normal file
69
SOURCES/1257-time-util-rename-variables.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From 5bfcf206bd16079ae8030a2c912ee8377a3f6d5f Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 15 Feb 2023 13:46:50 +0900
|
||||
Subject: [PATCH] time-util: rename variables
|
||||
|
||||
No functional changes, just refactoring.
|
||||
|
||||
(cherry picked from commit a83c1baaeb510f1916d2d8cf0324d100708c7073)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 6e1b34b025..d468848d09 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -632,10 +632,10 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
|
||||
const char *k, *utc = NULL, *tzn = NULL;
|
||||
struct tm tm, copy;
|
||||
- time_t x;
|
||||
usec_t usec, plus = 0, minus = 0;
|
||||
- int r, weekday = -1, dst = -1;
|
||||
+ int r, weekday = -1, isdst = -1;
|
||||
unsigned fractional = 0;
|
||||
+ time_t sec;
|
||||
|
||||
/* Allowed syntaxes:
|
||||
*
|
||||
@@ -744,18 +744,18 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
if (IN_SET(j, 0, 1)) {
|
||||
/* Found one of the two timezones specified. */
|
||||
t = strndupa_safe(t, e - t - 1);
|
||||
- dst = j;
|
||||
+ isdst = j;
|
||||
tzn = tzname[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- x = (time_t) (usec / USEC_PER_SEC);
|
||||
+ sec = (time_t) (usec / USEC_PER_SEC);
|
||||
|
||||
- if (!localtime_or_gmtime_r(&x, &tm, utc))
|
||||
+ if (!localtime_or_gmtime_r(&sec, &tm, utc))
|
||||
return -EINVAL;
|
||||
|
||||
- tm.tm_isdst = dst;
|
||||
+ tm.tm_isdst = isdst;
|
||||
if (!with_tz && tzn)
|
||||
tm.tm_zone = tzn;
|
||||
|
||||
@@ -870,11 +870,11 @@ from_tm:
|
||||
if (weekday >= 0 && tm.tm_wday != weekday)
|
||||
return -EINVAL;
|
||||
|
||||
- x = mktime_or_timegm(&tm, utc);
|
||||
- if (x < 0)
|
||||
+ sec = mktime_or_timegm(&tm, utc);
|
||||
+ if (sec < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- usec = usec_add(x * USEC_PER_SEC, fractional);
|
||||
+ usec = usec_add(sec * USEC_PER_SEC, fractional);
|
||||
|
||||
finish:
|
||||
usec = usec_add(usec, plus);
|
||||
@ -0,0 +1,44 @@
|
||||
From a1a7ab09cf96e30cfd0c89efaf8d03a5dc81e928 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 15 Feb 2023 13:51:15 +0900
|
||||
Subject: [PATCH] time-util: drop unnecessary assignment of timezone name
|
||||
|
||||
As mktime() does not use timezone neme.
|
||||
|
||||
(cherry picked from commit 97c5f7ba1f50fcd7b982b995b46692c8cad4afaa)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index d468848d09..92928e88a4 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -630,7 +630,7 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
{ "Sat", 6 },
|
||||
};
|
||||
|
||||
- const char *k, *utc = NULL, *tzn = NULL;
|
||||
+ const char *k, *utc = NULL;
|
||||
struct tm tm, copy;
|
||||
usec_t usec, plus = 0, minus = 0;
|
||||
int r, weekday = -1, isdst = -1;
|
||||
@@ -745,7 +745,6 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
/* Found one of the two timezones specified. */
|
||||
t = strndupa_safe(t, e - t - 1);
|
||||
isdst = j;
|
||||
- tzn = tzname[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -756,8 +755,6 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
return -EINVAL;
|
||||
|
||||
tm.tm_isdst = isdst;
|
||||
- if (!with_tz && tzn)
|
||||
- tm.tm_zone = tzn;
|
||||
|
||||
if (streq(t, "today")) {
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
@ -0,0 +1,275 @@
|
||||
From e4b1932cd1c0ad2d42a6271cb651e6979b5962ed Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 03:39:15 +0900
|
||||
Subject: [PATCH] time-util: make parse_timestamp() use the RFC-822/ISO 8601
|
||||
standard timezone spec
|
||||
|
||||
If the timezone is specified with a number e.g. +0900 or so, then
|
||||
let's parse the time as a UTC, and adjust it with the specified time
|
||||
shift.
|
||||
|
||||
Otherwise, if an area has timezone change, e.g.
|
||||
---
|
||||
Africa/Casablanca Sun Jun 17 01:59:59 2018 UT = Sun Jun 17 01:59:59 2018 +00 isdst=0 gmtoff=0
|
||||
Africa/Casablanca Sun Jun 17 02:00:00 2018 UT = Sun Jun 17 03:00:00 2018 +01 isdst=1 gmtoff=3600
|
||||
Africa/Casablanca Sun Oct 28 01:59:59 2018 UT = Sun Oct 28 02:59:59 2018 +01 isdst=1 gmtoff=3600
|
||||
Africa/Casablanca Sun Oct 28 02:00:00 2018 UT = Sun Oct 28 03:00:00 2018 +01 isdst=0 gmtoff=3600
|
||||
---
|
||||
then we could not determine isdst from the timezone (+01 in the above)
|
||||
and mktime() will provide wrong results.
|
||||
|
||||
Fixes #26370.
|
||||
|
||||
(cherry picked from commit 7a9afae6040af0417d893328cb44b622dcdcb94f)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 174 +++++++++++++++++++++++++++---------------
|
||||
1 file changed, 112 insertions(+), 62 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 92928e88a4..6fbbc2f655 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -609,7 +609,14 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
-static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
+static int parse_timestamp_impl(
|
||||
+ const char *t,
|
||||
+ bool with_tz,
|
||||
+ bool utc,
|
||||
+ int isdst,
|
||||
+ long gmtoff,
|
||||
+ usec_t *ret) {
|
||||
+
|
||||
static const struct {
|
||||
const char *name;
|
||||
const int nr;
|
||||
@@ -630,11 +637,11 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
{ "Sat", 6 },
|
||||
};
|
||||
|
||||
- const char *k, *utc = NULL;
|
||||
- struct tm tm, copy;
|
||||
usec_t usec, plus = 0, minus = 0;
|
||||
- int r, weekday = -1, isdst = -1;
|
||||
+ int r, weekday = -1;
|
||||
unsigned fractional = 0;
|
||||
+ const char *k;
|
||||
+ struct tm tm, copy;
|
||||
time_t sec;
|
||||
|
||||
/* Allowed syntaxes:
|
||||
@@ -707,46 +714,6 @@ static int parse_timestamp_impl(const char *t, usec_t *ret, bool with_tz) {
|
||||
|
||||
goto finish;
|
||||
}
|
||||
-
|
||||
- /* See if the timestamp is suffixed with UTC */
|
||||
- utc = endswith_no_case(t, " UTC");
|
||||
- if (utc)
|
||||
- t = strndupa_safe(t, utc - t);
|
||||
- else {
|
||||
- const char *e = NULL;
|
||||
- int j;
|
||||
-
|
||||
- tzset();
|
||||
-
|
||||
- /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note
|
||||
- * that we only support the local timezones here, nothing else. Not because we
|
||||
- * wouldn't want to, but simply because there are no nice APIs available to cover
|
||||
- * this. By accepting the local time zone strings, we make sure that all timestamps
|
||||
- * written by format_timestamp() can be parsed correctly, even though we don't
|
||||
- * support arbitrary timezone specifications. */
|
||||
-
|
||||
- for (j = 0; j <= 1; j++) {
|
||||
-
|
||||
- if (isempty(tzname[j]))
|
||||
- continue;
|
||||
-
|
||||
- e = endswith_no_case(t, tzname[j]);
|
||||
- if (!e)
|
||||
- continue;
|
||||
- if (e == t)
|
||||
- continue;
|
||||
- if (e[-1] != ' ')
|
||||
- continue;
|
||||
-
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (IN_SET(j, 0, 1)) {
|
||||
- /* Found one of the two timezones specified. */
|
||||
- t = strndupa_safe(t, e - t - 1);
|
||||
- isdst = j;
|
||||
- }
|
||||
- }
|
||||
}
|
||||
|
||||
sec = (time_t) (usec / USEC_PER_SEC);
|
||||
@@ -864,9 +831,32 @@ parse_usec:
|
||||
return -EINVAL;
|
||||
|
||||
from_tm:
|
||||
+ assert(plus == 0);
|
||||
+ assert(minus == 0);
|
||||
+
|
||||
if (weekday >= 0 && tm.tm_wday != weekday)
|
||||
return -EINVAL;
|
||||
|
||||
+ if (gmtoff < 0) {
|
||||
+ plus = -gmtoff * USEC_PER_SEC;
|
||||
+
|
||||
+ /* If gmtoff is negative, the string maye be too old to be parsed as UTC.
|
||||
+ * E.g. 1969-12-31 23:00:00 -06 == 1970-01-01 05:00:00 UTC
|
||||
+ * We assumed that gmtoff is in the range of -24:00…+24:00, hence the only date we need to
|
||||
+ * handle here is 1969-12-31. So, let's shift the date with one day, then subtract the shift
|
||||
+ * later. */
|
||||
+ if (tm.tm_year == 69 && tm.tm_mon == 11 && tm.tm_mday == 31) {
|
||||
+ /* Thu 1970-01-01-00:00:00 */
|
||||
+ tm.tm_year = 70;
|
||||
+ tm.tm_mon = 0;
|
||||
+ tm.tm_mday = 1;
|
||||
+ tm.tm_wday = 4;
|
||||
+ tm.tm_yday = 0;
|
||||
+ minus = USEC_PER_DAY;
|
||||
+ }
|
||||
+ } else
|
||||
+ minus = gmtoff * USEC_PER_SEC;
|
||||
+
|
||||
sec = mktime_or_timegm(&tm, utc);
|
||||
if (sec < 0)
|
||||
return -EINVAL;
|
||||
@@ -889,24 +879,93 @@ finish:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int parse_timestamp_with_tz(const char *t, size_t len, bool utc, int isdst, long gmtoff, usec_t *ret) {
|
||||
+ _cleanup_free_ char *buf = NULL;
|
||||
+
|
||||
+ assert(t);
|
||||
+ assert(len > 0);
|
||||
+
|
||||
+ buf = strndup(t, len);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ return parse_timestamp_impl(buf, /* with_tz = */ true, utc, isdst, gmtoff, ret);
|
||||
+}
|
||||
+
|
||||
+static int parse_timestamp_maybe_with_tz(const char *t, size_t len, bool valid_tz, usec_t *ret) {
|
||||
+ assert(t);
|
||||
+ assert(len > 0);
|
||||
+
|
||||
+ tzset();
|
||||
+
|
||||
+ for (int j = 0; j <= 1; j++) {
|
||||
+ if (isempty(tzname[j]))
|
||||
+ continue;
|
||||
+
|
||||
+ if (!streq(t + len + 1, tzname[j]))
|
||||
+ continue;
|
||||
+
|
||||
+ /* The specified timezone matches tzname[] of the local timezone. */
|
||||
+ return parse_timestamp_with_tz(t, len, /* utc = */ false, /* isdst = */ j, /* gmtoff = */ 0, ret);
|
||||
+ }
|
||||
+
|
||||
+ if (valid_tz)
|
||||
+ /* We know that the specified timezone is a valid zoneinfo (e.g. Asia/Tokyo). So, simply drop
|
||||
+ * the timezone and parse the remaining string as a local time. */
|
||||
+ return parse_timestamp_with_tz(t, len, /* utc = */ false, /* isdst = */ -1, /* gmtoff = */ 0, ret);
|
||||
+
|
||||
+ return parse_timestamp_impl(t, /* with_tz = */ false, /* utc = */ false, /* isdst = */ -1, /* gmtoff = */ 0, ret);
|
||||
+}
|
||||
+
|
||||
typedef struct ParseTimestampResult {
|
||||
usec_t usec;
|
||||
int return_value;
|
||||
} ParseTimestampResult;
|
||||
|
||||
int parse_timestamp(const char *t, usec_t *ret) {
|
||||
- char *last_space, *tz = NULL;
|
||||
ParseTimestampResult *shared, tmp;
|
||||
+ const char *k, *tz, *space;
|
||||
+ struct tm tm;
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
- last_space = strrchr(t, ' ');
|
||||
- if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
|
||||
- tz = last_space + 1;
|
||||
+ space = strrchr(t, ' ');
|
||||
+ if (!space)
|
||||
+ return parse_timestamp_impl(t, /* with_tz = */ false, /* utc = */ false, /* isdst = */ -1, /* gmtoff = */ 0, ret);
|
||||
|
||||
- if (!tz || endswith_no_case(t, " UTC"))
|
||||
- return parse_timestamp_impl(t, ret, false);
|
||||
+ /* The string starts with space. */
|
||||
+ if (space == t)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Shortcut, parse the string as UTC. */
|
||||
+ if (streq(space + 1, "UTC"))
|
||||
+ return parse_timestamp_with_tz(t, space - t, /* utc = */ true, /* isdst = */ -1, /* gmtoff = */ 0, ret);
|
||||
+
|
||||
+ /* If the timezone is compatible with RFC-822/ISO 8601 (e.g. +06, or -03:00) then parse the string as
|
||||
+ * UTC and shift the result. */
|
||||
+ k = strptime(space + 1, "%z", &tm);
|
||||
+ if (k && *k == '\0') {
|
||||
+ /* glibc accepts gmtoff more than 24 hours, but we refuse it. */
|
||||
+ if ((usec_t) labs(tm.tm_gmtoff) > USEC_PER_DAY / USEC_PER_SEC)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return parse_timestamp_with_tz(t, space - t, /* utc = */ true, /* isdst = */ -1, /* gmtoff = */ tm.tm_gmtoff, ret);
|
||||
+ }
|
||||
+
|
||||
+ /* If the last word is not a timezone file (e.g. Asia/Tokyo), then let's check if it matches
|
||||
+ * tzname[] of the local timezone, e.g. JST or CEST. */
|
||||
+ if (!timezone_is_valid(space + 1, LOG_DEBUG))
|
||||
+ return parse_timestamp_maybe_with_tz(t, space - t, /* valid_tz = */ false, ret);
|
||||
+
|
||||
+ /* Shortcut. If the current $TZ is equivalent to the specified timezone, it is not necessary to fork
|
||||
+ * the process. */
|
||||
+ tz = getenv("TZ");
|
||||
+ if (tz && *tz == ':' && streq(tz + 1, space + 1))
|
||||
+ return parse_timestamp_maybe_with_tz(t, space - t, /* valid_tz = */ true, ret);
|
||||
+
|
||||
+ /* Otherwise, to avoid polluting the current environment variables, let's fork the process and set
|
||||
+ * the specified timezone in the child process. */
|
||||
|
||||
shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
|
||||
if (shared == MAP_FAILED)
|
||||
@@ -918,11 +977,10 @@ int parse_timestamp(const char *t, usec_t *ret) {
|
||||
return r;
|
||||
}
|
||||
if (r == 0) {
|
||||
- bool with_tz = true;
|
||||
- char *colon_tz;
|
||||
+ const char *colon_tz;
|
||||
|
||||
/* tzset(3) says $TZ should be prefixed with ":" if we reference timezone files */
|
||||
- colon_tz = strjoina(":", tz);
|
||||
+ colon_tz = strjoina(":", space + 1);
|
||||
|
||||
if (setenv("TZ", colon_tz, 1) != 0) {
|
||||
shared->return_value = negative_errno();
|
||||
@@ -931,15 +989,7 @@ int parse_timestamp(const char *t, usec_t *ret) {
|
||||
|
||||
tzset();
|
||||
|
||||
- /* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
|
||||
- * Otherwise just cut it off. */
|
||||
- with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
|
||||
-
|
||||
- /* Cut off the timezone if we don't need it. */
|
||||
- if (with_tz)
|
||||
- t = strndupa_safe(t, last_space - t);
|
||||
-
|
||||
- shared->return_value = parse_timestamp_impl(t, &shared->usec, with_tz);
|
||||
+ shared->return_value = parse_timestamp_maybe_with_tz(t, space - t, /* valid_tz = */ true, &shared->usec);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
27
SOURCES/1260-time-util-fix-typo.patch
Normal file
27
SOURCES/1260-time-util-fix-typo.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 008aed2736dac288700f1c177690904da9c5137d Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 3 Mar 2023 15:24:23 +0900
|
||||
Subject: [PATCH] time-util: fix typo
|
||||
|
||||
Follow-up for 7a9afae6040af0417d893328cb44b622dcdcb94f.
|
||||
|
||||
(cherry picked from commit ca9c9d8d8e999fd80fc43d002c8d5b20c4c1a0a4)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
|
||||
index 6fbbc2f655..66bf4c17bb 100644
|
||||
--- a/src/basic/time-util.c
|
||||
+++ b/src/basic/time-util.c
|
||||
@@ -840,7 +840,7 @@ from_tm:
|
||||
if (gmtoff < 0) {
|
||||
plus = -gmtoff * USEC_PER_SEC;
|
||||
|
||||
- /* If gmtoff is negative, the string maye be too old to be parsed as UTC.
|
||||
+ /* If gmtoff is negative, the string may be too old to be parsed as UTC.
|
||||
* E.g. 1969-12-31 23:00:00 -06 == 1970-01-01 05:00:00 UTC
|
||||
* We assumed that gmtoff is in the range of -24:00…+24:00, hence the only date we need to
|
||||
* handle here is 1969-12-31. So, let's shift the date with one day, then subtract the shift
|
||||
36
SOURCES/1261-ci-bump-the-tools-tree-to-F42.patch
Normal file
36
SOURCES/1261-ci-bump-the-tools-tree-to-F42.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 5e10617a3a450a2bb6fbe031d1861559192bc85c Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <fsumsal@redhat.com>
|
||||
Date: Thu, 4 Sep 2025 15:31:27 +0200
|
||||
Subject: [PATCH] ci: bump the tools tree to F42
|
||||
|
||||
To fix the failing SB key enrollment:
|
||||
|
||||
3h3hBdsDxe: loading Boot0001 "UEFI QEMU QEMU HARDDISK " from PciRoot(0x0)/Pci(0x4,0x0)/Scsi(0x1,0x0)
|
||||
BdsDxe: starting Boot0001 "UEFI QEMU QEMU HARDDISK " from PciRoot(0x0)/Pci(0x4,0x0)/Scsi(0x1,0x0)
|
||||
systemd-boot@0x7d189000,0x7d1a6000
|
||||
Enrolling secure boot keys from directory: \loader\keys\auto
|
||||
Failed to write PK secure boot variable: Security violation
|
||||
systemd-stub@0x670fd000,0x67115000
|
||||
Overlapping PE sections detected. Boot may fail due to image memory corruption!
|
||||
EFI stub: Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path
|
||||
EFI stub: Measured initrd data into PCR 9
|
||||
|
||||
rhel-only: ci
|
||||
Related: RHEL-109488
|
||||
---
|
||||
.github/workflows/mkosi.yml | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml
|
||||
index 808ae0148e..2694ba14ec 100644
|
||||
--- a/.github/workflows/mkosi.yml
|
||||
+++ b/.github/workflows/mkosi.yml
|
||||
@@ -83,7 +83,7 @@ jobs:
|
||||
[Host]
|
||||
ToolsTree=default
|
||||
ToolsTreeDistribution=fedora
|
||||
- ToolsTreeRelease=41
|
||||
+ ToolsTreeRelease=42
|
||||
# Sometimes we run on a host with /dev/kvm, but it is broken, so explicitly disable it
|
||||
QemuKvm=no
|
||||
EOF
|
||||
27
SOURCES/1262-journald-extend-STDOUT_STREAMS_MAX-to-64k.patch
Normal file
27
SOURCES/1262-journald-extend-STDOUT_STREAMS_MAX-to-64k.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 8cec69eb3fe332ac618c34780dd5275d931d9bf8 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 1 Dec 2024 14:46:40 +0900
|
||||
Subject: [PATCH] journald: extend STDOUT_STREAMS_MAX to 64k
|
||||
|
||||
Closes #35390.
|
||||
|
||||
(cherry picked from commit c576ba7182f54f352c03f0768c9178b173fb8bcb)
|
||||
|
||||
Resolves: RHEL-111065
|
||||
---
|
||||
src/journal/journald-stream.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
|
||||
index 8bdcd8c2ae..3ec6e7fcf3 100644
|
||||
--- a/src/journal/journald-stream.c
|
||||
+++ b/src/journal/journald-stream.c
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
|
||||
-#define STDOUT_STREAMS_MAX 4096
|
||||
+#define STDOUT_STREAMS_MAX (64*1024)
|
||||
|
||||
/* During the "setup" protocol phase of the stream logic let's define a different maximum line length than
|
||||
* during the actual operational phase. We want to allow users to specify very short line lengths after all,
|
||||
@ -0,0 +1,163 @@
|
||||
From fa27bab14e2ede08dcac41ab78901ab3b653e556 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Macku <jamacku@redhat.com>
|
||||
Date: Tue, 26 Aug 2025 15:30:49 +0200
|
||||
Subject: [PATCH] Revert "Revert "udev-builtin-net_id: use firmware_node/sun
|
||||
for ID_NET_NAME_SLOT""
|
||||
|
||||
This reverts commit ae92c09f0ddfea2ff6042e152eec9af86013da38.
|
||||
|
||||
Also introduce rhel-9.8 naming scheme.
|
||||
|
||||
rhel-only: policy
|
||||
|
||||
Resolves: RHEL-50103
|
||||
---
|
||||
man/systemd.net-naming-scheme.xml | 9 ++++-
|
||||
src/shared/netif-naming-scheme.c | 1 +
|
||||
src/shared/netif-naming-scheme.h | 2 +
|
||||
src/udev/udev-builtin-net_id.c | 66 +++++++++++++++++++++++++++----
|
||||
4 files changed, 70 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
|
||||
index 34e8e46459..c6ee7b4b6e 100644
|
||||
--- a/man/systemd.net-naming-scheme.xml
|
||||
+++ b/man/systemd.net-naming-scheme.xml
|
||||
@@ -526,6 +526,13 @@
|
||||
<listitem><para>Same as naming scheme <constant>rhel-9.5</constant>.</para></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></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
</variablelist>
|
||||
|
||||
<para>By default <constant>rhel-9.0</constant> is used.</para>
|
||||
@@ -679,7 +686,7 @@ ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
|
||||
</example>
|
||||
|
||||
<example>
|
||||
- <title>PCI Ethernet card in hotplug slot with firmware index number</title>
|
||||
+ <title>PCI Ethernet card in slot with firmware index number</title>
|
||||
|
||||
<programlisting># /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
|
||||
ID_NET_NAME_MAC=enx000000000466
|
||||
diff --git a/src/shared/netif-naming-scheme.c b/src/shared/netif-naming-scheme.c
|
||||
index a38c3f1e2f..4ed866491e 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-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 },
|
||||
/* … 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 3cba656707..c16476522a 100644
|
||||
--- a/src/shared/netif-naming-scheme.h
|
||||
+++ b/src/shared/netif-naming-scheme.h
|
||||
@@ -42,6 +42,7 @@ typedef enum NamingSchemeFlags {
|
||||
* This is disabled since rhel-9.5, as it seems not to work at least for some setups. See upstream issue #28929. */
|
||||
NAMING_DEVICETREE_ALIASES = 1 << 15, /* Generate names from devicetree aliases */
|
||||
NAMING_SR_IOV_R = 1 << 17, /* Use "r" suffix for SR-IOV VF representors */
|
||||
+ NAMING_FIRMWARE_NODE_SUN = 1 << 18, /* Use firmware_node/sun to get PCI slot number */
|
||||
|
||||
/* And now the masks that combine the features above */
|
||||
NAMING_V238 = 0,
|
||||
@@ -76,6 +77,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,
|
||||
|
||||
EXTRA_NET_NAMING_SCHEMES
|
||||
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index 16c9971876..291fb4ba36 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -442,6 +442,51 @@ static int pci_get_hotplug_slot(sd_device *dev, uint32_t *ret) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
+static int get_device_firmware_node_sun(sd_device *dev, uint32_t *ret) {
|
||||
+ const char *attr;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(dev);
|
||||
+ assert(ret);
|
||||
+
|
||||
+ r = device_get_sysattr_value_filtered(dev, "firmware_node/sun", &attr);
|
||||
+ if (r < 0)
|
||||
+ return log_device_debug_errno(dev, r, "Failed to read firmware_node/sun, ignoring: %m");
|
||||
+
|
||||
+ r = safe_atou32(attr, ret);
|
||||
+ if (r < 0)
|
||||
+ return log_device_warning_errno(dev, r, "Failed to parse firmware_node/sun '%s', ignoring: %m", attr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int pci_get_slot_from_firmware_node_sun(sd_device *dev, uint32_t *ret) {
|
||||
+ int r;
|
||||
+ sd_device *slot_dev;
|
||||
+
|
||||
+ assert(dev);
|
||||
+ assert(ret);
|
||||
+
|
||||
+ /* Try getting the ACPI _SUN for the device */
|
||||
+ if (get_device_firmware_node_sun(dev, ret) >= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ r = sd_device_get_parent_with_subsystem_devtype(dev, "pci", NULL, &slot_dev);
|
||||
+ if (r < 0)
|
||||
+ return log_device_debug_errno(dev, r, "Failed to find pci parent, ignoring: %m");
|
||||
+
|
||||
+ if (is_pci_bridge(slot_dev) && is_pci_multifunction(dev) <= 0)
|
||||
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ESTALE),
|
||||
+ "Not using slot information because the parent pcieport "
|
||||
+ "is a bridge and the PCI device is not multifunction.");
|
||||
+
|
||||
+ /* Try getting the ACPI _SUN from the parent pcieport */
|
||||
+ if (get_device_firmware_node_sun(slot_dev, ret) >= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ return -ENOENT;
|
||||
+}
|
||||
+
|
||||
static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
|
||||
const char *sysname, *attr;
|
||||
unsigned domain, bus, slot, func;
|
||||
@@ -517,13 +562,20 @@ static int dev_pci_slot(sd_device *dev, const LinkInfo *info, NetNames *names) {
|
||||
domain, bus, slot, func, strempty(info->phys_port_name), dev_port,
|
||||
special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), empty_to_na(names->pci_path));
|
||||
|
||||
- r = pci_get_hotplug_slot(names->pcidev, &hotplug_slot);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- if (r > 0)
|
||||
- /* If the hotplug slot is found through the function ID, then drop the domain from the name.
|
||||
- * See comments in parse_hotplug_slot_from_function_id(). */
|
||||
- domain = 0;
|
||||
+ if (naming_scheme_has(NAMING_FIRMWARE_NODE_SUN))
|
||||
+ r = pci_get_slot_from_firmware_node_sun(names->pcidev, &hotplug_slot);
|
||||
+ else
|
||||
+ r = -1;
|
||||
+ /* If we don't find a slot using firmware_node/sun, fallback to hotplug_slot */
|
||||
+ if (r < 0) {
|
||||
+ r = pci_get_hotplug_slot(names->pcidev, &hotplug_slot);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ if (r > 0)
|
||||
+ /* If the hotplug slot is found through the function ID, then drop the domain from the name.
|
||||
+ * See comments in parse_hotplug_slot_from_function_id(). */
|
||||
+ domain = 0;
|
||||
+ }
|
||||
|
||||
s = names->pci_slot;
|
||||
l = sizeof(names->pci_slot);
|
||||
@ -0,0 +1,43 @@
|
||||
From 743c0fbd5ea56f926b36d6bbfc2d609bacd4353e Mon Sep 17 00:00:00 2001
|
||||
From: Etienne Champetier <e.champetier@ateme.com>
|
||||
Date: Thu, 22 Aug 2024 16:30:56 -0400
|
||||
Subject: [PATCH] udev-builtin-net_id: ignore firmware_node/sun == 0
|
||||
|
||||
Since ID_NET_NAME_SLOT was introduced we ignore slot == 0
|
||||
https://github.com/systemd/systemd/blob/0035597a30d120f70df2dd7da3d6128fb8ba6051/src/udev/udev-builtin-net_id.c#L139
|
||||
|
||||
Qemu sets _SUN to PCI_SLOT() for all NICs, so _SUN is not unique.
|
||||
https://gitlab.com/qemu-project/qemu/-/issues/2530
|
||||
|
||||
In my tests with libvirt I can only set 'slot="0x00"' in interface definition,
|
||||
so all NICs end up with _SUN == 0, and this commit is enough to avoid the issue.
|
||||
|
||||
Fixes 0a4ecc54cb9f2d3418b970c51bfadb69c34ae9eb
|
||||
|
||||
(cherry picked from commit 448f9f81fd32f8658449101ada2eadd853f6b06b)
|
||||
|
||||
Resolves: RHEL-50103
|
||||
---
|
||||
src/udev/udev-builtin-net_id.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
|
||||
index 291fb4ba36..e1895a38c0 100644
|
||||
--- a/src/udev/udev-builtin-net_id.c
|
||||
+++ b/src/udev/udev-builtin-net_id.c
|
||||
@@ -453,10 +453,14 @@ static int get_device_firmware_node_sun(sd_device *dev, uint32_t *ret) {
|
||||
if (r < 0)
|
||||
return log_device_debug_errno(dev, r, "Failed to read firmware_node/sun, ignoring: %m");
|
||||
|
||||
- r = safe_atou32(attr, ret);
|
||||
+ uint32_t sun;
|
||||
+ r = safe_atou32(attr, &sun);
|
||||
if (r < 0)
|
||||
return log_device_warning_errno(dev, r, "Failed to parse firmware_node/sun '%s', ignoring: %m", attr);
|
||||
+ if (sun == 0)
|
||||
+ return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EINVAL), "firmware_node/sun == 0, ignoring: %m");
|
||||
|
||||
+ *ret = sun;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
From c14ed0d0bf700b9959359004d5eef50d4d2db951 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Tue, 10 Jan 2023 14:08:41 +0100
|
||||
Subject: [PATCH] fundamental: fix compile check for explicit_bzero
|
||||
|
||||
Our HAVE_* variables are defined to 0 or 1, so '#if defined(HAVE_*)' is always true.
|
||||
The variable is not defined when compiling for EFI though, so we need the
|
||||
additional guard.
|
||||
|
||||
Fixup for 3f92dc2fd4070b213e6bc85263a9bef06ec9a486.
|
||||
|
||||
(I don't want to do something like add -DHAVE_EXPLICIT_BZERO=0 to the commandline
|
||||
in src/efi/boot/meson.build, because this quite verbose. Our compilation commandlines
|
||||
are very long already. Let's instead keep this localized in this one spot in the
|
||||
source file.)x
|
||||
|
||||
(cherry picked from commit 5deb391c6e6d2b8fd7b94234efea49cd6bee0d76)
|
||||
|
||||
Resolves: RHEL-108568
|
||||
---
|
||||
src/fundamental/memory-util-fundamental.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/fundamental/memory-util-fundamental.h b/src/fundamental/memory-util-fundamental.h
|
||||
index 8f50d8b8e1..e0ae33dc0d 100644
|
||||
--- a/src/fundamental/memory-util-fundamental.h
|
||||
+++ b/src/fundamental/memory-util-fundamental.h
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "macro-fundamental.h"
|
||||
|
||||
-#if defined(HAVE_EXPLICIT_BZERO)
|
||||
+#if !defined(SD_BOOT) && HAVE_EXPLICIT_BZERO
|
||||
static inline void *explicit_bzero_safe(void *p, size_t l) {
|
||||
if (p && l > 0)
|
||||
explicit_bzero(p, l);
|
||||
@ -0,0 +1,74 @@
|
||||
From 9906687d228f71768ddf115799ebb39272d1f655 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 12 Mar 2023 20:57:16 +0900
|
||||
Subject: [PATCH] time-util: make USEC_TIMESTAMP_FORMATTABLE_MAX for 32bit
|
||||
system off by one day
|
||||
|
||||
As the same reason why we take one day off for 64bit case.
|
||||
|
||||
This also makes both upper bounds always defined for testing.
|
||||
|
||||
(cherry picked from commit bd5770da76ee157d3b31323ed2d22f5d9082bb36)
|
||||
|
||||
Related: RHEL-109488
|
||||
---
|
||||
src/basic/time-util.h | 14 +++++++++-----
|
||||
src/test/test-date.c | 4 ++--
|
||||
src/test/test-time-util.c | 2 +-
|
||||
3 files changed, 12 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/basic/time-util.h b/src/basic/time-util.h
|
||||
index 9d44cac747..7f8bda0948 100644
|
||||
--- a/src/basic/time-util.h
|
||||
+++ b/src/basic/time-util.h
|
||||
@@ -200,13 +200,17 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
|
||||
return usec_sub_unsigned(timestamp, (usec_t) delta);
|
||||
}
|
||||
|
||||
+/* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit
|
||||
+ * year territory. However, since we want to stay away from this in all timezones we take one day off. */
|
||||
+#define USEC_TIMESTAMP_FORMATTABLE_MAX_64BIT ((usec_t) 253402214399000000) /* Thu 9999-12-30 23:59:59 UTC */
|
||||
+/* With a 32bit time_t we can't go beyond 2038...
|
||||
+ * We parse timestamp with RFC-822/ISO 8601 (e.g. +06, or -03:00) as UTC, hence the upper bound must be off
|
||||
+ * by USEC_PER_DAY. See parse_timestamp() for more details. */
|
||||
+#define USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT (((usec_t) INT32_MAX) * USEC_PER_SEC - USEC_PER_DAY)
|
||||
#if SIZEOF_TIME_T == 8
|
||||
- /* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit
|
||||
- * year territory. However, since we want to stay away from this in all timezones we take one day off. */
|
||||
-# define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 253402214399000000)
|
||||
+# define USEC_TIMESTAMP_FORMATTABLE_MAX USEC_TIMESTAMP_FORMATTABLE_MAX_64BIT
|
||||
#elif SIZEOF_TIME_T == 4
|
||||
-/* With a 32bit time_t we can't go beyond 2038... */
|
||||
-# define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000)
|
||||
+# define USEC_TIMESTAMP_FORMATTABLE_MAX USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT
|
||||
#else
|
||||
# error "Yuck, time_t is neither 4 nor 8 bytes wide?"
|
||||
#endif
|
||||
diff --git a/src/test/test-date.c b/src/test/test-date.c
|
||||
index cc11bd999e..ef316eeca7 100644
|
||||
--- a/src/test/test-date.c
|
||||
+++ b/src/test/test-date.c
|
||||
@@ -104,8 +104,8 @@ int main(int argc, char *argv[]) {
|
||||
test_should_fail("9999-12-31 00:00:00 UTC");
|
||||
test_should_fail("10000-01-01 00:00:00 UTC");
|
||||
#elif SIZEOF_TIME_T == 4
|
||||
- test_should_pass("2038-01-19 03:14:07 UTC");
|
||||
- test_should_fail("2038-01-19 03:14:08 UTC");
|
||||
+ test_should_pass("2038-01-18 03:14:07 UTC");
|
||||
+ test_should_fail("2038-01-18 03:14:08 UTC");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
|
||||
index 21b05a3010..71ef5906ba 100644
|
||||
--- a/src/test/test-time-util.c
|
||||
+++ b/src/test/test-time-util.c
|
||||
@@ -550,7 +550,7 @@ TEST(format_timestamp_utc) {
|
||||
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC");
|
||||
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX");
|
||||
#elif SIZEOF_TIME_T == 4
|
||||
- test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC");
|
||||
+ test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Mon 2038-01-18 03:14:07 UTC");
|
||||
test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX");
|
||||
#endif
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
From 0abac4254115db7d86549b517163a13de9377346 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-118215
|
||||
---
|
||||
.../Makefile | 0
|
||||
.../test.sh | 0
|
||||
test/units/testsuite-53.issue-16347.sh | 27 ++++++++++++++++++
|
||||
test/units/testsuite-53.sh | 28 +++----------------
|
||||
4 files changed, 31 insertions(+), 24 deletions(-)
|
||||
rename test/{TEST-53-ISSUE-16347 => TEST-53-TIMER}/Makefile (100%)
|
||||
rename test/{TEST-53-ISSUE-16347 => TEST-53-TIMER}/test.sh (100%)
|
||||
create mode 100755 test/units/testsuite-53.issue-16347.sh
|
||||
|
||||
diff --git a/test/TEST-53-ISSUE-16347/Makefile b/test/TEST-53-TIMER/Makefile
|
||||
similarity index 100%
|
||||
rename from test/TEST-53-ISSUE-16347/Makefile
|
||||
rename to test/TEST-53-TIMER/Makefile
|
||||
diff --git a/test/TEST-53-ISSUE-16347/test.sh b/test/TEST-53-TIMER/test.sh
|
||||
similarity index 100%
|
||||
rename from test/TEST-53-ISSUE-16347/test.sh
|
||||
rename to test/TEST-53-TIMER/test.sh
|
||||
diff --git a/test/units/testsuite-53.issue-16347.sh b/test/units/testsuite-53.issue-16347.sh
|
||||
new file mode 100755
|
||||
index 0000000000..8b266145cd
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-53.issue-16347.sh
|
||||
@@ -0,0 +1,27 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+# 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
|
||||
+
|
||||
+next_elapsed=$(systemctl show test-timer.timer -p NextElapseUSecRealtime --value)
|
||||
+next_elapsed=$(date -d "${next_elapsed}" +%s)
|
||||
+now=$(date +%s)
|
||||
+time_delta=$((next_elapsed - now))
|
||||
+
|
||||
+# Check that the timer will elapse in less than 20 minutes.
|
||||
+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
|
||||
+
|
||||
+ exit 1
|
||||
+fi
|
||||
diff --git a/test/units/testsuite-53.sh b/test/units/testsuite-53.sh
|
||||
index 84cd66129d..9c2a033aa9 100755
|
||||
--- a/test/units/testsuite-53.sh
|
||||
+++ b/test/units/testsuite-53.sh
|
||||
@@ -3,29 +3,9 @@
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
-: >/failed
|
||||
+# shellcheck source=test/units/test-control.sh
|
||||
+. "$(dirname "$0")"/test-control.sh
|
||||
|
||||
-# Reset host date to current time, 3 days in the past.
|
||||
-date -s "-3 days"
|
||||
+run_subtests
|
||||
|
||||
-# Run a timer for every 15 minutes.
|
||||
-systemd-run --unit test-timer --on-calendar "*:0/15:0" true
|
||||
-
|
||||
-next_elapsed=$(systemctl show test-timer.timer -p NextElapseUSecRealtime --value)
|
||||
-next_elapsed=$(date -d "${next_elapsed}" +%s)
|
||||
-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)) || {
|
||||
- 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
|
||||
-
|
||||
-if test ! -s /failed ; then
|
||||
- rm -f /failed
|
||||
- touch /testok
|
||||
-fi
|
||||
+touch /testok
|
||||
@ -0,0 +1,101 @@
|
||||
From 53b158318d6bfbb1e59b91bfad15e7d128622efb 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-118215
|
||||
---
|
||||
test/units/testsuite-53.restart-trigger.sh | 77 ++++++++++++++++++++++
|
||||
1 file changed, 77 insertions(+)
|
||||
create mode 100755 test/units/testsuite-53.restart-trigger.sh
|
||||
|
||||
diff --git a/test/units/testsuite-53.restart-trigger.sh b/test/units/testsuite-53.restart-trigger.sh
|
||||
new file mode 100755
|
||||
index 0000000000..057f379ddc
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-53.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
|
||||
@ -0,0 +1,156 @@
|
||||
From 14aa00df0638e8011dd7360eb58d3b0ac64a818a 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-118215
|
||||
---
|
||||
.../testsuite-53.RandomizedDelaySec-reload.sh | 97 +++++++++++++++++++
|
||||
test/units/util.sh | 18 ++++
|
||||
2 files changed, 115 insertions(+)
|
||||
create mode 100755 test/units/testsuite-53.RandomizedDelaySec-reload.sh
|
||||
|
||||
diff --git a/test/units/testsuite-53.RandomizedDelaySec-reload.sh b/test/units/testsuite-53.RandomizedDelaySec-reload.sh
|
||||
new file mode 100755
|
||||
index 0000000000..08f4f469d6
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-53.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 00b8c5e393..5728b324a9 100755
|
||||
--- a/test/units/util.sh
|
||||
+++ b/test/units/util.sh
|
||||
@@ -26,6 +26,24 @@ assert_eq() {(
|
||||
fi
|
||||
)}
|
||||
|
||||
+assert_le() {(
|
||||
+ set +ex
|
||||
+
|
||||
+ if [[ "${1:?}" -gt "${2:?}" ]]; then
|
||||
+ echo "FAIL: '$1' > '$2'" >&2
|
||||
+ exit 1
|
||||
+ fi
|
||||
+)}
|
||||
+
|
||||
+assert_ge() {(
|
||||
+ set +ex
|
||||
+
|
||||
+ if [[ "${1:?}" -lt "${2:?}" ]]; then
|
||||
+ echo "FAIL: '$1' < '$2'" >&2
|
||||
+ exit 1
|
||||
+ fi
|
||||
+)}
|
||||
+
|
||||
assert_in() {(
|
||||
set +ex
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
From a5e7446ae2442558f9c13d814e778f13a7018e23 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-118215
|
||||
---
|
||||
src/core/timer.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 60e8fea79f..2eadca4f1a 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -635,8 +635,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)
|
||||
@ -0,0 +1,49 @@
|
||||
From c603c6cb569f0900ddf07f0311ffa038a242fac8 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-118215
|
||||
---
|
||||
test/units/testsuite-53.restart-trigger.sh | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/test/units/testsuite-53.restart-trigger.sh b/test/units/testsuite-53.restart-trigger.sh
|
||||
index 057f379ddc..e5cd575d66 100755
|
||||
--- a/test/units/testsuite-53.restart-trigger.sh
|
||||
+++ b/test/units/testsuite-53.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}
|
||||
@ -0,0 +1,94 @@
|
||||
From d4299294d40b7fe713d0c9df0f7a42c70654e886 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Fri, 5 Apr 2024 12:18:58 +0200
|
||||
Subject: [PATCH] test: make test-fd-util more lenient when using
|
||||
fd_move_above_stdio()
|
||||
|
||||
On s390x this test fails when the SUT uses the z90crypt kernel module,
|
||||
as it's an another FD the test doesn't account for:
|
||||
|
||||
/* test_rearrange_stdio */
|
||||
Successfully forked off 'rearrange' as PID 57293.
|
||||
test_rearrange_stdio: r=0
|
||||
/proc/57293/fd:
|
||||
total 0
|
||||
lrwx------. 1 root root 64 Apr 5 06:18 0 -> /dev/pts/0
|
||||
lrwx------. 1 root root 64 Apr 5 06:18 1 -> /dev/pts/0
|
||||
lrwx------. 1 root root 64 Apr 5 06:18 2 -> /dev/pts/0
|
||||
lrwx------. 1 root root 64 Apr 5 06:18 3 -> /dev/z90crypt
|
||||
rearrange terminated by signal ABRT.
|
||||
|
||||
Debugging this was pain, since the child process didn't log anything
|
||||
once we closed stdout/stderr (for obvious reasons). Let's fix both
|
||||
issues by switching logging to kmsg once we close stdin/stdout/stderr,
|
||||
and also by making the test work fine when there are some extra FDs in
|
||||
the child's environment.
|
||||
|
||||
(cherry picked from commit a9805f8ca9c1561e373355fe7175579b31e1c08c)
|
||||
|
||||
Related: RHEL-114974
|
||||
---
|
||||
src/test/test-fd-util.c | 22 +++++++++++++---------
|
||||
1 file changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c
|
||||
index 5b5a712469..5d6c5325a5 100644
|
||||
--- a/src/test/test-fd-util.c
|
||||
+++ b/src/test/test-fd-util.c
|
||||
@@ -127,6 +127,7 @@ TEST(rearrange_stdio) {
|
||||
|
||||
if (r == 0) {
|
||||
_cleanup_free_ char *path = NULL;
|
||||
+ int pipe_read_fd, pair[2];
|
||||
char buffer[10];
|
||||
|
||||
/* Child */
|
||||
@@ -134,6 +135,10 @@ TEST(rearrange_stdio) {
|
||||
safe_close(STDERR_FILENO); /* Let's close an fd < 2, to make it more interesting */
|
||||
|
||||
assert_se(rearrange_stdio(-1, -1, -1) >= 0);
|
||||
+ /* Reconfigure logging after rearranging stdout/stderr, so we still log to somewhere if the
|
||||
+ * following tests fail, making it slightly less annoying to debug */
|
||||
+ log_set_target(LOG_TARGET_KMSG);
|
||||
+ log_open();
|
||||
|
||||
assert_se(fd_get_path(STDIN_FILENO, &path) >= 0);
|
||||
assert_se(path_equal(path, "/dev/null"));
|
||||
@@ -151,13 +156,12 @@ TEST(rearrange_stdio) {
|
||||
safe_close(STDOUT_FILENO);
|
||||
safe_close(STDERR_FILENO);
|
||||
|
||||
- {
|
||||
- int pair[2];
|
||||
- assert_se(pipe(pair) >= 0);
|
||||
- assert_se(pair[0] == 0);
|
||||
- assert_se(pair[1] == 1);
|
||||
- assert_se(fd_move_above_stdio(0) == 3);
|
||||
- }
|
||||
+ assert_se(pipe(pair) >= 0);
|
||||
+ assert_se(pair[0] == 0);
|
||||
+ assert_se(pair[1] == 1);
|
||||
+ pipe_read_fd = fd_move_above_stdio(0);
|
||||
+ assert_se(pipe_read_fd >= 3);
|
||||
+
|
||||
assert_se(open("/dev/full", O_WRONLY|O_CLOEXEC) == 0);
|
||||
assert_se(acquire_data_fd("foobar", 6, 0) == 2);
|
||||
|
||||
@@ -165,7 +169,7 @@ TEST(rearrange_stdio) {
|
||||
|
||||
assert_se(write(1, "x", 1) < 0 && errno == ENOSPC);
|
||||
assert_se(write(2, "z", 1) == 1);
|
||||
- assert_se(read(3, buffer, sizeof(buffer)) == 1);
|
||||
+ assert_se(read(pipe_read_fd, buffer, sizeof(buffer)) == 1);
|
||||
assert_se(buffer[0] == 'z');
|
||||
assert_se(read(0, buffer, sizeof(buffer)) == 6);
|
||||
assert_se(memcmp(buffer, "foobar", 6) == 0);
|
||||
@@ -173,7 +177,7 @@ TEST(rearrange_stdio) {
|
||||
assert_se(rearrange_stdio(-1, 1, 2) >= 0);
|
||||
assert_se(write(1, "a", 1) < 0 && errno == ENOSPC);
|
||||
assert_se(write(2, "y", 1) == 1);
|
||||
- assert_se(read(3, buffer, sizeof(buffer)) == 1);
|
||||
+ assert_se(read(pipe_read_fd, buffer, sizeof(buffer)) == 1);
|
||||
assert_se(buffer[0] == 'y');
|
||||
|
||||
assert_se(fd_get_path(0, &path) >= 0);
|
||||
51
SOURCES/1273-basic-add-PIDFS-magic-31709.patch
Normal file
51
SOURCES/1273-basic-add-PIDFS-magic-31709.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 2c74cdb28bad7e8122bfd51a6d4897f792ef3e2f Mon Sep 17 00:00:00 2001
|
||||
From: cpackham-atlnz <85916201+cpackham-atlnz@users.noreply.github.com>
|
||||
Date: Tue, 12 Mar 2024 00:55:36 +1300
|
||||
Subject: [PATCH] basic: add PIDFS magic (#31709)
|
||||
|
||||
Kernel commit cb12fd8e0dabb9a1c8aef55a6a41e2c255fcdf4b added pidfs.
|
||||
Update filesystems-gperf.gperf and missing_magic.h accordingly.
|
||||
|
||||
This fixes the following error building against a bleeding edge kernel.
|
||||
```
|
||||
../src/basic/meson.build:234:8: ERROR: Problem encountered: Unknown filesystems defined in kernel headers:
|
||||
|
||||
Filesystem found in kernel header but not in filesystems-gperf.gperf: PID_FS_MAGIC
|
||||
```
|
||||
|
||||
(cherry picked from commit ed01b92e1c92871bbd92711f280e2b2d15753f0e)
|
||||
|
||||
Resolves: RHEL-114974
|
||||
---
|
||||
src/basic/filesystems-gperf.gperf | 1 +
|
||||
src/basic/missing_magic.h | 5 +++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/src/basic/filesystems-gperf.gperf b/src/basic/filesystems-gperf.gperf
|
||||
index e8c5357f91..1cd66b5a5f 100644
|
||||
--- a/src/basic/filesystems-gperf.gperf
|
||||
+++ b/src/basic/filesystems-gperf.gperf
|
||||
@@ -91,6 +91,7 @@ ocfs2, {OCFS2_SUPER_MAGIC}
|
||||
openpromfs, {OPENPROM_SUPER_MAGIC}
|
||||
orangefs, {ORANGEFS_DEVREQ_MAGIC}
|
||||
overlay, {OVERLAYFS_SUPER_MAGIC}
|
||||
+pidfs, {PID_FS_MAGIC}
|
||||
pipefs, {PIPEFS_MAGIC}
|
||||
ppc-cmm, {PPC_CMM_MAGIC}
|
||||
proc, {PROC_SUPER_MAGIC}
|
||||
diff --git a/src/basic/missing_magic.h b/src/basic/missing_magic.h
|
||||
index c104fcfba3..82ede1873e 100644
|
||||
--- a/src/basic/missing_magic.h
|
||||
+++ b/src/basic/missing_magic.h
|
||||
@@ -128,6 +128,11 @@
|
||||
#define DEVMEM_MAGIC 0x454d444d
|
||||
#endif
|
||||
|
||||
+/* cb12fd8e0dabb9a1c8aef55a6a41e2c255fcdf4b (6.8) */
|
||||
+#ifndef PID_FS_MAGIC
|
||||
+#define PID_FS_MAGIC 0x50494446
|
||||
+#endif
|
||||
+
|
||||
/* Not in mainline but included in Ubuntu */
|
||||
#ifndef SHIFTFS_MAGIC
|
||||
#define SHIFTFS_MAGIC 0x6a656a62
|
||||
27
SOURCES/1274-man-fix-a-missing-word.patch
Normal file
27
SOURCES/1274-man-fix-a-missing-word.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 5844efbf70321f5dd902f987947786d1ab4409c6 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-115182
|
||||
---
|
||||
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 2a0e40a17d..9431fb20a1 100644
|
||||
--- a/man/systemd.resource-control.xml
|
||||
+++ b/man/systemd.resource-control.xml
|
||||
@@ -365,7 +365,7 @@
|
||||
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://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#pid">pids controller
|
||||
</ulink>.</para>
|
||||
|
||||
@ -0,0 +1,167 @@
|
||||
From 26d6ea70cfb9232dc9ab66ee0927fb546fe0418b Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Kozina <okozina@redhat.com>
|
||||
Date: Wed, 31 Jan 2024 13:11:21 +0100
|
||||
Subject: [PATCH] cryptsetup: Add optional support for linking volume key in
|
||||
keyring.
|
||||
|
||||
cryptsetup 2.7.0 adds feature to link effective volume key in custom
|
||||
kernel keyring during device activation. It can be used later to pass
|
||||
linked volume key to other services.
|
||||
|
||||
For example: kdump enabled systems installed on LUKS2 device.
|
||||
This feature allows it to store volume key linked in a kernel keyring
|
||||
to the kdump reserved memory and reuse it to reactivate LUKS2 device
|
||||
in case of kernel crash.
|
||||
|
||||
(cherry picked from commit c5daf14c88ba44cefabe052de93a29d28b6b0175)
|
||||
|
||||
Resolves: RHEL-97175
|
||||
---
|
||||
man/crypttab.xml | 21 ++++++++++++
|
||||
meson.build | 3 +-
|
||||
src/cryptsetup/cryptsetup.c | 65 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 88 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/man/crypttab.xml b/man/crypttab.xml
|
||||
index 1dd9bb1bb6..bd49e025fa 100644
|
||||
--- a/man/crypttab.xml
|
||||
+++ b/man/crypttab.xml
|
||||
@@ -239,6 +239,27 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><option>link-volume-key=</option></term>
|
||||
+
|
||||
+ <listitem><para>Specifies the kernel keyring and key description
|
||||
+ (see <citerefentry project='man-pages'><refentrytitle>keyrings</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
|
||||
+ where LUKS2 volume key gets linked during device activation. The kernel keyring
|
||||
+ description and key description must be separated by <literal>::</literal>.</para>
|
||||
+
|
||||
+ <para>The kernel keyring part can be a string description or a predefined
|
||||
+ kernel keyring prefixed with <literal>@</literal> (e.g.: to use <literal>@s</literal> session or
|
||||
+ <literal>@u</literal> user keyring directly). The type prefix text in the kernel keyring description
|
||||
+ is not required. The specified kernel keyring must already exist at the time of device activation.</para>
|
||||
+
|
||||
+ <para>The key part is a string description optionally prefixed by a <literal>%key_type:</literal>.
|
||||
+ If no type is specified, the <literal>user</literal> type key is linked by default. See
|
||||
+ <citerefentry project='man-pages'><refentrytitle>keyctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
+ for more information on key descriptions (KEY IDENTIFIERS section).</para>
|
||||
+
|
||||
+ <para>Note that the linked volume key is not cleaned up automatically when the device is detached.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><option>luks</option></term>
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index cbde702211..684324c6d7 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -1316,7 +1316,8 @@ if want_libcryptsetup != 'false' and not skip_deps
|
||||
|
||||
foreach ident : ['crypt_set_metadata_size',
|
||||
'crypt_activate_by_signed_key',
|
||||
- 'crypt_token_max']
|
||||
+ 'crypt_token_max',
|
||||
+ 'crypt_set_keyring_to_link']
|
||||
have_ident = have and cc.has_function(
|
||||
ident,
|
||||
prefix : '#include <libcryptsetup.h>',
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index 3f2cab1e41..f9130e2568 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -101,6 +101,9 @@ static bool arg_headless = false;
|
||||
static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC;
|
||||
static unsigned arg_tpm2_measure_pcr = UINT_MAX; /* This and the following field is about measuring the unlocked volume key to the local TPM */
|
||||
static char **arg_tpm2_measure_banks = NULL;
|
||||
+static char *arg_link_keyring = NULL;
|
||||
+static char *arg_link_key_type = NULL;
|
||||
+static char *arg_link_key_description = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_hash, freep);
|
||||
@@ -113,6 +116,9 @@ STATIC_DESTRUCTOR_REGISTER(arg_fido2_rp_id, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_measure_banks, strv_freep);
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_link_keyring, freep);
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_link_key_type, freep);
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_link_key_description, freep);
|
||||
|
||||
static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = {
|
||||
[PASSPHRASE_REGULAR] = "passphrase",
|
||||
@@ -486,6 +492,56 @@ static int parse_one_option(const char *option) {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
|
||||
|
||||
+ } else if ((val = startswith(option, "link-volume-key="))) {
|
||||
+#ifdef HAVE_CRYPT_SET_KEYRING_TO_LINK
|
||||
+ const char *sep, *c;
|
||||
+ _cleanup_free_ char *keyring = NULL, *key_type = NULL, *key_description = NULL;
|
||||
+
|
||||
+ /* Stick with cryptsetup --link-vk-to-keyring format
|
||||
+ * <keyring_description>::%<key_type>:<key_description>,
|
||||
+ * where %<key_type> is optional and defaults to 'user'.
|
||||
+ */
|
||||
+ if (!(sep = strstr(val, "::")))
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse link-volume-key= option value: %m");
|
||||
+
|
||||
+ /* cryptsetup (cli) supports <keyring_description> passed in various formats:
|
||||
+ * - well-known keyrings prefixed with '@' (@u user, @s session, etc)
|
||||
+ * - text descriptions prefixed with "%:" or "%keyring:".
|
||||
+ * - text desription with no prefix.
|
||||
+ * - numeric keyring id (ignored in current patch set). */
|
||||
+ if (*val == '@' || *val == '%')
|
||||
+ keyring = strndup(val, sep - val);
|
||||
+ else
|
||||
+ /* add type prefix if missing (crypt_set_keyring_to_link() expects it) */
|
||||
+ keyring = strnappend("%:", val, sep - val);
|
||||
+ if (!keyring)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ sep += 2;
|
||||
+
|
||||
+ /* %<key_type> is optional (and defaults to 'user') */
|
||||
+ if (*sep == '%') {
|
||||
+ /* must be separated by colon */
|
||||
+ if (!(c = strchr(sep, ':')))
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse link-volume-key= option value: %m");
|
||||
+
|
||||
+ key_type = strndup(sep + 1, c - sep - 1);
|
||||
+ if (!key_type)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ sep = c + 1;
|
||||
+ }
|
||||
+
|
||||
+ key_description = strdup(sep);
|
||||
+ if (!key_description)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ free_and_replace(arg_link_keyring, keyring);
|
||||
+ free_and_replace(arg_link_key_type, key_type);
|
||||
+ free_and_replace(arg_link_key_description, key_description);
|
||||
+#else
|
||||
+ log_error("Build lacks libcryptsetup support for linking volume keys in user specified kernel keyrings upon device activation, ignoring: %s", option);
|
||||
+#endif
|
||||
} else if (!streq(option, "x-initrd.attach"))
|
||||
log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option);
|
||||
|
||||
@@ -2207,6 +2263,15 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", crypt_get_device_name(cd));
|
||||
|
||||
+/* since cryptsetup 2.7.0 (Jan 2024) */
|
||||
+#if HAVE_CRYPT_SET_KEYRING_TO_LINK
|
||||
+ if (arg_link_key_description) {
|
||||
+ r = crypt_set_keyring_to_link(cd, arg_link_key_description, NULL, arg_link_key_type, arg_link_keyring);
|
||||
+ if (r < 0)
|
||||
+ log_warning_errno(r, "Failed to set keyring or key description to link volume key in, ignoring: %m");
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (arg_header) {
|
||||
r = crypt_set_data_device(cd, source);
|
||||
if (r < 0)
|
||||
27
SOURCES/1276-cryptsetup-fix-typo.patch
Normal file
27
SOURCES/1276-cryptsetup-fix-typo.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 44f65e9b9a0f67a69886d25367875e9707affc81 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 14 Feb 2024 04:01:36 +0900
|
||||
Subject: [PATCH] cryptsetup: fix typo
|
||||
|
||||
Follow-up for c5daf14c88ba44cefabe052de93a29d28b6b0175.
|
||||
|
||||
(cherry picked from commit a14d3b48f7647676a0c43bceaecd56d9a77e3de6)
|
||||
|
||||
Resolves: RHEL-97175
|
||||
---
|
||||
src/cryptsetup/cryptsetup.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index f9130e2568..1f672f19f1 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -507,7 +507,7 @@ static int parse_one_option(const char *option) {
|
||||
/* cryptsetup (cli) supports <keyring_description> passed in various formats:
|
||||
* - well-known keyrings prefixed with '@' (@u user, @s session, etc)
|
||||
* - text descriptions prefixed with "%:" or "%keyring:".
|
||||
- * - text desription with no prefix.
|
||||
+ * - text description with no prefix.
|
||||
* - numeric keyring id (ignored in current patch set). */
|
||||
if (*val == '@' || *val == '%')
|
||||
keyring = strndup(val, sep - val);
|
||||
@ -0,0 +1,27 @@
|
||||
From be6acfdfd0ddd5625d68bdeb1fb5962d710557be Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 17 Aug 2025 21:05:24 +0900
|
||||
Subject: [PATCH] cryptsetup: HAVE_CRYPT_SET_KEYRING_TO_LINK is always defined
|
||||
|
||||
Follow-up for c5daf14c88ba44cefabe052de93a29d28b6b0175 (v256).
|
||||
|
||||
(cherry picked from commit fb4aabf4432d523b97376099ce4353b5c268ae82)
|
||||
|
||||
Resolves: RHEL-97175
|
||||
---
|
||||
src/cryptsetup/cryptsetup.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c
|
||||
index 1f672f19f1..4dc315e810 100644
|
||||
--- a/src/cryptsetup/cryptsetup.c
|
||||
+++ b/src/cryptsetup/cryptsetup.c
|
||||
@@ -493,7 +493,7 @@ static int parse_one_option(const char *option) {
|
||||
log_warning_errno(r, "Failed to parse %s, ignoring: %m", option);
|
||||
|
||||
} else if ((val = startswith(option, "link-volume-key="))) {
|
||||
-#ifdef HAVE_CRYPT_SET_KEYRING_TO_LINK
|
||||
+#if HAVE_CRYPT_SET_KEYRING_TO_LINK
|
||||
const char *sep, *c;
|
||||
_cleanup_free_ char *keyring = NULL, *key_type = NULL, *key_description = NULL;
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From 9109aaae160fe7dcb9390829db619e4e8f90274f Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 31 Oct 2024 17:02:59 +0100
|
||||
Subject: [PATCH] coredump: make check that all argv[] meta data fields are
|
||||
passed strict
|
||||
|
||||
Otherwise, if some field is not supplied we might end up parsing a NULL
|
||||
string later. Let's catch that early.
|
||||
|
||||
(cherry picked from commit 098c3975acb3df61eedfe471fca27c21f13cf04c)
|
||||
|
||||
Related: RHEL-104138
|
||||
---
|
||||
src/coredump/coredump.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||
index dca78fa72c..b24f4c8cc3 100644
|
||||
--- a/src/coredump/coredump.c
|
||||
+++ b/src/coredump/coredump.c
|
||||
@@ -1067,9 +1067,10 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||
}
|
||||
}
|
||||
|
||||
- if (!context->meta[META_ARGV_PID])
|
||||
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
- "Failed to find the PID of crashing process");
|
||||
+ /* The basic fields from argv[] should always be there, refuse early if not */
|
||||
+ 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]);
|
||||
|
||||
r = parse_pid(context->meta[META_ARGV_PID], &context->pid);
|
||||
if (r < 0)
|
||||
@ -0,0 +1,122 @@
|
||||
From 38d7a52bcdad1cef1dba218f86e3905c24d51d9a 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
|
||||
|
||||
This was broken in f45b8015513d38ee5f7cc361db9c5b88c9aae704. Unfortunately
|
||||
the review does not talk about backward compatibility at all. There are
|
||||
two places where it matters:
|
||||
- During upgrades, the replacement of kernel.core_pattern is asynchronous.
|
||||
For example, during rpm upgrades, it would be updated a post-transaction
|
||||
file trigger. In other scenarios, the update might only happen after
|
||||
reboot. We have a potentially long window where the old pattern is in
|
||||
place. We need to capture coredumps during upgrades too.
|
||||
- With --backtrace. The interface of --backtrace, in hindsight, is not
|
||||
great. But there are users of --backtrace which were written to use
|
||||
a specific set of arguments, and we can't just break compatiblity.
|
||||
One example is systemd-coredump-python, but there are also reports of
|
||||
users using --backtrace to generate coredump logs.
|
||||
|
||||
Thus, we require the original set of args, and will use the additional args if
|
||||
found.
|
||||
|
||||
A test is added to verify that --backtrace works with and without the optional
|
||||
args.
|
||||
|
||||
(cherry picked from commit ded0aac389e647d35bce7ec4a48e718d77c0435b)
|
||||
|
||||
Related: RHEL-104138
|
||||
---
|
||||
src/coredump/coredump.c | 23 +++++++++++++++--------
|
||||
test/units/testsuite-74.coredump.sh | 18 +++++++++++-------
|
||||
2 files changed, 26 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||
index b24f4c8cc3..458857ffb2 100644
|
||||
--- a/src/coredump/coredump.c
|
||||
+++ b/src/coredump/coredump.c
|
||||
@@ -94,8 +94,12 @@ 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_HOSTNAME, /* %h: hostname */
|
||||
+ _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. */
|
||||
|
||||
/* 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
|
||||
@@ -106,7 +110,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. */
|
||||
+ * them is missing in a message sent over the socket. */
|
||||
|
||||
META_EXE = _META_MANDATORY_MAX,
|
||||
META_UNIT,
|
||||
@@ -1068,7 +1072,7 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||
}
|
||||
|
||||
/* The basic fields from argv[] should always be there, refuse early if not */
|
||||
- for (int i = 0; i < _META_ARGV_MAX; i++)
|
||||
+ 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]);
|
||||
|
||||
@@ -1286,14 +1290,17 @@ static int gather_pid_metadata_from_argv(
|
||||
char *t;
|
||||
|
||||
/* We gather all metadata that were passed via argv[] into an array of iovecs that
|
||||
- * we'll forward to the socket unit */
|
||||
+ * 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. */
|
||||
|
||||
- if (argc < _META_ARGV_MAX)
|
||||
+ if (argc < _META_ARGV_REQUIRED)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
- "Not enough arguments passed by the kernel (%i, expected %i).",
|
||||
- argc, _META_ARGV_MAX);
|
||||
+ "Not enough arguments passed by the kernel (%i, expected between %i and %i).",
|
||||
+ argc, _META_ARGV_REQUIRED, _META_ARGV_MAX);
|
||||
|
||||
- for (int i = 0; i < _META_ARGV_MAX; i++) {
|
||||
+ for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) {
|
||||
|
||||
t = argv[i];
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index 1093cad8a9..0163131096 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -218,14 +218,18 @@ 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 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
|
||||
+# 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]
|
||||
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 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 "$$"
|
||||
+ /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
|
||||
coredumpctl info COREDUMP_HOSTNAME="mymachine"
|
||||
|
||||
# This used to cause a stack overflow
|
||||
158
SOURCES/1280-coredump-use-d-in-kernel-core-pattern.patch
Normal file
158
SOURCES/1280-coredump-use-d-in-kernel-core-pattern.patch
Normal file
@ -0,0 +1,158 @@
|
||||
From fbc5015c95298c71c806b5e80207e52688aad69a 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
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The kernel provides %d which is documented as
|
||||
"dump mode—same as value returned by prctl(2) PR_GET_DUMPABLE".
|
||||
|
||||
We already query /proc/pid/auxv for this information, but unfortunately this
|
||||
check is subject to a race, because the crashed process may be replaced by an
|
||||
attacker before we read this data, for example replacing a SUID process that
|
||||
was killed by a signal with another process that is not SUID, tricking us into
|
||||
making the coredump of the original process readable by the attacker.
|
||||
|
||||
With this patch, we effectively add one more check to the list of conditions
|
||||
that need be satisfied if we are to make the coredump accessible to the user.
|
||||
|
||||
Reportedy-by: Qualys Security Advisory <qsa@qualys.com>
|
||||
|
||||
In principle, %d might return a value other than 0, 1, or 2 in the future.
|
||||
Thus, we accept those, but emit a notice.
|
||||
|
||||
(cherry picked from commit 0c49e0049b7665bb7769a13ef346fef92e1ad4d6)
|
||||
|
||||
Related: RHEL-104138
|
||||
---
|
||||
man/systemd-coredump.xml | 10 ++++++++++
|
||||
src/coredump/coredump.c | 22 +++++++++++++++++++---
|
||||
sysctl.d/50-coredump.conf.in | 2 +-
|
||||
test/units/testsuite-74.coredump.sh | 5 +++++
|
||||
4 files changed, 35 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
|
||||
index cb9f47745b..6cfa04f466 100644
|
||||
--- a/man/systemd-coredump.xml
|
||||
+++ b/man/systemd-coredump.xml
|
||||
@@ -259,6 +259,16 @@ 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>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>COREDUMP_OPEN_FDS=</varname></term>
|
||||
|
||||
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||
index 458857ffb2..cd10678c43 100644
|
||||
--- a/src/coredump/coredump.c
|
||||
+++ b/src/coredump/coredump.c
|
||||
@@ -97,7 +97,9 @@ 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 */
|
||||
_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. */
|
||||
|
||||
@@ -126,6 +128,7 @@ 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=",
|
||||
@@ -138,6 +141,7 @@ typedef struct Context {
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
+ unsigned dumpable;
|
||||
bool is_pid1;
|
||||
bool is_journald;
|
||||
} Context;
|
||||
@@ -453,14 +457,16 @@ static int grant_user_access(int core_fd, const Context *context) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- /* We allow access if we got all the data and at_secure is not set and
|
||||
- * the uid/gid matches euid/egid. */
|
||||
+ /* We allow access if %d/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 == 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 (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)",
|
||||
+ log_debug("Will %s access (dumpable=%u 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;
|
||||
}
|
||||
@@ -1089,6 +1095,16 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||
return log_error_errno(r, "Failed to parse GID \"%s\": %m", context->meta[META_ARGV_GID]);
|
||||
|
||||
|
||||
+ /* 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 5fb551a8cf..9c10a89828 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=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h
|
||||
+kernel.core_pattern=|{{ROOTLIBEXECDIR}}/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
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index 0163131096..b72313672c 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -225,12 +225,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
|
||||
+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
|
||||
@ -0,0 +1,230 @@
|
||||
From e638eb667af0e8ac9d3d409edbbf51507a4eef0e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Sat, 9 Sep 2023 09:29:27 +0200
|
||||
Subject: [PATCH] pidref: add structure that can reference a pid via both pidfd
|
||||
and pid_t
|
||||
|
||||
Let's start with the conversion of PID 1 to pidfds. Let's add a simple
|
||||
structure with just two fields that can be used to maintain a reference
|
||||
to arbitrary processes via both pid_t and pidfd.
|
||||
|
||||
This is an embeddable struct, to keep it in line with where we
|
||||
previously used a pid_t directly to track a process.
|
||||
|
||||
Of course, since this might contain an fd on systems where we have pidfd
|
||||
this structure has a proper lifecycle.
|
||||
|
||||
(Note that this is quite different from sd_event_add_child() event
|
||||
source objects as that one is only for child processes and collects
|
||||
process results, while this infra is much simpler and more generic and
|
||||
can be used to reference any process, anywhere in the tree.)
|
||||
|
||||
(cherry picked from commit 3bda3f17fa84557eeb28fa7c330cbd3a3f876d47)
|
||||
|
||||
Related: RHEL-104138
|
||||
---
|
||||
src/basic/meson.build | 1 +
|
||||
src/basic/pidref.c | 145 ++++++++++++++++++++++++++++++++++++++++++
|
||||
src/basic/pidref.h | 29 +++++++++
|
||||
3 files changed, 175 insertions(+)
|
||||
create mode 100644 src/basic/pidref.c
|
||||
create mode 100644 src/basic/pidref.h
|
||||
|
||||
diff --git a/src/basic/meson.build b/src/basic/meson.build
|
||||
index 11053a5ecd..b8b4213c70 100644
|
||||
--- a/src/basic/meson.build
|
||||
+++ b/src/basic/meson.build
|
||||
@@ -182,6 +182,7 @@ basic_sources = files(
|
||||
'path-util.h',
|
||||
'percent-util.c',
|
||||
'percent-util.h',
|
||||
+ 'pidref.c',
|
||||
'prioq.c',
|
||||
'prioq.h',
|
||||
'proc-cmdline.c',
|
||||
diff --git a/src/basic/pidref.c b/src/basic/pidref.c
|
||||
new file mode 100644
|
||||
index 0000000000..f41460938c
|
||||
--- /dev/null
|
||||
+++ b/src/basic/pidref.c
|
||||
@@ -0,0 +1,145 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
+
|
||||
+#include "errno-util.h"
|
||||
+#include "fd-util.h"
|
||||
+#include "missing_syscall.h"
|
||||
+#include "parse-util.h"
|
||||
+#include "pidref.h"
|
||||
+#include "process-util.h"
|
||||
+
|
||||
+int pidref_set_pid(PidRef *pidref, pid_t pid) {
|
||||
+ int fd;
|
||||
+
|
||||
+ assert(pidref);
|
||||
+
|
||||
+ if (pid < 0)
|
||||
+ return -ESRCH;
|
||||
+ if (pid == 0)
|
||||
+ pid = getpid_cached();
|
||||
+
|
||||
+ fd = pidfd_open(pid, 0);
|
||||
+ if (fd < 0) {
|
||||
+ /* Graceful fallback in case the kernel doesn't support pidfds or is out of fds */
|
||||
+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno) && !ERRNO_IS_RESOURCE(errno))
|
||||
+ return -errno;
|
||||
+
|
||||
+ fd = -EBADF;
|
||||
+ }
|
||||
+
|
||||
+ *pidref = (PidRef) {
|
||||
+ .fd = fd,
|
||||
+ .pid = pid,
|
||||
+ };
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int pidref_set_pidstr(PidRef *pidref, const char *pid) {
|
||||
+ pid_t nr;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(pidref);
|
||||
+
|
||||
+ r = parse_pid(pid, &nr);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return pidref_set_pid(pidref, nr);
|
||||
+}
|
||||
+
|
||||
+int pidref_set_pidfd(PidRef *pidref, int fd) {
|
||||
+ int r;
|
||||
+
|
||||
+ assert(pidref);
|
||||
+
|
||||
+ if (fd < 0)
|
||||
+ return -EBADF;
|
||||
+
|
||||
+ int fd_copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
+ if (fd_copy < 0) {
|
||||
+ pid_t pid;
|
||||
+
|
||||
+ if (!ERRNO_IS_RESOURCE(errno))
|
||||
+ return -errno;
|
||||
+
|
||||
+ /* Graceful fallback if we are out of fds */
|
||||
+ r = pidfd_get_pid(fd, &pid);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ *pidref = (PidRef) {
|
||||
+ .fd = -EBADF,
|
||||
+ .pid = pid,
|
||||
+ };
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return pidref_set_pidfd_consume(pidref, fd_copy);
|
||||
+}
|
||||
+
|
||||
+int pidref_set_pidfd_take(PidRef *pidref, int fd) {
|
||||
+ pid_t pid;
|
||||
+ int r;
|
||||
+
|
||||
+ assert(pidref);
|
||||
+
|
||||
+ if (fd < 0)
|
||||
+ return -EBADF;
|
||||
+
|
||||
+ r = pidfd_get_pid(fd, &pid);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ *pidref = (PidRef) {
|
||||
+ .fd = fd,
|
||||
+ .pid = pid,
|
||||
+ };
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int pidref_set_pidfd_consume(PidRef *pidref, int fd) {
|
||||
+ int r;
|
||||
+
|
||||
+ r = pidref_set_pidfd_take(pidref, fd);
|
||||
+ if (r < 0)
|
||||
+ safe_close(fd);
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+void pidref_done(PidRef *pidref) {
|
||||
+ assert(pidref);
|
||||
+
|
||||
+ *pidref = (PidRef) {
|
||||
+ .fd = safe_close(pidref->fd),
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+int pidref_kill(PidRef *pidref, int sig) {
|
||||
+
|
||||
+ if (!pidref)
|
||||
+ return -ESRCH;
|
||||
+
|
||||
+ if (pidref->fd >= 0)
|
||||
+ return RET_NERRNO(pidfd_send_signal(pidref->fd, sig, NULL, 0));
|
||||
+
|
||||
+ if (pidref->pid > 0)
|
||||
+ return RET_NERRNO(kill(pidref->pid, sig));
|
||||
+
|
||||
+ return -ESRCH;
|
||||
+}
|
||||
+
|
||||
+int pidref_kill_and_sigcont(PidRef *pidref, int sig) {
|
||||
+ int r;
|
||||
+
|
||||
+ r = pidref_kill(pidref, sig);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (!IN_SET(sig, SIGCONT, SIGKILL))
|
||||
+ (void) pidref_kill(pidref, SIGCONT);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/src/basic/pidref.h b/src/basic/pidref.h
|
||||
new file mode 100644
|
||||
index 0000000000..2411e510f1
|
||||
--- /dev/null
|
||||
+++ b/src/basic/pidref.h
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
+#pragma once
|
||||
+
|
||||
+#include "macro.h"
|
||||
+
|
||||
+/* An embeddable structure carrying a reference to a process. Supposed to be used when tracking processes continously. */
|
||||
+typedef struct PidRef {
|
||||
+ pid_t pid; /* always valid */
|
||||
+ int fd; /* only valid if pidfd are available in the kernel, and we manage to get an fd */
|
||||
+} PidRef;
|
||||
+
|
||||
+#define PIDREF_NULL (PidRef) { .fd = -EBADF }
|
||||
+
|
||||
+static inline bool pidref_is_set(const PidRef *pidref) {
|
||||
+ return pidref && pidref->pid > 0;
|
||||
+}
|
||||
+
|
||||
+int pidref_set_pid(PidRef *pidref, pid_t pid);
|
||||
+int pidref_set_pidstr(PidRef *pidref, const char *pid);
|
||||
+int pidref_set_pidfd(PidRef *pidref, int fd);
|
||||
+int pidref_set_pidfd_take(PidRef *pidref, int fd); /* takes ownership of the passed pidfd on success*/
|
||||
+int pidref_set_pidfd_consume(PidRef *pidref, int fd); /* takes ownership of the passed pidfd in both success and failure */
|
||||
+
|
||||
+void pidref_done(PidRef *pidref);
|
||||
+
|
||||
+int pidref_kill(PidRef *pidref, int sig);
|
||||
+int pidref_kill_and_sigcont(PidRef *pidref, int sig);
|
||||
+
|
||||
+#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
|
||||
54
SOURCES/1282-fd-util-introduce-parse_fd.patch
Normal file
54
SOURCES/1282-fd-util-introduce-parse_fd.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 8219e46540ddf0d6a7d3f97481debf297723a58f Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Fri, 5 May 2023 08:09:14 +0200
|
||||
Subject: [PATCH] fd-util: introduce parse_fd()
|
||||
|
||||
It's a simple wrapper for safe_atoi() that returns error if the parsed
|
||||
fd is < 0 .
|
||||
|
||||
(cherry picked from commit b8f83d7f0c35dca6ca3a23c42215d566e2815ca5)
|
||||
|
||||
Related: RHEL-104138
|
||||
---
|
||||
src/basic/parse-util.c | 15 +++++++++++++++
|
||||
src/basic/parse-util.h | 1 +
|
||||
2 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
|
||||
index 3b3efb0ab8..4161211c49 100644
|
||||
--- a/src/basic/parse-util.c
|
||||
+++ b/src/basic/parse-util.c
|
||||
@@ -313,6 +313,21 @@ int parse_errno(const char *t) {
|
||||
return e;
|
||||
}
|
||||
|
||||
+int parse_fd(const char *t) {
|
||||
+ int r, fd;
|
||||
+
|
||||
+ assert(t);
|
||||
+
|
||||
+ r = safe_atoi(t, &fd);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (fd < 0)
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ return fd;
|
||||
+}
|
||||
+
|
||||
static const char *mangle_base(const char *s, unsigned *base) {
|
||||
const char *k;
|
||||
|
||||
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
|
||||
index 8d8d52327b..5c012d702a 100644
|
||||
--- a/src/basic/parse-util.h
|
||||
+++ b/src/basic/parse-util.h
|
||||
@@ -20,6 +20,7 @@ int parse_mtu(int family, const char *s, uint32_t *ret);
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size);
|
||||
int parse_range(const char *t, unsigned *lower, unsigned *upper);
|
||||
int parse_errno(const char *t);
|
||||
+int parse_fd(const char *t);
|
||||
|
||||
#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30)
|
||||
#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29)
|
||||
@ -0,0 +1,245 @@
|
||||
From 27faf1af778849841d7c3140bd3d92aceaea2ee3 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
|
||||
|
||||
A new core_pattern specifier was added, %F, to provide a PIDFD
|
||||
to the usermode helper process referring to the crashed process.
|
||||
This removes all possible race conditions, ensuring only the
|
||||
crashed process gets inspected by systemd-coredump.
|
||||
|
||||
(cherry picked from commit 868d95577ec9f862580ad365726515459be582fc)
|
||||
|
||||
Resolves: RHEL-104138
|
||||
---
|
||||
man/systemd-coredump.xml | 9 ++++
|
||||
src/coredump/coredump.c | 89 ++++++++++++++++++++++++++++++++----
|
||||
sysctl.d/50-coredump.conf.in | 2 +-
|
||||
3 files changed, 89 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml
|
||||
index 6cfa04f466..b3d81d838a 100644
|
||||
--- a/man/systemd-coredump.xml
|
||||
+++ b/man/systemd-coredump.xml
|
||||
@@ -186,6 +186,15 @@ 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>
|
||||
+ </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 cd10678c43..e0aac3c8d0 100644
|
||||
--- a/src/coredump/coredump.c
|
||||
+++ b/src/coredump/coredump.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "mkdir-label.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
+#include "pidref.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
@@ -98,8 +99,8 @@ 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 */
|
||||
_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. */
|
||||
|
||||
@@ -129,6 +130,7 @@ 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=",
|
||||
@@ -136,6 +138,7 @@ static const char * const meta_field_names[_META_MAX] = {
|
||||
};
|
||||
|
||||
typedef struct Context {
|
||||
+ PidRef pidref;
|
||||
const char *meta[_META_MAX];
|
||||
size_t meta_size[_META_MAX];
|
||||
pid_t pid;
|
||||
@@ -146,6 +149,14 @@ typedef struct Context {
|
||||
bool is_journald;
|
||||
} Context;
|
||||
|
||||
+#define CONTEXT_NULL \
|
||||
+ (Context) { \
|
||||
+ .pidref = PIDREF_NULL, \
|
||||
+ .uid = UID_INVALID, \
|
||||
+ .gid = GID_INVALID, \
|
||||
+ }
|
||||
+
|
||||
+
|
||||
typedef enum CoredumpStorage {
|
||||
COREDUMP_STORAGE_NONE,
|
||||
COREDUMP_STORAGE_EXTERNAL,
|
||||
@@ -171,6 +182,12 @@ static uint64_t arg_journal_size_max = JOURNAL_SIZE_MAX;
|
||||
static uint64_t arg_keep_free = UINT64_MAX;
|
||||
static uint64_t arg_max_use = UINT64_MAX;
|
||||
|
||||
+static void context_done(Context *c) {
|
||||
+ assert(c);
|
||||
+
|
||||
+ pidref_done(&c->pidref);
|
||||
+}
|
||||
+
|
||||
static int parse_config(void) {
|
||||
static const ConfigTableItem items[] = {
|
||||
{ "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
|
||||
@@ -1114,7 +1131,7 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||
|
||||
static int process_socket(int fd) {
|
||||
_cleanup_close_ int input_fd = -EBADF, mntns_fd = -EBADF;
|
||||
- Context context = {};
|
||||
+ _cleanup_(context_done) Context context = CONTEXT_NULL;
|
||||
struct iovec_wrapper iovw = {};
|
||||
struct iovec iovec;
|
||||
int iterations = 0, r;
|
||||
@@ -1215,7 +1232,7 @@ static int process_socket(int fd) {
|
||||
goto finish;
|
||||
|
||||
/* Make sure we received at least all fields we need. */
|
||||
- for (int i = 0; i < _META_MANDATORY_MAX; i++)
|
||||
+ for (int i = 0; i < _META_ARGV_REQUIRED; i++)
|
||||
if (!context.meta[i]) {
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"A mandatory argument (%i) has not been sent, aborting.",
|
||||
@@ -1301,9 +1318,9 @@ static int gather_pid_metadata_from_argv(
|
||||
Context *context,
|
||||
int argc, char **argv) {
|
||||
|
||||
+ _cleanup_(pidref_done) PidRef local_pidref = PIDREF_NULL;
|
||||
_cleanup_free_ char *free_timestamp = NULL;
|
||||
- int r, signo;
|
||||
- char *t;
|
||||
+ int r, signo, kernel_fd = -EBADF;
|
||||
|
||||
/* We gather all metadata that were passed via argv[] into an array of iovecs that
|
||||
* we'll forward to the socket unit.
|
||||
@@ -1317,8 +1334,7 @@ static int gather_pid_metadata_from_argv(
|
||||
argc, _META_ARGV_REQUIRED, _META_ARGV_MAX);
|
||||
|
||||
for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) {
|
||||
-
|
||||
- t = argv[i];
|
||||
+ const char *t = argv[i];
|
||||
|
||||
switch (i) {
|
||||
|
||||
@@ -1343,6 +1359,47 @@ static int gather_pid_metadata_from_argv(
|
||||
break;
|
||||
}
|
||||
|
||||
+ 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(getpid_cached(), 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;
|
||||
@@ -1350,7 +1407,19 @@ 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 */
|
||||
- return save_context(context, iovw);
|
||||
+ r = save_context(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;
|
||||
}
|
||||
|
||||
static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
|
||||
@@ -1466,7 +1535,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
|
||||
}
|
||||
|
||||
static int process_kernel(int argc, char* argv[]) {
|
||||
- Context context = {};
|
||||
+ _cleanup_(context_done) Context context = CONTEXT_NULL;
|
||||
struct iovec_wrapper *iovw;
|
||||
int r, mntns_fd = -EBADF;
|
||||
|
||||
@@ -1543,7 +1612,7 @@ static int process_kernel(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
static int process_backtrace(int argc, char *argv[]) {
|
||||
- Context context = {};
|
||||
+ _cleanup_(context_done) Context context = CONTEXT_NULL;
|
||||
struct iovec_wrapper *iovw;
|
||||
char *message;
|
||||
int r;
|
||||
diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in
|
||||
index 9c10a89828..1c6230ad93 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=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d
|
||||
+kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d %F
|
||||
|
||||
# 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
|
||||
@ -0,0 +1,131 @@
|
||||
From 69c124810e3b4bc4b7aa441cfed65d3d7594d443 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-118215
|
||||
---
|
||||
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 2eadca4f1a..4b0266bc68 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -392,7 +392,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 we know the last time this was
|
||||
* triggered, schedule the job based relative
|
||||
@@ -403,21 +404,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;
|
||||
85
SOURCES/1285-strv-introduce-string_strv_hashmap_remove.patch
Normal file
85
SOURCES/1285-strv-introduce-string_strv_hashmap_remove.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From e16ede11dab405749b776aa6d58a9c7461a0dda5 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-14112
|
||||
---
|
||||
src/basic/strv.c | 17 +++++++++++++++++
|
||||
src/basic/strv.h | 5 +++++
|
||||
src/test/test-hashmap-plain.c | 16 ++++++++++++++++
|
||||
3 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/src/basic/strv.c b/src/basic/strv.c
|
||||
index 66b70befd6..1f5d6f058f 100644
|
||||
--- a/src/basic/strv.c
|
||||
+++ b/src/basic/strv.c
|
||||
@@ -920,6 +920,23 @@ int fputstrv(FILE *f, char * const *l, const char *separator, bool *space) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+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 6c9fa47943..9eb685fb86 100644
|
||||
--- a/src/basic/strv.h
|
||||
+++ b/src/basic/strv.h
|
||||
@@ -261,6 +261,11 @@ int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
|
||||
free_and_replace_full(a, b, strv_free)
|
||||
|
||||
extern const struct hash_ops string_strv_hash_ops;
|
||||
+
|
||||
+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 36a775012b..3bc96fc944 100644
|
||||
--- a/src/test/test-hashmap-plain.c
|
||||
+++ b/src/test/test-hashmap-plain.c
|
||||
@@ -996,6 +996,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));
|
||||
}
|
||||
|
||||
/* Signal to test-hashmap.c that tests from this compilation unit were run. */
|
||||
@ -0,0 +1,230 @@
|
||||
From fe5bad818a26875914f3b0c59fa3d4f5e6b3a41d 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-14112
|
||||
|
||||
[msekleta: I've backported strv_equal_ignore_order() in the same commit
|
||||
in order to get this to compile.]
|
||||
---
|
||||
src/basic/strv.c | 20 ++++++++++
|
||||
src/basic/strv.h | 1 +
|
||||
src/basic/unit-file.c | 35 +++++++++++++++++
|
||||
src/basic/unit-file.h | 8 ++++
|
||||
src/test/test-unit-file.c | 81 +++++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 145 insertions(+)
|
||||
|
||||
diff --git a/src/basic/strv.c b/src/basic/strv.c
|
||||
index 1f5d6f058f..47cc6931c1 100644
|
||||
--- a/src/basic/strv.c
|
||||
+++ b/src/basic/strv.c
|
||||
@@ -775,6 +775,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(char * const *l) {
|
||||
STRV_FOREACH(s, l)
|
||||
puts(*s);
|
||||
diff --git a/src/basic/strv.h b/src/basic/strv.h
|
||||
index 9eb685fb86..1de3c98e5c 100644
|
||||
--- a/src/basic/strv.h
|
||||
+++ b/src/basic/strv.h
|
||||
@@ -160,6 +160,7 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
|
||||
_STRV_FOREACH_PAIR(x, y, l, UNIQ_T(i, UNIQ))
|
||||
|
||||
char** strv_sort(char **l);
|
||||
+bool strv_equal_ignore_order(char **a, char **b);
|
||||
void strv_print(char * const *l);
|
||||
|
||||
#define strv_from_stdarg_alloca(first) \
|
||||
diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c
|
||||
index c81c69db30..d7d7fd70f6 100644
|
||||
--- a/src/basic/unit-file.c
|
||||
+++ b/src/basic/unit-file.c
|
||||
@@ -627,6 +627,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/basic/unit-file.h b/src/basic/unit-file.h
|
||||
index 1c43861f00..78f65dbc8e 100644
|
||||
--- a/src/basic/unit-file.h
|
||||
+++ b/src/basic/unit-file.h
|
||||
@@ -52,6 +52,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 dffa2822e6..389113c336 100644
|
||||
--- a/src/test/test-unit-file.c
|
||||
+++ b/src/test/test-unit-file.c
|
||||
@@ -1,10 +1,15 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
+#include "fileio.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) {
|
||||
@@ -85,6 +90,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_se(unit_file_build_name_map(lp, NULL, &unit_ids, &unit_names, &path_cache) > 0);
|
||||
+
|
||||
+ _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_se(unit_file_build_name_map(lp, &cache_timestamp_hash, &unit_ids, &unit_names, &path_cache) > 0);
|
||||
+
|
||||
+ 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_se(unlink(path) >= 0);
|
||||
+
|
||||
+ 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_se(unit_file_build_name_map(lp, NULL, &unit_ids_2, &unit_names_2, &path_cache_2) > 0);
|
||||
+
|
||||
+ 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_free) LookupPaths lp = {};
|
||||
+ ASSERT_OK(lookup_paths_init(&lp, LOOKUP_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_se(streq_ptr(runlevel_to_target(NULL), NULL));
|
||||
@ -0,0 +1,52 @@
|
||||
From 4726233b421628eae405b3b3fb08222cf0befae4 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-14112
|
||||
---
|
||||
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 9e349402ff..afe3fdab04 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -598,13 +598,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;
|
||||
|
||||
@@ -621,6 +619,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_requires_mounts_for(Unit *u) {
|
||||
@ -0,0 +1,33 @@
|
||||
From 1aa6c0d3bcac98d3442d07412f4296d5b9b18dc0 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-14112
|
||||
---
|
||||
test/units/testsuite-07.transient.sh | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
create mode 100755 test/units/testsuite-07.transient.sh
|
||||
|
||||
diff --git a/test/units/testsuite-07.transient.sh b/test/units/testsuite-07.transient.sh
|
||||
new file mode 100755
|
||||
index 0000000000..ae71a38143
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-07.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)" ]]
|
||||
@ -0,0 +1,34 @@
|
||||
From 2fe492a2f0fefa0f782cb04a248fc9dcd5667bf0 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-103801
|
||||
---
|
||||
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 e0aac3c8d0..28dabf017b 100644
|
||||
--- a/src/coredump/coredump.c
|
||||
+++ b/src/coredump/coredump.c
|
||||
@@ -1273,7 +1273,7 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, int mntns_
|
||||
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
|
||||
@ -0,0 +1,32 @@
|
||||
From 2a16be65ca89cf18adf63a99ae1b1748e63d6773 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-109558
|
||||
---
|
||||
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 08f505a271..2d5050eaca 100755
|
||||
--- a/src/ukify/ukify.py
|
||||
+++ b/src/ukify/ukify.py
|
||||
@@ -986,7 +986,7 @@ def inspect_section(opts, 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)'
|
||||
143
SOURCES/1291-timer-rebase-last_trigger-timestamp-if-needed.patch
Normal file
143
SOURCES/1291-timer-rebase-last_trigger-timestamp-if-needed.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From 6085358791b712a60fb22c7870abf0aa75c5f157 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-118215
|
||||
---
|
||||
src/core/timer.c | 15 +++--
|
||||
...tsuite-53.RandomizedDelaySec-persistent.sh | 67 +++++++++++++++++++
|
||||
2 files changed, 78 insertions(+), 4 deletions(-)
|
||||
create mode 100755 test/units/testsuite-53.RandomizedDelaySec-persistent.sh
|
||||
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 4b0266bc68..8fb79bc0cb 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -394,15 +394,23 @@ 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 we know the last time this was
|
||||
* triggered, schedule the job based relative
|
||||
* to that. If we don't, just start from
|
||||
* the activation time. */
|
||||
|
||||
- if (dual_timestamp_is_set(&t->last_trigger))
|
||||
+ 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;
|
||||
@@ -418,8 +426,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/testsuite-53.RandomizedDelaySec-persistent.sh b/test/units/testsuite-53.RandomizedDelaySec-persistent.sh
|
||||
new file mode 100755
|
||||
index 0000000000..af22daecc7
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-53.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
|
||||
@ -0,0 +1,130 @@
|
||||
From 01826a6ded513adea1dabeccc6b860baee277482 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Thu, 30 May 2024 10:44:36 +0200
|
||||
Subject: [PATCH] cryptsetup-generator: refactor add_crypttab_devices()
|
||||
|
||||
Move the processing of a crypttab entry to a separate function.
|
||||
|
||||
No functional changes, just refactoring.
|
||||
|
||||
(cherry picked from commit a07cb7d404582f9c0bfaedb9dd07f93848aa91c6)
|
||||
|
||||
Related: RHEL-127859
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 87 +++++++++++++++------------
|
||||
1 file changed, 49 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 9e8e7e746f..6ab3b85b6b 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -779,6 +779,52 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int add_crypttab_device(const char *name, const char *device, const char *keyspec, const char *options) {
|
||||
+ _cleanup_free_ char *keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL;
|
||||
+ crypto_device *d = NULL;
|
||||
+ char *uuid;
|
||||
+ int r;
|
||||
+
|
||||
+ uuid = startswith(device, "UUID=");
|
||||
+ if (!uuid)
|
||||
+ uuid = path_startswith(device, "/dev/disk/by-uuid/");
|
||||
+ if (!uuid)
|
||||
+ uuid = startswith(name, "luks-");
|
||||
+ if (uuid)
|
||||
+ d = hashmap_get(arg_disks, uuid);
|
||||
+
|
||||
+ if (arg_allow_list && !d) {
|
||||
+ log_info("Not creating device '%s' because it was not specified on the kernel command line.", name);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ r = split_locationspec(keyspec, &keyfile, &keydev);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (options && (!d || !d->options)) {
|
||||
+ r = filter_header_device(options, &headerdev, &filtered_header);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ options = filtered_header;
|
||||
+ }
|
||||
+
|
||||
+ r = create_disk(name,
|
||||
+ device,
|
||||
+ keyfile,
|
||||
+ keydev,
|
||||
+ (d && d->options) ? d->headerdev : headerdev,
|
||||
+ (d && d->options) ? d->options : options,
|
||||
+ arg_crypttab);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ if (d)
|
||||
+ d->create = false;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int add_crypttab_devices(void) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
unsigned crypttab_line = 0;
|
||||
@@ -795,10 +841,8 @@ static int add_crypttab_devices(void) {
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
- _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL,
|
||||
- *keyfile = NULL, *keydev = NULL, *headerdev = NULL, *filtered_header = NULL;
|
||||
- crypto_device *d = NULL;
|
||||
- char *l, *uuid;
|
||||
+ _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL;
|
||||
+ char *l;
|
||||
int k;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
@@ -819,42 +863,9 @@ static int add_crypttab_devices(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
- uuid = startswith(device, "UUID=");
|
||||
- if (!uuid)
|
||||
- uuid = path_startswith(device, "/dev/disk/by-uuid/");
|
||||
- if (!uuid)
|
||||
- uuid = startswith(name, "luks-");
|
||||
- if (uuid)
|
||||
- d = hashmap_get(arg_disks, uuid);
|
||||
-
|
||||
- if (arg_allow_list && !d) {
|
||||
- log_info("Not creating device '%s' because it was not specified on the kernel command line.", name);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- r = split_locationspec(keyspec, &keyfile, &keydev);
|
||||
+ r = add_crypttab_device(name, device, keyspec, options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
-
|
||||
- if (options && (!d || !d->options)) {
|
||||
- r = filter_header_device(options, &headerdev, &filtered_header);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- free_and_replace(options, filtered_header);
|
||||
- }
|
||||
-
|
||||
- r = create_disk(name,
|
||||
- device,
|
||||
- keyfile,
|
||||
- keydev,
|
||||
- (d && d->options) ? d->headerdev : headerdev,
|
||||
- (d && d->options) ? d->options : options,
|
||||
- arg_crypttab);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- if (d)
|
||||
- d->create = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -0,0 +1,43 @@
|
||||
From 238dadc16fb2bb6ad2fef5602dac5cd2c9aa31ed Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Thu, 30 May 2024 10:46:13 +0200
|
||||
Subject: [PATCH] cryptsetup-generator: continue parsing after error
|
||||
|
||||
Let's make the crypttab parser more robust and continue even if parsing
|
||||
of a line failed.
|
||||
|
||||
(cherry picked from commit 83813bae7ae471862ff84b038b5e4eaefae41c98)
|
||||
|
||||
Resolves: RHEL-127859
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 6ab3b85b6b..924a403ee5 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -828,7 +828,7 @@ static int add_crypttab_device(const char *name, const char *device, const char
|
||||
static int add_crypttab_devices(void) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
unsigned crypttab_line = 0;
|
||||
- int r;
|
||||
+ int r, ret = 0;
|
||||
|
||||
if (!arg_read_crypttab)
|
||||
return 0;
|
||||
@@ -863,12 +863,10 @@ static int add_crypttab_devices(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
- r = add_crypttab_device(name, device, keyspec, options);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ RET_GATHER(ret, add_crypttab_device(name, device, keyspec, options));
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static int add_proc_cmdline_devices(void) {
|
||||
@ -0,0 +1,39 @@
|
||||
From 25a4e8e1d411f56fcee5b53d1620c42f3bba16e6 Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Thu, 30 May 2024 13:32:20 +0200
|
||||
Subject: [PATCH] cryptsetup-generator: parse all cmdline devices too
|
||||
|
||||
(cherry picked from commit 47c703d949e84997d11d657fade68064c04a46c8)
|
||||
|
||||
Related: RHEL-127859
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 924a403ee5..1136f5aed7 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -870,7 +870,7 @@ static int add_crypttab_devices(void) {
|
||||
}
|
||||
|
||||
static int add_proc_cmdline_devices(void) {
|
||||
- int r;
|
||||
+ int r, ret = 0;
|
||||
crypto_device *d;
|
||||
|
||||
HASHMAP_FOREACH(d, arg_disks) {
|
||||
@@ -896,11 +896,10 @@ static int add_proc_cmdline_devices(void) {
|
||||
d->headerdev,
|
||||
d->options ?: arg_default_options,
|
||||
"/proc/cmdline");
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ RET_GATHER(ret, r);
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(crypt_device_hash_ops, char, string_hash_func, string_compare_func,
|
||||
@ -0,0 +1,33 @@
|
||||
From 1ba4f74ed15a3b715eba0f21a12239af6e44146f Mon Sep 17 00:00:00 2001
|
||||
From: David Tardon <dtardon@redhat.com>
|
||||
Date: Thu, 30 May 2024 13:33:57 +0200
|
||||
Subject: [PATCH] cryptsetup-generator: always process cmdline devices
|
||||
|
||||
(cherry picked from commit d181939e2e382631d9b067e0b4cfbf11b709a297)
|
||||
|
||||
Related: RHEL-127859
|
||||
---
|
||||
src/cryptsetup/cryptsetup-generator.c | 9 ++-------
|
||||
1 file changed, 2 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
|
||||
index 1136f5aed7..06292f7f73 100644
|
||||
--- a/src/cryptsetup/cryptsetup-generator.c
|
||||
+++ b/src/cryptsetup/cryptsetup-generator.c
|
||||
@@ -925,14 +925,9 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
|
||||
return 0;
|
||||
|
||||
r = add_crypttab_devices();
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- r = add_proc_cmdline_devices();
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
+ RET_GATHER(r, add_proc_cmdline_devices());
|
||||
|
||||
- return 0;
|
||||
+ return r;
|
||||
}
|
||||
|
||||
DEFINE_MAIN_GENERATOR_FUNCTION(run);
|
||||
44
SOURCES/1296-logind-add-background-light-session-class.patch
Normal file
44
SOURCES/1296-logind-add-background-light-session-class.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From a48488d06e60af0d02387488d4de0abbaddf93ad Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 27 Nov 2023 18:39:02 +0100
|
||||
Subject: [PATCH] logind: add "background-light" session class
|
||||
|
||||
This is the same as the "background" class, but does *not* pull in a
|
||||
service manager. It might be useful for things like select cron jobs
|
||||
that do not intend to call per-user IPC calls.
|
||||
|
||||
Replaces: #23569
|
||||
Fixes: #23978
|
||||
|
||||
(cherry picked from commit b5100c736f1fce2b6b22c07cf2725e4ec3764a75)
|
||||
|
||||
Related: RHEL-109833
|
||||
---
|
||||
src/login/logind-session.c | 1 +
|
||||
src/login/logind-session.h | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
|
||||
index 8c8dd0d43e..5ba1e690ac 100644
|
||||
--- a/src/login/logind-session.c
|
||||
+++ b/src/login/logind-session.c
|
||||
@@ -1525,6 +1525,7 @@ static const char* const session_class_table[_SESSION_CLASS_MAX] = {
|
||||
[SESSION_GREETER] = "greeter",
|
||||
[SESSION_LOCK_SCREEN] = "lock-screen",
|
||||
[SESSION_BACKGROUND] = "background",
|
||||
+ [SESSION_BACKGROUND_LIGHT] = "background-light",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
|
||||
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
|
||||
index 5ee059aa4f..a02d72c211 100644
|
||||
--- a/src/login/logind-session.h
|
||||
+++ b/src/login/logind-session.h
|
||||
@@ -23,6 +23,7 @@ typedef enum SessionClass {
|
||||
SESSION_GREETER,
|
||||
SESSION_LOCK_SCREEN,
|
||||
SESSION_BACKGROUND,
|
||||
+ SESSION_BACKGROUND_LIGHT, /* Like SESSION_BACKGROUND, but without the service manager */
|
||||
_SESSION_CLASS_MAX,
|
||||
_SESSION_CLASS_INVALID = -EINVAL,
|
||||
} SessionClass;
|
||||
@ -0,0 +1,118 @@
|
||||
From d5d08290cf66a0c491a875345902d5c3bfeb6c5a 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-109833
|
||||
|
||||
[msekleta: this is absolutely minimal version of the ideas implemented in
|
||||
https://github.com/systemd/systemd/pull/30884. At this point I want to avoid
|
||||
big/risky backports and what I am proposing here should suffice.]
|
||||
---
|
||||
man/pam_systemd.xml | 11 ++++++++++-
|
||||
src/login/logind-session.c | 5 +++--
|
||||
src/login/logind-user.c | 16 +++++++++++++++-
|
||||
src/login/pam_systemd.c | 6 ++++--
|
||||
4 files changed, 32 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml
|
||||
index 60b8577822..55239ea3d7 100644
|
||||
--- a/man/pam_systemd.xml
|
||||
+++ b/man/pam_systemd.xml
|
||||
@@ -95,8 +95,17 @@
|
||||
<literal>lock-screen</literal> or <literal>background</literal>. See
|
||||
<citerefentry><refentrytitle>sd_session_get_class</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
|
||||
details about the session class.</para></listitem>
|
||||
- </varlistentry>
|
||||
|
||||
+ <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.</para>
|
||||
+ </varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>type=</varname></term>
|
||||
|
||||
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
|
||||
index 5ba1e690ac..2ad05e3798 100644
|
||||
--- a/src/login/logind-session.c
|
||||
+++ b/src/login/logind-session.c
|
||||
@@ -680,8 +680,9 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
|
||||
s->user->slice,
|
||||
description,
|
||||
/* These two have StopWhenUnneeded= set, hence add a dep towards them */
|
||||
- STRV_MAKE(s->user->runtime_dir_service,
|
||||
- s->user->service),
|
||||
+ s->class == SESSION_BACKGROUND_LIGHT ?
|
||||
+ STRV_MAKE(s->user->runtime_dir_service) :
|
||||
+ STRV_MAKE(s->user->runtime_dir_service, s->user->service),
|
||||
after,
|
||||
user_record_home_directory(s->user->user_record),
|
||||
properties,
|
||||
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
|
||||
index e02ad754ee..ffa32c6ce5 100644
|
||||
--- a/src/login/logind-user.c
|
||||
+++ b/src/login/logind-user.c
|
||||
@@ -441,6 +441,19 @@ static int user_update_slice(User *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static bool user_wants_service_manager(User *u) {
|
||||
+ assert(u);
|
||||
+
|
||||
+ LIST_FOREACH(sessions_by_user, s, u->sessions)
|
||||
+ if (s->class != SESSION_BACKGROUND_LIGHT)
|
||||
+ return true;
|
||||
+
|
||||
+ if (user_check_linger_file(u) > 0)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
int user_start(User *u) {
|
||||
assert(u);
|
||||
|
||||
@@ -464,7 +477,8 @@ int user_start(User *u) {
|
||||
(void) user_update_slice(u);
|
||||
|
||||
/* Start user@UID.service */
|
||||
- user_start_service(u);
|
||||
+ if (user_wants_service_manager(u))
|
||||
+ user_start_service(u);
|
||||
|
||||
if (!u->started) {
|
||||
if (!dual_timestamp_is_set(&u->timestamp))
|
||||
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
|
||||
index a288b3602a..c7377e21a8 100644
|
||||
--- a/src/login/pam_systemd.c
|
||||
+++ b/src/login/pam_systemd.c
|
||||
@@ -753,14 +753,16 @@ _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(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
|
||||
36
SOURCES/1298-core-fix-array-size-in-unit_log_resources.patch
Normal file
36
SOURCES/1298-core-fix-array-size-in-unit_log_resources.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 52defa44074113197a8caade1254a61cfdcfa363 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Schmaus <flo@geekplace.eu>
|
||||
Date: Thu, 9 Nov 2023 08:59:59 +0100
|
||||
Subject: [PATCH] core: fix array size in unit_log_resources()
|
||||
|
||||
In 0531bded79dc ("core: include peak memory in unit_log_resources()") new log
|
||||
messages where added, however the size of the according arrays to hold the
|
||||
messages was not adjusted.
|
||||
|
||||
Fixes: 0531bded79dc ("core: include peak memory in unit_log_resources()")
|
||||
(cherry picked from commit 893028523469b3ec459388428ddc466942cdaf4d)
|
||||
|
||||
Resolves: RHEL-131338
|
||||
---
|
||||
src/core/unit.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index afe3fdab04..009f416280 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -2242,12 +2242,12 @@ static int raise_level(int log_level, bool condition_info, bool condition_notice
|
||||
}
|
||||
|
||||
static int unit_log_resources(Unit *u) {
|
||||
- struct iovec iovec[1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + _CGROUP_IO_ACCOUNTING_METRIC_MAX + 4];
|
||||
+ struct iovec iovec[1 + 1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + _CGROUP_IO_ACCOUNTING_METRIC_MAX + 4];
|
||||
bool any_traffic = false, have_ip_accounting = false, any_io = false, have_io_accounting = false;
|
||||
_cleanup_free_ char *igress = NULL, *egress = NULL, *rr = NULL, *wr = NULL;
|
||||
int log_level = LOG_DEBUG; /* May be raised if resources consumed over a threshold */
|
||||
size_t n_message_parts = 0, n_iovec = 0;
|
||||
- char* message_parts[1 + 2 + 2 + 1], *t;
|
||||
+ char* message_parts[1 + 1 + 2 + 2 + 1], *t;
|
||||
nsec_t nsec = NSEC_INFINITY;
|
||||
uint64_t memory_peak = UINT64_MAX;
|
||||
int r;
|
||||
@ -0,0 +1,63 @@
|
||||
From 8e0da3f5c5518350215a7186dfa748207ba921e8 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Mon, 5 Dec 2022 21:05:54 +0000
|
||||
Subject: [PATCH] pid1: add env var to override default mount rate limit burst
|
||||
|
||||
I am hitting the rate limit on a busy system with low resources, and
|
||||
it stalls the boot process which is Very Bad (TM).
|
||||
|
||||
(cherry picked from commit 24a4542cfa674ee80b54afcc223f2490a011966b)
|
||||
|
||||
Related: RHEL-129153
|
||||
---
|
||||
docs/ENVIRONMENT.md | 7 +++++++
|
||||
src/core/mount.c | 11 ++++++++++-
|
||||
2 files changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
|
||||
index 54b779d312..88e6f5b372 100644
|
||||
--- a/docs/ENVIRONMENT.md
|
||||
+++ b/docs/ENVIRONMENT.md
|
||||
@@ -281,6 +281,13 @@ All tools:
|
||||
type as unsupported may not prevent loading some units of that type if they
|
||||
are referenced by other units of another supported type.
|
||||
|
||||
+* `$SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST` — can be set to override the mount
|
||||
+ units burst rate limit for parsing `/proc/self/mountinfo`. On a system with
|
||||
+ few resources but many mounts the rate limit may be hit, which will cause the
|
||||
+ processing of mount units to stall. The burst limit may be adjusted when the
|
||||
+ default is not appropriate for a given system. Defaults to `5`, accepts
|
||||
+ positive integers.
|
||||
+
|
||||
`systemd-remount-fs`:
|
||||
|
||||
* `$SYSTEMD_REMOUNT_ROOT_RW=1` — if set and no entry for the root directory
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index 79772fb6f1..a8e101aa64 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1910,6 +1910,7 @@ static void mount_enumerate(Manager *m) {
|
||||
mnt_init_debug(0);
|
||||
|
||||
if (!m->mount_monitor) {
|
||||
+ unsigned mount_rate_limit_burst = 5;
|
||||
int fd;
|
||||
|
||||
m->mount_monitor = mnt_new_monitor();
|
||||
@@ -1949,7 +1950,15 @@ static void mount_enumerate(Manager *m) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, 5);
|
||||
+ /* Let users override the default (5 in 1s), as it stalls the boot sequence on busy systems. */
|
||||
+ const char *e = secure_getenv("SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST");
|
||||
+ if (e) {
|
||||
+ r = safe_atou(e, &mount_rate_limit_burst);
|
||||
+ if (r < 0)
|
||||
+ log_debug("Invalid value in $SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST, ignoring: %s", e);
|
||||
+ }
|
||||
+
|
||||
+ r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, mount_rate_limit_burst);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to enable rate limit for mount events: %m");
|
||||
goto fail;
|
||||
@ -0,0 +1,75 @@
|
||||
From 4f880e4dfc1b2e25046be380182535c39a931109 Mon Sep 17 00:00:00 2001
|
||||
From: xujing <xujing125@huawei.com>
|
||||
Date: Wed, 16 Oct 2024 15:19:09 +0800
|
||||
Subject: [PATCH] pid1: add env var to override default mount rate limit
|
||||
interval
|
||||
|
||||
Similar to 24a4542c. 24a4542c can only be set 1 in 1s at most,
|
||||
sometimes we may need to set to something else(such as 1 in 2s).
|
||||
So it's best to let the user decide.
|
||||
|
||||
This also allows users to solve #34690.
|
||||
|
||||
(cherry picked from commit cc2030f928981947db8fb9ec185a82024abab2c4)
|
||||
|
||||
Related: RHEL-129153
|
||||
---
|
||||
docs/ENVIRONMENT.md | 7 +++++++
|
||||
src/core/mount.c | 14 +++++++++++---
|
||||
2 files changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
|
||||
index 88e6f5b372..711364a2f7 100644
|
||||
--- a/docs/ENVIRONMENT.md
|
||||
+++ b/docs/ENVIRONMENT.md
|
||||
@@ -288,6 +288,13 @@ All tools:
|
||||
default is not appropriate for a given system. Defaults to `5`, accepts
|
||||
positive integers.
|
||||
|
||||
+* `$SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_INTERVAL_SEC` — can be set to override the mount
|
||||
+ units interval rate limit for parsing `/proc/self/mountinfo`. Similar to
|
||||
+ `$SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST`, the interval limit maybe adjusted when
|
||||
+ the default is not appropriate for a given system. The default value is 1 and the
|
||||
+ default application time unit is second, and the time unit can beoverriden as usual
|
||||
+ by specifying it explicitly, see the systemd.time(7) man page.
|
||||
+
|
||||
`systemd-remount-fs`:
|
||||
|
||||
* `$SYSTEMD_REMOUNT_ROOT_RW=1` — if set and no entry for the root directory
|
||||
diff --git a/src/core/mount.c b/src/core/mount.c
|
||||
index a8e101aa64..be6fbf4cc4 100644
|
||||
--- a/src/core/mount.c
|
||||
+++ b/src/core/mount.c
|
||||
@@ -1910,6 +1910,7 @@ static void mount_enumerate(Manager *m) {
|
||||
mnt_init_debug(0);
|
||||
|
||||
if (!m->mount_monitor) {
|
||||
+ usec_t mount_rate_limit_interval = 1 * USEC_PER_SEC;
|
||||
unsigned mount_rate_limit_burst = 5;
|
||||
int fd;
|
||||
|
||||
@@ -1951,14 +1952,21 @@ static void mount_enumerate(Manager *m) {
|
||||
}
|
||||
|
||||
/* Let users override the default (5 in 1s), as it stalls the boot sequence on busy systems. */
|
||||
- const char *e = secure_getenv("SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST");
|
||||
+ const char *e = secure_getenv("SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_INTERVAL_SEC");
|
||||
+ if (e) {
|
||||
+ r = parse_sec(e, &mount_rate_limit_interval);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Invalid value in $SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_INTERVAL_SEC, ignoring: %s", e);
|
||||
+ }
|
||||
+
|
||||
+ e = secure_getenv("SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST");
|
||||
if (e) {
|
||||
r = safe_atou(e, &mount_rate_limit_burst);
|
||||
if (r < 0)
|
||||
- log_debug("Invalid value in $SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST, ignoring: %s", e);
|
||||
+ log_debug_errno(r, "Invalid value in $SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST, ignoring: %s", e);
|
||||
}
|
||||
|
||||
- r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, mount_rate_limit_burst);
|
||||
+ r = sd_event_source_set_ratelimit(m->mount_event_source, mount_rate_limit_interval, mount_rate_limit_burst);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to enable rate limit for mount events: %m");
|
||||
goto fail;
|
||||
28
SOURCES/1301-core-service-fix-error-cause-in-the-log.patch
Normal file
28
SOURCES/1301-core-service-fix-error-cause-in-the-log.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From de696eb8fc5caf5d5ad0a314fa21f8ca78bf8071 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Tue, 9 May 2023 00:21:20 +0900
|
||||
Subject: [PATCH] core/service: fix error cause in the log
|
||||
|
||||
Fixes a bug caused by a5648b809457d120500b2acb18b31e2168a4817a.
|
||||
Fixes #27575.
|
||||
|
||||
(cherry picked from commit f86a388de339bc9fd3bc90df7de0d9693b52369f)
|
||||
|
||||
Resolves: RHEL-138414
|
||||
---
|
||||
src/core/service.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 305f3b7170..9c938aee91 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -989,7 +989,7 @@ static int service_load_pid_file(Service *s, bool may_warn) {
|
||||
r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd);
|
||||
}
|
||||
if (r < 0)
|
||||
- return log_unit_full_errno(UNIT(s), prio, fd,
|
||||
+ return log_unit_full_errno(UNIT(s), prio, r,
|
||||
"Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state));
|
||||
|
||||
/* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd
|
||||
@ -0,0 +1,45 @@
|
||||
From 7640cebb70cc13ada4f0b6e3e26b7973be6d1b23 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Fri, 26 Jan 2024 00:47:23 +0800
|
||||
Subject: [PATCH] fstab-generator: drop assertions for mount opts
|
||||
|
||||
fstab_filter_options accepts NULL and (with later changes)
|
||||
might even return NULL.
|
||||
|
||||
(cherry picked from commit c521ce42b43ad542a8e3c6e5e83ceb653ca6a71e)
|
||||
|
||||
Related: RHEL-92752
|
||||
---
|
||||
src/fstab-generator/fstab-generator.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
|
||||
index b9606a5341..fe0283b4e7 100644
|
||||
--- a/src/fstab-generator/fstab-generator.c
|
||||
+++ b/src/fstab-generator/fstab-generator.c
|
||||
@@ -486,7 +486,6 @@ static int add_mount(
|
||||
|
||||
assert(what);
|
||||
assert(where);
|
||||
- assert(opts);
|
||||
assert(target_unit);
|
||||
assert(source);
|
||||
|
||||
@@ -797,6 +796,9 @@ static int add_sysusr_sysroot_usr_bind_mount(const char *source) {
|
||||
static MountPointFlags fstab_options_to_flags(const char *options, bool is_swap) {
|
||||
MountPointFlags flags = 0;
|
||||
|
||||
+ if (isempty(options))
|
||||
+ return 0;
|
||||
+
|
||||
if (fstab_test_option(options, "x-systemd.makefs\0"))
|
||||
flags |= MOUNT_MAKEFS;
|
||||
if (fstab_test_option(options, "x-systemd.growfs\0"))
|
||||
@@ -872,7 +874,6 @@ static int parse_fstab_one(
|
||||
|
||||
assert(what_original);
|
||||
assert(fstype);
|
||||
- assert(options);
|
||||
|
||||
if (prefix_sysroot && !mount_in_initrd(where_original, options, accept_root))
|
||||
return 0;
|
||||
@ -0,0 +1,114 @@
|
||||
From 0a4f0be757c73e3320d1c611de9845f7713b10d0 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-92752
|
||||
---
|
||||
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 fe0283b4e7..28677a2f39 100644
|
||||
--- a/src/fstab-generator/fstab-generator.c
|
||||
+++ b/src/fstab-generator/fstab-generator.c
|
||||
@@ -105,15 +105,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)
|
||||
@@ -122,19 +122,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;
|
||||
|
||||
@@ -164,7 +151,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) {
|
||||
@@ -182,7 +169,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=//foobar
|
||||
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
|
||||
57
SOURCES/1304-core-reorder-systemd-arguments-on-reexec.patch
Normal file
57
SOURCES/1304-core-reorder-systemd-arguments-on-reexec.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From 88dfaa167328461ac18e8e764c97e19632b34161 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Thu, 29 Jun 2023 13:31:19 +0200
|
||||
Subject: [PATCH] core: reorder systemd arguments on reexec
|
||||
|
||||
When reexecuting system let's put our arguments carrying deserialization
|
||||
info first followed by any existing arguments to make sure they get
|
||||
parsed in case we get weird stuff from the kernel cmdline (like --).
|
||||
|
||||
See: https://github.com/systemd/systemd/issues/28184
|
||||
(cherry picked from commit 06afda6b38d5d730fca3c65449096425933272bc)
|
||||
|
||||
Resolves: RHEL-111135
|
||||
---
|
||||
src/core/main.c | 6 +++++-
|
||||
test/TEST-01-BASIC/test.sh | 5 +++++
|
||||
2 files changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index f230270340..2eba3a3c50 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -1814,13 +1814,17 @@ static int do_reexecute(
|
||||
xsprintf(sfd, "%i", fileno(arg_serialization));
|
||||
|
||||
i = 1; /* Leave args[0] empty for now. */
|
||||
- filter_args(args, &i, argv, argc);
|
||||
|
||||
+ /* Put our stuff first to make sure it always gets parsed in case
|
||||
+ * we get weird stuff from the kernel cmdline (like --) */
|
||||
if (switch_root_dir)
|
||||
args[i++] = "--switched-root";
|
||||
args[i++] = arg_system ? "--system" : "--user";
|
||||
args[i++] = "--deserialize";
|
||||
args[i++] = sfd;
|
||||
+
|
||||
+ filter_args(args, &i, argv, argc);
|
||||
+
|
||||
args[i++] = NULL;
|
||||
|
||||
assert(i <= args_size);
|
||||
diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh
|
||||
index cc6d0651c1..d0e714ac30 100755
|
||||
--- a/test/TEST-01-BASIC/test.sh
|
||||
+++ b/test/TEST-01-BASIC/test.sh
|
||||
@@ -8,6 +8,11 @@ RUN_IN_UNPRIVILEGED_CONTAINER=${RUN_IN_UNPRIVILEGED_CONTAINER:-yes}
|
||||
TEST_REQUIRE_INSTALL_TESTS=0
|
||||
TEST_SUPPORTING_SERVICES_SHOULD_BE_MASKED=0
|
||||
|
||||
+# Check if we can correctly deserialize if the kernel cmdline contains "weird" stuff
|
||||
+# like an invalid argument, "end of arguments" separator, or a sysvinit argument (-z)
|
||||
+# See: https://github.com/systemd/systemd/issues/28184
|
||||
+KERNEL_APPEND="foo -- -z bar --- baz $KERNEL_APPEND"
|
||||
+
|
||||
# shellcheck source=test/test-functions
|
||||
. "${TEST_BASE_DIR:?}/test-functions"
|
||||
|
||||
5322
SOURCES/1305-basic-add-RuntimeScope-enum.patch
Normal file
5322
SOURCES/1305-basic-add-RuntimeScope-enum.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@
|
||||
From 2728e6821ab6f5c0c5316a367bb1aa626b036779 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 9 Mar 2023 17:41:25 +0100
|
||||
Subject: [PATCH] runtime-scope: add helper that turns RuntimeScope enum into
|
||||
--system/--user string
|
||||
|
||||
(cherry picked from commit 40d73340faabb6073602ba3ff41896f3478a2cbf)
|
||||
|
||||
Related: RHEL-137252
|
||||
---
|
||||
src/basic/runtime-scope.c | 8 ++++++++
|
||||
src/basic/runtime-scope.h | 2 ++
|
||||
src/core/main.c | 2 +-
|
||||
src/systemctl/systemctl-start-special.c | 2 +-
|
||||
4 files changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/basic/runtime-scope.c b/src/basic/runtime-scope.c
|
||||
index 88afb53d0b..3d653d6cef 100644
|
||||
--- a/src/basic/runtime-scope.c
|
||||
+++ b/src/basic/runtime-scope.c
|
||||
@@ -10,3 +10,11 @@ static const char* const runtime_scope_table[_RUNTIME_SCOPE_MAX] = {
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(runtime_scope, RuntimeScope);
|
||||
+
|
||||
+static const char* const runtime_scope_cmdline_option_table[_RUNTIME_SCOPE_MAX] = {
|
||||
+ [RUNTIME_SCOPE_SYSTEM] = "--system",
|
||||
+ [RUNTIME_SCOPE_USER] = "--user",
|
||||
+ [RUNTIME_SCOPE_GLOBAL] = "--global",
|
||||
+};
|
||||
+
|
||||
+DEFINE_STRING_TABLE_LOOKUP_TO_STRING(runtime_scope_cmdline_option, RuntimeScope);
|
||||
diff --git a/src/basic/runtime-scope.h b/src/basic/runtime-scope.h
|
||||
index 6a7f9e65d4..6553e4c199 100644
|
||||
--- a/src/basic/runtime-scope.h
|
||||
+++ b/src/basic/runtime-scope.h
|
||||
@@ -15,3 +15,5 @@ typedef enum RuntimeScope {
|
||||
|
||||
const char *runtime_scope_to_string(RuntimeScope scope) _const_;
|
||||
RuntimeScope runtime_scope_from_string(const char *s) _const_;
|
||||
+
|
||||
+const char *runtime_scope_cmdline_option_to_string(RuntimeScope scope) _const_;
|
||||
diff --git a/src/core/main.c b/src/core/main.c
|
||||
index 3ef613a8b1..18f5781126 100644
|
||||
--- a/src/core/main.c
|
||||
+++ b/src/core/main.c
|
||||
@@ -1821,7 +1821,7 @@ static int do_reexecute(
|
||||
* we get weird stuff from the kernel cmdline (like --) */
|
||||
if (switch_root_dir)
|
||||
args[i++] = "--switched-root";
|
||||
- args[i++] = arg_runtime_scope == RUNTIME_SCOPE_SYSTEM ? "--system" : "--user";
|
||||
+ args[i++] = runtime_scope_cmdline_option_to_string(arg_runtime_scope);
|
||||
args[i++] = "--deserialize";
|
||||
args[i++] = sfd;
|
||||
|
||||
diff --git a/src/systemctl/systemctl-start-special.c b/src/systemctl/systemctl-start-special.c
|
||||
index 503d69f2a0..8373dabe15 100644
|
||||
--- a/src/systemctl/systemctl-start-special.c
|
||||
+++ b/src/systemctl/systemctl-start-special.c
|
||||
@@ -260,7 +260,7 @@ int verb_start_system_special(int argc, char *argv[], void *userdata) {
|
||||
if (arg_runtime_scope != RUNTIME_SCOPE_SYSTEM)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Bad action for %s mode.",
|
||||
- arg_runtime_scope == RUNTIME_SCOPE_GLOBAL ? "--global" : "--user");
|
||||
+ runtime_scope_cmdline_option_to_string(arg_runtime_scope));
|
||||
|
||||
return verb_start_special(argc, argv, userdata);
|
||||
}
|
||||
79
SOURCES/1307-sd-path-add-support-for-XDG_STATE_HOME.patch
Normal file
79
SOURCES/1307-sd-path-add-support-for-XDG_STATE_HOME.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 3be3354126953a51625015b43ab5abc11315cd40 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Mon, 26 Jun 2023 18:55:14 +0200
|
||||
Subject: [PATCH] sd-path: add support for XDG_STATE_HOME
|
||||
|
||||
(cherry picked from commit 9a653235d12a795a8bd6adf6289ea735ccae71af)
|
||||
|
||||
Related: RHEL-137252
|
||||
---
|
||||
man/sd_path_lookup.xml | 1 +
|
||||
src/libsystemd/sd-path/sd-path.c | 3 +++
|
||||
src/path/path.c | 2 ++
|
||||
src/systemd/sd-path.h | 5 ++++-
|
||||
4 files changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/man/sd_path_lookup.xml b/man/sd_path_lookup.xml
|
||||
index 01fb1ed8f1..c2ea6469a1 100644
|
||||
--- a/man/sd_path_lookup.xml
|
||||
+++ b/man/sd_path_lookup.xml
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
<constant>SD_PATH_USER_CONFIGURATION</constant>,
|
||||
<constant>SD_PATH_USER_RUNTIME</constant>,
|
||||
+ <constant>SD_PATH_USER_STATE_PRIVATE</constant>,
|
||||
<constant>SD_PATH_USER_STATE_CACHE</constant>,
|
||||
|
||||
<constant>SD_PATH_USER</constant>,
|
||||
diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c
|
||||
index 2c8181fbfb..73a51aebc2 100644
|
||||
--- a/src/libsystemd/sd-path/sd-path.c
|
||||
+++ b/src/libsystemd/sd-path/sd-path.c
|
||||
@@ -281,6 +281,9 @@ static int get_path(uint64_t type, char **buffer, const char **ret) {
|
||||
case SD_PATH_USER_STATE_CACHE:
|
||||
return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret);
|
||||
|
||||
+ case SD_PATH_USER_STATE_PRIVATE:
|
||||
+ return from_home_dir("XDG_STATE_HOME", ".local/state", buffer, ret);
|
||||
+
|
||||
case SD_PATH_USER:
|
||||
r = get_home_dir(buffer);
|
||||
if (r < 0)
|
||||
diff --git a/src/path/path.c b/src/path/path.c
|
||||
index 0024a60611..9d9b24d5e2 100644
|
||||
--- a/src/path/path.c
|
||||
+++ b/src/path/path.c
|
||||
@@ -41,6 +41,8 @@ static const char* const path_table[_SD_PATH_MAX] = {
|
||||
[SD_PATH_USER_CONFIGURATION] = "user-configuration",
|
||||
[SD_PATH_USER_RUNTIME] = "user-runtime",
|
||||
[SD_PATH_USER_STATE_CACHE] = "user-state-cache",
|
||||
+ [SD_PATH_USER_STATE_PRIVATE] = "user-state-private",
|
||||
+
|
||||
[SD_PATH_USER] = "user",
|
||||
[SD_PATH_USER_DOCUMENTS] = "user-documents",
|
||||
[SD_PATH_USER_MUSIC] = "user-music",
|
||||
diff --git a/src/systemd/sd-path.h b/src/systemd/sd-path.h
|
||||
index 161a8e0c8d..0c04e7c22e 100644
|
||||
--- a/src/systemd/sd-path.h
|
||||
+++ b/src/systemd/sd-path.h
|
||||
@@ -53,9 +53,10 @@ enum {
|
||||
SD_PATH_USER_SHARED,
|
||||
|
||||
/* User configuration, state, runtime ... */
|
||||
- SD_PATH_USER_CONFIGURATION, /* takes both actual configuration (like /etc) and state (like /var/lib) */
|
||||
+ SD_PATH_USER_CONFIGURATION,
|
||||
SD_PATH_USER_RUNTIME,
|
||||
SD_PATH_USER_STATE_CACHE,
|
||||
+ /* → SD_PATH_USER_STATE_PRIVATE is added at the bottom */
|
||||
|
||||
/* User resources */
|
||||
SD_PATH_USER, /* $HOME itself */
|
||||
@@ -110,6 +111,8 @@ enum {
|
||||
/* systemd-networkd search paths */
|
||||
SD_PATH_SYSTEMD_SEARCH_NETWORK,
|
||||
|
||||
+ SD_PATH_USER_STATE_PRIVATE,
|
||||
+
|
||||
_SD_PATH_MAX
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user