Blob Blame History Raw
From acf81f97412be44d60be03a0a2e3ca62f4a5146b Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 1 Sep 2021 09:24:15 +0900
Subject: [PATCH] udev-node: split out permission handling from udev_node_add()

And then merge udev_node_add() and udev_node_update_old_links().

(cherry picked from commit 2f48561e0db3cd63f65e9311b4d69282b4ac605d)

Related: #1977994
---
 src/udev/udev-event.c |   9 +-
 src/udev/udev-node.c  | 204 +++++++++++++++++++-----------------------
 src/udev/udev-node.h  |  12 ++-
 3 files changed, 106 insertions(+), 119 deletions(-)

diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index b28089be71..8b9f8aecfe 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -895,9 +895,6 @@ static int update_devnode(UdevEvent *event) {
         if (r < 0)
                 return log_device_error_errno(dev, r, "Failed to get devnum: %m");
 
-        /* remove/update possible left-over symlinks from old database entry */
-        (void) udev_node_update_old_links(dev, event->dev_db_clone);
-
         if (!uid_is_valid(event->uid)) {
                 r = device_get_devnode_uid(dev, &event->uid);
                 if (r < 0 && r != -ENOENT)
@@ -921,7 +918,11 @@ static int update_devnode(UdevEvent *event) {
 
         bool apply_mac = device_for_action(dev, SD_DEVICE_ADD);
 
-        return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
+        r = udev_node_apply_permissions(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
+        if (r < 0)
+                return log_device_error_errno(dev, r, "Failed to apply devnode permissions: %m");
+
+        return udev_node_update(dev, event->dev_db_clone);
 }
 
 static int event_execute_rules_on_remove(
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 9e52906571..7cc9ee3670 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -356,45 +356,117 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
         return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP;
 }
 
-int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
-        const char *name;
+static int device_get_devpath_by_devnum(sd_device *dev, char **ret) {
+        const char *subsystem;
+        dev_t devnum;
+        int r;
+
+        assert(dev);
+        assert(ret);
+
+        r = sd_device_get_subsystem(dev, &subsystem);
+        if (r < 0)
+                return r;
+
+        r = sd_device_get_devnum(dev, &devnum);
+        if (r < 0)
+                return r;
+
+        return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
+}
+
+int udev_node_update(sd_device *dev, sd_device *dev_old) {
+        _cleanup_free_ char *filename = NULL;
+        const char *devnode, *devlink;
         int r;
 
         assert(dev);
         assert(dev_old);
 
-        /* update possible left-over symlinks */
-        FOREACH_DEVICE_DEVLINK(dev_old, name) {
-                const char *name_current;
-                bool found = false;
+        r = sd_device_get_devname(dev, &devnode);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
 
-                /* check if old link name still belongs to this device */
-                FOREACH_DEVICE_DEVLINK(dev, name_current)
-                        if (streq(name, name_current)) {
-                                found = true;
-                                break;
-                        }
+        if (DEBUG_LOGGING) {
+                const char *id = NULL;
 
-                if (found)
+                (void) device_get_device_id(dev, &id);
+                log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
+        }
+
+        /* update possible left-over symlinks */
+        FOREACH_DEVICE_DEVLINK(dev_old, devlink) {
+                /* check if old link name still belongs to this device */
+                if (device_has_devlink(dev, devlink))
                         continue;
 
                 log_device_debug(dev,
-                                 "Updating old device symlink '%s', which is no longer belonging to this device.",
-                                 name);
+                                 "Removing/updating old device symlink '%s', which is no longer belonging to this device.",
+                                 devlink);
 
-                r = link_update(dev, name, false);
+                r = link_update(dev, devlink, /* add = */ false);
                 if (r < 0)
                         log_device_warning_errno(dev, r,
-                                                 "Failed to update device symlink '%s', ignoring: %m",
-                                                 name);
+                                                 "Failed to remove/update device symlink '%s', ignoring: %m",
+                                                 devlink);
         }
 
+        /* create/update symlinks, add symlinks to name index */
+        FOREACH_DEVICE_DEVLINK(dev, devlink) {
+                r = link_update(dev, devlink, /* add = */ true);
+                if (r < 0)
+                        log_device_warning_errno(dev, r,
+                                                 "Failed to create/update device symlink '%s', ignoring: %m",
+                                                 devlink);
+        }
+
+        r = device_get_devpath_by_devnum(dev, &filename);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
+
+        /* always add /dev/{block,char}/$major:$minor */
+        r = node_symlink(dev, devnode, filename);
+        if (r < 0)
+                return log_device_warning_errno(dev, r, "Failed to create device symlink '%s': %m", filename);
+
+        return 0;
+}
+
+int udev_node_remove(sd_device *dev) {
+        _cleanup_free_ char *filename = NULL;
+        const char *devlink;
+        int r;
+
+        assert(dev);
+
+        /* remove/update symlinks, remove symlinks from name index */
+        FOREACH_DEVICE_DEVLINK(dev, devlink) {
+                r = link_update(dev, devlink, /* add = */ false);
+                if (r < 0)
+                        log_device_warning_errno(dev, r,
+                                                 "Failed to remove/update device symlink '%s', ignoring: %m",
+                                                 devlink);
+        }
+
+        r = device_get_devpath_by_devnum(dev, &filename);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
+
+        /* remove /dev/{block,char}/$major:$minor */
+        if (unlink(filename) < 0 && errno != ENOENT)
+                return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", filename);
+
         return 0;
 }
 
-static int node_permissions_apply(sd_device *dev, bool apply_mac,
-                                  mode_t mode, uid_t uid, gid_t gid,
-                                  OrderedHashmap *seclabel_list) {
+int udev_node_apply_permissions(
+                sd_device *dev,
+                bool apply_mac,
+                mode_t mode,
+                uid_t uid,
+                gid_t gid,
+                OrderedHashmap *seclabel_list) {
+
         const char *devnode, *subsystem, *id = NULL;
         bool apply_mode, apply_uid, apply_gid;
         _cleanup_close_ int node_fd = -1;
@@ -511,95 +583,5 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
         if (r < 0)
                 log_device_debug_errno(dev, r, "Failed to adjust timestamp of node %s: %m", devnode);
 
-        return r;
-}
-
-static int xsprintf_dev_num_path_from_sd_device(sd_device *dev, char **ret) {
-        const char *subsystem;
-        dev_t devnum;
-        int r;
-
-        assert(ret);
-
-        r = sd_device_get_subsystem(dev, &subsystem);
-        if (r < 0)
-                return r;
-
-        r = sd_device_get_devnum(dev, &devnum);
-        if (r < 0)
-                return r;
-
-        return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
-}
-
-int udev_node_add(sd_device *dev, bool apply,
-                  mode_t mode, uid_t uid, gid_t gid,
-                  OrderedHashmap *seclabel_list) {
-        const char *devnode, *devlink;
-        _cleanup_free_ char *filename = NULL;
-        int r;
-
-        assert(dev);
-
-        r = sd_device_get_devname(dev, &devnode);
-        if (r < 0)
-                return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
-
-        if (DEBUG_LOGGING) {
-                const char *id = NULL;
-
-                (void) device_get_device_id(dev, &id);
-                log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
-        }
-
-        r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
-        if (r < 0)
-                return r;
-
-        /* create/update symlinks, add symlinks to name index */
-        FOREACH_DEVICE_DEVLINK(dev, devlink) {
-                r = link_update(dev, devlink, true);
-                if (r < 0)
-                        log_device_warning_errno(dev, r,
-                                                 "Failed to update device symlink '%s', ignoring: %m",
-                                                 devlink);
-        }
-
-        r = xsprintf_dev_num_path_from_sd_device(dev, &filename);
-        if (r < 0)
-                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
-
-        /* always add /dev/{block,char}/$major:$minor */
-        r = node_symlink(dev, devnode, filename);
-        if (r < 0)
-                return log_device_warning_errno(dev, r, "Failed to create device symlink '%s': %m", filename);
-
-        return 0;
-}
-
-int udev_node_remove(sd_device *dev) {
-        _cleanup_free_ char *filename = NULL;
-        const char *devlink;
-        int r;
-
-        assert(dev);
-
-        /* remove/update symlinks, remove symlinks from name index */
-        FOREACH_DEVICE_DEVLINK(dev, devlink) {
-                r = link_update(dev, devlink, false);
-                if (r < 0)
-                        log_device_warning_errno(dev, r,
-                                                 "Failed to update device symlink '%s', ignoring: %m",
-                                                 devlink);
-        }
-
-        r = xsprintf_dev_num_path_from_sd_device(dev, &filename);
-        if (r < 0)
-                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
-
-        /* remove /dev/{block,char}/$major:$minor */
-        if (unlink(filename) < 0 && errno != ENOENT)
-                return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", filename);
-
         return 0;
 }
diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h
index 2349f9c471..a34af77146 100644
--- a/src/udev/udev-node.h
+++ b/src/udev/udev-node.h
@@ -8,10 +8,14 @@
 
 #include "hashmap.h"
 
-int udev_node_add(sd_device *dev, bool apply,
-                  mode_t mode, uid_t uid, gid_t gid,
-                  OrderedHashmap *seclabel_list);
+int udev_node_apply_permissions(
+                sd_device *dev,
+                bool apply_mac,
+                mode_t mode,
+                uid_t uid,
+                gid_t gid,
+                OrderedHashmap *seclabel_list);
 int udev_node_remove(sd_device *dev);
-int udev_node_update_old_links(sd_device *dev, sd_device *dev_old);
+int udev_node_update(sd_device *dev, sd_device *dev_old);
 
 size_t udev_node_escape_path(const char *src, char *dest, size_t size);