From acf81f97412be44d60be03a0a2e3ca62f4a5146b Mon Sep 17 00:00:00 2001 From: Yu Watanabe 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);