From 449375d2adadb0ce7a8975876ca797ae4f926e48 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 13 Sep 2022 03:29:11 +0900 Subject: [PATCH 1/3] fs-util: use path_make_relative_parent() at one more place --- src/basic/fs-util.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index d1272fb04b..a0898bf4f5 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -406,13 +406,7 @@ int symlink_idempotent(const char *from, const char *to, bool make_relative) { assert(to); if (make_relative) { - _cleanup_free_ char *parent = NULL; - - r = path_extract_directory(to, &parent); - if (r < 0) - return r; - - r = path_make_relative(parent, from, &relpath); + r = path_make_relative_parent(to, from, &relpath); if (r < 0) return r; From 590d81002bbce1a1bcce21056d12873fb96ee3a9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 13 Sep 2022 03:30:34 +0900 Subject: [PATCH 2/3] fs-util,label: introduce symlink_atomic_full() and symlink_atomic_full_label() These new functions optionally create symlink of relative path. --- src/basic/fs-util.c | 12 ++++++++++-- src/basic/fs-util.h | 5 ++++- src/shared/label.c | 4 ++-- src/shared/label.h | 5 ++++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index a0898bf4f5..cbab59b777 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -432,13 +432,21 @@ int symlink_idempotent(const char *from, const char *to, bool make_relative) { return 0; } -int symlink_atomic(const char *from, const char *to) { - _cleanup_free_ char *t = NULL; +int symlink_atomic_full(const char *from, const char *to, bool make_relative) { + _cleanup_free_ char *relpath = NULL, *t = NULL; int r; assert(from); assert(to); + if (make_relative) { + r = path_make_relative_parent(to, from, &relpath); + if (r < 0) + return r; + + from = relpath; + } + r = tempfn_random(to, NULL, &t); if (r < 0) return r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 080959d3b9..f2174af15d 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -58,7 +58,10 @@ static inline int touch(const char *path) { int symlink_idempotent(const char *from, const char *to, bool make_relative); -int symlink_atomic(const char *from, const char *to); +int symlink_atomic_full(const char *from, const char *to, bool make_relative); +static inline int symlink_atomic(const char *from, const char *to) { + return symlink_atomic_full(from, to, false); +} int mknod_atomic(const char *path, mode_t mode, dev_t dev); int mkfifo_atomic(const char *path, mode_t mode); int mkfifoat_atomic(int dir_fd, const char *path, mode_t mode); diff --git a/src/shared/label.c b/src/shared/label.c index dde93e1dde..d00158a258 100644 --- a/src/shared/label.c +++ b/src/shared/label.c @@ -61,7 +61,7 @@ int symlink_label(const char *old_path, const char *new_path) { return mac_smack_fix(new_path, 0); } -int symlink_atomic_label(const char *from, const char *to) { +int symlink_atomic_full_label(const char *from, const char *to, bool make_relative) { int r; assert(from); @@ -71,7 +71,7 @@ int symlink_atomic_label(const char *from, const char *to) { if (r < 0) return r; - r = symlink_atomic(from, to); + r = symlink_atomic_full(from, to, make_relative); mac_selinux_create_file_clear(); if (r < 0) diff --git a/src/shared/label.h b/src/shared/label.h index 88aa47b7b8..2f899e2bdd 100644 --- a/src/shared/label.h +++ b/src/shared/label.h @@ -17,7 +17,10 @@ static inline int label_fix(const char *path, LabelFixFlags flags) { } int symlink_label(const char *old_path, const char *new_path); -int symlink_atomic_label(const char *from, const char *to); +int symlink_atomic_full_label(const char *from, const char *to, bool make_relative); +static inline int symlink_atomic_label(const char *from, const char *to) { + return symlink_atomic_full_label(from, to, false); +} int mknod_label(const char *pathname, mode_t mode, dev_t dev); int btrfs_subvol_make_label(const char *path); From 6d42138593b003ca4cd1a11ead2d119e6d730841 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 11 Apr 2022 12:18:13 +0900 Subject: [PATCH 3/3] udev-node: use symlink_atomic_full_label() to create devlink If the filename of a device symlink is too long, then the temporary filename may become invalid, and we fail to create symlink. The function `tempfn_random()` used in symlink_atomic_full() generates a safe temporary filename. Note that, thanks to the PR #23043, now only one worker can handle the same symlink simultaneously. Hence, the device ID based temporary filename is not necessary. --- src/udev/udev-node.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 4e7dca06de..a1d47083dd 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -14,6 +14,7 @@ #include "format-util.h" #include "fs-util.h" #include "hexdecoct.h" +#include "label.h" #include "mkdir-label.h" #include "parse-util.h" #include "path-util.h" @@ -69,8 +70,6 @@ int udev_node_cleanup(void) { } static int node_symlink(sd_device *dev, const char *devnode, const char *slink) { - _cleanup_free_ char *target = NULL; - const char *id, *slink_tmp; struct stat st; int r; @@ -91,34 +90,16 @@ static int node_symlink(sd_device *dev, const char *devnode, const char *slink) } else if (errno != ENOENT) return log_device_debug_errno(dev, errno, "Failed to lstat() '%s': %m", slink); + r = mkdir_parents_label(slink, 0755); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to create parent directory of '%s': %m", slink); + /* use relative link */ - r = path_make_relative_parent(slink, devnode, &target); + r = symlink_atomic_full_label(devnode, slink, /* make_relative = */ true); if (r < 0) - return log_device_debug_errno(dev, r, "Failed to get relative path from '%s' to '%s': %m", slink, devnode); - - r = device_get_device_id(dev, &id); - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to get device id: %m"); - - slink_tmp = strjoina(slink, ".tmp-", id); - (void) unlink(slink_tmp); - - r = mkdir_parents_label(slink_tmp, 0755); - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to create parent directory of '%s': %m", slink_tmp); - - mac_selinux_create_file_prepare(slink_tmp, S_IFLNK); - r = RET_NERRNO(symlink(target, slink_tmp)); - mac_selinux_create_file_clear(); - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target); - - if (rename(slink_tmp, slink) < 0) { - r = log_device_debug_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink); - (void) unlink(slink_tmp); - return r; - } + return log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink, devnode); + log_device_debug(dev, "Successfully created symlink '%s' to '%s'", slink, devnode); return 0; }