You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
6.8 KiB
156 lines
6.8 KiB
7 months ago
|
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) {
|