4295f9
From acf81f97412be44d60be03a0a2e3ca62f4a5146b Mon Sep 17 00:00:00 2001
4295f9
From: Yu Watanabe <watanabe.yu+github@gmail.com>
4295f9
Date: Wed, 1 Sep 2021 09:24:15 +0900
4295f9
Subject: [PATCH] udev-node: split out permission handling from udev_node_add()
4295f9
4295f9
And then merge udev_node_add() and udev_node_update_old_links().
4295f9
4295f9
(cherry picked from commit 2f48561e0db3cd63f65e9311b4d69282b4ac605d)
4295f9
4295f9
Related: #1977994
4295f9
---
4295f9
 src/udev/udev-event.c |   9 +-
4295f9
 src/udev/udev-node.c  | 204 +++++++++++++++++++-----------------------
4295f9
 src/udev/udev-node.h  |  12 ++-
4295f9
 3 files changed, 106 insertions(+), 119 deletions(-)
4295f9
4295f9
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
4295f9
index b28089be71..8b9f8aecfe 100644
4295f9
--- a/src/udev/udev-event.c
4295f9
+++ b/src/udev/udev-event.c
4295f9
@@ -895,9 +895,6 @@ static int update_devnode(UdevEvent *event) {
4295f9
         if (r < 0)
4295f9
                 return log_device_error_errno(dev, r, "Failed to get devnum: %m");
4295f9
 
4295f9
-        /* remove/update possible left-over symlinks from old database entry */
4295f9
-        (void) udev_node_update_old_links(dev, event->dev_db_clone);
4295f9
-
4295f9
         if (!uid_is_valid(event->uid)) {
4295f9
                 r = device_get_devnode_uid(dev, &event->uid);
4295f9
                 if (r < 0 && r != -ENOENT)
4295f9
@@ -921,7 +918,11 @@ static int update_devnode(UdevEvent *event) {
4295f9
 
4295f9
         bool apply_mac = device_for_action(dev, SD_DEVICE_ADD);
4295f9
 
4295f9
-        return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
4295f9
+        r = udev_node_apply_permissions(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list);
4295f9
+        if (r < 0)
4295f9
+                return log_device_error_errno(dev, r, "Failed to apply devnode permissions: %m");
4295f9
+
4295f9
+        return udev_node_update(dev, event->dev_db_clone);
4295f9
 }
4295f9
 
4295f9
 static int event_execute_rules_on_remove(
4295f9
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
4295f9
index 9e52906571..7cc9ee3670 100644
4295f9
--- a/src/udev/udev-node.c
4295f9
+++ b/src/udev/udev-node.c
4295f9
@@ -356,45 +356,117 @@ static int link_update(sd_device *dev, const char *slink_in, bool add) {
4295f9
         return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP;
4295f9
 }
4295f9
 
4295f9
-int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) {
4295f9
-        const char *name;
4295f9
+static int device_get_devpath_by_devnum(sd_device *dev, char **ret) {
4295f9
+        const char *subsystem;
4295f9
+        dev_t devnum;
4295f9
+        int r;
4295f9
+
4295f9
+        assert(dev);
4295f9
+        assert(ret);
4295f9
+
4295f9
+        r = sd_device_get_subsystem(dev, &subsystem);
4295f9
+        if (r < 0)
4295f9
+                return r;
4295f9
+
4295f9
+        r = sd_device_get_devnum(dev, &devnum);
4295f9
+        if (r < 0)
4295f9
+                return r;
4295f9
+
4295f9
+        return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
4295f9
+}
4295f9
+
4295f9
+int udev_node_update(sd_device *dev, sd_device *dev_old) {
4295f9
+        _cleanup_free_ char *filename = NULL;
4295f9
+        const char *devnode, *devlink;
4295f9
         int r;
4295f9
 
4295f9
         assert(dev);
4295f9
         assert(dev_old);
4295f9
 
4295f9
-        /* update possible left-over symlinks */
4295f9
-        FOREACH_DEVICE_DEVLINK(dev_old, name) {
4295f9
-                const char *name_current;
4295f9
-                bool found = false;
4295f9
+        r = sd_device_get_devname(dev, &devnode);
4295f9
+        if (r < 0)
4295f9
+                return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
4295f9
 
4295f9
-                /* check if old link name still belongs to this device */
4295f9
-                FOREACH_DEVICE_DEVLINK(dev, name_current)
4295f9
-                        if (streq(name, name_current)) {
4295f9
-                                found = true;
4295f9
-                                break;
4295f9
-                        }
4295f9
+        if (DEBUG_LOGGING) {
4295f9
+                const char *id = NULL;
4295f9
 
4295f9
-                if (found)
4295f9
+                (void) device_get_device_id(dev, &id;;
4295f9
+                log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
4295f9
+        }
4295f9
+
4295f9
+        /* update possible left-over symlinks */
4295f9
+        FOREACH_DEVICE_DEVLINK(dev_old, devlink) {
4295f9
+                /* check if old link name still belongs to this device */
4295f9
+                if (device_has_devlink(dev, devlink))
4295f9
                         continue;
4295f9
 
4295f9
                 log_device_debug(dev,
4295f9
-                                 "Updating old device symlink '%s', which is no longer belonging to this device.",
4295f9
-                                 name);
4295f9
+                                 "Removing/updating old device symlink '%s', which is no longer belonging to this device.",
4295f9
+                                 devlink);
4295f9
 
4295f9
-                r = link_update(dev, name, false);
4295f9
+                r = link_update(dev, devlink, /* add = */ false);
4295f9
                 if (r < 0)
4295f9
                         log_device_warning_errno(dev, r,
4295f9
-                                                 "Failed to update device symlink '%s', ignoring: %m",
4295f9
-                                                 name);
4295f9
+                                                 "Failed to remove/update device symlink '%s', ignoring: %m",
4295f9
+                                                 devlink);
4295f9
         }
4295f9
 
4295f9
+        /* create/update symlinks, add symlinks to name index */
4295f9
+        FOREACH_DEVICE_DEVLINK(dev, devlink) {
4295f9
+                r = link_update(dev, devlink, /* add = */ true);
4295f9
+                if (r < 0)
4295f9
+                        log_device_warning_errno(dev, r,
4295f9
+                                                 "Failed to create/update device symlink '%s', ignoring: %m",
4295f9
+                                                 devlink);
4295f9
+        }
4295f9
+
4295f9
+        r = device_get_devpath_by_devnum(dev, &filename);
4295f9
+        if (r < 0)
4295f9
+                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
4295f9
+
4295f9
+        /* always add /dev/{block,char}/$major:$minor */
4295f9
+        r = node_symlink(dev, devnode, filename);
4295f9
+        if (r < 0)
4295f9
+                return log_device_warning_errno(dev, r, "Failed to create device symlink '%s': %m", filename);
4295f9
+
4295f9
+        return 0;
4295f9
+}
4295f9
+
4295f9
+int udev_node_remove(sd_device *dev) {
4295f9
+        _cleanup_free_ char *filename = NULL;
4295f9
+        const char *devlink;
4295f9
+        int r;
4295f9
+
4295f9
+        assert(dev);
4295f9
+
4295f9
+        /* remove/update symlinks, remove symlinks from name index */
4295f9
+        FOREACH_DEVICE_DEVLINK(dev, devlink) {
4295f9
+                r = link_update(dev, devlink, /* add = */ false);
4295f9
+                if (r < 0)
4295f9
+                        log_device_warning_errno(dev, r,
4295f9
+                                                 "Failed to remove/update device symlink '%s', ignoring: %m",
4295f9
+                                                 devlink);
4295f9
+        }
4295f9
+
4295f9
+        r = device_get_devpath_by_devnum(dev, &filename);
4295f9
+        if (r < 0)
4295f9
+                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
4295f9
+
4295f9
+        /* remove /dev/{block,char}/$major:$minor */
4295f9
+        if (unlink(filename) < 0 && errno != ENOENT)
4295f9
+                return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", filename);
4295f9
+
4295f9
         return 0;
4295f9
 }
4295f9
 
4295f9
-static int node_permissions_apply(sd_device *dev, bool apply_mac,
4295f9
-                                  mode_t mode, uid_t uid, gid_t gid,
4295f9
-                                  OrderedHashmap *seclabel_list) {
4295f9
+int udev_node_apply_permissions(
4295f9
+                sd_device *dev,
4295f9
+                bool apply_mac,
4295f9
+                mode_t mode,
4295f9
+                uid_t uid,
4295f9
+                gid_t gid,
4295f9
+                OrderedHashmap *seclabel_list) {
4295f9
+
4295f9
         const char *devnode, *subsystem, *id = NULL;
4295f9
         bool apply_mode, apply_uid, apply_gid;
4295f9
         _cleanup_close_ int node_fd = -1;
4295f9
@@ -511,95 +583,5 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac,
4295f9
         if (r < 0)
4295f9
                 log_device_debug_errno(dev, r, "Failed to adjust timestamp of node %s: %m", devnode);
4295f9
 
4295f9
-        return r;
4295f9
-}
4295f9
-
4295f9
-static int xsprintf_dev_num_path_from_sd_device(sd_device *dev, char **ret) {
4295f9
-        const char *subsystem;
4295f9
-        dev_t devnum;
4295f9
-        int r;
4295f9
-
4295f9
-        assert(ret);
4295f9
-
4295f9
-        r = sd_device_get_subsystem(dev, &subsystem);
4295f9
-        if (r < 0)
4295f9
-                return r;
4295f9
-
4295f9
-        r = sd_device_get_devnum(dev, &devnum);
4295f9
-        if (r < 0)
4295f9
-                return r;
4295f9
-
4295f9
-        return device_path_make_major_minor(streq(subsystem, "block") ? S_IFBLK : S_IFCHR, devnum, ret);
4295f9
-}
4295f9
-
4295f9
-int udev_node_add(sd_device *dev, bool apply,
4295f9
-                  mode_t mode, uid_t uid, gid_t gid,
4295f9
-                  OrderedHashmap *seclabel_list) {
4295f9
-        const char *devnode, *devlink;
4295f9
-        _cleanup_free_ char *filename = NULL;
4295f9
-        int r;
4295f9
-
4295f9
-        assert(dev);
4295f9
-
4295f9
-        r = sd_device_get_devname(dev, &devnode);
4295f9
-        if (r < 0)
4295f9
-                return log_device_debug_errno(dev, r, "Failed to get devnode: %m");
4295f9
-
4295f9
-        if (DEBUG_LOGGING) {
4295f9
-                const char *id = NULL;
4295f9
-
4295f9
-                (void) device_get_device_id(dev, &id;;
4295f9
-                log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strna(id));
4295f9
-        }
4295f9
-
4295f9
-        r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list);
4295f9
-        if (r < 0)
4295f9
-                return r;
4295f9
-
4295f9
-        /* create/update symlinks, add symlinks to name index */
4295f9
-        FOREACH_DEVICE_DEVLINK(dev, devlink) {
4295f9
-                r = link_update(dev, devlink, true);
4295f9
-                if (r < 0)
4295f9
-                        log_device_warning_errno(dev, r,
4295f9
-                                                 "Failed to update device symlink '%s', ignoring: %m",
4295f9
-                                                 devlink);
4295f9
-        }
4295f9
-
4295f9
-        r = xsprintf_dev_num_path_from_sd_device(dev, &filename);
4295f9
-        if (r < 0)
4295f9
-                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
4295f9
-
4295f9
-        /* always add /dev/{block,char}/$major:$minor */
4295f9
-        r = node_symlink(dev, devnode, filename);
4295f9
-        if (r < 0)
4295f9
-                return log_device_warning_errno(dev, r, "Failed to create device symlink '%s': %m", filename);
4295f9
-
4295f9
-        return 0;
4295f9
-}
4295f9
-
4295f9
-int udev_node_remove(sd_device *dev) {
4295f9
-        _cleanup_free_ char *filename = NULL;
4295f9
-        const char *devlink;
4295f9
-        int r;
4295f9
-
4295f9
-        assert(dev);
4295f9
-
4295f9
-        /* remove/update symlinks, remove symlinks from name index */
4295f9
-        FOREACH_DEVICE_DEVLINK(dev, devlink) {
4295f9
-                r = link_update(dev, devlink, false);
4295f9
-                if (r < 0)
4295f9
-                        log_device_warning_errno(dev, r,
4295f9
-                                                 "Failed to update device symlink '%s', ignoring: %m",
4295f9
-                                                 devlink);
4295f9
-        }
4295f9
-
4295f9
-        r = xsprintf_dev_num_path_from_sd_device(dev, &filename);
4295f9
-        if (r < 0)
4295f9
-                return log_device_debug_errno(dev, r, "Failed to get device path: %m");
4295f9
-
4295f9
-        /* remove /dev/{block,char}/$major:$minor */
4295f9
-        if (unlink(filename) < 0 && errno != ENOENT)
4295f9
-                return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", filename);
4295f9
-
4295f9
         return 0;
4295f9
 }
4295f9
diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h
4295f9
index 2349f9c471..a34af77146 100644
4295f9
--- a/src/udev/udev-node.h
4295f9
+++ b/src/udev/udev-node.h
4295f9
@@ -8,10 +8,14 @@
4295f9
 
4295f9
 #include "hashmap.h"
4295f9
 
4295f9
-int udev_node_add(sd_device *dev, bool apply,
4295f9
-                  mode_t mode, uid_t uid, gid_t gid,
4295f9
-                  OrderedHashmap *seclabel_list);
4295f9
+int udev_node_apply_permissions(
4295f9
+                sd_device *dev,
4295f9
+                bool apply_mac,
4295f9
+                mode_t mode,
4295f9
+                uid_t uid,
4295f9
+                gid_t gid,
4295f9
+                OrderedHashmap *seclabel_list);
4295f9
 int udev_node_remove(sd_device *dev);
4295f9
-int udev_node_update_old_links(sd_device *dev, sd_device *dev_old);
4295f9
+int udev_node_update(sd_device *dev, sd_device *dev_old);
4295f9
 
4295f9
 size_t udev_node_escape_path(const char *src, char *dest, size_t size);