From 12a7f04a2b9135a4751dba71e2f688525d7c93e7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Aug 2021 22:41:08 +0200 Subject: [PATCH 1/5] discover-image: pass the right fd to fd_getcrtime() --- src/shared/discover-image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index 521264ec29b..5f8bf437764 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -305,7 +305,7 @@ static int image_make( } /* Get directory creation time (not available everywhere, but that's OK */ - (void) fd_getcrtime(dfd, &crtime); + (void) fd_getcrtime(fd, &crtime); /* If the IMMUTABLE bit is set, we consider the directory read-only. Since the ioctl is not * supported everywhere we ignore failures. */ From 3832cb90ba1557d5fe0e24f0b280bfefe44a2406 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Aug 2021 14:03:10 +0200 Subject: [PATCH 2/5] stdio-util: give snprintf_ok() some love as per docs snprintf() can fail in which case it returns -1. The snprintf_ok() macro so far unconditionally cast the return value of snprintf() to size_t, which would turn -1 to (size_t) INT_MAX, presumably, at least on 2 complements system. Let's be more careful with types here, and first check if return value is positive, before casting to size_t. Also, while we are at it, let's return the input buffer as return value or NULL instead of 1 or 0. It's marginally more useful, but more importantly, is more inline with most of our other codebase that typically doesn't use booleans to signal success. All uses of snprintf_ok() don't care for the type of the return, hence this change does not propagate anywhere else. --- src/basic/stdio-util.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h index 0ed48b3fd4b..69d7062ec6f 100644 --- a/src/basic/stdio-util.h +++ b/src/basic/stdio-util.h @@ -9,8 +9,13 @@ #include "macro.h" #include "memory-util.h" -#define snprintf_ok(buf, len, fmt, ...) \ - ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len)) +#define snprintf_ok(buf, len, fmt, ...) \ + ({ \ + char *_buf = (buf); \ + size_t _len = (len); \ + int _snpf = snprintf(_buf, _len, (fmt), __VA_ARGS__); \ + _snpf >= 0 && (size_t) _snpf < _len ? _buf : NULL; \ + }) #define xsprintf(buf, fmt, ...) \ assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__), "xsprintf: " #buf "[] must be big enough") From 6e1e4b59f9ba89518382c7389da2d87911ec1d76 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Aug 2021 09:43:07 +0200 Subject: [PATCH 3/5] fd-util: add macro for generating /proc/self/fd/ paths on the fly --- src/basic/fd-util.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 61b6684cb3c..2382d52d40c 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -7,6 +7,7 @@ #include #include "macro.h" +#include "stdio-util.h" /* maximum length of fdname */ #define FDNAME_MAX 255 @@ -104,7 +105,20 @@ static inline int make_null_stdio(void) { 0; \ }) - int fd_reopen(int fd, int flags); int read_nr_open(void); int btrfs_defrag_fd(int fd); + +/* The maximum length a buffer for a /proc/self/fd/ path needs */ +#define PROC_FD_PATH_MAX \ + (STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)) + +static inline char *format_proc_fd_path(char buf[static PROC_FD_PATH_MAX], int fd) { + assert(buf); + assert(fd >= 0); + assert_se(snprintf_ok(buf, PROC_FD_PATH_MAX, "/proc/self/fd/%i", fd)); + return buf; +} + +#define FORMAT_PROC_FD_PATH(fd) \ + format_proc_fd_path((char[PROC_FD_PATH_MAX]) {}, (fd)) From 48a01cd93483d93de6f58431bb316dcedc55f3d3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Aug 2021 09:43:19 +0200 Subject: [PATCH 4/5] test: add test for FORMAT_PROC_FD_PATH() --- src/test/test-fd-util.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c index 1cd3bdfbbec..39a50013b96 100644 --- a/src/test/test-fd-util.c +++ b/src/test/test-fd-util.c @@ -278,6 +278,14 @@ static void test_close_all_fds(void) { log_open(); } +static void test_format_proc_fd_path(void) { + assert_se(streq_ptr(FORMAT_PROC_FD_PATH(0), "/proc/self/fd/0")); + assert_se(streq_ptr(FORMAT_PROC_FD_PATH(1), "/proc/self/fd/1")); + assert_se(streq_ptr(FORMAT_PROC_FD_PATH(2), "/proc/self/fd/2")); + assert_se(streq_ptr(FORMAT_PROC_FD_PATH(3), "/proc/self/fd/3")); + assert_se(streq_ptr(FORMAT_PROC_FD_PATH(2147483647), "/proc/self/fd/2147483647")); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -290,6 +298,7 @@ int main(int argc, char *argv[]) { test_rearrange_stdio(); test_read_nr_open(); test_close_all_fds(); + test_format_proc_fd_path(); return 0; } From ddb6eeafe2d3445eeab2c450cf9d270d68b3a4b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Aug 2021 09:43:25 +0200 Subject: [PATCH 5/5] tree-wide: port things over to FORMAT_PROC_FD_PATH() --- src/basic/fd-util.c | 8 ++---- src/basic/fileio.c | 5 +--- src/basic/fs-util.c | 31 +++++------------------ src/basic/namespace-util.c | 4 +-- src/basic/tmpfile-util.c | 6 +---- src/basic/xattr-util.c | 13 +++++----- src/core/service.c | 4 +-- src/nspawn/nspawn-patch-uid.c | 20 +++++---------- src/partition/repart.c | 16 ++++-------- src/shared/chown-recursive.c | 4 +-- src/shared/mount-util.c | 18 +++++-------- src/shared/selinux-util.c | 6 ++--- src/shared/smack-util.c | 8 +++--- src/systemctl/fuzz-systemctl-parse-argv.c | 8 ++---- src/tmpfiles/tmpfiles.c | 23 +++++------------ 15 files changed, 52 insertions(+), 122 deletions(-) diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c index 6b6457dbc22..d7cf85e0ee8 100644 --- a/src/basic/fd-util.c +++ b/src/basic/fd-util.c @@ -433,11 +433,9 @@ bool fdname_is_valid(const char *s) { } int fd_get_path(int fd, char **ret) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; int r; - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - r = readlink_malloc(procfs_path, ret); + r = readlink_malloc(FORMAT_PROC_FD_PATH(fd), ret); if (r == -ENOENT) { /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make * things debuggable and distinguish the two. */ @@ -647,7 +645,6 @@ finish: } int fd_reopen(int fd, int flags) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; int new_fd; /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to @@ -657,8 +654,7 @@ int fd_reopen(int fd, int flags) { * * This implicitly resets the file read index to 0. */ - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - new_fd = open(procfs_path, flags); + new_fd = open(FORMAT_PROC_FD_PATH(fd), flags); if (new_fd < 0) { if (errno != ENOENT) return -errno; diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 19fe6e214c9..f44fa57de47 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -721,8 +721,6 @@ int read_full_file_full( if (dir_fd == AT_FDCWD) r = sockaddr_un_set_path(&sa.un, filename); else { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - /* If we shall operate relative to some directory, then let's use O_PATH first to * open the socket inode, and then connect to it via /proc/self/fd/. We have to do * this since there's not connectat() that takes a directory fd as first arg. */ @@ -731,8 +729,7 @@ int read_full_file_full( if (dfd < 0) return -errno; - xsprintf(procfs_path, "/proc/self/fd/%i", dfd); - r = sockaddr_un_set_path(&sa.un, procfs_path); + r = sockaddr_un_set_path(&sa.un, FORMAT_PROC_FD_PATH(dfd)); } if (r < 0) return r; diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 28c7247e052..027f86fc0b0 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -308,14 +308,11 @@ int fchmod_umask(int fd, mode_t m) { } int fchmod_opath(int fd, mode_t m) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - /* This function operates also on fd that might have been opened with * O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like * fchownat() does. */ - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - if (chmod(procfs_path, m) < 0) { + if (chmod(FORMAT_PROC_FD_PATH(fd), m) < 0) { if (errno != ENOENT) return -errno; @@ -329,12 +326,9 @@ int fchmod_opath(int fd, mode_t m) { } int futimens_opath(int fd, const struct timespec ts[2]) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - /* Similar to fchmod_path() but for futimens() */ - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - if (utimensat(AT_FDCWD, procfs_path, ts, 0) < 0) { + if (utimensat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), ts, 0) < 0) { if (errno != ENOENT) return -errno; @@ -380,7 +374,6 @@ int fd_warn_permissions(const char *path, int fd) { } int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { - char fdpath[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_close_ int fd = -1; int r, ret = 0; @@ -412,8 +405,6 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi /* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode, * ownership and time of the file node in all cases, even if the fd refers to an O_PATH object — which is * something fchown(), fchmod(), futimensat() don't allow. */ - xsprintf(fdpath, "/proc/self/fd/%i", fd); - ret = fchmod_and_chown(fd, mode, uid, gid); if (stamp != USEC_INFINITY) { @@ -421,9 +412,9 @@ int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gi timespec_store(&ts[0], stamp); ts[1] = ts[0]; - r = utimensat(AT_FDCWD, fdpath, ts, 0); + r = utimensat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), ts, 0); } else - r = utimensat(AT_FDCWD, fdpath, NULL, 0); + r = utimensat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), NULL, 0); if (r < 0 && ret >= 0) return -errno; @@ -703,13 +694,10 @@ int unlink_or_warn(const char *filename) { } int inotify_add_watch_fd(int fd, int what, uint32_t mask) { - char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; int wd; /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */ - xsprintf(path, "/proc/self/fd/%i", what); - - wd = inotify_add_watch(fd, path, mask); + wd = inotify_add_watch(fd, FORMAT_PROC_FD_PATH(what), mask); if (wd < 0) return -errno; @@ -1156,7 +1144,6 @@ int chase_symlinks_and_opendir( char **ret_path, DIR **ret_dir) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; DIR *d; @@ -1182,8 +1169,7 @@ int chase_symlinks_and_opendir( return r; assert(path_fd >= 0); - xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); - d = opendir(procfs_path); + d = opendir(FORMAT_PROC_FD_PATH(path_fd)); if (!d) return -errno; @@ -1237,12 +1223,9 @@ int chase_symlinks_and_stat( } int access_fd(int fd, int mode) { - char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; - /* Like access() but operates on an already open fd */ - xsprintf(p, "/proc/self/fd/%i", fd); - if (access(p, mode) < 0) { + if (access(FORMAT_PROC_FD_PATH(fd), mode) < 0) { if (errno != ENOENT) return -errno; diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index a55b76df97b..d1fee952458 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -89,9 +89,7 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int /* Can't setns to your own userns, since then you could escalate from non-root to root in * your own namespace, so check if namespaces are equal before attempting to enter. */ - char userns_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - xsprintf(userns_fd_path, "/proc/self/fd/%d", userns_fd); - r = files_same(userns_fd_path, "/proc/self/ns/user", 0); + r = files_same(FORMAT_PROC_FD_PATH(userns_fd), "/proc/self/ns/user", 0); if (r < 0) return r; if (r) diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c index 91c8ff17254..36930cb34b5 100644 --- a/src/basic/tmpfile-util.c +++ b/src/basic/tmpfile-util.c @@ -300,11 +300,7 @@ int link_tmpfile(int fd, const char *path, const char *target) { if (r < 0) return r; } else { - char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; - - xsprintf(proc_fd_path, "/proc/self/fd/%i", fd); - - if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0) + if (linkat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0) return -errno; } diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c index e60e8bc920b..3d5eb6c378f 100644 --- a/src/basic/xattr-util.c +++ b/src/basic/xattr-util.c @@ -108,11 +108,10 @@ static int getxattrat_fake_prepare( int dirfd, const char *filename, int flags, - char ret_fn[static STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1], + char ret_fn[static PROC_FD_PATH_MAX], int *ret_fd) { _cleanup_close_ int fd = -1; - assert(ret_fn); assert(ret_fd); @@ -125,13 +124,15 @@ static int getxattrat_fake_prepare( if (!(flags & AT_EMPTY_PATH)) return -EINVAL; - snprintf(ret_fn, STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1, "/proc/self/fd/%i", dirfd); + assert(dirfd >= 0); + + format_proc_fd_path(ret_fn, dirfd); } else { fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); if (fd < 0) return -errno; - snprintf(ret_fn, STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1, "/proc/self/fd/%i", fd); + format_proc_fd_path(ret_fn, fd); } /* Pass the FD to the caller, since in case we do openat() the filename depends on it. */ @@ -148,8 +149,8 @@ int fgetxattrat_fake( int flags, size_t *ret_size) { - char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; _cleanup_close_ int fd = -1; + char fn[PROC_FD_PATH_MAX]; ssize_t l; int r; @@ -172,8 +173,8 @@ int fgetxattrat_fake_malloc( int flags, char **value) { - char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; _cleanup_close_ int fd = -1; + char fn[PROC_FD_PATH_MAX]; int r; r = getxattrat_fake_prepare(dirfd, filename, flags, fn, &fd); diff --git a/src/core/service.c b/src/core/service.c index 4115db0a302..c55304d170e 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -916,7 +916,6 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) { } static int service_load_pid_file(Service *s, bool may_warn) { - char procfs[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; bool questionable_pid_file = false; _cleanup_free_ char *k = NULL; _cleanup_close_ int fd = -1; @@ -945,8 +944,7 @@ static int service_load_pid_file(Service *s, bool may_warn) { /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd * chase_symlinks() returned us into a proper fd first. */ - xsprintf(procfs, "/proc/self/fd/%i", fd); - r = read_one_line_file(procfs, &k); + r = read_one_line_file(FORMAT_PROC_FD_PATH(fd), &k); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m", diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c index 785332e0910..f47f8273610 100644 --- a/src/nspawn/nspawn-patch-uid.c +++ b/src/nspawn/nspawn-patch-uid.c @@ -22,7 +22,6 @@ #if HAVE_ACL static int get_acl(int fd, const char *name, acl_type_t type, acl_t *ret) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; acl_t acl; assert(fd >= 0); @@ -35,14 +34,11 @@ static int get_acl(int fd, const char *name, acl_type_t type, acl_t *ret) { if (child_fd < 0) return -errno; - xsprintf(procfs_path, "/proc/self/fd/%i", child_fd); - acl = acl_get_file(procfs_path, type); + acl = acl_get_file(FORMAT_PROC_FD_PATH(child_fd), type); } else if (type == ACL_TYPE_ACCESS) acl = acl_get_fd(fd); - else { - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - acl = acl_get_file(procfs_path, type); - } + else + acl = acl_get_file(FORMAT_PROC_FD_PATH(fd), type); if (!acl) return -errno; @@ -51,7 +47,6 @@ static int get_acl(int fd, const char *name, acl_type_t type, acl_t *ret) { } static int set_acl(int fd, const char *name, acl_type_t type, acl_t acl) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; int r; assert(fd >= 0); @@ -64,14 +59,11 @@ static int set_acl(int fd, const char *name, acl_type_t type, acl_t acl) { if (child_fd < 0) return -errno; - xsprintf(procfs_path, "/proc/self/fd/%i", child_fd); - r = acl_set_file(procfs_path, type, acl); + r = acl_set_file(FORMAT_PROC_FD_PATH(child_fd), type, acl); } else if (type == ACL_TYPE_ACCESS) r = acl_set_fd(fd, acl); - else { - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - r = acl_set_file(procfs_path, type, acl); - } + else + r = acl_set_file(FORMAT_PROC_FD_PATH(fd), type, acl); if (r < 0) return -errno; diff --git a/src/partition/repart.c b/src/partition/repart.c index 6f3b3dbe179..e3080864b4b 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -1581,12 +1581,8 @@ static int context_load_partition_table( * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */ if (*backing_fd < 0) r = fdisk_assign_device(c, node, arg_dry_run); - else { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - xsprintf(procfs_path, "/proc/self/fd/%i", *backing_fd); - - r = fdisk_assign_device(c, procfs_path, arg_dry_run); - } + else + r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(*backing_fd), arg_dry_run); if (r == -EINVAL && arg_size_auto) { struct stat st; @@ -4593,7 +4589,6 @@ static int find_root(char **ret, int *ret_fd) { } static int resize_pt(int fd) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; int r; @@ -4605,14 +4600,13 @@ static int resize_pt(int fd) { if (!c) return log_oom(); - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - r = fdisk_assign_device(c, procfs_path, 0); + r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(fd), 0); if (r < 0) - return log_error_errno(r, "Failed to open device '%s': %m", procfs_path); + return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd)); r = fdisk_has_label(c); if (r < 0) - return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", procfs_path); + return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", FORMAT_PROC_FD_PATH(fd)); if (r == 0) { log_debug("Not resizing partition table, as there currently is none."); return 0; diff --git a/src/shared/chown-recursive.c b/src/shared/chown-recursive.c index 4563729b7c9..50848715e34 100644 --- a/src/shared/chown-recursive.c +++ b/src/shared/chown-recursive.c @@ -21,7 +21,6 @@ static int chown_one( gid_t gid, mode_t mask) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; const char *n; int r; @@ -30,11 +29,10 @@ static int chown_one( /* We change ACLs through the /proc/self/fd/%i path, so that we have a stable reference that works * with O_PATH. */ - xsprintf(procfs_path, "/proc/self/fd/%i", fd); /* Drop any ACL if there is one */ FOREACH_STRING(n, "system.posix_acl_access", "system.posix_acl_default") - if (removexattr(procfs_path, n) < 0) + if (removexattr(FORMAT_PROC_FD_PATH(fd), n) < 0) if (!IN_SET(errno, ENODATA, EOPNOTSUPP, ENOSYS, ENOTTY)) return -errno; diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index cf8ca8d9d3f..9a3f33915e1 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -42,10 +42,7 @@ int mount_fd(const char *source, unsigned long mountflags, const void *data) { - char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - - xsprintf(path, "/proc/self/fd/%i", target_fd); - if (mount(source, path, filesystemtype, mountflags, data) < 0) { + if (mount(source, FORMAT_PROC_FD_PATH(target_fd), filesystemtype, mountflags, data) < 0) { if (errno != ENOENT) return -errno; @@ -733,8 +730,7 @@ static int mount_in_namespace( _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; _cleanup_close_ int self_mntns_fd = -1, mntns_fd = -1, root_fd = -1, pidns_fd = -1, chased_src_fd = -1; - char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p, - chased_src[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p; bool mount_slave_created = false, mount_slave_mounted = false, mount_tmp_created = false, mount_tmp_mounted = false, mount_outside_created = false, mount_outside_mounted = false; @@ -767,9 +763,8 @@ static int mount_in_namespace( if (st.st_ino == self_mntns_st.st_ino && st.st_dev == self_mntns_st.st_dev) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to activate bind mount in target, not running in a mount namespace"); - /* One day, when bind mounting /proc/self/fd/n works across - * namespace boundaries we should rework this logic to make - * use of it... */ + /* One day, when bind mounting /proc/self/fd/n works across namespace boundaries we should rework + * this logic to make use of it... */ p = strjoina(propagate_path, "/"); r = laccess(p, F_OK); @@ -779,7 +774,6 @@ static int mount_in_namespace( r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, NULL, &chased_src_fd); if (r < 0) return log_debug_errno(r, "Failed to resolve source path of %s: %m", src); - xsprintf(chased_src, "/proc/self/fd/%i", chased_src_fd); if (fstat(chased_src_fd, &st) < 0) return log_debug_errno(errno, "Failed to stat() resolved source path %s: %m", src); @@ -824,9 +818,9 @@ static int mount_in_namespace( mount_tmp_created = true; if (is_image) - r = verity_dissect_and_mount(chased_src, mount_tmp, options, NULL, NULL, NULL); + r = verity_dissect_and_mount(FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, options, NULL, NULL, NULL); else - r = mount_follow_verbose(LOG_DEBUG, chased_src, mount_tmp, NULL, MS_BIND, NULL); + r = mount_follow_verbose(LOG_DEBUG, FORMAT_PROC_FD_PATH(chased_src_fd), mount_tmp, NULL, MS_BIND, NULL); if (r < 0) goto finish; diff --git a/src/shared/selinux-util.c b/src/shared/selinux-util.c index e4890e8170d..34e78e6792a 100644 --- a/src/shared/selinux-util.c +++ b/src/shared/selinux-util.c @@ -266,7 +266,6 @@ int mac_selinux_fix_container_fd(int fd, const char *path, const char *inside_pa assert(inside_path); #if HAVE_SELINUX - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_freecon_ char* fcon = NULL; struct stat st; int r; @@ -292,8 +291,7 @@ int mac_selinux_fix_container_fd(int fd, const char *path, const char *inside_pa goto fail; } - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - if (setfilecon_raw(procfs_path, fcon) < 0) { + if (setfilecon_raw(FORMAT_PROC_FD_PATH(fd), fcon) < 0) { _cleanup_freecon_ char *oldcon = NULL; /* If the FS doesn't support labels, then exit without warning */ @@ -307,7 +305,7 @@ int mac_selinux_fix_container_fd(int fd, const char *path, const char *inside_pa r = -errno; /* If the old label is identical to the new one, suppress any kind of error */ - if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon)) + if (getfilecon_raw(FORMAT_PROC_FD_PATH(fd), &oldcon) >= 0 && streq(fcon, oldcon)) return 0; goto fail; diff --git a/src/shared/smack-util.c b/src/shared/smack-util.c index 3362ee3924b..2ae11e7f9a7 100644 --- a/src/shared/smack-util.c +++ b/src/shared/smack-util.c @@ -121,8 +121,7 @@ int mac_smack_apply_pid(pid_t pid, const char *label) { return r; } -static int smack_fix_fd(int fd , const char *abspath, LabelFixFlags flags) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; +static int smack_fix_fd(int fd, const char *abspath, LabelFixFlags flags) { const char *label; struct stat st; int r; @@ -153,8 +152,7 @@ static int smack_fix_fd(int fd , const char *abspath, LabelFixFlags flags) { else return 0; - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) { + if (setxattr(FORMAT_PROC_FD_PATH(fd), "security.SMACK64", label, strlen(label), 0) < 0) { _cleanup_free_ char *old_label = NULL; r = -errno; @@ -168,7 +166,7 @@ static int smack_fix_fd(int fd , const char *abspath, LabelFixFlags flags) { return 0; /* If the old label is identical to the new one, suppress any kind of error */ - if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 && + if (getxattr_malloc(FORMAT_PROC_FD_PATH(fd), "security.SMACK64", &old_label, false) >= 0 && streq(old_label, label)) return 0; diff --git a/src/systemctl/fuzz-systemctl-parse-argv.c b/src/systemctl/fuzz-systemctl-parse-argv.c index 66b48eee857..eed8c671448 100644 --- a/src/systemctl/fuzz-systemctl-parse-argv.c +++ b/src/systemctl/fuzz-systemctl-parse-argv.c @@ -50,12 +50,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { else log_info(r == 0 ? "Done!" : "Action!"); - if (orig_stdout_fd >= 0) { - char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; - - xsprintf(path, "/proc/self/fd/%d", orig_stdout_fd); - assert_se(freopen(path, "w", stdout)); - } + if (orig_stdout_fd >= 0) + assert_se(freopen(FORMAT_PROC_FD_PATH(orig_stdout_fd), "w", stdout)); release_busses(); /* We open the bus for communication with logind. * It needs to be closed to avoid apparent leaks. */ diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index dd05dd9b4ee..38e9844d357 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1058,18 +1058,15 @@ static int parse_xattrs_from_arg(Item *i) { } static int fd_set_xattrs(Item *i, int fd, const char *path, const struct stat *st) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; char **name, **value; assert(i); assert(fd >= 0); assert(path); - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - STRV_FOREACH_PAIR(name, value, i->xattrs) { log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path); - if (setxattr(procfs_path, *name, *value, strlen(*value), 0) < 0) + if (setxattr(FORMAT_PROC_FD_PATH(fd), *name, *value, strlen(*value), 0) < 0) return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m", *name, *value, path); } @@ -1161,7 +1158,6 @@ static int path_set_acl(const char *path, const char *pretty, acl_type_t type, a static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *st) { int r = 0; #if HAVE_ACL - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; struct stat stbuf; assert(item); @@ -1184,14 +1180,12 @@ static int fd_set_acls(Item *item, int fd, const char *path, const struct stat * return 0; } - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - if (item->acl_access) - r = path_set_acl(procfs_path, path, ACL_TYPE_ACCESS, item->acl_access, item->append_or_force); + r = path_set_acl(FORMAT_PROC_FD_PATH(fd), path, ACL_TYPE_ACCESS, item->acl_access, item->append_or_force); /* set only default acls to folders */ if (r == 0 && item->acl_default && S_ISDIR(st->st_mode)) - r = path_set_acl(procfs_path, path, ACL_TYPE_DEFAULT, item->acl_default, item->append_or_force); + r = path_set_acl(FORMAT_PROC_FD_PATH(fd), path, ACL_TYPE_DEFAULT, item->acl_default, item->append_or_force); if (ERRNO_IS_NOT_SUPPORTED(r)) { log_debug_errno(r, "ACLs not supported by file system at %s", path); @@ -1938,17 +1932,14 @@ static int item_do(Item *i, int fd, const char *path, fdaction_t action) { r = action(i, fd, path, &st); if (S_ISDIR(st.st_mode)) { - char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; _cleanup_closedir_ DIR *d = NULL; struct dirent *de; - /* The passed 'fd' was opened with O_PATH. We need to convert - * it into a 'regular' fd before reading the directory content. */ - xsprintf(procfs_path, "/proc/self/fd/%i", fd); - - d = opendir(procfs_path); + /* The passed 'fd' was opened with O_PATH. We need to convert it into a 'regular' fd before + * reading the directory content. */ + d = opendir(FORMAT_PROC_FD_PATH(fd)); if (!d) { - log_error_errno(errno, "Failed to opendir() '%s': %m", procfs_path); + log_error_errno(errno, "Failed to opendir() '%s': %m", FORMAT_PROC_FD_PATH(fd)); if (r == 0) r = -errno; goto finish;