systemd-252-20

Resolves: RHEL-13199,RHEL-16354,RHEL-5988
This commit is contained in:
Jan Macku 2023-12-08 10:00:06 +01:00
parent 14ddea439d
commit d3e892ecce
50 changed files with 8241 additions and 1 deletions

View File

@ -0,0 +1,37 @@
From 57d5e48a572b98d6ab978072daddac2f7faf8dc8 Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Wed, 2 Nov 2022 11:05:01 -0400
Subject: [PATCH] udev/net: allow new link name as an altname before renaming
happens
When configuring a link's alternative names, the link's new name to-be
is not allowed to be included because interface renaming will fail if
the new name is already present as an alternative name. However,
rtnl_set_link_name will delete the conflicting alternative name before
renaming the device, if necessary.
Allow the new link name to be set as an alternative name before the
device is renamed. This means that if the rename is later skipped (i.e.
because the link is already up), then the name can at least still be
present as an alternative name.
(cherry picked from commit d0b31efc1ab7f6826ad834cf6b9e371bf73776aa)
Related: RHEL-5988
---
src/udev/net/link-config.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index e408725b08..5d28526527 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -841,8 +841,6 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
}
}
- if (link->new_name)
- strv_remove(altnames, link->new_name);
strv_remove(altnames, link->ifname);
r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames);

View File

@ -0,0 +1,64 @@
From ded04e17443f1e9a99705d39ae7dde72eb24ef34 Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Fri, 2 Dec 2022 15:26:18 -0500
Subject: [PATCH] sd-netlink: do not swap old name and alternative name
Commit 434a348380 ("netlink: do not fail when new interface name is
already used as an alternative name") added logic to set the old
interface name as an alternative name, but only when the new name is
currently an alternative name. This is not the desired outcome in most
cases, and the important part of this commit was to delete the new name
from the list of alternative names if necessary.
(cherry picked from commit 080afbb57c4b2d592c5cf77ab10c6e0be74f0732)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/netlink-util.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index 12cdc99ff2..6b4c25fe5a 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -3,7 +3,6 @@
#include "sd-netlink.h"
#include "fd-util.h"
-#include "format-util.h"
#include "io-util.h"
#include "memory-util.h"
#include "netlink-internal.h"
@@ -15,7 +14,6 @@
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
_cleanup_strv_free_ char **alternative_names = NULL;
- char old_name[IF_NAMESIZE] = {};
int r;
assert(rtnl);
@@ -35,10 +33,6 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
if (r < 0)
return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
name, ifindex);
-
- r = format_ifname(ifindex, old_name);
- if (r < 0)
- return log_debug_errno(r, "Failed to get current name of network interface %i: %m", ifindex);
}
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
@@ -53,13 +47,6 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
if (r < 0)
return r;
- if (!isempty(old_name)) {
- r = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(old_name));
- if (r < 0)
- log_debug_errno(r, "Failed to set '%s' as an alternative name on network interface %i, ignoring: %m",
- old_name, ifindex);
- }
-
return 0;
}

View File

@ -0,0 +1,66 @@
From 9b6a3b192ba0f22ce99aa5c48c6c7143d12dddba Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Wed, 2 Nov 2022 05:36:14 -0400
Subject: [PATCH] sd-netlink: restore altname on error in rtnl_set_link_name
If a current alternative name is to be used to rename a network
interface, the alternative name must be removed first. If interface
renaming fails, restore the alternative name that was deleted if
necessary.
(cherry picked from commit 4d600667f8af2985850b03a46357e068d3fb8570)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/netlink-util.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index 6b4c25fe5a..cfcf2578d6 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -14,6 +14,7 @@
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
_cleanup_strv_free_ char **alternative_names = NULL;
+ bool altname_deleted = false;
int r;
assert(rtnl);
@@ -33,21 +34,33 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
if (r < 0)
return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
name, ifindex);
+
+ altname_deleted = true;
}
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
if (r < 0)
- return r;
+ goto fail;
r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
if (r < 0)
- return r;
+ goto fail;
r = sd_netlink_call(*rtnl, message, 0, NULL);
if (r < 0)
- return r;
+ goto fail;
return 0;
+
+fail:
+ if (altname_deleted) {
+ int q = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(name));
+ if (q < 0)
+ log_debug_errno(q, "Failed to restore '%s' as an alternative name on network interface %i, ignoring: %m",
+ name, ifindex);
+ }
+
+ return r;
}
int rtnl_set_link_properties(

View File

@ -0,0 +1,65 @@
From ca122b3f1e00ba6a70e7575266502579108c4b47 Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Fri, 2 Dec 2022 15:35:25 -0500
Subject: [PATCH] udev: attempt device rename even if interface is up
Currently rename_netif() will not attempt to rename a device if it is
already up, because the kernel will return -EBUSY unless live renaming
is allowed on the device. This restriction will be removed in a future
kernel version [1].
To cover both cases, always attempt to rename the interface and return 0
if we get -EBUSY.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=bd039b5ea2a9
(cherry picked from commit 53584e7b61373c26635b906eb64e98fbd3fd3ba4)
Related: RHEL-5988
---
src/udev/udev-event.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index b3d92d5150..08d69cf1f0 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -862,7 +862,6 @@ int udev_event_spawn(
static int rename_netif(UdevEvent *event) {
const char *oldname;
sd_device *dev;
- unsigned flags;
int ifindex, r;
assert(event);
@@ -896,17 +895,7 @@ static int rename_netif(UdevEvent *event) {
return 0;
}
- r = rtnl_get_link_info(&event->rtnl, ifindex, NULL, &flags, NULL, NULL, NULL);
- if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to get link flags: %m");
-
- if (FLAGS_SET(flags, IFF_UP)) {
- log_device_info(dev, "Network interface '%s' is already up, refusing to rename to '%s'.",
- oldname, event->name);
- return 0;
- }
-
- /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */
+ /* Set ID_RENAMING boolean property here. It will be dropped when the corresponding move uevent is processed. */
r = device_add_property(dev, "ID_RENAMING", "1");
if (r < 0)
return log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m");
@@ -927,6 +916,11 @@ static int rename_netif(UdevEvent *event) {
return log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
+ if (r == -EBUSY) {
+ log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",
+ oldname, event->name);
+ return 0;
+ }
if (r < 0)
return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
ifindex, oldname, event->name);

View File

@ -0,0 +1,74 @@
From 32188058ad3b9a8bfc555215982145a128adfc44 Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Tue, 22 Nov 2022 17:01:47 -0500
Subject: [PATCH] sd-netlink: add a test for rtnl_set_link_name()
Add a test that verifies a deleted alternative name is restored on error
in rtnl_set_link_name().
(cherry picked from commit b338a8bb402a3ab241a617e096b21ae6a7b7badf)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/test-netlink.c | 27 ++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index 3f74ecc068..2d93f9eba0 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -8,6 +8,7 @@
#include <linux/if_macsec.h>
#include <linux/l2tp.h>
#include <linux/nl80211.h>
+#include <unistd.h>
#include "sd-netlink.h"
@@ -16,6 +17,7 @@
#include "macro.h"
#include "netlink-genl.h"
#include "netlink-internal.h"
+#include "netlink-util.h"
#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -667,6 +669,30 @@ static void test_genl(void) {
}
}
+static void test_rtnl_set_link_name(sd_netlink *rtnl, int ifindex) {
+ _cleanup_strv_free_ char **alternative_names = NULL;
+ int r;
+
+ log_debug("/* %s */", __func__);
+
+ if (geteuid() != 0)
+ return (void) log_tests_skipped("not root");
+
+ /* Test that the new name (which is currently an alternative name) is
+ * restored as an alternative name on error. Create an error by using
+ * an invalid device name, namely one that exceeds IFNAMSIZ
+ * (alternative names can exceed IFNAMSIZ, but not regular names). */
+ r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename"));
+ if (r == -EPERM)
+ return (void) log_tests_skipped("missing required capabilities");
+
+ assert_se(r >= 0);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename") == -EINVAL);
+ assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
+ assert_se(strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
+}
+
int main(void) {
sd_netlink *rtnl;
sd_netlink_message *m;
@@ -698,6 +724,7 @@ int main(void) {
test_pipe(if_loopback);
test_event_loop(if_loopback);
test_link_configure(rtnl, if_loopback);
+ test_rtnl_set_link_name(rtnl, if_loopback);
test_get_addresses(rtnl);
test_message_link_bridge(rtnl);

View File

@ -0,0 +1,50 @@
From 6e095bdbd88ddbe289210720e7a55b62fa593ab8 Mon Sep 17 00:00:00 2001
From: Nick Rosbrook <nick.rosbrook@canonical.com>
Date: Wed, 7 Dec 2022 12:28:28 -0500
Subject: [PATCH] test-network: add a test for renaming device to current
altname
(cherry picked from commit f68f644a167af3452be853b631fa9144c6716c28)
Related: RHEL-5988
---
.../test-network/conf/12-dummy-rename-to-altname.link | 7 +++++++
test/test-network/systemd-networkd-tests.py | 11 +++++++++++
2 files changed, 18 insertions(+)
create mode 100644 test/test-network/conf/12-dummy-rename-to-altname.link
diff --git a/test/test-network/conf/12-dummy-rename-to-altname.link b/test/test-network/conf/12-dummy-rename-to-altname.link
new file mode 100644
index 0000000000..bef4bf3dc5
--- /dev/null
+++ b/test/test-network/conf/12-dummy-rename-to-altname.link
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+OriginalName=dummy98
+
+[Link]
+Name=dummyalt
+AlternativeName=dummyalt hogehogehogehogehogehoge
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index 87710ef3fb..696618790a 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -936,6 +936,17 @@ class NetworkctlTests(unittest.TestCase, Utilities):
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
self.assertRegex(output, 'hogehogehogehogehogehoge')
+ @expectedFailureIfAlternativeNameIsNotAvailable()
+ def test_rename_to_altname(self):
+ copy_network_unit('26-netdev-link-local-addressing-yes.network',
+ '12-dummy.netdev', '12-dummy-rename-to-altname.link')
+ start_networkd()
+ self.wait_online(['dummyalt:degraded'])
+
+ output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummyalt', env=env)
+ self.assertIn('hogehogehogehogehogehoge', output)
+ self.assertNotIn('dummy98', output)
+
def test_reconfigure(self):
copy_network_unit('25-address-static.network', '12-dummy.netdev')
start_networkd()

View File

@ -0,0 +1,58 @@
From d808bd97790dd8a38d844c827d2d9dbcb700d8c0 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 11:20:35 +0900
Subject: [PATCH] udev: align table
(cherry picked from commit bb1234d1d6b7b14424093a917890bb4013b4ff3e)
Related: RHEL-5988
---
src/udev/udev-event.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 08d69cf1f0..3ac12d9b52 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -119,24 +119,24 @@ struct subst_map_entry {
};
static const struct subst_map_entry map[] = {
- { .name = "devnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE },
- { .name = "tempnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE }, /* deprecated */
- { .name = "attr", .fmt = 's', .type = FORMAT_SUBST_ATTR },
- { .name = "sysfs", .fmt = 's', .type = FORMAT_SUBST_ATTR }, /* deprecated */
- { .name = "env", .fmt = 'E', .type = FORMAT_SUBST_ENV },
- { .name = "kernel", .fmt = 'k', .type = FORMAT_SUBST_KERNEL },
+ { .name = "devnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE },
+ { .name = "tempnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE }, /* deprecated */
+ { .name = "attr", .fmt = 's', .type = FORMAT_SUBST_ATTR },
+ { .name = "sysfs", .fmt = 's', .type = FORMAT_SUBST_ATTR }, /* deprecated */
+ { .name = "env", .fmt = 'E', .type = FORMAT_SUBST_ENV },
+ { .name = "kernel", .fmt = 'k', .type = FORMAT_SUBST_KERNEL },
{ .name = "number", .fmt = 'n', .type = FORMAT_SUBST_KERNEL_NUMBER },
- { .name = "driver", .fmt = 'd', .type = FORMAT_SUBST_DRIVER },
- { .name = "devpath", .fmt = 'p', .type = FORMAT_SUBST_DEVPATH },
- { .name = "id", .fmt = 'b', .type = FORMAT_SUBST_ID },
- { .name = "major", .fmt = 'M', .type = FORMAT_SUBST_MAJOR },
- { .name = "minor", .fmt = 'm', .type = FORMAT_SUBST_MINOR },
- { .name = "result", .fmt = 'c', .type = FORMAT_SUBST_RESULT },
- { .name = "parent", .fmt = 'P', .type = FORMAT_SUBST_PARENT },
- { .name = "name", .fmt = 'D', .type = FORMAT_SUBST_NAME },
- { .name = "links", .fmt = 'L', .type = FORMAT_SUBST_LINKS },
- { .name = "root", .fmt = 'r', .type = FORMAT_SUBST_ROOT },
- { .name = "sys", .fmt = 'S', .type = FORMAT_SUBST_SYS },
+ { .name = "driver", .fmt = 'd', .type = FORMAT_SUBST_DRIVER },
+ { .name = "devpath", .fmt = 'p', .type = FORMAT_SUBST_DEVPATH },
+ { .name = "id", .fmt = 'b', .type = FORMAT_SUBST_ID },
+ { .name = "major", .fmt = 'M', .type = FORMAT_SUBST_MAJOR },
+ { .name = "minor", .fmt = 'm', .type = FORMAT_SUBST_MINOR },
+ { .name = "result", .fmt = 'c', .type = FORMAT_SUBST_RESULT },
+ { .name = "parent", .fmt = 'P', .type = FORMAT_SUBST_PARENT },
+ { .name = "name", .fmt = 'D', .type = FORMAT_SUBST_NAME },
+ { .name = "links", .fmt = 'L', .type = FORMAT_SUBST_LINKS },
+ { .name = "root", .fmt = 'r', .type = FORMAT_SUBST_ROOT },
+ { .name = "sys", .fmt = 'S', .type = FORMAT_SUBST_SYS },
};
static const char *format_type_to_string(FormatSubstitutionType t) {

View File

@ -0,0 +1,47 @@
From 3b4d91e7ab44738f3773a3bfd4a6c5fb9bbc7322 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 14:00:09 +0900
Subject: [PATCH] sd-device: make device_set_syspath() clear sysname and sysnum
Otherwise, when a new syspath is assigned to the sd-device object,
sd_device_get_sysname() or _sysnum() will provide an outdated device
name or number.
(cherry picked from commit 9a26098e90116fdb5fcffa03485b375ee0c82b6a)
Related: RHEL-5988
---
src/libsystemd/sd-device/device-private.c | 4 ----
src/libsystemd/sd-device/sd-device.c | 4 ++++
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index bc7a838608..2c1d922ea3 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -646,10 +646,6 @@ int device_rename(sd_device *device, const char *name) {
if (r < 0)
return r;
- /* Here, only clear the sysname and sysnum. They will be set when requested. */
- device->sysnum = NULL;
- device->sysname = mfree(device->sysname);
-
r = sd_device_get_property_value(device, "INTERFACE", &interface);
if (r == -ENOENT)
return 0;
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index f2e142457b..c822a0b2f0 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -250,6 +250,10 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
free_and_replace(device->syspath, syspath);
device->devpath = devpath;
+
+ /* Unset sysname and sysnum, they will be assigned when requested. */
+ device->sysnum = NULL;
+ device->sysname = mfree(device->sysname);
return 0;
}

View File

@ -0,0 +1,62 @@
From 2c6ea8a97986c58954603b587875a52b043e4d9b Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 14:07:16 +0900
Subject: [PATCH] sd-device: do not directly access entry in sd-device object
No functional change, just refactoring.
(cherry picked from commit 1de6a49721957a85a4934ddbdf88d535774597b1)
Related: RHEL-5988
---
src/libsystemd/sd-device/device-private.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index 2c1d922ea3..9cec037237 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -621,7 +621,7 @@ int device_get_devlink_priority(sd_device *device, int *ret) {
int device_rename(sd_device *device, const char *name) {
_cleanup_free_ char *new_syspath = NULL;
- const char *interface;
+ const char *s;
int r;
assert(device);
@@ -630,7 +630,11 @@ int device_rename(sd_device *device, const char *name) {
if (!filename_is_valid(name))
return -EINVAL;
- r = path_extract_directory(device->syspath, &new_syspath);
+ r = sd_device_get_syspath(device, &s);
+ if (r < 0)
+ return r;
+
+ r = path_extract_directory(s, &new_syspath);
if (r < 0)
return r;
@@ -642,18 +646,18 @@ int device_rename(sd_device *device, const char *name) {
/* At the time this is called, the renamed device may not exist yet. Hence, we cannot validate
* the new syspath. */
- r = device_set_syspath(device, new_syspath, false);
+ r = device_set_syspath(device, new_syspath, /* verify = */ false);
if (r < 0)
return r;
- r = sd_device_get_property_value(device, "INTERFACE", &interface);
+ r = sd_device_get_property_value(device, "INTERFACE", &s);
if (r == -ENOENT)
return 0;
if (r < 0)
return r;
/* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
- r = device_add_property_internal(device, "INTERFACE_OLD", interface);
+ r = device_add_property_internal(device, "INTERFACE_OLD", s);
if (r < 0)
return r;

View File

@ -0,0 +1,148 @@
From 7f183125fbec97bd6e4c0b3ac792b0e0c23132e0 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 15:00:30 +0900
Subject: [PATCH] udev: move device_rename() from device-private.c
The function is used only by udevd.
(cherry picked from commit ff88b949531e70639c507f74da875a7de2adf543)
Related: RHEL-5988
---
src/libsystemd/sd-device/device-private.c | 45 ----------------------
src/libsystemd/sd-device/device-private.h | 1 -
src/udev/udev-event.c | 46 +++++++++++++++++++++++
3 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index 9cec037237..36b0da4f12 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -619,51 +619,6 @@ int device_get_devlink_priority(sd_device *device, int *ret) {
return 0;
}
-int device_rename(sd_device *device, const char *name) {
- _cleanup_free_ char *new_syspath = NULL;
- const char *s;
- int r;
-
- assert(device);
- assert(name);
-
- if (!filename_is_valid(name))
- return -EINVAL;
-
- r = sd_device_get_syspath(device, &s);
- if (r < 0)
- return r;
-
- r = path_extract_directory(s, &new_syspath);
- if (r < 0)
- return r;
-
- if (!path_extend(&new_syspath, name))
- return -ENOMEM;
-
- if (!path_is_safe(new_syspath))
- return -EINVAL;
-
- /* At the time this is called, the renamed device may not exist yet. Hence, we cannot validate
- * the new syspath. */
- r = device_set_syspath(device, new_syspath, /* verify = */ false);
- if (r < 0)
- return r;
-
- r = sd_device_get_property_value(device, "INTERFACE", &s);
- if (r == -ENOENT)
- return 0;
- if (r < 0)
- return r;
-
- /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
- r = device_add_property_internal(device, "INTERFACE_OLD", s);
- if (r < 0)
- return r;
-
- return device_add_property_internal(device, "INTERFACE", name);
-}
-
static int device_shallow_clone(sd_device *device, sd_device **ret) {
_cleanup_(sd_device_unrefp) sd_device *dest = NULL;
const char *val = NULL;
diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h
index a59f130aff..e57b74ba24 100644
--- a/src/libsystemd/sd-device/device-private.h
+++ b/src/libsystemd/sd-device/device-private.h
@@ -53,7 +53,6 @@ int device_properties_prepare(sd_device *device);
int device_get_properties_nulstr(sd_device *device, const char **ret_nulstr, size_t *ret_len);
int device_get_properties_strv(sd_device *device, char ***ret);
-int device_rename(sd_device *device, const char *name);
int device_clone_with_db(sd_device *device, sd_device **ret);
int device_tag_index(sd_device *dev, sd_device *dev_old, bool add);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 3ac12d9b52..1dc05f863d 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -12,6 +12,7 @@
#include "sd-event.h"
#include "alloc-util.h"
+#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
#include "fd-util.h"
@@ -859,6 +860,51 @@ int udev_event_spawn(
return r; /* 0 for success, and positive if the program failed */
}
+static int device_rename(sd_device *device, const char *name) {
+ _cleanup_free_ char *new_syspath = NULL;
+ const char *s;
+ int r;
+
+ assert(device);
+ assert(name);
+
+ if (!filename_is_valid(name))
+ return -EINVAL;
+
+ r = sd_device_get_syspath(device, &s);
+ if (r < 0)
+ return r;
+
+ r = path_extract_directory(s, &new_syspath);
+ if (r < 0)
+ return r;
+
+ if (!path_extend(&new_syspath, name))
+ return -ENOMEM;
+
+ if (!path_is_safe(new_syspath))
+ return -EINVAL;
+
+ /* At the time this is called, the renamed device may not exist yet. Hence, we cannot validate
+ * the new syspath. */
+ r = device_set_syspath(device, new_syspath, /* verify = */ false);
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_property_value(device, "INTERFACE", &s);
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
+ return r;
+
+ /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
+ r = device_add_property_internal(device, "INTERFACE_OLD", s);
+ if (r < 0)
+ return r;
+
+ return device_add_property_internal(device, "INTERFACE", name);
+}
+
static int rename_netif(UdevEvent *event) {
const char *oldname;
sd_device *dev;

View File

@ -0,0 +1,155 @@
From 1f4bc8c496d2a310ffa3e7174af40f7e596cd2d1 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 14:58:58 +0900
Subject: [PATCH] udev: restore syspath and properties on failure
Otherwise, invalid sysname or properties may be broadcast to udev
listeners.
(cherry picked from commit 210033847c340c43dd6835520f21f8b23ba29579)
Related: RHEL-5988
---
src/udev/udev-event.c | 93 +++++++++++++++++++++++++++++--------------
1 file changed, 64 insertions(+), 29 deletions(-)
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 1dc05f863d..fab454ae37 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -906,7 +906,8 @@ static int device_rename(sd_device *device, const char *name) {
}
static int rename_netif(UdevEvent *event) {
- const char *oldname;
+ _cleanup_free_ char *old_syspath = NULL, *old_sysname = NULL;
+ const char *s;
sd_device *dev;
int ifindex, r;
@@ -917,15 +918,6 @@ static int rename_netif(UdevEvent *event) {
dev = ASSERT_PTR(event->dev);
- /* Read sysname from cloned sd-device object, otherwise use-after-free is triggered, as the
- * main object will be renamed and dev->sysname will be freed in device_rename(). */
- r = sd_device_get_sysname(event->dev_db_clone, &oldname);
- if (r < 0)
- return log_device_error_errno(dev, r, "Failed to get sysname: %m");
-
- if (streq(event->name, oldname))
- return 0; /* The interface name is already requested name. */
-
if (!device_for_action(dev, SD_DEVICE_ADD))
return 0; /* Rename the interface only when it is added. */
@@ -933,7 +925,7 @@ static int rename_netif(UdevEvent *event) {
if (r == -ENOENT)
return 0; /* Device is not a network interface. */
if (r < 0)
- return log_device_error_errno(dev, r, "Failed to get ifindex: %m");
+ return log_device_warning_errno(dev, r, "Failed to get ifindex: %m");
if (naming_scheme_has(NAMING_REPLACE_STRICTLY) &&
!ifname_valid(event->name)) {
@@ -941,39 +933,82 @@ static int rename_netif(UdevEvent *event) {
return 0;
}
- /* Set ID_RENAMING boolean property here. It will be dropped when the corresponding move uevent is processed. */
- r = device_add_property(dev, "ID_RENAMING", "1");
+ r = sd_device_get_sysname(dev, &s);
if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m");
+ return log_device_warning_errno(dev, r, "Failed to get sysname: %m");
- r = device_rename(dev, event->name);
+ if (streq(event->name, s))
+ return 0; /* The interface name is already requested name. */
+
+ old_sysname = strdup(s);
+ if (!old_sysname)
+ return -ENOMEM;
+
+ r = sd_device_get_syspath(dev, &s);
if (r < 0)
- return log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name);
+ return log_device_warning_errno(dev, r, "Failed to get syspath: %m");
+
+ old_syspath = strdup(s);
+ if (!old_syspath)
+ return -ENOMEM;
+
+ r = device_rename(dev, event->name);
+ if (r < 0) {
+ log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name);
+ goto revert;
+ }
+
+ /* Set ID_RENAMING boolean property here. It will be dropped when the corresponding move uevent is processed. */
+ r = device_add_property(dev, "ID_RENAMING", "1");
+ if (r < 0) {
+ log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m");
+ goto revert;
+ }
/* Also set ID_RENAMING boolean property to cloned sd_device object and save it to database
* before calling rtnl_set_link_name(). Otherwise, clients (e.g., systemd-networkd) may receive
* RTM_NEWLINK netlink message before the database is updated. */
r = device_add_property(event->dev_db_clone, "ID_RENAMING", "1");
- if (r < 0)
- return log_device_warning_errno(event->dev_db_clone, r, "Failed to add 'ID_RENAMING' property: %m");
+ if (r < 0) {
+ log_device_warning_errno(event->dev_db_clone, r, "Failed to add 'ID_RENAMING' property: %m");
+ goto revert;
+ }
r = device_update_db(event->dev_db_clone);
- if (r < 0)
- return log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
+ if (r < 0) {
+ log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m");
+ goto revert;
+ }
r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
- if (r == -EBUSY) {
- log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",
- oldname, event->name);
- return 0;
+ if (r < 0) {
+ if (r == -EBUSY) {
+ log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",
+ old_sysname, event->name);
+ r = 0;
+ } else
+ log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
+ ifindex, old_sysname, event->name);
+ goto revert;
}
- if (r < 0)
- return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m",
- ifindex, oldname, event->name);
-
- log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name);
+ log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, old_sysname, event->name);
return 1;
+
+revert:
+ /* Restore 'dev_db_clone' */
+ (void) device_add_property(event->dev_db_clone, "ID_RENAMING", NULL);
+ (void) device_update_db(event->dev_db_clone);
+
+ /* Restore 'dev' */
+ (void) device_set_syspath(dev, old_syspath, /* verify = */ false);
+ if (sd_device_get_property_value(dev, "INTERFACE_OLD", &s) >= 0) {
+ (void) device_add_property_internal(dev, "INTERFACE", s);
+ (void) device_add_property_internal(dev, "INTERFACE_OLD", NULL);
+ }
+ (void) device_add_property(dev, "ID_RENAMING", NULL);
+
+ return r;
}
static int update_devnode(UdevEvent *event) {

View File

@ -0,0 +1,56 @@
From 284d6f9171ba819bcccb6a2df7c3012ba8483a0c Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 16:44:11 +0900
Subject: [PATCH] sd-device: introduce device_get_property_int()
(cherry picked from commit eedfef0f0d2654fcde2a3b694e62518d688af827)
Related: RHEL-5988
---
src/libsystemd/sd-device/device-private.h | 1 +
src/libsystemd/sd-device/sd-device.c | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h
index e57b74ba24..d9a519a4d9 100644
--- a/src/libsystemd/sd-device/device-private.h
+++ b/src/libsystemd/sd-device/device-private.h
@@ -18,6 +18,7 @@ int device_new_from_strv(sd_device **ret, char **strv);
int device_opendir(sd_device *device, const char *subdir, DIR **ret);
int device_get_property_bool(sd_device *device, const char *key);
+int device_get_property_int(sd_device *device, const char *key, int *ret);
int device_get_sysattr_int(sd_device *device, const char *sysattr, int *ret_value);
int device_get_sysattr_unsigned(sd_device *device, const char *sysattr, unsigned *ret_value);
int device_get_sysattr_bool(sd_device *device, const char *sysattr);
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index c822a0b2f0..7ee67b4641 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -2186,6 +2186,26 @@ int device_get_property_bool(sd_device *device, const char *key) {
return parse_boolean(value);
}
+int device_get_property_int(sd_device *device, const char *key, int *ret) {
+ const char *value;
+ int r, v;
+
+ assert(device);
+ assert(key);
+
+ r = sd_device_get_property_value(device, key, &value);
+ if (r < 0)
+ return r;
+
+ r = safe_atoi(value, &v);
+ if (r < 0)
+ return r;
+
+ if (ret)
+ *ret = v;
+ return 0;
+}
+
_public_ int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret) {
const char *s;
sd_id128_t id;

View File

@ -0,0 +1,32 @@
From 42a11f89c8836493847a69906ef2765e2e984dbf Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 16:11:04 +0900
Subject: [PATCH] core/device: downgrade log level for ignored errors
(cherry picked from commit 58b0a3e5112a27daa181383458f68955eb081551)
Related: RHEL-5988
---
src/core/device.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/core/device.c b/src/core/device.c
index 224fc90835..09b7d56e1e 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -1095,13 +1095,13 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
r = sd_device_get_syspath(dev, &sysfs);
if (r < 0) {
- log_device_error_errno(dev, r, "Failed to get device syspath, ignoring: %m");
+ log_device_warning_errno(dev, r, "Failed to get device syspath, ignoring: %m");
return 0;
}
r = sd_device_get_action(dev, &action);
if (r < 0) {
- log_device_error_errno(dev, r, "Failed to get udev action, ignoring: %m");
+ log_device_warning_errno(dev, r, "Failed to get udev action, ignoring: %m");
return 0;
}

View File

@ -0,0 +1,45 @@
From b59fda96b0e24b93dcdb061da24c42a924ae0b20 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 16:11:52 +0900
Subject: [PATCH] core/device: ignore failed uevents
When udevd failed to process the device, SYSTEMD_ALIAS or any other
properties may contain invalid values. Let's refuse to handle the uevent.
(cherry picked from commit e9336d6ac346df38d96c91ba0447b3c76ee6697b)
Related: RHEL-5988
---
src/core/device.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/core/device.c b/src/core/device.c
index 09b7d56e1e..f007bdfd9b 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -1108,6 +1108,25 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *
if (action == SD_DEVICE_MOVE)
device_remove_old_on_move(m, dev);
+ /* When udevd failed to process the device, SYSTEMD_ALIAS or any other properties may contain invalid
+ * values. Let's refuse to handle the uevent. */
+ if (sd_device_get_property_value(dev, "UDEV_WORKER_FAILED", NULL) >= 0) {
+ int v;
+
+ if (device_get_property_int(dev, "UDEV_WORKER_ERRNO", &v) >= 0)
+ log_device_warning_errno(dev, v, "systemd-udevd failed to process the device, ignoring: %m");
+ else if (device_get_property_int(dev, "UDEV_WORKER_EXIT_STATUS", &v) >= 0)
+ log_device_warning(dev, "systemd-udevd failed to process the device with exit status %i, ignoring.", v);
+ else if (device_get_property_int(dev, "UDEV_WORKER_SIGNAL", &v) >= 0) {
+ const char *s;
+ (void) sd_device_get_property_value(dev, "UDEV_WORKER_SIGNAL_NAME", &s);
+ log_device_warning(dev, "systemd-udevd failed to process the device with signal %i(%s), ignoring.", v, strna(s));
+ } else
+ log_device_warning(dev, "systemd-udevd failed to process the device with unknown result, ignoring.");
+
+ return 0;
+ }
+
/* A change event can signal that a device is becoming ready, in particular if the device is using
* the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for
* change events */

View File

@ -0,0 +1,99 @@
From 9e9f53612dc2356796cffb25826008944aede0e3 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 16:02:09 +0900
Subject: [PATCH] test: add tests for failure in renaming network interface
(cherry picked from commit 2d0d75b279924934c4c8e9acbc48456b01b71f00)
Related: RHEL-5988
---
test/units/testsuite-17.02.sh | 78 +++++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
diff --git a/test/units/testsuite-17.02.sh b/test/units/testsuite-17.02.sh
index 7abbce7747..ed3b39d074 100755
--- a/test/units/testsuite-17.02.sh
+++ b/test/units/testsuite-17.02.sh
@@ -102,4 +102,82 @@ timeout 30 bash -c 'while [[ "$(systemctl show --property=ActiveState --value /s
# cleanup
ip link del hoge
+teardown_netif_renaming_conflict() {
+ set +ex
+
+ if [[ -n "$KILL_PID" ]]; then
+ kill "$KILL_PID"
+ fi
+
+ rm -rf "$TMPDIR"
+
+ rm -f /run/udev/rules.d/50-testsuite.rules
+ udevadm control --reload --timeout=30
+
+ ip link del hoge
+ ip link del foobar
+}
+
+test_netif_renaming_conflict() {
+ local since found=
+
+ trap teardown_netif_renaming_conflict RETURN
+
+ cat >/run/udev/rules.d/50-testsuite.rules <<EOF
+ACTION!="add", GOTO="hoge_end"
+SUBSYSTEM!="net", GOTO="hoge_end"
+
+OPTIONS="log_level=debug"
+
+KERNEL=="foobar", NAME="hoge"
+
+LABEL="hoge_end"
+EOF
+
+ udevadm control --log-priority=debug --reload --timeout=30
+
+ ip link add hoge type dummy
+ udevadm wait --timeout=30 --settle /sys/devices/virtual/net/hoge
+
+ TMPDIR=$(mktemp -d -p /tmp udev-tests.XXXXXX)
+ udevadm monitor --udev --property --subsystem-match=net >"$TMPDIR"/monitor.txt &
+ KILL_PID="$!"
+
+ # make sure that 'udevadm monitor' actually monitor uevents
+ sleep 1
+
+ since="$(date '+%H:%M:%S')"
+
+ # add another interface which will conflict with an existing interface
+ ip link add foobar type dummy
+
+ for _ in {1..40}; do
+ if (
+ grep -q 'ACTION=add' "$TMPDIR"/monitor.txt
+ grep -q 'DEVPATH=/devices/virtual/net/foobar' "$TMPDIR"/monitor.txt
+ grep -q 'SUBSYSTEM=net' "$TMPDIR"/monitor.txt
+ grep -q 'INTERFACE=foobar' "$TMPDIR"/monitor.txt
+ grep -q 'ID_NET_DRIVER=dummy' "$TMPDIR"/monitor.txt
+ grep -q 'ID_NET_NAME=foobar' "$TMPDIR"/monitor.txt
+ # Even when network interface renaming is failed, SYSTEMD_ALIAS with the conflicting name will be broadcast.
+ grep -q 'SYSTEMD_ALIAS=/sys/subsystem/net/devices/hoge' "$TMPDIR"/monitor.txt
+ grep -q 'UDEV_WORKER_FAILED=1' "$TMPDIR"/monitor.txt
+ grep -q 'UDEV_WORKER_ERRNO=17' "$TMPDIR"/monitor.txt
+ grep -q 'UDEV_WORKER_ERRNO_NAME=EEXIST' "$TMPDIR"/monitor.txt
+ ); then
+ cat "$TMPDIR"/monitor.txt
+ found=1
+ break
+ fi
+ sleep .5
+ done
+ test -n "$found"
+
+ timeout 30 bash -c "while ! journalctl _PID=1 _COMM=systemd --since $since | grep -q 'foobar: systemd-udevd failed to process the device, ignoring: File exists'; do sleep 1; done"
+ # check if the invalid SYSTEMD_ALIAS property for the interface foobar is ignored by PID1
+ assert_eq "$(systemctl show --property=SysFSPath --value /sys/subsystem/net/devices/hoge)" "/sys/devices/virtual/net/hoge"
+}
+
+test_netif_renaming_conflict
+
exit 0

View File

@ -0,0 +1,623 @@
From a3c14074e6cd91053ffafb0eb4b16054564e4239 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 20:33:35 +0900
Subject: [PATCH] test: modernize test-netlink.c
(cherry picked from commit eafff21da2978bfa4c5c4171a595abaeb1d170dc)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/test-netlink.c | 362 ++++++++---------------
1 file changed, 116 insertions(+), 246 deletions(-)
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index 2d93f9eba0..f740035639 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -24,11 +24,12 @@
#include "strv.h"
#include "tests.h"
-static void test_message_link_bridge(sd_netlink *rtnl) {
+TEST(message_newlink_bridge) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
uint32_t cost;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
assert_se(sd_rtnl_message_link_set_family(message, AF_BRIDGE) >= 0);
@@ -44,99 +45,81 @@ static void test_message_link_bridge(sd_netlink *rtnl) {
assert_se(sd_netlink_message_exit_container(message) >= 0);
}
-static void test_link_configure(sd_netlink *rtnl, int ifindex) {
+TEST(message_getlink) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
- uint32_t mtu_out;
- const char *name_out;
- struct ether_addr mac_out;
-
- log_debug("/* %s */", __func__);
-
- /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
- assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
-
- assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
-
- assert_se(sd_netlink_message_read_string(reply, IFLA_IFNAME, &name_out) >= 0);
- assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &mac_out) >= 0);
- assert_se(sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu_out) >= 0);
-}
-
-static void test_link_get(sd_netlink *rtnl, int ifindex) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
- const char *str_data;
+ int ifindex;
uint8_t u8_data;
+ uint16_t u16_data;
uint32_t u32_data;
+ const char *str_data;
struct ether_addr eth_data;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
+ ifindex = (int) if_nametoindex("lo");
- assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
- assert_se(m);
+ /* we'd really like to test NEWLINK, but let's not mess with the running kernel */
+ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
+ assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
- assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1);
+ /* u8 */
+ assert_se(sd_netlink_message_read_u8(reply, IFLA_CARRIER, &u8_data) >= 0);
+ assert_se(sd_netlink_message_read_u8(reply, IFLA_OPERSTATE, &u8_data) >= 0);
+ assert_se(sd_netlink_message_read_u8(reply, IFLA_LINKMODE, &u8_data) >= 0);
- assert_se(sd_netlink_message_read_string(r, IFLA_IFNAME, &str_data) == 0);
+ /* u16 */
+ assert_se(sd_netlink_message_get_type(reply, &u16_data) >= 0);
+ assert_se(u16_data == RTM_NEWLINK);
- assert_se(sd_netlink_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0);
- assert_se(sd_netlink_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0);
- assert_se(sd_netlink_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0);
+ /* u32 */
+ assert_se(sd_netlink_message_read_u32(reply, IFLA_MTU, &u32_data) >= 0);
+ assert_se(sd_netlink_message_read_u32(reply, IFLA_GROUP, &u32_data) >= 0);
+ assert_se(sd_netlink_message_read_u32(reply, IFLA_TXQLEN, &u32_data) >= 0);
+ assert_se(sd_netlink_message_read_u32(reply, IFLA_NUM_TX_QUEUES, &u32_data) >= 0);
+ assert_se(sd_netlink_message_read_u32(reply, IFLA_NUM_RX_QUEUES, &u32_data) >= 0);
- assert_se(sd_netlink_message_read_u32(r, IFLA_MTU, &u32_data) == 0);
- assert_se(sd_netlink_message_read_u32(r, IFLA_GROUP, &u32_data) == 0);
- assert_se(sd_netlink_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0);
- assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0);
- assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0);
+ /* string */
+ assert_se(sd_netlink_message_read_string(reply, IFLA_IFNAME, &str_data) >= 0);
- assert_se(sd_netlink_message_read_ether_addr(r, IFLA_ADDRESS, &eth_data) == 0);
+ /* ether_addr */
+ assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &eth_data) >= 0);
}
-static void test_address_get(sd_netlink *rtnl, int ifindex) {
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
+TEST(message_address) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
+ int ifindex;
struct in_addr in_data;
struct ifa_cacheinfo cache;
const char *label;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
+ ifindex = (int) if_nametoindex("lo");
- assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
- assert_se(m);
- assert_se(sd_netlink_message_set_request_dump(m, true) >= 0);
- assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1);
+ assert_se(sd_rtnl_message_new_addr(rtnl, &message, RTM_GETADDR, ifindex, AF_INET) >= 0);
+ assert_se(sd_netlink_message_set_request_dump(message, true) >= 0);
+ assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
- assert_se(sd_netlink_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0);
- assert_se(sd_netlink_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0);
- assert_se(sd_netlink_message_read_string(r, IFA_LABEL, &label) == 0);
- assert_se(sd_netlink_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0);
+ assert_se(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data) >= 0);
+ assert_se(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data) >= 0);
+ assert_se(sd_netlink_message_read_string(reply, IFA_LABEL, &label) >= 0);
+ assert_se(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache) == 0);
}
-static void test_route(sd_netlink *rtnl) {
+TEST(message_route) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
struct in_addr addr, addr_data;
uint32_t index = 2, u32_data;
- int r;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
- r = sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
- if (r < 0) {
- log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
- return;
- }
+ assert_se(sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC) >= 0);
addr.s_addr = htobe32(INADDR_LOOPBACK);
- r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr);
- if (r < 0) {
- log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
- return;
- }
-
- r = sd_netlink_message_append_u32(req, RTA_OIF, index);
- if (r < 0) {
- log_error_errno(r, "Could not append RTA_OIF attribute: %m");
- return;
- }
+ assert_se(sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr) >= 0);
+ assert_se(sd_netlink_message_append_u32(req, RTA_OIF, index) >= 0);
assert_se(sd_netlink_message_rewind(req, rtnl) >= 0);
@@ -149,135 +132,94 @@ static void test_route(sd_netlink *rtnl) {
assert_se((req = sd_netlink_message_unref(req)) == NULL);
}
-static void test_multiple(void) {
- sd_netlink *rtnl1, *rtnl2;
-
- log_debug("/* %s */", __func__);
-
- assert_se(sd_netlink_open(&rtnl1) >= 0);
- assert_se(sd_netlink_open(&rtnl2) >= 0);
-
- rtnl1 = sd_netlink_unref(rtnl1);
- rtnl2 = sd_netlink_unref(rtnl2);
-}
-
static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
- char *ifname = userdata;
const char *data;
assert_se(rtnl);
assert_se(m);
- assert_se(userdata);
- log_info("%s: got link info about %s", __func__, ifname);
- free(ifname);
+ assert_se(streq_ptr(userdata, "foo"));
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
assert_se(streq(data, "lo"));
+ log_info("%s: got link info about %s", __func__, data);
return 1;
}
-static void test_event_loop(int ifindex) {
+TEST(netlink_event_loop) {
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
- char *ifname;
-
- log_debug("/* %s */", __func__);
-
- ifname = strdup("lo2");
- assert_se(ifname);
+ _cleanup_free_ char *userdata = NULL;
+ int ifindex;
assert_se(sd_netlink_open(&rtnl) >= 0);
- assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
+ ifindex = (int) if_nametoindex("lo");
- assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, ifname, 0, NULL) >= 0);
+ assert_se(userdata = strdup("foo"));
assert_se(sd_event_default(&event) >= 0);
-
assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0);
+ assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
+ assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, userdata, 0, NULL) >= 0);
+
assert_se(sd_event_run(event, 0) >= 0);
assert_se(sd_netlink_detach_event(rtnl) >= 0);
-
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
static void test_async_destroy(void *userdata) {
}
-static void test_async(int ifindex) {
+TEST(netlink_call_async) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
+ _cleanup_free_ char *userdata = NULL;
sd_netlink_destroy_t destroy_callback;
const char *description;
- char *ifname;
-
- log_debug("/* %s */", __func__);
-
- ifname = strdup("lo");
- assert_se(ifname);
+ int ifindex;
assert_se(sd_netlink_open(&rtnl) >= 0);
+ ifindex = (int) if_nametoindex("lo");
- assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
+ assert_se(userdata = strdup("foo"));
- assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, ifname, 0, "hogehoge") >= 0);
+ assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
+ assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, userdata, 0, "hogehoge") >= 0);
assert_se(sd_netlink_slot_get_netlink(slot) == rtnl);
- assert_se(sd_netlink_slot_get_userdata(slot) == ifname);
- assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
- assert_se(destroy_callback == test_async_destroy);
- assert_se(sd_netlink_slot_get_floating(slot) == 0);
- assert_se(sd_netlink_slot_get_description(slot, &description) == 1);
- assert_se(streq(description, "hogehoge"));
-
- assert_se(sd_netlink_wait(rtnl, 0) >= 0);
- assert_se(sd_netlink_process(rtnl, &r) >= 0);
-
- assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
-}
-static void test_slot_set(int ifindex) {
- _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
- _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
- sd_netlink_destroy_t destroy_callback;
- const char *description;
- char *ifname;
-
- log_debug("/* %s */", __func__);
-
- ifname = strdup("lo");
- assert_se(ifname);
-
- assert_se(sd_netlink_open(&rtnl) >= 0);
-
- assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
-
- assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, NULL, NULL, 0, NULL) >= 0);
+ assert_se(sd_netlink_slot_get_userdata(slot) == userdata);
+ assert_se(sd_netlink_slot_set_userdata(slot, NULL) == userdata);
+ assert_se(sd_netlink_slot_get_userdata(slot) == NULL);
+ assert_se(sd_netlink_slot_set_userdata(slot, userdata) == NULL);
+ assert_se(sd_netlink_slot_get_userdata(slot) == userdata);
- assert_se(sd_netlink_slot_get_netlink(slot) == rtnl);
- assert_se(!sd_netlink_slot_get_userdata(slot));
- assert_se(!sd_netlink_slot_set_userdata(slot, ifname));
- assert_se(sd_netlink_slot_get_userdata(slot) == ifname);
- assert_se(sd_netlink_slot_get_destroy_callback(slot, NULL) == 0);
+ assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
+ assert_se(destroy_callback == test_async_destroy);
+ assert_se(sd_netlink_slot_set_destroy_callback(slot, NULL) >= 0);
+ assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 0);
+ assert_se(destroy_callback == NULL);
assert_se(sd_netlink_slot_set_destroy_callback(slot, test_async_destroy) >= 0);
assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1);
assert_se(destroy_callback == test_async_destroy);
+
assert_se(sd_netlink_slot_get_floating(slot) == 0);
assert_se(sd_netlink_slot_set_floating(slot, 1) == 1);
assert_se(sd_netlink_slot_get_floating(slot) == 1);
- assert_se(sd_netlink_slot_get_description(slot, NULL) == 0);
- assert_se(sd_netlink_slot_set_description(slot, "hogehoge") >= 0);
+
assert_se(sd_netlink_slot_get_description(slot, &description) == 1);
assert_se(streq(description, "hogehoge"));
+ assert_se(sd_netlink_slot_set_description(slot, NULL) >= 0);
+ assert_se(sd_netlink_slot_get_description(slot, &description) == 0);
+ assert_se(description == NULL);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
- assert_se(sd_netlink_process(rtnl, &r) >= 0);
+ assert_se(sd_netlink_process(rtnl, &reply) >= 0);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
@@ -322,23 +264,21 @@ static void test_async_object_destroy(void *userdata) {
test_async_object_unref(t);
}
-static void test_async_destroy_callback(int ifindex) {
+TEST(async_destroy_callback) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
_cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL;
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
- char *ifname;
+ int ifindex;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
+ ifindex = (int) if_nametoindex("lo");
assert_se(t = new(struct test_async_object, 1));
- assert_se(ifname = strdup("lo"));
*t = (struct test_async_object) {
.n_ref = 1,
- .ifname = ifname,
};
-
- assert_se(sd_netlink_open(&rtnl) >= 0);
+ assert_se(t->ifname = strdup("lo"));
/* destroy callback is called after processing message */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
@@ -349,7 +289,7 @@ static void test_async_destroy_callback(int ifindex) {
assert_se(t->n_ref == 2);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
- assert_se(sd_netlink_process(rtnl, &r) == 1);
+ assert_se(sd_netlink_process(rtnl, &reply) == 1);
assert_se(t->n_ref == 1);
assert_se(!sd_netlink_message_unref(m));
@@ -394,14 +334,13 @@ static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
return 1;
}
-static void test_pipe(int ifindex) {
+TEST(pipe) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
- int counter = 0;
-
- log_debug("/* %s */", __func__);
+ int ifindex, counter = 0;
assert_se(sd_netlink_open(&rtnl) >= 0);
+ ifindex = (int) if_nametoindex("lo");
assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0);
@@ -420,13 +359,14 @@ static void test_pipe(int ifindex) {
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
-static void test_container(sd_netlink *rtnl) {
+TEST(message_container) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
uint16_t u16_data;
uint32_t u32_data;
const char *string_data;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
@@ -434,9 +374,7 @@ static void test_container(sd_netlink *rtnl) {
assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0);
assert_se(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
- assert_se(sd_netlink_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0);
assert_se(sd_netlink_message_close_container(m) >= 0);
- assert_se(sd_netlink_message_close_container(m) == -EINVAL);
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
@@ -453,16 +391,12 @@ static void test_container(sd_netlink *rtnl) {
assert_se(sd_netlink_message_exit_container(m) >= 0);
assert_se(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0);
-
- assert_se(sd_netlink_message_exit_container(m) == -EINVAL);
}
-static void test_match(void) {
+TEST(sd_netlink_add_match) {
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
- log_debug("/* %s */", __func__);
-
assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
@@ -475,17 +409,17 @@ static void test_match(void) {
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
-static void test_get_addresses(sd_netlink *rtnl) {
+TEST(dump_addresses) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
- sd_netlink_message *m;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
assert_se(sd_netlink_message_set_request_dump(req, true) >= 0);
assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
- for (m = reply; m; m = sd_netlink_message_next(m)) {
+ for (sd_netlink_message *m = reply; m; m = sd_netlink_message_next(m)) {
uint16_t type;
unsigned char scope, flags;
int family, ifindex;
@@ -505,21 +439,20 @@ static void test_get_addresses(sd_netlink *rtnl) {
}
}
-static void test_message(sd_netlink *rtnl) {
+TEST(sd_netlink_message_get_errno) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
}
-static void test_array(void) {
+TEST(message_array) {
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
- log_debug("/* %s */", __func__);
-
assert_se(sd_genl_socket_open(&genl) >= 0);
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
@@ -557,12 +490,13 @@ static void test_array(void) {
assert_se(sd_netlink_message_exit_container(m) >= 0);
}
-static void test_strv(sd_netlink *rtnl) {
+TEST(message_strv) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
_cleanup_strv_free_ char **names_in = NULL, **names_out;
const char *p;
- log_debug("/* %s */", __func__);
+ assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1) >= 0);
@@ -624,7 +558,7 @@ static int genl_ctrl_match_callback(sd_netlink *genl, sd_netlink_message *m, voi
return 0;
}
-static void test_genl(void) {
+TEST(genl) {
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
@@ -632,8 +566,6 @@ static void test_genl(void) {
uint8_t cmd;
int r;
- log_debug("/* %s */", __func__);
-
assert_se(sd_genl_socket_open(&genl) >= 0);
assert_se(sd_event_default(&event) >= 0);
assert_se(sd_netlink_attach_event(genl, event, 0) >= 0);
@@ -669,15 +601,17 @@ static void test_genl(void) {
}
}
-static void test_rtnl_set_link_name(sd_netlink *rtnl, int ifindex) {
+TEST(rtnl_set_link_name) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_strv_free_ char **alternative_names = NULL;
- int r;
-
- log_debug("/* %s */", __func__);
+ int ifindex, r;
if (geteuid() != 0)
return (void) log_tests_skipped("not root");
+ assert_se(sd_netlink_open(&rtnl) >= 0);
+ ifindex = (int) if_nametoindex("lo");
+
/* Test that the new name (which is currently an alternative name) is
* restored as an alternative name on error. Create an error by using
* an invalid device name, namely one that exceeds IFNAMSIZ
@@ -693,68 +627,4 @@ static void test_rtnl_set_link_name(sd_netlink *rtnl, int ifindex) {
assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
}
-int main(void) {
- sd_netlink *rtnl;
- sd_netlink_message *m;
- sd_netlink_message *r;
- const char *string_data;
- int if_loopback;
- uint16_t type;
-
- test_setup_logging(LOG_DEBUG);
-
- test_match();
- test_multiple();
-
- assert_se(sd_netlink_open(&rtnl) >= 0);
- assert_se(rtnl);
-
- test_route(rtnl);
- test_message(rtnl);
- test_container(rtnl);
- test_array();
- test_strv(rtnl);
-
- if_loopback = (int) if_nametoindex("lo");
- assert_se(if_loopback > 0);
-
- test_async(if_loopback);
- test_slot_set(if_loopback);
- test_async_destroy_callback(if_loopback);
- test_pipe(if_loopback);
- test_event_loop(if_loopback);
- test_link_configure(rtnl, if_loopback);
- test_rtnl_set_link_name(rtnl, if_loopback);
-
- test_get_addresses(rtnl);
- test_message_link_bridge(rtnl);
-
- assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);
- assert_se(m);
-
- assert_se(sd_netlink_message_get_type(m, &type) >= 0);
- assert_se(type == RTM_GETLINK);
-
- assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM);
-
- assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1);
- assert_se(sd_netlink_message_get_type(r, &type) >= 0);
- assert_se(type == RTM_NEWLINK);
-
- assert_se((r = sd_netlink_message_unref(r)) == NULL);
-
- assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM);
- assert_se((m = sd_netlink_message_unref(m)) == NULL);
- assert_se((r = sd_netlink_message_unref(r)) == NULL);
-
- test_link_get(rtnl, if_loopback);
- test_address_get(rtnl, if_loopback);
-
- assert_se((m = sd_netlink_message_unref(m)) == NULL);
- assert_se((r = sd_netlink_message_unref(r)) == NULL);
- assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
-
- test_genl();
-
- return EXIT_SUCCESS;
-}
+DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -0,0 +1,105 @@
From 49fa9a23e444f864a4f06fb0c7b1f54ff0513206 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 9 Jan 2023 21:00:53 +0900
Subject: [PATCH] test-netlink: use dummy interface to test assigning new
interface name
Fixes #25981.
(cherry picked from commit 5ccbe7fb197b01e0cf1f1ab523703274ef552555)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/test-netlink.c | 59 ++++++++++++++++++++++--
1 file changed, 55 insertions(+), 4 deletions(-)
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index f740035639..9ad8ecf320 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -601,30 +601,81 @@ TEST(genl) {
}
}
+static void remove_dummy_interfacep(int *ifindex) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
+
+ if (!ifindex || *ifindex <= 0)
+ return;
+
+ assert_se(sd_netlink_open(&rtnl) >= 0);
+
+ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_DELLINK, *ifindex) >= 0);
+ assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1);
+}
+
TEST(rtnl_set_link_name) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
+ _cleanup_(remove_dummy_interfacep) int ifindex = 0;
_cleanup_strv_free_ char **alternative_names = NULL;
- int ifindex, r;
+ int r;
if (geteuid() != 0)
return (void) log_tests_skipped("not root");
assert_se(sd_netlink_open(&rtnl) >= 0);
- ifindex = (int) if_nametoindex("lo");
+
+ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 0) >= 0);
+ assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink") >= 0);
+ assert_se(sd_netlink_message_open_container(message, IFLA_LINKINFO) >= 0);
+ assert_se(sd_netlink_message_append_string(message, IFLA_INFO_KIND, "dummy") >= 0);
+ r = sd_netlink_call(rtnl, message, 0, &reply);
+ if (r == -EPERM)
+ return (void) log_tests_skipped("missing required capabilities");
+ if (r == -EOPNOTSUPP)
+ return (void) log_tests_skipped("dummy network interface is not supported");
+ assert_se(r >= 0);
+
+ message = sd_netlink_message_unref(message);
+ reply = sd_netlink_message_unref(reply);
+
+ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, 0) >= 0);
+ assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, "test-netlink") >= 0);
+ assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
+
+ assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
+ assert_se(ifindex > 0);
/* Test that the new name (which is currently an alternative name) is
* restored as an alternative name on error. Create an error by using
* an invalid device name, namely one that exceeds IFNAMSIZ
* (alternative names can exceed IFNAMSIZ, but not regular names). */
- r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename"));
+ r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename", "test-shortname"));
if (r == -EPERM)
return (void) log_tests_skipped("missing required capabilities");
-
+ if (r == -EOPNOTSUPP)
+ return (void) log_tests_skipped("alternative name is not supported");
assert_se(r >= 0);
+
+ assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
+ assert_se(strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(strv_contains(alternative_names, "test-shortname"));
+
assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename") == -EINVAL);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "test-shortname") >= 0);
+
+ alternative_names = strv_free(alternative_names);
assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
assert_se(strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(!strv_contains(alternative_names, "test-shortname"));
+
assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
+
+ alternative_names = strv_free(alternative_names);
+ assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
+ assert_se(!strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(!strv_contains(alternative_names, "test-shortname"));
}
DEFINE_TEST_MAIN(LOG_DEBUG);

View File

@ -0,0 +1,26 @@
From 2deb458c5fd4ac318018b8464fa677dc4570ba61 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 16:34:31 +0900
Subject: [PATCH] udev: use SYNTHETIC_ERRNO() at one more place
(cherry picked from commit b3cfe5900108df81fbf547b297d51ac8c7359a9b)
Related: RHEL-5988
---
src/udev/udevadm-test-builtin.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
index 81b633611e..5570eec789 100644
--- a/src/udev/udevadm-test-builtin.c
+++ b/src/udev/udevadm-test-builtin.c
@@ -87,8 +87,7 @@ int builtin_main(int argc, char *argv[], void *userdata) {
cmd = udev_builtin_lookup(arg_command);
if (cmd < 0) {
- log_error("Unknown command '%s'", arg_command);
- r = -EINVAL;
+ r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown command '%s'", arg_command);
goto finish;
}

View File

@ -0,0 +1,351 @@
From 09bc1c97130c4e646233ee3ea27ba03c226117d7 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 11:29:49 +0900
Subject: [PATCH] udev: make udev_builtin_run() take UdevEvent*
No functional change, preparation for later commits.
(cherry picked from commit 5668f3a7cfccca704ea8e8bdc84ca7e17a5f101e)
Related: RHEL-5988
---
src/udev/udev-builtin-blkid.c | 3 ++-
src/udev/udev-builtin-btrfs.c | 3 ++-
src/udev/udev-builtin-hwdb.c | 3 ++-
src/udev/udev-builtin-input_id.c | 6 ++----
src/udev/udev-builtin-keyboard.c | 3 ++-
src/udev/udev-builtin-kmod.c | 5 ++---
src/udev/udev-builtin-net_id.c | 3 ++-
src/udev/udev-builtin-net_setup_link.c | 7 ++++---
src/udev/udev-builtin-path_id.c | 5 ++---
src/udev/udev-builtin-uaccess.c | 3 ++-
src/udev/udev-builtin-usb_id.c | 5 ++---
src/udev/udev-builtin.c | 7 ++++---
src/udev/udev-builtin.h | 6 ++++--
src/udev/udev-event.c | 2 +-
src/udev/udev-rules.c | 2 +-
src/udev/udevadm-test-builtin.c | 10 ++++++++--
16 files changed, 42 insertions(+), 31 deletions(-)
diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c
index 9f5646ffdd..63d1bd579d 100644
--- a/src/udev/udev-builtin-blkid.c
+++ b/src/udev/udev-builtin-blkid.c
@@ -237,7 +237,8 @@ static int probe_superblocks(blkid_probe pr) {
return blkid_do_safeprobe(pr);
}
-static int builtin_blkid(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_blkid(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *devnode, *root_partition = NULL, *data, *name;
_cleanup_(blkid_free_probep) blkid_probe pr = NULL;
bool noraid = false, is_gpt = false;
diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c
index 8cd627807f..b36eadb47a 100644
--- a/src/udev/udev-builtin-btrfs.c
+++ b/src/udev/udev-builtin-btrfs.c
@@ -13,7 +13,8 @@
#include "udev-builtin.h"
#include "util.h"
-static int builtin_btrfs(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_btrfs(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
struct btrfs_ioctl_vol_args args = {};
_cleanup_close_ int fd = -1;
int r;
diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c
index 8d652e46fe..19e07e734f 100644
--- a/src/udev/udev-builtin-hwdb.c
+++ b/src/udev/udev-builtin-hwdb.c
@@ -118,7 +118,7 @@ next:
return r;
}
-static int builtin_hwdb(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_hwdb(UdevEvent *event, int argc, char *argv[], bool test) {
static const struct option options[] = {
{ "filter", required_argument, NULL, 'f' },
{ "device", required_argument, NULL, 'd' },
@@ -131,6 +131,7 @@ static int builtin_hwdb(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[
const char *subsystem = NULL;
const char *prefix = NULL;
_cleanup_(sd_device_unrefp) sd_device *srcdev = NULL;
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
if (!hwdb)
diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c
index 0742120248..4322ce04b3 100644
--- a/src/udev/udev-builtin-input_id.c
+++ b/src/udev/udev-builtin-input_id.c
@@ -356,8 +356,8 @@ static bool test_key(sd_device *dev,
return found;
}
-static int builtin_input_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
- sd_device *pdev;
+static int builtin_input_id(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *pdev, *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
unsigned long bitmask_ev[NBITS(EV_MAX)];
unsigned long bitmask_abs[NBITS(ABS_MAX)];
unsigned long bitmask_key[NBITS(KEY_MAX)];
@@ -367,8 +367,6 @@ static int builtin_input_id(sd_device *dev, sd_netlink **rtnl, int argc, char *a
bool is_pointer;
bool is_key;
- assert(dev);
-
/* walk up the parental chain until we find the real input device; the
* argument is very likely a subdevice of this, like eventN */
for (pdev = dev; pdev; ) {
diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c
index 6dd9eebd93..dac087a9e6 100644
--- a/src/udev/udev-builtin-keyboard.c
+++ b/src/udev/udev-builtin-keyboard.c
@@ -159,7 +159,8 @@ static int set_trackpoint_sensitivity(sd_device *dev, const char *value) {
return 0;
}
-static int builtin_keyboard(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_keyboard(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
unsigned release[1024];
unsigned release_count = 0;
_cleanup_close_ int fd = -1;
diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c
index eade042f35..3ab5c485f8 100644
--- a/src/udev/udev-builtin-kmod.c
+++ b/src/udev/udev-builtin-kmod.c
@@ -22,11 +22,10 @@ _printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *fi
log_internalv(priority, 0, file, line, fn, format, args);
}
-static int builtin_kmod(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_kmod(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
- assert(dev);
-
if (!ctx)
return 0;
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index c57568f8cb..cecf854b98 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -1109,7 +1109,8 @@ static int get_link_info(sd_device *dev, LinkInfo *info) {
return 0;
}
-static int builtin_net_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_net_id(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *prefix;
NetNames names = {};
LinkInfo info = {
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index ea7b1c5f60..4bf42cd492 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -10,14 +10,15 @@
static LinkConfigContext *ctx = NULL;
-static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, char **argv, bool test) {
+static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(link_freep) Link *link = NULL;
int r;
if (argc > 1)
return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
- r = link_new(ctx, rtnl, dev, &link);
+ r = link_new(ctx, &event->rtnl, dev, &link);
if (r == -ENODEV) {
log_device_debug_errno(dev, r, "Link vanished while getting information, ignoring.");
return 0;
@@ -38,7 +39,7 @@ static int builtin_net_setup_link(sd_device *dev, sd_netlink **rtnl, int argc, c
return log_device_error_errno(dev, r, "Failed to get link config: %m");
}
- r = link_apply_config(ctx, rtnl, link);
+ r = link_apply_config(ctx, &event->rtnl, link);
if (r == -ENODEV)
log_device_debug_errno(dev, r, "Link vanished while applying configuration, ignoring.");
else if (r < 0)
diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c
index d58a3d5d60..6f4d7cbc5b 100644
--- a/src/udev/udev-builtin-path_id.c
+++ b/src/udev/udev-builtin-path_id.c
@@ -581,15 +581,14 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) {
return 0;
}
-static int builtin_path_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(sd_device_unrefp) sd_device *dev_other_branch = NULL;
_cleanup_free_ char *path = NULL, *compat_path = NULL;
bool supported_transport = false, supported_parent = false;
const char *subsystem;
int r;
- assert(dev);
-
/* walk up the chain of devices and compose path */
for (sd_device *parent = dev; parent; ) {
const char *subsys, *sysname;
diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c
index 6e73d99375..36c993cbb0 100644
--- a/src/udev/udev-builtin-uaccess.c
+++ b/src/udev/udev-builtin-uaccess.c
@@ -16,7 +16,8 @@
#include "log.h"
#include "udev-builtin.h"
-static int builtin_uaccess(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_uaccess(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
const char *path = NULL, *seat;
bool changed_acl = false;
uid_t uid;
diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c
index 847c2b8316..f3fc3cfdb3 100644
--- a/src/udev/udev-builtin-usb_id.c
+++ b/src/udev/udev-builtin-usb_id.c
@@ -224,7 +224,8 @@ static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
* 6.) If the device supplies a serial number, this number
* is concatenated with the identification with an underscore '_'.
*/
-static int builtin_usb_id(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
+static int builtin_usb_id(UdevEvent *event, int argc, char *argv[], bool test) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
char vendor_str[64] = "";
char vendor_str_enc[256];
const char *vendor_id;
@@ -250,8 +251,6 @@ static int builtin_usb_id(sd_device *dev, sd_netlink **rtnl, int argc, char *arg
const char *syspath, *sysname, *devtype, *interface_syspath;
int r;
- assert(dev);
-
r = sd_device_get_syspath(dev, &syspath);
if (r < 0)
return r;
diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
index c98c6fa714..c84db8855c 100644
--- a/src/udev/udev-builtin.c
+++ b/src/udev/udev-builtin.c
@@ -98,11 +98,12 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) {
return _UDEV_BUILTIN_INVALID;
}
-int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, const char *command, bool test) {
+int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test) {
_cleanup_strv_free_ char **argv = NULL;
int r;
- assert(dev);
+ assert(event);
+ assert(event->dev);
assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX);
assert(command);
@@ -115,7 +116,7 @@ int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd,
/* we need '0' here to reset the internal state */
optind = 0;
- return builtins[cmd]->cmd(dev, rtnl, strv_length(argv), argv, test);
+ return builtins[cmd]->cmd(event, strv_length(argv), argv, test);
}
int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val) {
diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h
index bcfec03aae..919d51e798 100644
--- a/src/udev/udev-builtin.h
+++ b/src/udev/udev-builtin.h
@@ -6,6 +6,8 @@
#include "sd-device.h"
#include "sd-netlink.h"
+#include "udev-event.h"
+
typedef enum UdevBuiltinCommand {
#if HAVE_BLKID
UDEV_BUILTIN_BLKID,
@@ -30,7 +32,7 @@ typedef enum UdevBuiltinCommand {
typedef struct UdevBuiltin {
const char *name;
- int (*cmd)(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test);
+ int (*cmd)(UdevEvent *event, int argc, char *argv[], bool test);
const char *help;
int (*init)(void);
void (*exit)(void);
@@ -74,7 +76,7 @@ void udev_builtin_exit(void);
UdevBuiltinCommand udev_builtin_lookup(const char *command);
const char *udev_builtin_name(UdevBuiltinCommand cmd);
bool udev_builtin_run_once(UdevBuiltinCommand cmd);
-int udev_builtin_run(sd_device *dev, sd_netlink **rtnl, UdevBuiltinCommand cmd, const char *command, bool test);
+int udev_builtin_run(UdevEvent *event, UdevBuiltinCommand cmd, const char *command, bool test);
void udev_builtin_list(void);
bool udev_builtin_should_reload(void);
int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val);
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index fab454ae37..cf90d6f205 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -1200,7 +1200,7 @@ void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_s
if (builtin_cmd != _UDEV_BUILTIN_INVALID) {
log_device_debug(event->dev, "Running built-in command \"%s\"", command);
- r = udev_builtin_run(event->dev, &event->rtnl, builtin_cmd, command, false);
+ r = udev_builtin_run(event, builtin_cmd, command, false);
if (r < 0)
log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command);
} else {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index a8473041c3..9336ce1cd3 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1972,7 +1972,7 @@ static int udev_rule_apply_token_to_event(
log_rule_debug(dev, rules, "Importing properties from results of builtin command '%s'", buf);
- r = udev_builtin_run(dev, &event->rtnl, cmd, buf, false);
+ r = udev_builtin_run(event, cmd, buf, false);
if (r < 0) {
/* remember failure */
log_rule_debug_errno(dev, rules, r, "Failed to run builtin '%s': %m", buf);
diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c
index 5570eec789..5d1fafbd03 100644
--- a/src/udev/udevadm-test-builtin.c
+++ b/src/udev/udevadm-test-builtin.c
@@ -72,7 +72,7 @@ static int parse_argv(int argc, char *argv[]) {
}
int builtin_main(int argc, char *argv[], void *userdata) {
- _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+ _cleanup_(udev_event_freep) UdevEvent *event = NULL;
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
UdevBuiltinCommand cmd;
int r;
@@ -97,7 +97,13 @@ int builtin_main(int argc, char *argv[], void *userdata) {
goto finish;
}
- r = udev_builtin_run(dev, &rtnl, cmd, arg_command, true);
+ event = udev_event_new(dev, 0, NULL, LOG_DEBUG);
+ if (!event) {
+ r = log_oom();
+ goto finish;
+ }
+
+ r = udev_builtin_run(event, cmd, arg_command, true);
if (r < 0)
log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command);

View File

@ -0,0 +1,26 @@
From 87a2e6ccd7989f2b271f557c6303a4eb412a03cb Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 11:46:11 +0900
Subject: [PATCH] udev/net: verify ID_NET_XYZ before trying to assign it as an
alternative name
(cherry picked from commit e65c6c1baa8ea905f7e5bad3b8486d509775ec6a)
Related: RHEL-5988
---
src/udev/net/link-config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 5d28526527..4fcf373f8e 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -834,7 +834,7 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
default:
assert_not_reached();
}
- if (!isempty(n)) {
+ if (ifname_valid_full(n, IFNAME_VALID_ALTERNATIVE)) {
r = strv_extend(&altnames, n);
if (r < 0)
return log_oom();

View File

@ -0,0 +1,29 @@
From dd4c492721ed4be1b4c26cd937566dac2e97ba19 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 13:05:09 +0900
Subject: [PATCH] udev/net: generate new network interface name only on add
uevent
On other uevents, the name will be anyway ignored in rename_netif() in
udev-event.c.
(cherry picked from commit cd941e6596adba6bb139c387ae596f26b35701f7)
Related: RHEL-5988
---
src/udev/net/link-config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 4fcf373f8e..c9789bcb7c 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -722,7 +722,7 @@ static int link_generate_new_name(Link *link) {
config = link->config;
device = link->device;
- if (link->action == SD_DEVICE_MOVE) {
+ if (link->action != SD_DEVICE_ADD) {
log_link_debug(link, "Skipping to apply Name= and NamePolicy= on '%s' uevent.",
device_action_to_string(link->action));
goto no_rename;

View File

@ -0,0 +1,191 @@
From ea5725b1e621c2733c28f818c3a58615a385337e Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 13:29:37 +0900
Subject: [PATCH] sd-netlink: make rtnl_set_link_name() optionally append
alternative names
(cherry picked from commit 81824455008070253c62bf5c27187028ba8e7e99)
Related: RHEL-5988
---
src/libsystemd/sd-netlink/netlink-util.c | 89 ++++++++++++++++++------
src/libsystemd/sd-netlink/netlink-util.h | 5 +-
src/libsystemd/sd-netlink/test-netlink.c | 6 +-
src/udev/udev-event.c | 2 +-
4 files changed, 78 insertions(+), 24 deletions(-)
diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c
index cfcf2578d6..5438737b42 100644
--- a/src/libsystemd/sd-netlink/netlink-util.c
+++ b/src/libsystemd/sd-netlink/netlink-util.c
@@ -11,44 +11,93 @@
#include "process-util.h"
#include "strv.h"
-int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
+static int set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
- _cleanup_strv_free_ char **alternative_names = NULL;
- bool altname_deleted = false;
int r;
assert(rtnl);
assert(ifindex > 0);
assert(name);
- if (!ifname_valid(name))
+ /* Assign the requested name. */
+ r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
+ if (r < 0)
+ return r;
+
+ return sd_netlink_call(*rtnl, message, 0, NULL);
+}
+
+int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const *alternative_names) {
+ _cleanup_strv_free_ char **original_altnames = NULL, **new_altnames = NULL;
+ bool altname_deleted = false;
+ int r;
+
+ assert(rtnl);
+ assert(ifindex > 0);
+
+ if (isempty(name) && strv_isempty(alternative_names))
+ return 0;
+
+ if (name && !ifname_valid(name))
return -EINVAL;
- r = rtnl_get_link_alternative_names(rtnl, ifindex, &alternative_names);
+ /* If the requested name is already assigned as an alternative name, then first drop it. */
+ r = rtnl_get_link_alternative_names(rtnl, ifindex, &original_altnames);
if (r < 0)
log_debug_errno(r, "Failed to get alternative names on network interface %i, ignoring: %m",
ifindex);
- if (strv_contains(alternative_names, name)) {
- r = rtnl_delete_link_alternative_names(rtnl, ifindex, STRV_MAKE(name));
- if (r < 0)
- return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
- name, ifindex);
+ if (name) {
+ if (strv_contains(original_altnames, name)) {
+ r = rtnl_delete_link_alternative_names(rtnl, ifindex, STRV_MAKE(name));
+ if (r < 0)
+ return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m",
+ name, ifindex);
+
+ altname_deleted = true;
+ }
- altname_deleted = true;
+ r = set_link_name(rtnl, ifindex, name);
+ if (r < 0)
+ goto fail;
}
- r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex);
- if (r < 0)
- goto fail;
+ /* Filter out already assigned names from requested alternative names. Also, dedup the request. */
+ STRV_FOREACH(a, alternative_names) {
+ if (streq_ptr(name, *a))
+ continue;
- r = sd_netlink_message_append_string(message, IFLA_IFNAME, name);
- if (r < 0)
- goto fail;
+ if (strv_contains(original_altnames, *a))
+ continue;
- r = sd_netlink_call(*rtnl, message, 0, NULL);
- if (r < 0)
- goto fail;
+ if (strv_contains(new_altnames, *a))
+ continue;
+
+ if (!ifname_valid_full(*a, IFNAME_VALID_ALTERNATIVE))
+ continue;
+
+ r = strv_extend(&new_altnames, *a);
+ if (r < 0)
+ return r;
+ }
+
+ strv_sort(new_altnames);
+
+ /* Finally, assign alternative names. */
+ r = rtnl_set_link_alternative_names(rtnl, ifindex, new_altnames);
+ if (r == -EEXIST) /* Already assigned to another interface? */
+ STRV_FOREACH(a, new_altnames) {
+ r = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(*a));
+ if (r < 0)
+ log_debug_errno(r, "Failed to assign '%s' as an alternative name on network interface %i, ignoring: %m",
+ *a, ifindex);
+ }
+ else if (r < 0)
+ log_debug_errno(r, "Failed to assign alternative names on network interface %i, ignoring: %m", ifindex);
return 0;
diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h
index d14392a018..888e28642d 100644
--- a/src/libsystemd/sd-netlink/netlink-util.h
+++ b/src/libsystemd/sd-netlink/netlink-util.h
@@ -29,7 +29,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free);
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret);
-int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
+int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name, char* const* alternative_names);
+static inline int rtnl_append_link_alternative_names(sd_netlink **rtnl, int ifindex, char* const *alternative_names) {
+ return rtnl_set_link_name(rtnl, ifindex, NULL, alternative_names);
+}
int rtnl_set_link_properties(
sd_netlink **rtnl,
int ifindex,
diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c
index 9ad8ecf320..43124b99ae 100644
--- a/src/libsystemd/sd-netlink/test-netlink.c
+++ b/src/libsystemd/sd-netlink/test-netlink.c
@@ -662,12 +662,13 @@ TEST(rtnl_set_link_name) {
assert_se(strv_contains(alternative_names, "testlongalternativename"));
assert_se(strv_contains(alternative_names, "test-shortname"));
- assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename") == -EINVAL);
- assert_se(rtnl_set_link_name(&rtnl, ifindex, "test-shortname") >= 0);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename", NULL) == -EINVAL);
+ assert_se(rtnl_set_link_name(&rtnl, ifindex, "test-shortname", STRV_MAKE("testlongalternativename", "test-shortname", "test-additional-name")) >= 0);
alternative_names = strv_free(alternative_names);
assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
assert_se(strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(strv_contains(alternative_names, "test-additional-name"));
assert_se(!strv_contains(alternative_names, "test-shortname"));
assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0);
@@ -675,6 +676,7 @@ TEST(rtnl_set_link_name) {
alternative_names = strv_free(alternative_names);
assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0);
assert_se(!strv_contains(alternative_names, "testlongalternativename"));
+ assert_se(strv_contains(alternative_names, "test-additional-name"));
assert_se(!strv_contains(alternative_names, "test-shortname"));
}
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index cf90d6f205..2662806d61 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -980,7 +980,7 @@ static int rename_netif(UdevEvent *event) {
goto revert;
}
- r = rtnl_set_link_name(&event->rtnl, ifindex, event->name);
+ r = rtnl_set_link_name(&event->rtnl, ifindex, event->name, NULL);
if (r < 0) {
if (r == -EBUSY) {
log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",

View File

@ -0,0 +1,233 @@
From 11f76dbf187708c3eda4a4daeb058f544ea28af5 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 12:28:23 +0900
Subject: [PATCH] udev/net: assign alternative names only on add uevent
Previously, we first assign alternative names to a network interface,
then later change its main name if requested. So, we could not assign
the name that currently assigned as the main name of an interface as an
alternative name. So, we retry to assign the previous main name as an
alternative name on later move uevent.
However, that causes some confusing situation. E.g. if a .link file has
```
Name=foo
AlternativeNames=foo baz
```
then even if the interface is renamed by a user e.g. by invoking 'ip link'
command manually, the interface can be still referenced as 'foo', as the
name is now assigned as an alternative name.
This makes the order of name assignment inverse: the main name is first
changed, and then the requested alternative names are assigned. And
udevd do not assign alternative names on move uevent.
Replaces #27506.
(cherry picked from commit 9094ae52caca0c19ff6abdbd95d17d8e401ea3b1)
Resolves: RHEL-5988
---
src/udev/net/link-config.c | 37 ++++++++-------------
src/udev/net/link-config.h | 1 +
src/udev/udev-builtin-net_setup_link.c | 2 ++
src/udev/udev-event.c | 45 ++++++++++++++++++++++----
src/udev/udev-event.h | 1 +
5 files changed, 55 insertions(+), 31 deletions(-)
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index c9789bcb7c..2d8c902fd3 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -363,6 +363,7 @@ Link *link_free(Link *link) {
sd_device_unref(link->device);
free(link->kind);
free(link->driver);
+ strv_free(link->altnames);
return mfree(link);
}
@@ -791,19 +792,22 @@ no_rename:
return 0;
}
-static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
- _cleanup_strv_free_ char **altnames = NULL, **current_altnames = NULL;
+static int link_generate_alternative_names(Link *link) {
+ _cleanup_strv_free_ char **altnames = NULL;
LinkConfig *config;
sd_device *device;
int r;
assert(link);
- assert(link->config);
- assert(link->device);
- assert(rtnl);
+ config = ASSERT_PTR(link->config);
+ device = ASSERT_PTR(link->device);
+ assert(!link->altnames);
- config = link->config;
- device = link->device;
+ if (link->action != SD_DEVICE_ADD) {
+ log_link_debug(link, "Skipping to apply AlternativeNames= and AlternativeNamesPolicy= on '%s' uevent.",
+ device_action_to_string(link->action));
+ return 0;
+ }
if (config->alternative_names) {
altnames = strv_copy(config->alternative_names);
@@ -841,22 +845,7 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) {
}
}
- strv_remove(altnames, link->ifname);
-
- r = rtnl_get_link_alternative_names(rtnl, link->ifindex, &current_altnames);
- if (r < 0)
- log_link_debug_errno(link, r, "Failed to get alternative names, ignoring: %m");
-
- STRV_FOREACH(p, current_altnames)
- strv_remove(altnames, *p);
-
- strv_uniq(altnames);
- strv_sort(altnames);
- r = rtnl_set_link_alternative_names(rtnl, link->ifindex, altnames);
- if (r < 0)
- log_link_full_errno(link, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r,
- "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
-
+ link->altnames = TAKE_PTR(altnames);
return 0;
}
@@ -958,7 +947,7 @@ int link_apply_config(LinkConfigContext *ctx, sd_netlink **rtnl, Link *link) {
if (r < 0)
return r;
- r = link_apply_alternative_names(link, rtnl);
+ r = link_generate_alternative_names(link);
if (r < 0)
return r;
diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h
index ea9f560f45..874a391543 100644
--- a/src/udev/net/link-config.h
+++ b/src/udev/net/link-config.h
@@ -27,6 +27,7 @@ typedef struct Link {
int ifindex;
const char *ifname;
const char *new_name;
+ char **altnames;
LinkConfig *config;
sd_device *device;
diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c
index 4bf42cd492..e964bf7bf4 100644
--- a/src/udev/udev-builtin-net_setup_link.c
+++ b/src/udev/udev-builtin-net_setup_link.c
@@ -49,6 +49,8 @@ static int builtin_net_setup_link(UdevEvent *event, int argc, char **argv, bool
if (link->new_name)
udev_builtin_add_property(dev, test, "ID_NET_NAME", link->new_name);
+ event->altnames = TAKE_PTR(link->altnames);
+
return 0;
}
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 2662806d61..3315d34eff 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -88,6 +88,7 @@ UdevEvent *udev_event_free(UdevEvent *event) {
ordered_hashmap_free_free_free(event->seclabel_list);
free(event->program_result);
free(event->name);
+ strv_free(event->altnames);
return mfree(event);
}
@@ -918,9 +919,6 @@ static int rename_netif(UdevEvent *event) {
dev = ASSERT_PTR(event->dev);
- if (!device_for_action(dev, SD_DEVICE_ADD))
- return 0; /* Rename the interface only when it is added. */
-
r = sd_device_get_ifindex(dev, &ifindex);
if (r == -ENOENT)
return 0; /* Device is not a network interface. */
@@ -980,7 +978,7 @@ static int rename_netif(UdevEvent *event) {
goto revert;
}
- r = rtnl_set_link_name(&event->rtnl, ifindex, event->name, NULL);
+ r = rtnl_set_link_name(&event->rtnl, ifindex, event->name, event->altnames);
if (r < 0) {
if (r == -EBUSY) {
log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.",
@@ -1011,6 +1009,35 @@ revert:
return r;
}
+static int assign_altnames(UdevEvent *event) {
+ sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
+ int ifindex, r;
+ const char *s;
+
+ if (strv_isempty(event->altnames))
+ return 0;
+
+ r = sd_device_get_ifindex(dev, &ifindex);
+ if (r == -ENOENT)
+ return 0; /* Device is not a network interface. */
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to get ifindex: %m");
+
+ r = sd_device_get_sysname(dev, &s);
+ if (r < 0)
+ return log_device_warning_errno(dev, r, "Failed to get sysname: %m");
+
+ /* Filter out the current interface name. */
+ strv_remove(event->altnames, s);
+
+ r = rtnl_append_link_alternative_names(&event->rtnl, ifindex, event->altnames);
+ if (r < 0)
+ log_device_full_errno(dev, r == -EOPNOTSUPP ? LOG_DEBUG : LOG_WARNING, r,
+ "Could not set AlternativeName= or apply AlternativeNamesPolicy=, ignoring: %m");
+
+ return 0;
+}
+
static int update_devnode(UdevEvent *event) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
int r;
@@ -1163,9 +1190,13 @@ int udev_event_execute_rules(
DEVICE_TRACE_POINT(rules_finished, dev);
- r = rename_netif(event);
- if (r < 0)
- return r;
+ if (action == SD_DEVICE_ADD) {
+ r = rename_netif(event);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ (void) assign_altnames(event);
+ }
r = update_devnode(event);
if (r < 0)
diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h
index 74d065ce23..13bd85dcf7 100644
--- a/src/udev/udev-event.h
+++ b/src/udev/udev-event.h
@@ -23,6 +23,7 @@ typedef struct UdevEvent {
sd_device *dev_parent;
sd_device *dev_db_clone;
char *name;
+ char **altnames;
char *program_result;
mode_t mode;
uid_t uid;

View File

@ -0,0 +1,105 @@
From dec129d192c7815bdfbb71c88a1d7cdc3092f11f Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 16 May 2023 16:28:54 +0900
Subject: [PATCH] test: add tests for renaming network interface
(cherry picked from commit 40b6b448bda5294582e685091123952fbcd43502)
Related: RHEL-5988
---
test/units/testsuite-17.12.sh | 86 +++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
create mode 100755 test/units/testsuite-17.12.sh
diff --git a/test/units/testsuite-17.12.sh b/test/units/testsuite-17.12.sh
new file mode 100755
index 0000000000..df74d356ee
--- /dev/null
+++ b/test/units/testsuite-17.12.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.1-or-later
+set -ex
+set -o pipefail
+
+# shellcheck source=test/units/assert.sh
+. "$(dirname "$0")"/assert.sh
+
+create_link_file() {
+ name=${1?}
+
+ mkdir -p /run/systemd/network/
+ cat >/run/systemd/network/10-test.link <<EOF
+[Match]
+Kind=dummy
+MACAddress=00:50:56:c0:00:18
+
+[Link]
+Name=$name
+AlternativeName=test1 test2 test3 test4
+EOF
+ udevadm control --reload
+}
+
+udevadm control --log-level=debug
+
+create_link_file test1
+ip link add address 00:50:56:c0:00:18 type dummy
+udevadm wait --settle --timeout=30 /sys/class/net/test1
+output=$(ip link show dev test1)
+if ! [[ "$output" =~ altname ]]; then
+ echo "alternative name for network interface not supported, skipping test."
+ exit 0
+fi
+assert_not_in "altname test1" "$output"
+assert_in "altname test2" "$output"
+assert_in "altname test3" "$output"
+assert_in "altname test4" "$output"
+
+# By triggering add event, Name= and AlternativeNames= are re-applied
+create_link_file test2
+udevadm trigger --action add --settle /sys/class/net/test1
+udevadm wait --settle --timeout=30 /sys/class/net/test2
+output=$(ip link show dev test2)
+assert_in "altname test1" "$output"
+assert_not_in "altname test2" "$output"
+assert_in "altname test3" "$output"
+assert_in "altname test4" "$output"
+
+# Name= and AlternativeNames= are not applied on move event
+create_link_file test3
+udevadm trigger --action move --settle /sys/class/net/test2
+udevadm wait --settle --timeout=30 /sys/class/net/test2
+output=$(ip link show dev test2)
+assert_in "altname test1" "$output"
+assert_not_in "altname test2" "$output"
+assert_in "altname test3" "$output"
+assert_in "altname test4" "$output"
+
+# Test move event triggered by manual renaming
+ip link set dev test2 name hoge
+udevadm wait --settle --timeout=30 /sys/class/net/hoge
+output=$(ip link show dev hoge)
+assert_in "altname test1" "$output"
+assert_not_in "altname test2" "$output"
+assert_in "altname test3" "$output"
+assert_in "altname test4" "$output"
+assert_not_in "altname hoge" "$output"
+
+# Re-test add event
+udevadm trigger --action add --settle /sys/class/net/hoge
+udevadm wait --settle --timeout=30 /sys/class/net/test3
+output=$(ip link show dev test3)
+assert_in "altname test1" "$output"
+assert_in "altname test2" "$output"
+assert_not_in "altname test3" "$output"
+assert_in "altname test4" "$output"
+assert_not_in "altname hoge" "$output"
+
+# cleanup
+ip link del dev test3
+
+rm -f /run/systemd/network/10-test.link
+udevadm control --reload --log-level=info
+
+exit 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
From 27e95f2513e24a6abc26c56f05c67c34492442d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 15 Nov 2022 15:00:57 +0100
Subject: [PATCH] bootctl: make --json output normal json
We would output a sequence of concatenated JSON strings. 'jq' accepts such
output without fuss, and can even automatically build an array with --slurp/-s.
Nevertheless, parsing this format is more effort for the reader, since it's not
"standard JSON". E.g. Python's json module cannot do this out-of-the-box, but
needs some loop with json.JSONDecoder.raw_decode() and then collecting the
objects into an array. Such streaming output make sense in case of logs, where
we stream the output and it has no predefined length. But here we expect at
most a few dozen entries, so it's nicer to write normal JSON that is trivial to
parse.
I'm treating this is a bugfix and not attempting to provide compatibility
backwards. I don't think the previous format was seeing much use, and it's
trivial to adapt to the new one.
(cherry picked from commit b570204a97bccfbfce8fc4ffa65306f8a06fe16e)
Related: RHEL-13199
---
src/shared/bootspec.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
index d3cfb41a12..fe44b5e9d2 100644
--- a/src/shared/bootspec.c
+++ b/src/shared/bootspec.c
@@ -1408,6 +1408,8 @@ int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
assert(config);
if (!FLAGS_SET(json_format, JSON_FORMAT_OFF)) {
+ _cleanup_(json_variant_unrefp) JsonVariant *array = NULL;
+
for (size_t i = 0; i < config->n_entries; i++) {
_cleanup_free_ char *opts = NULL;
const BootEntry *e = config->entries + i;
@@ -1447,9 +1449,13 @@ int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) {
if (r < 0)
return log_oom();
- json_variant_dump(v, json_format, stdout, NULL);
+ r = json_variant_append_array(&array, v);
+ if (r < 0)
+ return log_oom();
}
+ json_variant_dump(array, json_format, NULL, NULL);
+
} else {
for (size_t n = 0; n < config->n_entries; n++) {
r = show_boot_entry(

View File

@ -0,0 +1,28 @@
From 8fced1b2ed30b9cda338c35946d8dcc3820ac25a Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 5 Jul 2023 19:43:43 +0200
Subject: [PATCH] test: replace readfp() with read_file()
ConfigParser.readfp() has been deprecated since Python 3.2 and was
dropped completely in Python 3.11.
(cherry picked from commit ba4a1cd8a863f65ff016be72e520c323aa1e1a6f)
Related: RHEL-13199
---
test/sysv-generator-test.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
index 484b610a02..84237bab61 100755
--- a/test/sysv-generator-test.py
+++ b/test/sysv-generator-test.py
@@ -80,7 +80,7 @@ class SysvGeneratorTest(unittest.TestCase):
cp = RawConfigParser(dict_type=MultiDict)
cp.optionxform = lambda o: o # don't lower-case option names
with open(service) as f:
- cp.readfp(f)
+ cp.read_file(f)
results[os.path.basename(service)] = cp
return (err, results)

View File

@ -0,0 +1,81 @@
From fe66c5955044cf2b93fa788ae7bdfe3a07f11449 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Sun, 21 May 2023 14:32:09 +0100
Subject: [PATCH] stub/measure: document and measure .uname UKI section
(cherry picked from commit b6f2e6860220aa89550f690b12246c4e8eb6e908)
Resolves: RHEL-13199
---
man/systemd-stub.xml | 3 +++
src/boot/measure.c | 3 +++
src/fundamental/tpm-pcr.c | 1 +
src/fundamental/tpm-pcr.h | 1 +
4 files changed, 8 insertions(+)
diff --git a/man/systemd-stub.xml b/man/systemd-stub.xml
index 415d663f53..85d30129d6 100644
--- a/man/systemd-stub.xml
+++ b/man/systemd-stub.xml
@@ -57,6 +57,9 @@
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry> file of
the OS the kernel belongs to, in the <literal>.osrel</literal> PE section.</para></listitem>
+ <listitem><para>Kernel version information, i.e. the output of <command>uname -r</command> for the
+ kernel included in the UKI, in the <literal>.uname</literal> PE section.</para></listitem>
+
<listitem><para>The initrd will be loaded from the <literal>.initrd</literal> PE section.
</para></listitem>
diff --git a/src/boot/measure.c b/src/boot/measure.c
index 0bbd386449..67ab84753e 100644
--- a/src/boot/measure.c
+++ b/src/boot/measure.c
@@ -79,6 +79,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --initrd=PATH Path to initrd image file %7$s .initrd\n"
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
" --dtb=PATH Path to Devicetree file %7$s .dtb\n"
+ " --uname=PATH Path to 'uname -r' file %7$s .uname\n"
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
@@ -118,6 +119,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_INITRD,
ARG_SPLASH,
ARG_DTB,
+ ARG_UNAME,
_ARG_PCRSIG, /* the .pcrsig section is not input for signing, hence not actually an argument here */
_ARG_SECTION_LAST,
ARG_PCRPKEY = _ARG_SECTION_LAST,
@@ -139,6 +141,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "initrd", required_argument, NULL, ARG_INITRD },
{ "splash", required_argument, NULL, ARG_SPLASH },
{ "dtb", required_argument, NULL, ARG_DTB },
+ { "uname", required_argument, NULL, ARG_UNAME },
{ "pcrpkey", required_argument, NULL, ARG_PCRPKEY },
{ "current", no_argument, NULL, 'c' },
{ "bank", required_argument, NULL, ARG_BANK },
diff --git a/src/fundamental/tpm-pcr.c b/src/fundamental/tpm-pcr.c
index 7609d83c2e..0685d37b05 100644
--- a/src/fundamental/tpm-pcr.c
+++ b/src/fundamental/tpm-pcr.c
@@ -11,6 +11,7 @@ const char* const unified_sections[_UNIFIED_SECTION_MAX + 1] = {
[UNIFIED_SECTION_INITRD] = ".initrd",
[UNIFIED_SECTION_SPLASH] = ".splash",
[UNIFIED_SECTION_DTB] = ".dtb",
+ [UNIFIED_SECTION_UNAME] = ".uname",
[UNIFIED_SECTION_PCRSIG] = ".pcrsig",
[UNIFIED_SECTION_PCRPKEY] = ".pcrpkey",
NULL,
diff --git a/src/fundamental/tpm-pcr.h b/src/fundamental/tpm-pcr.h
index 235d4841b0..24240b82ed 100644
--- a/src/fundamental/tpm-pcr.h
+++ b/src/fundamental/tpm-pcr.h
@@ -34,6 +34,7 @@ typedef enum UnifiedSection {
UNIFIED_SECTION_INITRD,
UNIFIED_SECTION_SPLASH,
UNIFIED_SECTION_DTB,
+ UNIFIED_SECTION_UNAME,
UNIFIED_SECTION_PCRSIG,
UNIFIED_SECTION_PCRPKEY,
_UNIFIED_SECTION_MAX,

View File

@ -0,0 +1,96 @@
From 16b3bb1a1bb8a0a42ad6eb56fd33dcb800c8af04 Mon Sep 17 00:00:00 2001
From: Luca Boccassi <bluca@debian.org>
Date: Thu, 29 Jun 2023 23:41:48 +0100
Subject: [PATCH] boot: measure .sbat section
We are now merging .sbat sections from sd-stub and kernel image, so
measure it in PCR11.
(cherry picked from commit d5f91cf79361cab58e32bf7b76c41ba244add75f)
Resolves: RHEL-13199
---
man/systemd-measure.xml | 8 +++++---
src/boot/measure.c | 3 +++
src/fundamental/tpm-pcr.c | 1 +
src/fundamental/tpm-pcr.h | 1 +
4 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/man/systemd-measure.xml b/man/systemd-measure.xml
index 46fc979654..e08dbcdac9 100644
--- a/man/systemd-measure.xml
+++ b/man/systemd-measure.xml
@@ -66,9 +66,10 @@
<listitem><para>Pre-calculate the expected values seen in PCR register 11 after boot-up of a unified
kernel image consisting of the components specified with <option>--linux=</option>,
<option>--osrel=</option>, <option>--cmdline=</option>, <option>--initrd=</option>,
- <option>--splash=</option>, <option>--dtb=</option>, <option>--pcrpkey=</option> see below. Only
- <option>--linux=</option> is mandatory. (Alternatively, specify <option>--current</option> to use the
- current values of PCR register 11 instead.)</para></listitem>
+ <option>--splash=</option>, <option>--dtb=</option>, <option>--sbat=</option>,
+ <option>--pcrpkey=</option> see below. Only <option>--linux=</option> is mandatory. (Alternatively,
+ specify <option>--current</option> to use the current values of PCR register 11 instead.)</para>
+ </listitem>
</varlistentry>
<varlistentry>
@@ -104,6 +105,7 @@
<term><option>--initrd=PATH</option></term>
<term><option>--splash=PATH</option></term>
<term><option>--dtb=PATH</option></term>
+ <term><option>--sbat=PATH</option></term>
<term><option>--pcrpkey=PATH</option></term>
<listitem><para>When used with the <command>calculate</command> or <command>sign</command> verb,
diff --git a/src/boot/measure.c b/src/boot/measure.c
index 67ab84753e..84a7c357a4 100644
--- a/src/boot/measure.c
+++ b/src/boot/measure.c
@@ -80,6 +80,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
" --dtb=PATH Path to Devicetree file %7$s .dtb\n"
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
+ " --sbat=PATH Path to SBAT file %7$s .sbat\n"
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
@@ -120,6 +121,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_SPLASH,
ARG_DTB,
ARG_UNAME,
+ ARG_SBAT,
_ARG_PCRSIG, /* the .pcrsig section is not input for signing, hence not actually an argument here */
_ARG_SECTION_LAST,
ARG_PCRPKEY = _ARG_SECTION_LAST,
@@ -142,6 +144,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "splash", required_argument, NULL, ARG_SPLASH },
{ "dtb", required_argument, NULL, ARG_DTB },
{ "uname", required_argument, NULL, ARG_UNAME },
+ { "sbat", required_argument, NULL, ARG_SBAT },
{ "pcrpkey", required_argument, NULL, ARG_PCRPKEY },
{ "current", no_argument, NULL, 'c' },
{ "bank", required_argument, NULL, ARG_BANK },
diff --git a/src/fundamental/tpm-pcr.c b/src/fundamental/tpm-pcr.c
index 0685d37b05..2f7e9b428d 100644
--- a/src/fundamental/tpm-pcr.c
+++ b/src/fundamental/tpm-pcr.c
@@ -12,6 +12,7 @@ const char* const unified_sections[_UNIFIED_SECTION_MAX + 1] = {
[UNIFIED_SECTION_SPLASH] = ".splash",
[UNIFIED_SECTION_DTB] = ".dtb",
[UNIFIED_SECTION_UNAME] = ".uname",
+ [UNIFIED_SECTION_SBAT] = ".sbat",
[UNIFIED_SECTION_PCRSIG] = ".pcrsig",
[UNIFIED_SECTION_PCRPKEY] = ".pcrpkey",
NULL,
diff --git a/src/fundamental/tpm-pcr.h b/src/fundamental/tpm-pcr.h
index 24240b82ed..794d593825 100644
--- a/src/fundamental/tpm-pcr.h
+++ b/src/fundamental/tpm-pcr.h
@@ -35,6 +35,7 @@ typedef enum UnifiedSection {
UNIFIED_SECTION_SPLASH,
UNIFIED_SECTION_DTB,
UNIFIED_SECTION_UNAME,
+ UNIFIED_SECTION_SBAT,
UNIFIED_SECTION_PCRSIG,
UNIFIED_SECTION_PCRPKEY,
_UNIFIED_SECTION_MAX,

View File

@ -0,0 +1,42 @@
From 3c235c8d26813ae428053c284b67ddfe70d9caed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 22 Nov 2023 15:38:47 +0100
Subject: [PATCH] Revert "test_ukify: no stinky root needed for signing"
This reverts commit 0d66468243d888dd721ba0072cbad742ab6fc690.
There was a huge rewrite of the tpm2 code that removed the requirement for
device access, but backporting that would be a huge effort. Let's instead skip
the tests for now. (They pass under root.)
Related: RHEL-13199
---
src/ukify/test/test_ukify.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py
index b12c09d4bf..5a42a94799 100755
--- a/src/ukify/test/test_ukify.py
+++ b/src/ukify/test/test_ukify.py
@@ -661,6 +661,10 @@ def test_pcr_signing(kernel_initrd, tmpdir):
pytest.skip('linux+initrd not found')
if systemd_measure() is None:
pytest.skip('systemd-measure not found')
+ if os.getuid() != 0:
+ pytest.skip('must be root to access tpm2')
+ if subprocess.call(['systemd-creds', 'has-tpm2', '-q']) != 0:
+ pytest.skip('tpm2 is not available')
ourdir = pathlib.Path(__file__).parent
pub = unbase64(ourdir / 'example.tpm2-pcr-public.pem.base64')
@@ -724,6 +728,10 @@ def test_pcr_signing2(kernel_initrd, tmpdir):
pytest.skip('linux+initrd not found')
if systemd_measure() is None:
pytest.skip('systemd-measure not found')
+ if os.getuid() != 0:
+ pytest.skip('must be root to access tpm2')
+ if subprocess.call(['systemd-creds', 'has-tpm2', '-q']) != 0:
+ pytest.skip('tpm2 is not available')
ourdir = pathlib.Path(__file__).parent
pub = unbase64(ourdir / 'example.tpm2-pcr-public.pem.base64')

View File

@ -0,0 +1,36 @@
From 2adec0d845e6d00a604ddaa5639759896b78728f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 28 Aug 2023 18:22:43 +0300
Subject: [PATCH] ukify: move to /usr/bin and mark as non non-experimental
The tool is moved into the $PATH and a compat symlink is provided.
It is fairly widely used now, and realistically we need to keep backwards
compat or people will be very unhappy.
(cherry picked from commit f65aa477d90ab7fbbc50ba05c55180213d5992e0)
Related: RHEL-13199
---
meson.build | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index b874c2f9b4..e0495ed36a 100644
--- a/meson.build
+++ b/meson.build
@@ -3861,9 +3861,13 @@ ukify = custom_target(
command : [jinja2_cmdline, '@INPUT@', '@OUTPUT@'],
install : want_ukify,
install_mode : 'rwxr-xr-x',
- install_dir : rootlibexecdir)
+ install_dir : bindir)
if want_ukify
public_programs += ukify
+
+ meson.add_install_script(sh, '-c',
+ ln_s.format(bindir / 'ukify',
+ rootlibexecdir / 'ukify'))
endif
if want_tests != 'false' and want_kernel_install

View File

@ -0,0 +1,221 @@
From 90f26ba66f256fd65c6e7c38ed6f2138fed6b3ed Mon Sep 17 00:00:00 2001
From: Joerg Behrmann <behrmann@physik.fu-berlin.de>
Date: Wed, 23 Nov 2022 16:43:19 +0100
Subject: [PATCH] kernel-install: Add uki layout
Currently the kernel-install man page only documents the bls layout for use
with the boot loader spec type #1. 90-loaderentry.install uses this layout to
generate loader entries and copy the kernel image and initrd to $BOOT.
This commit documents a second layout "uki" and adds 90-uki-copy.install,
which copies a UKI "uki.efi" from the staging area or any file with the .efi
extension given on the command line to
$BOOT/EFI/Linux/$ENTRY_TOKEN-$KERNEl_VERSION(+$TRIES).efi
This allows for both locally generated and distro-provided UKIs to be handled
by kernel-install.
(cherry picked from commit 0ccfd3564b2532a4da6526a9e030362c4a142b77)
Resolves: RHEL-16354
---
man/kernel-install.xml | 38 ++++++++--
src/kernel-install/90-uki-copy.install | 97 ++++++++++++++++++++++++++
src/kernel-install/meson.build | 2 +
3 files changed, 131 insertions(+), 6 deletions(-)
create mode 100755 src/kernel-install/90-uki-copy.install
diff --git a/man/kernel-install.xml b/man/kernel-install.xml
index b8ea2b16b2..b1822a8847 100644
--- a/man/kernel-install.xml
+++ b/man/kernel-install.xml
@@ -108,6 +108,14 @@
is missing), or "Linux <replaceable>KERNEL-VERSION</replaceable>", if unset.</para>
<para>If <varname>$KERNEL_INSTALL_LAYOUT</varname> is not "bls", this plugin does nothing.</para></listitem>
+
+ <listitem><para><filename>90-uki-copy.install</filename> copies a file
+ <filename>uki.efi</filename> from <varname>$KERNEL_INSTALL_STAGING_AREA</varname> or if it does
+ not exist the <replaceable>KERNEL-IMAGE</replaceable> argument, iff it has a
+ <literal>.efi</literal> extension, to
+ <filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.efi</filename>.</para>
+
+ <para>If <varname>$KERNEL_INSTALL_LAYOUT</varname> is not "uki", this plugin does nothing.</para></listitem>
</itemizedlist>
</listitem>
</varlistentry>
@@ -132,6 +140,9 @@
<listitem><para><filename>90-loaderentry.install</filename> removes the file
<filename>$BOOT/loader/entries/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.conf</filename>.</para></listitem>
+
+ <listitem><para><filename>90-uki-copy.install</filename> removes the file
+ <filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.efi</filename>.</para></listitem>
</itemizedlist>
</listitem>
</varlistentry>
@@ -213,7 +224,7 @@
(EFI System Partition) are mounted, and also conceptually referred to as <varname>$BOOT</varname>. Can
be overridden by setting <varname>$BOOT_ROOT</varname> (see below).</para>
- <para><varname>$KERNEL_INSTALL_LAYOUT=bls|other|...</varname> is set for the plugins to specify the
+ <para><varname>$KERNEL_INSTALL_LAYOUT=bls|uki|other|...</varname> is set for the plugins to specify the
installation layout. Defaults to <option>bls</option> if
<filename>$BOOT/<replaceable>ENTRY-TOKEN</replaceable></filename> exists, or <option>other</option>
otherwise. Additional layout names may be defined by convention. If a plugin uses a special layout,
@@ -235,6 +246,18 @@
<para>Implemented by <filename>90-loaderentry.install</filename>.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>uki</term>
+ <listitem>
+ <para>Standard <ulink
+ url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader
+ Specification</ulink> Type #2 layout, compatible with
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>:
+ unified kernel images under <filename>$BOOT/EFI/Linux</filename> as
+ <filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>[+<replaceable>TRIES</replaceable>].efi</filename>.</para>
+ <para>Implemented by <filename>90-uki-copy.install</filename>.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>other</term>
<listitem>
@@ -312,12 +335,15 @@
<filename>/etc/kernel/tries</filename>
</term>
<listitem>
- <para>Read by <filename>90-loaderentry.install</filename>. If this file exists a numeric value is read from
- it and the naming of the generated entry file is slightly altered to include it as
- <filename>$BOOT/loader/entries/<replaceable>MACHINE-ID</replaceable>-<replaceable>KERNEL-VERSION</replaceable>+<replaceable>TRIES</replaceable>.conf</filename>. This
+ <para>Read by <filename>90-loaderentry.install</filename> and
+ <filename>90-uki-copy.install</filename>. If this file exists a numeric value is read from it
+ and the naming of the generated entry file or UKI is slightly altered to include it as
+ <filename>$BOOT/loader/entries/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>+<replaceable>TRIES</replaceable>.conf</filename>
+ or
+ <filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>+<replaceable>TRIES</replaceable>.conf</filename>, respectively. This
is useful for boot loaders such as
- <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> which
- implement boot attempt counting with a counter embedded in the entry file name.
+ <citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ which implement boot attempt counting with a counter embedded in the entry file name.
<varname>$KERNEL_INSTALL_CONF_ROOT</varname> may be used to override the path.</para>
</listitem>
</varlistentry>
diff --git a/src/kernel-install/90-uki-copy.install b/src/kernel-install/90-uki-copy.install
new file mode 100755
index 0000000000..d6e3deb723
--- /dev/null
+++ b/src/kernel-install/90-uki-copy.install
@@ -0,0 +1,97 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <https://www.gnu.org/licenses/>.
+
+set -e
+
+COMMAND="${1:?}"
+KERNEL_VERSION="${2:?}"
+# shellcheck disable=SC2034
+ENTRY_DIR_ABS="$3"
+KERNEL_IMAGE="$4"
+
+[ "$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
+
+ENTRY_TOKEN="$KERNEL_INSTALL_ENTRY_TOKEN"
+BOOT_ROOT="$KERNEL_INSTALL_BOOT_ROOT"
+
+UKI_DIR="$BOOT_ROOT/EFI/Linux"
+
+case "$COMMAND" in
+ remove)
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
+ echo "Removing $UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION*.efi"
+ exec rm -f \
+ "$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION.efi" \
+ "$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION+"*".efi"
+ ;;
+ add)
+ ;;
+ *)
+ exit 0
+ ;;
+esac
+
+if ! [ -d "$UKI_DIR" ]; then
+ echo "Error: entry directory '$UKI_DIR' does not exist" >&2
+ exit 1
+fi
+
+TRIES_FILE="${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}/tries"
+
+if [ -f "$TRIES_FILE" ]; then
+ read -r TRIES <"$TRIES_FILE"
+ if ! echo "$TRIES" | grep -q '^[0-9][0-9]*$'; then
+ echo "$TRIES_FILE does not contain an integer." >&2
+ exit 1
+ fi
+ UKI_FILE="$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION+$TRIES.efi"
+else
+ UKI_FILE="$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION.efi"
+fi
+
+# If there is a UKI named uki.efi on the staging area use that, if not use what
+# was passed in as $KERNEL_IMAGE but insist it has a .efi extension
+if [ -f "$KERNEL_INSTALL_STAGING_AREA/uki.efi" ]; then
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_INSTALL_STAGING_AREA/uki.efi"
+ install -m 0644 "$KERNEL_INSTALL_STAGING_AREA/uki.efi" "$UKI_FILE" || {
+ echo "Error: could not copy '$KERNEL_INSTALL_STAGING_AREA/uki.efi' to '$UKI_FILE'." >&2
+ exit 1
+ }
+elif [ -n "$KERNEL_IMAGE" ]; then
+ [ -f "$KERNEL_IMAGE" ] || {
+ echo "Error: UKI '$KERNEL_IMAGE' not a file." >&2
+ exit 1
+ }
+ [ "$KERNEL_IMAGE" != "${KERNEL_IMAGE%*.efi}.efi" ] && {
+ echo "Error: $KERNEL_IMAGE is missing .efi suffix." >&2
+ exit 1
+ }
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_IMAGE"
+ install -m 0644 "$KERNEL_IMAGE" "$UKI_FILE" || {
+ echo "Error: could not copy '$KERNEL_IMAGE' to '$UKI_FILE'." >&2
+ exit 1
+ }
+else
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "No UKI available. Nothing to do."
+ exit 0
+fi
+chown root:root "$UKI_FILE" || :
+
+exit 0
diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build
index 90a0e3ae49..68a4d43862 100644
--- a/src/kernel-install/meson.build
+++ b/src/kernel-install/meson.build
@@ -3,6 +3,8 @@
kernel_install_in = files('kernel-install.in')
loaderentry_install = files('90-loaderentry.install')
+uki_copy_install = files('90-uki-copy.install')
+
if want_kernel_install
install_data('50-depmod.install',
loaderentry_install,

View File

@ -0,0 +1,25 @@
From 5d3d683fd54100fea2a355b0ebc8b03d9b6c964b Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 25 Jan 2023 13:57:09 +0100
Subject: [PATCH] kernel-install: remove math slang from man page
(cherry picked from commit 642617f431457382ec2140a52ee08bfbb3e5e1db)
Related: RHEL-16354
---
man/kernel-install.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/kernel-install.xml b/man/kernel-install.xml
index b1822a8847..1bc6e7aa05 100644
--- a/man/kernel-install.xml
+++ b/man/kernel-install.xml
@@ -111,7 +111,7 @@
<listitem><para><filename>90-uki-copy.install</filename> copies a file
<filename>uki.efi</filename> from <varname>$KERNEL_INSTALL_STAGING_AREA</varname> or if it does
- not exist the <replaceable>KERNEL-IMAGE</replaceable> argument, iff it has a
+ not exist the <replaceable>KERNEL-IMAGE</replaceable> argument, only if it has a
<literal>.efi</literal> extension, to
<filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.efi</filename>.</para>

View File

@ -0,0 +1,80 @@
From 4f3593718196c007838eebf5d9b42f09318bd4e6 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 20 Jan 2023 09:05:18 +0100
Subject: [PATCH] kernel-install: handle uki installs automatically
Detect image type using "bootctl kernel-identify $kernel",
store result in KERNEL_INSTALL_IMAGE_TYPE.
Extend layout autodetection to check the kernel image type
and pick layout=uki for UKIs.
Resolves: https://github.com/systemd/systemd/issues/25822
(cherry picked from commit 3d5f0bfe4e72fdc4d8f8d65f96dc5501dfed8a64)
Related: RHEL-16354
---
man/kernel-install.xml | 17 +++++++++++++----
src/kernel-install/kernel-install.in | 12 ++++++++++--
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/man/kernel-install.xml b/man/kernel-install.xml
index 1bc6e7aa05..4d91b7b20b 100644
--- a/man/kernel-install.xml
+++ b/man/kernel-install.xml
@@ -224,10 +224,8 @@
(EFI System Partition) are mounted, and also conceptually referred to as <varname>$BOOT</varname>. Can
be overridden by setting <varname>$BOOT_ROOT</varname> (see below).</para>
- <para><varname>$KERNEL_INSTALL_LAYOUT=bls|uki|other|...</varname> is set for the plugins to specify the
- installation layout. Defaults to <option>bls</option> if
- <filename>$BOOT/<replaceable>ENTRY-TOKEN</replaceable></filename> exists, or <option>other</option>
- otherwise. Additional layout names may be defined by convention. If a plugin uses a special layout,
+ <para><varname>$KERNEL_INSTALL_LAYOUT=auto|bls|uki|other|...</varname> is set for the plugins to specify the
+ installation layout. Additional layout names may be defined by convention. If a plugin uses a special layout,
it's encouraged to declare its own layout name and configure <varname>layout=</varname> in
<filename>install.conf</filename> upon initial installation. The following values are currently
understood:</para>
@@ -264,6 +262,17 @@
<para>Some other layout not understood natively by <command>kernel-install</command>.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>auto</term>
+ <listitem>
+ <para>Pick the layout automatically. If the kernel is a UKI set layout to
+ <option>uki</option>. If not default to <option>bls</option> if
+ <filename>$BOOT/loader/entries.srel</filename> with content <literal>type1</literal> or
+ <filename>$BOOT/<replaceable>ENTRY-TOKEN</replaceable></filename> exists, or
+ <option>other</option> otherwise.</para>
+ <para>Leaving layout blank has the same effect. This is the default.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
<para><varname>$KERNEL_INSTALL_INITRD_GENERATOR</varname> is set for plugins to select the initrd
diff --git a/src/kernel-install/kernel-install.in b/src/kernel-install/kernel-install.in
index fa2c0d5276..25884fc0e2 100755
--- a/src/kernel-install/kernel-install.in
+++ b/src/kernel-install/kernel-install.in
@@ -250,10 +250,18 @@ if [ -z "$ENTRY_TOKEN" ]; then
echo "No entry-token candidate matched, using \"$ENTRY_TOKEN\" from machine-id"
fi
-if [ -z "$layout" ]; then
+export KERNEL_INSTALL_IMAGE_TYPE=""
+if [ -f "$1" ]; then
+ KERNEL_INSTALL_IMAGE_TYPE="$(bootctl kernel-identify "$1" 2>/dev/null || echo "unknown")"
+fi
+
+if [ "$layout" = "auto" ] || [ -z "$layout" ]; then
# No layout configured by the administrator. Let's try to figure it out
# automatically from metadata already contained in $BOOT_ROOT.
- if [ -e "$BOOT_ROOT/loader/entries.srel" ]; then
+ if [ "$KERNEL_INSTALL_IMAGE_TYPE" = "uki" ]; then
+ layout="uki"
+ log_verbose "Kernel image is UKI, using layout=$layout"
+ elif [ -e "$BOOT_ROOT/loader/entries.srel" ]; then
read -r ENTRIES_SREL <"$BOOT_ROOT/loader/entries.srel"
if [ "$ENTRIES_SREL" = "type1" ]; then
# The loader/entries.srel file clearly indicates that the installed

View File

@ -0,0 +1,31 @@
From cb2ead4b9fc17554a8694fd213bfb100d9c15678 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 20 Jan 2023 12:59:33 +0100
Subject: [PATCH] 90-uki-copy.install: create $BOOT/EFI/Linux directory if
needed
Do not consider a missing 'Linux' subdirectory an error.
Just create it instead.
(cherry picked from commit c7314ee7e290b3978e2f2d7726d07656eda071f9)
Related: RHEL-16354
---
src/kernel-install/90-uki-copy.install | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/kernel-install/90-uki-copy.install b/src/kernel-install/90-uki-copy.install
index d6e3deb723..6c71b211d7 100755
--- a/src/kernel-install/90-uki-copy.install
+++ b/src/kernel-install/90-uki-copy.install
@@ -49,8 +49,8 @@ case "$COMMAND" in
esac
if ! [ -d "$UKI_DIR" ]; then
- echo "Error: entry directory '$UKI_DIR' does not exist" >&2
- exit 1
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "creating $UKI_DIR"
+ mkdir -p "$UKI_DIR"
fi
TRIES_FILE="${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}/tries"

View File

@ -0,0 +1,36 @@
From d0b5386bde65b8c488d23f16ec4049d1e6378c25 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Sun, 5 Nov 2023 13:50:25 +0100
Subject: [PATCH] kernel-install: Log location that uki is installed in
Let's log where we install a UKI when running in verbose mode.
(cherry picked from commit 4f5278eead35bc66cc943a493eab8a8b78174400)
Related: RHEL-16354
---
src/kernel-install/90-uki-copy.install | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/kernel-install/90-uki-copy.install b/src/kernel-install/90-uki-copy.install
index 6c71b211d7..c66c09719c 100755
--- a/src/kernel-install/90-uki-copy.install
+++ b/src/kernel-install/90-uki-copy.install
@@ -69,7 +69,7 @@ fi
# If there is a UKI named uki.efi on the staging area use that, if not use what
# was passed in as $KERNEL_IMAGE but insist it has a .efi extension
if [ -f "$KERNEL_INSTALL_STAGING_AREA/uki.efi" ]; then
- [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_INSTALL_STAGING_AREA/uki.efi"
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_INSTALL_STAGING_AREA/uki.efi as $UKI_FILE"
install -m 0644 "$KERNEL_INSTALL_STAGING_AREA/uki.efi" "$UKI_FILE" || {
echo "Error: could not copy '$KERNEL_INSTALL_STAGING_AREA/uki.efi' to '$UKI_FILE'." >&2
exit 1
@@ -83,7 +83,7 @@ elif [ -n "$KERNEL_IMAGE" ]; then
echo "Error: $KERNEL_IMAGE is missing .efi suffix." >&2
exit 1
}
- [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_IMAGE"
+ [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $KERNEL_IMAGE as $UKI_FILE"
install -m 0644 "$KERNEL_IMAGE" "$UKI_FILE" || {
echo "Error: could not copy '$KERNEL_IMAGE' to '$UKI_FILE'." >&2
exit 1

View File

@ -0,0 +1,25 @@
From f0ab67eb46103c68a1fc708b45e2fa6b93780efb Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 19 Dec 2022 22:25:28 +0100
Subject: [PATCH] bootctl: fix errno logging
(cherry picked from commit e425849e995e448f529d3c106bf1e3de2ca23a35)
Related: RHEL-16354
---
src/boot/bootctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 7da48b4ca4..67fcbcc8cd 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -2028,7 +2028,7 @@ static int install_random_seed(const char *esp) {
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing random seed file.");
if (rename(tmp, path) < 0)
- return log_error_errno(r, "Failed to move random seed file into place: %m");
+ return log_error_errno(errno, "Failed to move random seed file into place: %m");
tmp = mfree(tmp);

View File

@ -0,0 +1,214 @@
From ca716a0fdfd434e52384dd74ff4c909aa95b6c81 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 16 Jan 2023 18:58:21 +0100
Subject: [PATCH] bootctl: add kernel-identity command
The command takes a kernel as argument and checks what kind of kernel
the image is. Returns one of uki, pe or unknown.
(cherry picked from commit 53c368d71ba43da7414ac86c58291a11da05ba84)
Resolves: RHEL-16354
---
man/bootctl.xml | 13 +++++
meson.build | 5 +-
src/boot/bootctl-uki.c | 109 +++++++++++++++++++++++++++++++++++++++++
src/boot/bootctl-uki.h | 3 ++
src/boot/bootctl.c | 4 ++
5 files changed, 133 insertions(+), 1 deletion(-)
create mode 100644 src/boot/bootctl-uki.c
create mode 100644 src/boot/bootctl-uki.h
diff --git a/man/bootctl.xml b/man/bootctl.xml
index dfc56d6125..0f992ec383 100644
--- a/man/bootctl.xml
+++ b/man/bootctl.xml
@@ -217,6 +217,19 @@
</variablelist>
</refsect1>
+ <refsect1>
+ <title><command>kernel</command> Commands</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><option>kernel-identify</option> <replaceable>kernel</replaceable></term>
+
+ <listitem><para>Takes a kernel image as argument. Checks what kind of kernel the image is. Returns
+ one of uki, pe or unknown.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
diff --git a/meson.build b/meson.build
index e0495ed36a..936e612a01 100644
--- a/meson.build
+++ b/meson.build
@@ -2566,7 +2566,10 @@ if conf.get('HAVE_BLKID') == 1 and conf.get('HAVE_GNU_EFI') == 1
public_programs += executable(
'bootctl',
- 'src/boot/bootctl.c',
+ ['src/boot/bootctl.c',
+ 'src/boot/bootctl-uki.c',
+ 'src/boot/bootctl-uki.h',
+ ],
include_directories : includes,
link_with : [boot_link_with],
dependencies : [libblkid],
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
new file mode 100644
index 0000000000..7e8e8a570b
--- /dev/null
+++ b/src/boot/bootctl-uki.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "bootctl-uki.h"
+#include "fd-util.h"
+#include "parse-util.h"
+#include "pe-header.h"
+
+#define MAX_SECTIONS 96
+
+static const uint8_t dos_file_magic[2] = "MZ";
+static const uint8_t pe_file_magic[4] = "PE\0\0";
+
+static const uint8_t name_osrel[8] = ".osrel";
+static const uint8_t name_linux[8] = ".linux";
+static const uint8_t name_initrd[8] = ".initrd";
+
+static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
+ _cleanup_free_ struct PeSectionHeader *sections = NULL;
+ struct DosFileHeader dos;
+ struct PeHeader pe;
+ size_t scount;
+ uint64_t soff, items;
+ int rc;
+
+ items = fread(&dos, 1, sizeof(dos), uki);
+ if (items != sizeof(dos))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "DOS header read error");
+ if (memcmp(dos.Magic, dos_file_magic, sizeof(dos_file_magic)) != 0)
+ goto no_sections;
+
+ rc = fseek(uki, le32toh(dos.ExeHeader), SEEK_SET);
+ if (rc < 0)
+ return log_error_errno(errno, "seek to PE header");
+ items = fread(&pe, 1, sizeof(pe), uki);
+ if (items != sizeof(pe))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "PE header read error");
+ if (memcmp(pe.Magic, pe_file_magic, sizeof(pe_file_magic)) != 0)
+ goto no_sections;
+
+ soff = le32toh(dos.ExeHeader) + sizeof(pe) + le16toh(pe.FileHeader.SizeOfOptionalHeader);
+ rc = fseek(uki, soff, SEEK_SET);
+ if (rc < 0)
+ return log_error_errno(errno, "seek to PE section headers");
+
+ scount = le16toh(pe.FileHeader.NumberOfSections);
+ if (scount > MAX_SECTIONS)
+ goto no_sections;
+ sections = new(struct PeSectionHeader, scount);
+ if (!sections)
+ return log_oom();
+ items = fread(sections, sizeof(*sections), scount, uki);
+ if (items != scount)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "PE section header read error");
+
+ *ret = TAKE_PTR(sections);
+ *ret_n = scount;
+ return 0;
+
+no_sections:
+ *ret = NULL;
+ *ret_n = 0;
+ return 0;
+}
+
+static int find_pe_section(struct PeSectionHeader *sections, size_t scount,
+ const uint8_t *name, size_t namelen, size_t *ret) {
+ for (size_t s = 0; s < scount; s++) {
+ if (memcmp_nn(sections[s].Name, sizeof(sections[s].Name),
+ name, namelen) == 0) {
+ if (ret)
+ *ret = s;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static bool is_uki(struct PeSectionHeader *sections, size_t scount) {
+ return (find_pe_section(sections, scount, name_osrel, sizeof(name_osrel), NULL) &&
+ find_pe_section(sections, scount, name_linux, sizeof(name_linux), NULL) &&
+ find_pe_section(sections, scount, name_initrd, sizeof(name_initrd), NULL));
+}
+
+int verb_kernel_identify(int argc, char *argv[], void *userdata) {
+ _cleanup_fclose_ FILE *uki = NULL;
+ _cleanup_free_ struct PeSectionHeader *sections = NULL;
+ size_t scount;
+ int rc;
+
+ uki = fopen(argv[1], "re");
+ if (!uki)
+ return log_error_errno(errno, "Failed to open UKI file '%s': %m", argv[1]);
+
+ rc = pe_sections(uki, &sections, &scount);
+ if (rc < 0)
+ return EXIT_FAILURE;
+
+ if (sections) {
+ if (is_uki(sections, scount)) {
+ puts("uki");
+ return EXIT_SUCCESS;
+ }
+ puts("pe");
+ return EXIT_SUCCESS;
+ }
+
+ puts("unknown");
+ return EXIT_SUCCESS;
+}
diff --git a/src/boot/bootctl-uki.h b/src/boot/bootctl-uki.h
new file mode 100644
index 0000000000..3c1fb5bc6a
--- /dev/null
+++ b/src/boot/bootctl-uki.h
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+int verb_kernel_identify(int argc, char *argv[], void *userdata);
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 67fcbcc8cd..58e4af85f8 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -14,6 +14,7 @@
#include "alloc-util.h"
#include "blkid-util.h"
+#include "bootctl-uki.h"
#include "bootspec.h"
#include "chase-symlinks.h"
#include "copy.h"
@@ -1453,6 +1454,8 @@ static int help(int argc, char *argv[], void *userdata) {
" remove Remove systemd-boot from the ESP and EFI variables\n"
" is-installed Test whether systemd-boot is installed in the ESP\n"
" random-seed Initialize random seed in ESP and EFI variables\n"
+ "\n%3$skernel Commands:%4$s\n"
+ " kernel-identify Identify kernel image type.\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"
@@ -2567,6 +2570,7 @@ static int bootctl_main(int argc, char *argv[]) {
{ "update", VERB_ANY, 1, 0, verb_install },
{ "remove", VERB_ANY, 1, 0, verb_remove },
{ "is-installed", VERB_ANY, 1, 0, verb_is_installed },
+ { "kernel-identify", 2, 2, 0, verb_kernel_identify },
{ "list", VERB_ANY, 1, 0, verb_list },
{ "set-default", 2, 2, 0, verb_set_efivar },
{ "set-oneshot", 2, 2, 0, verb_set_efivar },

View File

@ -0,0 +1,150 @@
From 3012047a48f67f6cceba50ce326497aa647074ea Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 17 Jan 2023 22:06:06 +0100
Subject: [PATCH] bootctl: add kernel-inspect command
Takes a kernel image as argument. Prints details about the kernel.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit a05255981ba5b04f1cf54ea656fbce1dfd9c3a68)
Resolves: RHEL-16354
---
man/bootctl.xml | 6 ++++
src/boot/bootctl-uki.c | 79 ++++++++++++++++++++++++++++++++++++++++++
src/boot/bootctl-uki.h | 1 +
src/boot/bootctl.c | 1 +
4 files changed, 87 insertions(+)
diff --git a/man/bootctl.xml b/man/bootctl.xml
index 0f992ec383..c12fe93214 100644
--- a/man/bootctl.xml
+++ b/man/bootctl.xml
@@ -227,6 +227,12 @@
<listitem><para>Takes a kernel image as argument. Checks what kind of kernel the image is. Returns
one of uki, pe or unknown.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><option>kernel-inspect</option> <replaceable>kernel</replaceable></term>
+
+ <listitem><para>Takes a kernel image as argument. Prints details about the kernel.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
index 7e8e8a570b..3085f703a8 100644
--- a/src/boot/bootctl-uki.c
+++ b/src/boot/bootctl-uki.c
@@ -13,6 +13,8 @@ static const uint8_t pe_file_magic[4] = "PE\0\0";
static const uint8_t name_osrel[8] = ".osrel";
static const uint8_t name_linux[8] = ".linux";
static const uint8_t name_initrd[8] = ".initrd";
+static const uint8_t name_cmdline[8] = ".cmdline";
+static const uint8_t name_uname[8] = ".uname";
static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
_cleanup_free_ struct PeSectionHeader *sections = NULL;
@@ -107,3 +109,80 @@ int verb_kernel_identify(int argc, char *argv[], void *userdata) {
puts("unknown");
return EXIT_SUCCESS;
}
+
+static int read_pe_section(FILE *uki, const struct PeSectionHeader *section,
+ void **ret, size_t *ret_n) {
+ _cleanup_free_ void *data = NULL;
+ uint32_t size, bytes;
+ uint64_t soff;
+ int rc;
+
+ soff = le32toh(section->PointerToRawData);
+ size = le32toh(section->VirtualSize);
+
+ if (size > 16 * 1024)
+ return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "PE section too big");
+
+ rc = fseek(uki, soff, SEEK_SET);
+ if (rc < 0)
+ return log_error_errno(errno, "seek to PE section");
+
+ data = malloc(size+1);
+ if (!data)
+ return log_oom();
+ ((uint8_t*) data)[size] = 0; /* safety NUL byte */
+
+ bytes = fread(data, 1, size, uki);
+ if (bytes != size)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "PE section read error");
+
+ *ret = TAKE_PTR(data);
+ if (ret_n)
+ *ret_n = size;
+ return 0;
+}
+
+static void inspect_uki(FILE *uki, struct PeSectionHeader *sections, size_t scount) {
+ _cleanup_free_ char *cmdline = NULL;
+ _cleanup_free_ char *uname = NULL;
+ size_t idx;
+
+ if (find_pe_section(sections, scount, name_cmdline, sizeof(name_cmdline), &idx))
+ read_pe_section(uki, sections + idx, (void**)&cmdline, NULL);
+
+ if (find_pe_section(sections, scount, name_uname, sizeof(name_uname), &idx))
+ read_pe_section(uki, sections + idx, (void**)&uname, NULL);
+
+ if (cmdline)
+ printf(" Cmdline: %s\n", cmdline);
+ if (uname)
+ printf(" Version: %s\n", uname);
+}
+
+int verb_kernel_inspect(int argc, char *argv[], void *userdata) {
+ _cleanup_fclose_ FILE *uki = NULL;
+ _cleanup_free_ struct PeSectionHeader *sections = NULL;
+ size_t scount;
+ int rc;
+
+ uki = fopen(argv[1], "re");
+ if (!uki)
+ return log_error_errno(errno, "Failed to open UKI file '%s': %m", argv[1]);
+
+ rc = pe_sections(uki, &sections, &scount);
+ if (rc < 0)
+ return EXIT_FAILURE;
+
+ if (sections) {
+ if (is_uki(sections, scount)) {
+ puts("Kernel Type: uki");
+ inspect_uki(uki, sections, scount);
+ return EXIT_SUCCESS;
+ }
+ puts("Kernel Type: pe");
+ return EXIT_SUCCESS;
+ }
+
+ puts("Kernel Type: unknown");
+ return EXIT_SUCCESS;
+}
diff --git a/src/boot/bootctl-uki.h b/src/boot/bootctl-uki.h
index 3c1fb5bc6a..effb984d80 100644
--- a/src/boot/bootctl-uki.h
+++ b/src/boot/bootctl-uki.h
@@ -1,3 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
int verb_kernel_identify(int argc, char *argv[], void *userdata);
+int verb_kernel_inspect(int argc, char *argv[], void *userdata);
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 58e4af85f8..b98673cd11 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -2571,6 +2571,7 @@ static int bootctl_main(int argc, char *argv[]) {
{ "remove", VERB_ANY, 1, 0, verb_remove },
{ "is-installed", VERB_ANY, 1, 0, verb_is_installed },
{ "kernel-identify", 2, 2, 0, verb_kernel_identify },
+ { "kernel-inspect", 2, 2, 0, verb_kernel_inspect },
{ "list", VERB_ANY, 1, 0, verb_list },
{ "set-default", 2, 2, 0, verb_set_efivar },
{ "set-oneshot", 2, 2, 0, verb_set_efivar },

View File

@ -0,0 +1,24 @@
From c1736cd4c9d0cb7b39333280bd30657e68481436 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 20 Jan 2023 13:30:48 +0100
Subject: [PATCH] bootctl: add kernel-inspect to --help text
(cherry picked from commit 24a3b37f12a1a752e5a1379cadc15031b04c3fba)
Related: RHEL-16354
---
src/boot/bootctl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index b98673cd11..cc35147376 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -1456,6 +1456,7 @@ static int help(int argc, char *argv[], void *userdata) {
" random-seed Initialize random seed in ESP and EFI variables\n"
"\n%3$skernel Commands:%4$s\n"
" kernel-identify Identify kernel image type.\n"
+ " kernel-inspect Prints details about the kernel.\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"

View File

@ -0,0 +1,29 @@
From d5d960b0b8db73ffe4cff9d156b0883876d722ac Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 20 Jan 2023 18:29:13 +0100
Subject: [PATCH] bootctl: drop full stop at end of --help texts
We never do that, don't do so here either.
(cherry picked from commit 2b197967bf251ecf58b93fed0f51b9d4cd83fda4)
Related: RHEL-16354
---
src/boot/bootctl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index cc35147376..681c5bd44f 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -1455,8 +1455,8 @@ static int help(int argc, char *argv[], void *userdata) {
" is-installed Test whether systemd-boot is installed in the ESP\n"
" random-seed Initialize random seed in ESP and EFI variables\n"
"\n%3$skernel Commands:%4$s\n"
- " kernel-identify Identify kernel image type.\n"
- " kernel-inspect Prints details about the kernel.\n"
+ " kernel-identify Identify kernel image type\n"
+ " kernel-inspect Prints details about the kernel\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"

View File

@ -0,0 +1,44 @@
From 6ee66a4736bde681956ef8ab601a72a5cb7b19ed Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 20 Jan 2023 18:30:06 +0100
Subject: [PATCH] bootctl: change section title for kernel image commands
Let's call them kernel *images*, not just *kernels*.
(cherry picked from commit 1e7d6cc07211de425bcc5c408c1f4376d6717305)
Related: RHEL-16354
---
man/bootctl.xml | 2 +-
src/boot/bootctl.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/man/bootctl.xml b/man/bootctl.xml
index c12fe93214..d82f12d5bb 100644
--- a/man/bootctl.xml
+++ b/man/bootctl.xml
@@ -218,7 +218,7 @@
</refsect1>
<refsect1>
- <title><command>kernel</command> Commands</title>
+ <title>Kernel Image Commands</title>
<variablelist>
<varlistentry>
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 681c5bd44f..4f2a6288fb 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -1454,9 +1454,9 @@ static int help(int argc, char *argv[], void *userdata) {
" remove Remove systemd-boot from the ESP and EFI variables\n"
" is-installed Test whether systemd-boot is installed in the ESP\n"
" random-seed Initialize random seed in ESP and EFI variables\n"
- "\n%3$skernel Commands:%4$s\n"
+ "\n%3$sKernel Image Commands:%4$s\n"
" kernel-identify Identify kernel image type\n"
- " kernel-inspect Prints details about the kernel\n"
+ " kernel-inspect Prints details about the kernel image\n"
"\n%3$sOptions:%4$s\n"
" -h --help Show this help\n"
" --version Print version\n"

View File

@ -0,0 +1,25 @@
From 2eae3094d018587e2550aaf895a7cbdeaea679bd Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 20 Jan 2023 18:40:57 +0100
Subject: [PATCH] bootctl: remove space that should not be there
(cherry picked from commit e684d2d5f85a82ed47eb063809145540df01ae1a)
Related: RHEL-16354
---
src/boot/bootctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 4f2a6288fb..3044f67b5a 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -1433,7 +1433,7 @@ static int help(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_oom();
- printf("%1$s [OPTIONS...] COMMAND ...\n"
+ printf("%1$s [OPTIONS...] COMMAND ...\n"
"\n%5$sControl EFI firmware boot settings and manage boot loader.%6$s\n"
"\n%3$sGeneric EFI Firmware/Boot Loader Commands:%4$s\n"
" status Show status of installed boot loader and EFI variables\n"

View File

@ -0,0 +1,73 @@
From 6204aa43883fdf02d72bd0db6d3cfbfa7c075213 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Fri, 20 Jan 2023 15:40:36 +0100
Subject: [PATCH] bootctl: kernel-inspect: print os info
(cherry picked from commit 2d4260482cb8463f4de9502efd26bf8c64262669)
Related: RHEL-16354
---
src/boot/bootctl-uki.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
index 3085f703a8..6bdf926350 100644
--- a/src/boot/bootctl-uki.c
+++ b/src/boot/bootctl-uki.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "bootctl-uki.h"
+#include "env-file.h"
#include "fd-util.h"
#include "parse-util.h"
#include "pe-header.h"
@@ -142,10 +143,31 @@ static int read_pe_section(FILE *uki, const struct PeSectionHeader *section,
return 0;
}
+static void inspect_osrel(char *osrel, size_t osrel_size) {
+ _cleanup_fclose_ FILE *s = NULL;
+ _cleanup_free_ char *pname = NULL, *name = NULL;
+ int r;
+
+ assert(osrel);
+ s = fmemopen(osrel, osrel_size, "r");
+ if (!s)
+ return (void) log_warning_errno(errno, "Failed to open embedded os-release file, ignoring: %m");
+
+ r = parse_env_file(s, NULL,
+ "PRETTY_NAME", &pname,
+ "NAME", &name);
+ if (r < 0)
+ return (void) log_warning_errno(r, "Failed to parse embedded os-release file, ignoring: %m");
+
+ if (pname || name)
+ printf(" OS: %s\n", pname ?: name);
+}
+
static void inspect_uki(FILE *uki, struct PeSectionHeader *sections, size_t scount) {
_cleanup_free_ char *cmdline = NULL;
_cleanup_free_ char *uname = NULL;
- size_t idx;
+ _cleanup_free_ char *osrel = NULL;
+ size_t osrel_size, idx;
if (find_pe_section(sections, scount, name_cmdline, sizeof(name_cmdline), &idx))
read_pe_section(uki, sections + idx, (void**)&cmdline, NULL);
@@ -153,10 +175,15 @@ static void inspect_uki(FILE *uki, struct PeSectionHeader *sections, size_t scou
if (find_pe_section(sections, scount, name_uname, sizeof(name_uname), &idx))
read_pe_section(uki, sections + idx, (void**)&uname, NULL);
+ if (find_pe_section(sections, scount, name_osrel, sizeof(name_osrel), &idx))
+ read_pe_section(uki, sections + idx, (void**)&osrel, &osrel_size);
+
if (cmdline)
printf(" Cmdline: %s\n", cmdline);
if (uname)
printf(" Version: %s\n", uname);
+ if (osrel)
+ inspect_osrel(osrel, osrel_size);
}
int verb_kernel_inspect(int argc, char *argv[], void *userdata) {

View File

@ -0,0 +1,207 @@
From a9c7fe86260ca906c7378503e059eca0ad014947 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 24 Jan 2023 22:59:59 +0900
Subject: [PATCH] bootctl-uki: several coding style fixlets
Mostly follow-ups for #26082.
(cherry picked from commit 5b532e14e3ac1d8f8cef90fd8c5b1ce277458ae7)
Related: RHEL-16354
---
src/boot/bootctl-uki.c | 105 +++++++++++++++++++++++------------------
1 file changed, 60 insertions(+), 45 deletions(-)
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
index 6bdf926350..3492fa548f 100644
--- a/src/boot/bootctl-uki.c
+++ b/src/boot/bootctl-uki.c
@@ -23,7 +23,10 @@ static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
struct PeHeader pe;
size_t scount;
uint64_t soff, items;
- int rc;
+
+ assert(uki);
+ assert(ret);
+ assert(ret_n);
items = fread(&dos, 1, sizeof(dos), uki);
if (items != sizeof(dos))
@@ -31,9 +34,9 @@ static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
if (memcmp(dos.Magic, dos_file_magic, sizeof(dos_file_magic)) != 0)
goto no_sections;
- rc = fseek(uki, le32toh(dos.ExeHeader), SEEK_SET);
- if (rc < 0)
+ if (fseek(uki, le32toh(dos.ExeHeader), SEEK_SET) < 0)
return log_error_errno(errno, "seek to PE header");
+
items = fread(&pe, 1, sizeof(pe), uki);
if (items != sizeof(pe))
return log_error_errno(SYNTHETIC_ERRNO(EIO), "PE header read error");
@@ -41,8 +44,7 @@ static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
goto no_sections;
soff = le32toh(dos.ExeHeader) + sizeof(pe) + le16toh(pe.FileHeader.SizeOfOptionalHeader);
- rc = fseek(uki, soff, SEEK_SET);
- if (rc < 0)
+ if (fseek(uki, soff, SEEK_SET) < 0)
return log_error_errno(errno, "seek to PE section headers");
scount = le16toh(pe.FileHeader.NumberOfSections);
@@ -65,58 +67,72 @@ no_sections:
return 0;
}
-static int find_pe_section(struct PeSectionHeader *sections, size_t scount,
- const uint8_t *name, size_t namelen, size_t *ret) {
- for (size_t s = 0; s < scount; s++) {
- if (memcmp_nn(sections[s].Name, sizeof(sections[s].Name),
- name, namelen) == 0) {
+static bool find_pe_section(
+ struct PeSectionHeader *sections,
+ size_t scount,
+ const uint8_t *name,
+ size_t namelen,
+ size_t *ret) {
+
+ assert(sections || scount == 0);
+ assert(name || namelen == 0);
+
+ for (size_t s = 0; s < scount; s++)
+ if (memcmp_nn(sections[s].Name, sizeof(sections[s].Name), name, namelen) == 0) {
if (ret)
*ret = s;
- return 1;
+ return true;
}
- }
- return 0;
+
+ return false;
}
static bool is_uki(struct PeSectionHeader *sections, size_t scount) {
- return (find_pe_section(sections, scount, name_osrel, sizeof(name_osrel), NULL) &&
+ assert(sections || scount == 0);
+
+ return
+ find_pe_section(sections, scount, name_osrel, sizeof(name_osrel), NULL) &&
find_pe_section(sections, scount, name_linux, sizeof(name_linux), NULL) &&
- find_pe_section(sections, scount, name_initrd, sizeof(name_initrd), NULL));
+ find_pe_section(sections, scount, name_initrd, sizeof(name_initrd), NULL);
}
int verb_kernel_identify(int argc, char *argv[], void *userdata) {
_cleanup_fclose_ FILE *uki = NULL;
_cleanup_free_ struct PeSectionHeader *sections = NULL;
size_t scount;
- int rc;
+ int r;
uki = fopen(argv[1], "re");
if (!uki)
return log_error_errno(errno, "Failed to open UKI file '%s': %m", argv[1]);
- rc = pe_sections(uki, &sections, &scount);
- if (rc < 0)
- return EXIT_FAILURE;
+ r = pe_sections(uki, &sections, &scount);
+ if (r < 0)
+ return r;
- if (sections) {
- if (is_uki(sections, scount)) {
- puts("uki");
- return EXIT_SUCCESS;
- }
+ if (!sections)
+ puts("unknown");
+ else if (is_uki(sections, scount))
+ puts("uki");
+ else
puts("pe");
- return EXIT_SUCCESS;
- }
- puts("unknown");
return EXIT_SUCCESS;
}
-static int read_pe_section(FILE *uki, const struct PeSectionHeader *section,
- void **ret, size_t *ret_n) {
+static int read_pe_section(
+ FILE *uki,
+ const struct PeSectionHeader *section,
+ void **ret,
+ size_t *ret_n) {
+
_cleanup_free_ void *data = NULL;
uint32_t size, bytes;
uint64_t soff;
- int rc;
+
+ assert(uki);
+ assert(section);
+ assert(ret);
soff = le32toh(section->PointerToRawData);
size = le32toh(section->VirtualSize);
@@ -124,8 +140,7 @@ static int read_pe_section(FILE *uki, const struct PeSectionHeader *section,
if (size > 16 * 1024)
return log_error_errno(SYNTHETIC_ERRNO(E2BIG), "PE section too big");
- rc = fseek(uki, soff, SEEK_SET);
- if (rc < 0)
+ if (fseek(uki, soff, SEEK_SET) < 0)
return log_error_errno(errno, "seek to PE section");
data = malloc(size+1);
@@ -169,6 +184,9 @@ static void inspect_uki(FILE *uki, struct PeSectionHeader *sections, size_t scou
_cleanup_free_ char *osrel = NULL;
size_t osrel_size, idx;
+ assert(uki);
+ assert(sections || scount == 0);
+
if (find_pe_section(sections, scount, name_cmdline, sizeof(name_cmdline), &idx))
read_pe_section(uki, sections + idx, (void**)&cmdline, NULL);
@@ -190,26 +208,23 @@ int verb_kernel_inspect(int argc, char *argv[], void *userdata) {
_cleanup_fclose_ FILE *uki = NULL;
_cleanup_free_ struct PeSectionHeader *sections = NULL;
size_t scount;
- int rc;
+ int r;
uki = fopen(argv[1], "re");
if (!uki)
return log_error_errno(errno, "Failed to open UKI file '%s': %m", argv[1]);
- rc = pe_sections(uki, &sections, &scount);
- if (rc < 0)
- return EXIT_FAILURE;
+ r = pe_sections(uki, &sections, &scount);
+ if (r < 0)
+ return r;
- if (sections) {
- if (is_uki(sections, scount)) {
- puts("Kernel Type: uki");
- inspect_uki(uki, sections, scount);
- return EXIT_SUCCESS;
- }
+ if (!sections)
+ puts("Kernel Type: unknown");
+ else if (is_uki(sections, scount)) {
+ puts("Kernel Type: uki");
+ inspect_uki(uki, sections, scount);
+ } else
puts("Kernel Type: pe");
- return EXIT_SUCCESS;
- }
- puts("Kernel Type: unknown");
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,171 @@
From a83545ba5d0cc1b29f2bb4e2b794ce14b138e3fe Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 23 Jan 2023 12:28:38 +0100
Subject: [PATCH] tree-wide: unify how we pick OS pretty name to display
(cherry picked from commit 02b7005e38db756711cd6463bda34e93cf304c3c)
Related: RHEL-16354
---
src/analyze/analyze-plot.c | 3 ++-
src/basic/os-util.c | 9 +++++++++
src/basic/os-util.h | 2 ++
src/core/main.c | 2 +-
src/firstboot/firstboot.c | 5 +++--
src/hostname/hostnamed.c | 7 ++++++-
src/journal-remote/journal-gatewayd.c | 9 ++++++---
7 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/analyze/analyze-plot.c b/src/analyze/analyze-plot.c
index 24f4add099..8aca691b3d 100644
--- a/src/analyze/analyze-plot.c
+++ b/src/analyze/analyze-plot.c
@@ -6,6 +6,7 @@
#include "bus-error.h"
#include "bus-map-properties.h"
#include "format-table.h"
+#include "os-util.h"
#include "sort-util.h"
#include "version.h"
@@ -283,7 +284,7 @@ static int produce_plot_as_svg(
svg("<text x=\"20\" y=\"50\">%s</text>", pretty_times);
if (host)
svg("<text x=\"20\" y=\"30\">%s %s (%s %s %s) %s %s</text>",
- isempty(host->os_pretty_name) ? "Linux" : host->os_pretty_name,
+ os_release_pretty_name(host->os_pretty_name, NULL),
strempty(host->hostname),
strempty(host->kernel_name),
strempty(host->kernel_release),
diff --git a/src/basic/os-util.c b/src/basic/os-util.c
index 8f8bb0881e..66cbfc76a5 100644
--- a/src/basic/os-util.c
+++ b/src/basic/os-util.c
@@ -370,3 +370,12 @@ int os_release_support_ended(const char *support_end, bool quiet) {
usec_t ts = now(CLOCK_REALTIME);
return DIV_ROUND_UP(ts, USEC_PER_SEC) > (usec_t) eol;
}
+
+const char *os_release_pretty_name(const char *pretty_name, const char *name) {
+ /* Distills a "pretty" name to show from os-release data. First argument is supposed to be the
+ * PRETTY_NAME= field, the second one the NAME= field. This function is trivial, of course, and
+ * exists mostly to ensure we use the same logic wherever possible. */
+
+ return empty_to_null(pretty_name) ?:
+ empty_to_null(name) ?: "Linux";
+}
diff --git a/src/basic/os-util.h b/src/basic/os-util.h
index d22f5ab8e7..1239f6f6b7 100644
--- a/src/basic/os-util.h
+++ b/src/basic/os-util.h
@@ -33,3 +33,5 @@ int load_os_release_pairs(const char *root, char ***ret);
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
int os_release_support_ended(const char *support_end, bool quiet);
+
+const char *os_release_pretty_name(const char *pretty_name, const char *name);
diff --git a/src/core/main.c b/src/core/main.c
index d3ec526e7e..0e2e5448bb 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1339,7 +1339,7 @@ static int os_release_status(void) {
return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
- const char *label = empty_to_null(pretty_name) ?: empty_to_null(name) ?: "Linux";
+ const char *label = os_release_pretty_name(pretty_name, name);
if (show_status_on(arg_show_status)) {
if (log_get_show_color())
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 63db78b52d..10eda1d302 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -96,7 +96,7 @@ static bool press_any_key(void) {
}
static void print_welcome(void) {
- _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
+ _cleanup_free_ char *pretty_name = NULL, *os_name = NULL, *ansi_color = NULL;
static bool done = false;
const char *pn, *ac;
int r;
@@ -110,12 +110,13 @@ static void print_welcome(void) {
r = parse_os_release(
arg_root,
"PRETTY_NAME", &pretty_name,
+ "NAME", &os_name,
"ANSI_COLOR", &ansi_color);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read os-release file, ignoring: %m");
- pn = isempty(pretty_name) ? "Linux" : pretty_name;
+ pn = os_release_pretty_name(pretty_name, os_name);
ac = isempty(ansi_color) ? "0" : ansi_color;
if (colors_enabled())
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index 486b093062..2a675caada 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -147,6 +147,7 @@ static void context_read_machine_info(Context *c) {
}
static void context_read_os_release(Context *c) {
+ _cleanup_free_ char *os_name = NULL, *os_pretty_name = NULL;
struct stat current_stat = {};
int r;
@@ -163,12 +164,16 @@ static void context_read_os_release(Context *c) {
(UINT64_C(1) << PROP_OS_HOME_URL));
r = parse_os_release(NULL,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
+ "PRETTY_NAME", &os_pretty_name,
+ "NAME", &os_name,
"CPE_NAME", &c->data[PROP_OS_CPE_NAME],
"HOME_URL", &c->data[PROP_OS_HOME_URL]);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read os-release file, ignoring: %m");
+ if (free_and_strdup(&c->data[PROP_OS_PRETTY_NAME], os_release_pretty_name(os_pretty_name, os_name)) < 0)
+ log_oom();
+
c->etc_os_release_stat = current_stat;
}
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 34def4670e..e848ae5026 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -732,7 +732,7 @@ static int request_handler_machine(
_cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL;
RequestMeta *m = ASSERT_PTR(connection_cls);
int r;
- _cleanup_free_ char* hostname = NULL, *os_name = NULL;
+ _cleanup_free_ char* hostname = NULL, *pretty_name = NULL, *os_name = NULL;
uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0;
sd_id128_t mid, bid;
_cleanup_free_ char *v = NULL, *json = NULL;
@@ -763,7 +763,10 @@ static int request_handler_machine(
if (r < 0)
return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m");
- (void) parse_os_release(NULL, "PRETTY_NAME", &os_name);
+ (void) parse_os_release(
+ NULL,
+ "PRETTY_NAME", &pretty_name,
+ "NAME=", &os_name);
(void) get_virtualization(&v);
r = asprintf(&json,
@@ -778,7 +781,7 @@ static int request_handler_machine(
SD_ID128_FORMAT_VAL(mid),
SD_ID128_FORMAT_VAL(bid),
hostname_cleanup(hostname),
- os_name ? os_name : "Linux",
+ os_release_pretty_name(pretty_name, os_name),
v ? v : "bare",
usage,
cutoff_from,

View File

@ -0,0 +1,102 @@
From 5374c8fb7c32e79f9dcd24333e5c117bd8963a1a Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 25 Jan 2023 11:05:46 +0900
Subject: [PATCH] bootctl-uki: several follow-ups for inspect_osrel()
Follow-ups for #26124 and #26158.
- use os_release_pretty_name(),
- constify the buffer passed to inspect_osrel(),
- propagate errors in inspect_osrele(), and ignore them in the caller
side,
- and several coding style fixlets.
(cherry picked from commit 1b7586df976d7b033b4901a099337d83578bb8f1)
Related: RHEL-16354
---
src/boot/bootctl-uki.c | 36 ++++++++++++++++++++----------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
index 3492fa548f..fd249c43fb 100644
--- a/src/boot/bootctl-uki.c
+++ b/src/boot/bootctl-uki.c
@@ -3,6 +3,7 @@
#include "bootctl-uki.h"
#include "env-file.h"
#include "fd-util.h"
+#include "os-util.h"
#include "parse-util.h"
#include "pe-header.h"
@@ -158,50 +159,53 @@ static int read_pe_section(
return 0;
}
-static void inspect_osrel(char *osrel, size_t osrel_size) {
+static int inspect_osrel(const void *osrel, size_t osrel_size) {
_cleanup_fclose_ FILE *s = NULL;
_cleanup_free_ char *pname = NULL, *name = NULL;
int r;
- assert(osrel);
- s = fmemopen(osrel, osrel_size, "r");
+ assert(osrel || osrel_size == 0);
+
+ if (!osrel)
+ return 0;
+
+ s = fmemopen((void*) osrel, osrel_size, "r");
if (!s)
- return (void) log_warning_errno(errno, "Failed to open embedded os-release file, ignoring: %m");
+ return log_warning_errno(errno, "Failed to open embedded os-release file, ignoring: %m");
r = parse_env_file(s, NULL,
"PRETTY_NAME", &pname,
"NAME", &name);
if (r < 0)
- return (void) log_warning_errno(r, "Failed to parse embedded os-release file, ignoring: %m");
+ return log_warning_errno(r, "Failed to parse embedded os-release file, ignoring: %m");
- if (pname || name)
- printf(" OS: %s\n", pname ?: name);
+ printf(" OS: %s\n", os_release_pretty_name(pname, name));
+ return 0;
}
static void inspect_uki(FILE *uki, struct PeSectionHeader *sections, size_t scount) {
- _cleanup_free_ char *cmdline = NULL;
- _cleanup_free_ char *uname = NULL;
- _cleanup_free_ char *osrel = NULL;
- size_t osrel_size, idx;
+ _cleanup_free_ char *cmdline = NULL, *uname = NULL;
+ _cleanup_free_ void *osrel = NULL;
+ size_t osrel_size = 0, idx;
assert(uki);
assert(sections || scount == 0);
if (find_pe_section(sections, scount, name_cmdline, sizeof(name_cmdline), &idx))
- read_pe_section(uki, sections + idx, (void**)&cmdline, NULL);
+ read_pe_section(uki, sections + idx, (void**) &cmdline, NULL);
if (find_pe_section(sections, scount, name_uname, sizeof(name_uname), &idx))
- read_pe_section(uki, sections + idx, (void**)&uname, NULL);
+ read_pe_section(uki, sections + idx, (void**) &uname, NULL);
if (find_pe_section(sections, scount, name_osrel, sizeof(name_osrel), &idx))
- read_pe_section(uki, sections + idx, (void**)&osrel, &osrel_size);
+ read_pe_section(uki, sections + idx, &osrel, &osrel_size);
if (cmdline)
printf(" Cmdline: %s\n", cmdline);
if (uname)
printf(" Version: %s\n", uname);
- if (osrel)
- inspect_osrel(osrel, osrel_size);
+
+ (void) inspect_osrel(osrel, osrel_size);
}
int verb_kernel_inspect(int argc, char *argv[], void *userdata) {

View File

@ -0,0 +1,25 @@
From 47a9030cad80a684b9affcc2c35ef264e7a8b145 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Thu, 9 Feb 2023 10:44:35 +0100
Subject: [PATCH] bootctl: Add missing %m
(cherry picked from commit 3b42ffe590c5728af50feb138890a44264c4b02e)
Related: RHEL-16354
---
src/boot/bootctl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index 3044f67b5a..a0ca2afec2 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -1420,7 +1420,7 @@ static int install_entry_token(void) {
r = write_string_file("/etc/kernel/entry-token", arg_entry_token, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755);
if (r < 0)
- return log_error_errno(r, "Failed to write entry token '%s' to /etc/kernel/entry-token", arg_entry_token);
+ return log_error_errno(r, "Failed to write entry token '%s' to /etc/kernel/entry-token: %m", arg_entry_token);
return 0;
}

View File

@ -0,0 +1,41 @@
From 618e38b8b775f45c0a18975ae33753b92c954092 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 24 Jan 2023 10:28:25 +0100
Subject: [PATCH] bootctl: tweak DOS header magic check
Read the magic first, try reading the full DOS exe header only in case
the magic check succeeds.
This avoids throwing an header read error on small dummy files as used
by test-kernel-install.
(cherry picked from commit 78088b8f43717a43661cd2c1627a9860904c4794)
Related: RHEL-16354
---
src/boot/bootctl-uki.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/boot/bootctl-uki.c b/src/boot/bootctl-uki.c
index fd249c43fb..d90a850b1c 100644
--- a/src/boot/bootctl-uki.c
+++ b/src/boot/bootctl-uki.c
@@ -30,11 +30,16 @@ static int pe_sections(FILE *uki, struct PeSectionHeader **ret, size_t *ret_n) {
assert(ret_n);
items = fread(&dos, 1, sizeof(dos), uki);
- if (items != sizeof(dos))
- return log_error_errno(SYNTHETIC_ERRNO(EIO), "DOS header read error");
+ if (items < sizeof(dos.Magic))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "File is smaller than DOS magic (got %"PRIu64" of %zu bytes)",
+ items, sizeof(dos.Magic));
if (memcmp(dos.Magic, dos_file_magic, sizeof(dos_file_magic)) != 0)
goto no_sections;
+ if (items != sizeof(dos))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "File is smaller than DOS header (got %"PRIu64" of %zu bytes)",
+ items, sizeof(dos));
+
if (fseek(uki, le32toh(dos.ExeHeader), SEEK_SET) < 0)
return log_error_errno(errno, "seek to PE header");

View File

@ -21,7 +21,7 @@
Name: systemd
Url: https://systemd.io
Version: 252
Release: 19%{?dist}
Release: 20%{?dist}
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -460,6 +460,55 @@ Patch0379: 0379-ci-add-missing-permissions.patch
Patch0380: 0380-ci-permissions-write-all.patch
Patch0381: 0381-ci-lint-exclude-.in-files-from-ShellCheck-lint.patch
Patch0382: 0382-udev-raise-RLIMIT_NOFILE-as-high-as-we-can.patch
Patch0383: 0383-udev-net-allow-new-link-name-as-an-altname-before-re.patch
Patch0384: 0384-sd-netlink-do-not-swap-old-name-and-alternative-name.patch
Patch0385: 0385-sd-netlink-restore-altname-on-error-in-rtnl_set_link.patch
Patch0386: 0386-udev-attempt-device-rename-even-if-interface-is-up.patch
Patch0387: 0387-sd-netlink-add-a-test-for-rtnl_set_link_name.patch
Patch0388: 0388-test-network-add-a-test-for-renaming-device-to-curre.patch
Patch0389: 0389-udev-align-table.patch
Patch0390: 0390-sd-device-make-device_set_syspath-clear-sysname-and-.patch
Patch0391: 0391-sd-device-do-not-directly-access-entry-in-sd-device-.patch
Patch0392: 0392-udev-move-device_rename-from-device-private.c.patch
Patch0393: 0393-udev-restore-syspath-and-properties-on-failure.patch
Patch0394: 0394-sd-device-introduce-device_get_property_int.patch
Patch0395: 0395-core-device-downgrade-log-level-for-ignored-errors.patch
Patch0396: 0396-core-device-ignore-failed-uevents.patch
Patch0397: 0397-test-add-tests-for-failure-in-renaming-network-inter.patch
Patch0398: 0398-test-modernize-test-netlink.c.patch
Patch0399: 0399-test-netlink-use-dummy-interface-to-test-assigning-n.patch
Patch0400: 0400-udev-use-SYNTHETIC_ERRNO-at-one-more-place.patch
Patch0401: 0401-udev-make-udev_builtin_run-take-UdevEvent.patch
Patch0402: 0402-udev-net-verify-ID_NET_XYZ-before-trying-to-assign-i.patch
Patch0403: 0403-udev-net-generate-new-network-interface-name-only-on.patch
Patch0404: 0404-sd-netlink-make-rtnl_set_link_name-optionally-append.patch
Patch0405: 0405-udev-net-assign-alternative-names-only-on-add-uevent.patch
Patch0406: 0406-test-add-tests-for-renaming-network-interface.patch
Patch0407: 0407-Backport-ukify-from-upstream.patch
Patch0408: 0408-bootctl-make-json-output-normal-json.patch
Patch0409: 0409-test-replace-readfp-with-read_file.patch
Patch0410: 0410-stub-measure-document-and-measure-.uname-UKI-section.patch
Patch0411: 0411-boot-measure-.sbat-section.patch
Patch0412: 0412-Revert-test_ukify-no-stinky-root-needed-for-signing.patch
Patch0413: 0413-ukify-move-to-usr-bin-and-mark-as-non-non-experiment.patch
Patch0414: 0414-kernel-install-Add-uki-layout.patch
Patch0415: 0415-kernel-install-remove-math-slang-from-man-page.patch
Patch0416: 0416-kernel-install-handle-uki-installs-automatically.patch
Patch0417: 0417-90-uki-copy.install-create-BOOT-EFI-Linux-directory-.patch
Patch0418: 0418-kernel-install-Log-location-that-uki-is-installed-in.patch
Patch0419: 0419-bootctl-fix-errno-logging.patch
Patch0420: 0420-bootctl-add-kernel-identity-command.patch
Patch0421: 0421-bootctl-add-kernel-inspect-command.patch
Patch0422: 0422-bootctl-add-kernel-inspect-to-help-text.patch
Patch0423: 0423-bootctl-drop-full-stop-at-end-of-help-texts.patch
Patch0424: 0424-bootctl-change-section-title-for-kernel-image-comman.patch
Patch0425: 0425-bootctl-remove-space-that-should-not-be-there.patch
Patch0426: 0426-bootctl-kernel-inspect-print-os-info.patch
Patch0427: 0427-bootctl-uki-several-coding-style-fixlets.patch
Patch0428: 0428-tree-wide-unify-how-we-pick-OS-pretty-name-to-displa.patch
Patch0429: 0429-bootctl-uki-several-follow-ups-for-inspect_osrel.patch
Patch0430: 0430-bootctl-Add-missing-m.patch
Patch0431: 0431-bootctl-tweak-DOS-header-magic-check.patch
# Downstream-only patches (90009999)
@ -1281,6 +1330,57 @@ getent passwd systemd-oom &>/dev/null || useradd -r -l -g systemd-oom -d / -s /s
%files standalone-sysusers -f .file-list-standalone-sysusers
%changelog
* Fri Dec 08 2023 systemd maintenance team <systemd-maint@redhat.com> - 252-20
- udev/net: allow new link name as an altname before renaming happens (RHEL-5988)
- sd-netlink: do not swap old name and alternative name (RHEL-5988)
- sd-netlink: restore altname on error in rtnl_set_link_name (RHEL-5988)
- udev: attempt device rename even if interface is up (RHEL-5988)
- sd-netlink: add a test for rtnl_set_link_name() (RHEL-5988)
- test-network: add a test for renaming device to current altname (RHEL-5988)
- udev: align table (RHEL-5988)
- sd-device: make device_set_syspath() clear sysname and sysnum (RHEL-5988)
- sd-device: do not directly access entry in sd-device object (RHEL-5988)
- udev: move device_rename() from device-private.c (RHEL-5988)
- udev: restore syspath and properties on failure (RHEL-5988)
- sd-device: introduce device_get_property_int() (RHEL-5988)
- core/device: downgrade log level for ignored errors (RHEL-5988)
- core/device: ignore failed uevents (RHEL-5988)
- test: add tests for failure in renaming network interface (RHEL-5988)
- test: modernize test-netlink.c (RHEL-5988)
- test-netlink: use dummy interface to test assigning new interface name (RHEL-5988)
- udev: use SYNTHETIC_ERRNO() at one more place (RHEL-5988)
- udev: make udev_builtin_run() take UdevEvent* (RHEL-5988)
- udev/net: verify ID_NET_XYZ before trying to assign it as an alternative name (RHEL-5988)
- udev/net: generate new network interface name only on add uevent (RHEL-5988)
- sd-netlink: make rtnl_set_link_name() optionally append alternative names (RHEL-5988)
- udev/net: assign alternative names only on add uevent (RHEL-5988)
- test: add tests for renaming network interface (RHEL-5988)
- Backport ukify from upstream (RHEL-13199)
- bootctl: make --json output normal json (RHEL-13199)
- test: replace readfp() with read_file() (RHEL-13199)
- stub/measure: document and measure .uname UKI section (RHEL-13199)
- boot: measure .sbat section (RHEL-13199)
- Revert "test_ukify: no stinky root needed for signing" (RHEL-13199)
- ukify: move to /usr/bin and mark as non non-experimental (RHEL-13199)
- kernel-install: Add uki layout (RHEL-16354)
- kernel-install: remove math slang from man page (RHEL-16354)
- kernel-install: handle uki installs automatically (RHEL-16354)
- 90-uki-copy.install: create $BOOT/EFI/Linux directory if needed (RHEL-16354)
- kernel-install: Log location that uki is installed in (RHEL-16354)
- bootctl: fix errno logging (RHEL-16354)
- bootctl: add kernel-identity command (RHEL-16354)
- bootctl: add kernel-inspect command (RHEL-16354)
- bootctl: add kernel-inspect to --help text (RHEL-16354)
- bootctl: drop full stop at end of --help texts (RHEL-16354)
- bootctl: change section title for kernel image commands (RHEL-16354)
- bootctl: remove space that should not be there (RHEL-16354)
- bootctl: kernel-inspect: print os info (RHEL-16354)
- bootctl-uki: several coding style fixlets (RHEL-16354)
- tree-wide: unify how we pick OS pretty name to display (RHEL-16354)
- bootctl-uki: several follow-ups for inspect_osrel() (RHEL-16354)
- bootctl: Add missing %m (RHEL-16354)
- bootctl: tweak DOS header magic check (RHEL-16354)
* Mon Nov 13 2023 systemd maintenance team <systemd-maint@redhat.com> - 252-19
- ci: Extend source-git-automation (RHEL-1086)
- netif-naming-scheme: let's also include rhel8 schemes (RHEL-7026)