diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index a92241ca02..d20b9a5df5 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -713,7 +713,7 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { n1, path); } -int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) { +int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; _cleanup_close_ int fd = -1; unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */ @@ -725,10 +725,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, assert(path); /* Either the file may be missing, or we return an fd to the final object, but both make no sense */ - if (FLAGS_SET(flags, CHASE_NONEXISTENT | CHASE_OPEN)) + if ((flags & CHASE_NONEXISTENT) && ret_fd) return -EINVAL; - if (FLAGS_SET(flags, CHASE_STEP | CHASE_OPEN)) + if ((flags & CHASE_STEP) && ret_fd) return -EINVAL; if (isempty(path)) @@ -754,17 +754,17 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * function what to do when encountering a symlink with an absolute path as directory: prefix it by the * specified path. * - * There are three ways to invoke this function: + * There are five ways to invoke this function: * - * 1. Without CHASE_STEP or CHASE_OPEN: in this case the path is resolved and the normalized path is returned - * in `ret`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 is returned if the file - * doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is returned if the destination was - * found, -ENOENT if it wasn't. + * 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is + * returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 + * is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is + * returned if the destination was found, -ENOENT if it wasn't. * - * 2. With CHASE_OPEN: in this case the destination is opened after chasing it as O_PATH and this file + * 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file * descriptor is returned as return value. This is useful to open files relative to some root * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using - * fd_reopen() or such) before it can be used for reading/writing. CHASE_OPEN may not be combined with + * fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with * CHASE_NONEXISTENT. * * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first @@ -780,21 +780,21 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of * the mount point is emitted. - * */ /* A root directory of "/" or "" is identical to none */ if (empty_or_root(original_root)) original_root = NULL; - if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) { - /* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set + if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) { + /* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root set * and doesn't care about any of the other special features we provide either. */ r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); if (r < 0) return -errno; - return r; + *ret_fd = r; + return 0; } if (original_root) { @@ -803,7 +803,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return r; if (flags & CHASE_PREFIX_ROOT) { - /* We don't support relative paths in combination with a root directory */ if (!path_is_absolute(path)) return -EINVAL; @@ -948,7 +947,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { char *joined; - _cleanup_free_ char *destination = NULL; /* This is a symlink, in this case read the destination. But let's make sure we don't follow @@ -1034,15 +1032,15 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return -ENOMEM; } - if (ret) - *ret = TAKE_PTR(done); + if (ret_path) + *ret_path = TAKE_PTR(done); - if (flags & CHASE_OPEN) { - /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a proper fd by - * opening /proc/self/fd/xyz. */ + if (ret_fd) { + /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a + * proper fd by opening /proc/self/fd/xyz. */ assert(fd >= 0); - return TAKE_FD(fd); + *ret_fd = TAKE_FD(fd); } if (flags & CHASE_STEP) @@ -1051,14 +1049,14 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, return exists; chased_one: - if (ret) { + if (ret_path) { char *c; c = strjoin(strempty(done), todo); if (!c) return -ENOMEM; - *ret = c; + *ret_path = c; } return 0; @@ -1087,9 +1085,10 @@ int chase_symlinks_and_open( return r; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); r = fd_reopen(path_fd, open_flags); if (r < 0) @@ -1112,6 +1111,7 @@ int chase_symlinks_and_opendir( _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; DIR *d; + int r; if (!ret_dir) return -EINVAL; @@ -1128,9 +1128,10 @@ int chase_symlinks_and_opendir( return 0; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); d = opendir(procfs_path); @@ -1149,10 +1150,12 @@ int chase_symlinks_and_stat( const char *root, unsigned chase_flags, char **ret_path, - struct stat *ret_stat) { + struct stat *ret_stat, + int *ret_fd) { _cleanup_close_ int path_fd = -1; _cleanup_free_ char *p = NULL; + int r; assert(path); assert(ret_stat); @@ -1168,18 +1171,18 @@ int chase_symlinks_and_stat( return 1; } - path_fd = chase_symlinks(path, root, chase_flags|CHASE_OPEN, ret_path ? &p : NULL); - if (path_fd < 0) - return path_fd; + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); if (fstat(path_fd, ret_stat) < 0) return -errno; if (ret_path) *ret_path = TAKE_PTR(p); - - if (chase_flags & CHASE_OPEN) - return TAKE_FD(path_fd); + if (ret_fd) + *ret_fd = TAKE_FD(path_fd); return 1; } diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index fa0f0de9a3..78d68be9fd 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -79,23 +79,21 @@ enum { CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */ CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */ - CHASE_OPEN = 1 << 4, /* Return an O_PATH object to the final component */ - CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */ - CHASE_STEP = 1 << 6, /* Just execute a single step of the normalization */ - CHASE_NOFOLLOW = 1 << 7, /* Do not follow the path's right-most compontent. With CHASE_OPEN, when - * the path's right-most component refers to symlink, return O_PATH fd of - * the symlink. */ - CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */ + CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */ + CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */ + CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's + * right-most component refers to symlink, return O_PATH fd of the symlink. */ + CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */ }; /* How many iterations to execute before returning -ELOOP */ #define CHASE_SYMLINKS_MAX 32 -int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret); +int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd); int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); -int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat); +int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); /* Useful for usage with _cleanup_(), removes a directory and frees the pointer */ static inline void rmdir_and_free(char *p) { diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index 6b82eab640..1f318252a9 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -33,7 +33,7 @@ int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, Mkd if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) { _cleanup_free_ char *p = NULL; - r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p); + r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p, NULL); if (r < 0) return r; if (r == 0) diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index d3b8e44f18..a79377f05d 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -264,7 +264,7 @@ int path_is_mount_point(const char *t, const char *root, int flags) { * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we * look at needs to be /usr, not /. */ if (flags & AT_SYMLINK_FOLLOW) { - r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical); + r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical, NULL); if (r < 0) return r; diff --git a/src/basic/path-util.c b/src/basic/path-util.c index b9544b4bac..98b6d0617f 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -273,7 +273,7 @@ char **path_strv_resolve(char **l, const char *root) { } else t = *s; - r = chase_symlinks(t, root, 0, &u); + r = chase_symlinks(t, root, 0, &u, NULL); if (r == -ENOENT) { if (root) { u = TAKE_PTR(orig); diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 2cd722c106..4572e004bb 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -335,7 +335,7 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) { if (r < 0) return r; - return chase_symlinks(p, NULL, 0, ret); + return chase_symlinks(p, NULL, 0, ret, NULL); } int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) { diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 035011e34f..d98ec32a0b 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1471,7 +1471,7 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er if (!path_is_absolute(init)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init); - r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased); + r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased, NULL); if (r < 0) return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init); diff --git a/src/core/namespace.c b/src/core/namespace.c index 973b64007c..f6f7736819 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -875,7 +875,7 @@ static int follow_symlink( * a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the * end and already have a fully normalized name. */ - r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target); + r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target, NULL); if (r < 0) return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m)); if (r > 0) /* Reached the end, nothing more to resolve */ @@ -957,7 +957,7 @@ static int apply_mount( * mount source paths are always relative to the host root, hence we pass NULL as root directory to * chase_symlinks() here. */ - r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased); + r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased, NULL); if (r == -ENOENT && m->ignore) { log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m)); return 0; diff --git a/src/core/service.c b/src/core/service.c index 256ca46fd8..525ce42890 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -946,22 +946,27 @@ static int service_load_pid_file(Service *s, bool may_warn) { prio = may_warn ? LOG_INFO : LOG_DEBUG; - fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL); - if (fd == -ENOLINK) { - log_unit_full(UNIT(s), LOG_DEBUG, fd, "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); + r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); + if (r == -ENOLINK) { + log_unit_full(UNIT(s), LOG_DEBUG, r, + "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); questionable_pid_file = true; - fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN, NULL); + r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd); } - if (fd < 0) - return log_unit_full(UNIT(s), prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); + if (r < 0) + return log_unit_full(UNIT(s), prio, fd, + "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); - /* 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. */ + /* 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); 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", s->pid_file); + return log_unit_error_errno(UNIT(s), r, + "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m", + s->pid_file); r = parse_pid(k, &pid); if (r < 0) diff --git a/src/core/socket.c b/src/core/socket.c index 71ab3c647f..285aa641d3 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1429,7 +1429,7 @@ static int socket_determine_selinux_label(Socket *s, char **ret) { if (!c) goto no_label; - r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path); + r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL); if (r < 0) goto no_label; diff --git a/src/core/unit.c b/src/core/unit.c index 58c99d9e07..4fcc142ae9 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4974,7 +4974,7 @@ int unit_fail_if_noncanonical(Unit *u, const char* where) { assert(u); assert(where); - r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where); + r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where, NULL); if (r < 0) { log_unit_debug_errno(u, r, "Failed to check %s for symlinks, ignoring: %m", where); return 0; diff --git a/src/delta/delta.c b/src/delta/delta.c index bc11aa828a..cd33850b96 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -73,11 +73,11 @@ static int equivalent(const char *a, const char *b) { _cleanup_free_ char *x = NULL, *y = NULL; int r; - r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x); + r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x, NULL); if (r < 0) return r; - r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y); + r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y, NULL); if (r < 0) return r; @@ -378,7 +378,7 @@ static int should_skip_path(const char *prefix, const char *suffix) { dirname = prefix_roota(prefix, suffix); - if (chase_symlinks(dirname, NULL, 0, &target) < 0) + if (chase_symlinks(dirname, NULL, 0, &target, NULL) < 0) return false; NULSTR_FOREACH(p, prefixes) { diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 76270aec17..026a25f575 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -563,7 +563,7 @@ static int parse_fstab(bool initrd) { * target is the final directory. */ r = chase_symlinks(where, initrd ? "/sysroot" : NULL, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, - &canonical_where); + &canonical_where, NULL); if (r < 0) /* If we can't canonicalize we continue on as if it wasn't a symlink */ log_debug_errno(r, "Failed to read symlink target for %s, ignoring: %m", where); else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */ diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 6d6bb1cf63..6d9b5cfc2f 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1086,7 +1086,7 @@ static int add_matches(sd_journal *j, char **args) { _cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL; struct stat st; - r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p); + r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p, NULL); if (r < 0) return log_error_errno(r, "Couldn't canonicalize path: %m"); diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index c4a7f2f3d3..4a5e8ff944 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -146,7 +146,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { _syspath); if (verify) { - r = chase_symlinks(_syspath, NULL, 0, &syspath); + r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL); if (r == -ENOENT) return -ENODEV; /* the device does not exist (any more?) */ if (r < 0) @@ -157,7 +157,7 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { char *p; /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */ - r = chase_symlinks("/sys", NULL, 0, &real_sys); + r = chase_symlinks("/sys", NULL, 0, &real_sys, NULL); if (r < 0) return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m"); diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 0d58b5eb8b..c2747112d4 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -846,7 +846,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu if (laccess(p, F_OK) < 0) return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points."); - r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src); + r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src, NULL); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m"); diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 457ba4ea16..9f0220a75e 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -360,7 +360,7 @@ static int parse_argv(int argc, char *argv[]) { if (!u) return log_oom(); - r = chase_symlinks(u, NULL, 0, &arg_mount_what); + r = chase_symlinks(u, NULL, 0, &arg_mount_what, NULL); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", u); } else { @@ -377,7 +377,7 @@ static int parse_argv(int argc, char *argv[]) { if (argc > optind+1) { if (arg_transport == BUS_TRANSPORT_LOCAL) { - r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where); + r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where, NULL); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]); } else { @@ -1004,7 +1004,7 @@ static int action_umount( if (!u) return log_oom(); - r = chase_symlinks(u, NULL, 0, &p); + r = chase_symlinks(u, NULL, 0, &p, NULL); if (r < 0) { r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]); continue; diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 2f842754a4..6407503c4c 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -633,7 +633,7 @@ int mount_all(const char *dest, if (!tmpfs_tmp && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_TMPFS_TMP)) continue; - r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where); + r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where); @@ -734,7 +734,7 @@ static int mount_bind(const char *dest, CustomMount *m) { if (stat(m->source, &source_st) < 0) return log_error_errno(errno, "Failed to stat %s: %m", m->source); - r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where); + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); if (r > 0) { /* Path exists already? */ @@ -795,7 +795,7 @@ static int mount_tmpfs( assert(dest); assert(m); - r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where); + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); if (r == 0) { /* Doesn't exist yet? */ @@ -835,7 +835,7 @@ static int mount_overlay(const char *dest, CustomMount *m) { assert(dest); assert(m); - r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where); + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); if (r == 0) { /* Doesn't exist yet? */ @@ -878,7 +878,7 @@ static int mount_inaccessible(const char *dest, CustomMount *m) { assert(dest); assert(m); - r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st); + r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st, NULL); if (r < 0) { log_full_errno(m->graceful ? LOG_DEBUG : LOG_ERR, r, "Failed to resolve %s/%s: %m", dest, m->destination); return m->graceful ? 0 : r; @@ -906,7 +906,7 @@ static int mount_arbitrary(const char *dest, CustomMount *m) { assert(dest); assert(m); - r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where); + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); if (r == 0) { /* Doesn't exist yet? */ diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 40a7de981a..7760bcaa2d 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1668,7 +1668,7 @@ static int setup_timezone(const char *dest) { if (m == TIMEZONE_OFF) return 0; - r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc); + r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL); if (r < 0) { log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); return 0; @@ -1699,7 +1699,7 @@ static int setup_timezone(const char *dest) { return 0; /* Already pointing to the right place? Then do nothing .. */ check = strjoina(dest, "/usr/share/zoneinfo/", z); - r = chase_symlinks(check, dest, 0, NULL); + r = chase_symlinks(check, dest, 0, NULL, NULL); if (r < 0) log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z); else { @@ -1726,7 +1726,7 @@ static int setup_timezone(const char *dest) { _cleanup_free_ char *resolved = NULL; int found; - found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved); + found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL); if (found < 0) { log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m"); return 0; @@ -1832,7 +1832,7 @@ static int setup_resolv_conf(const char *dest) { if (m == RESOLV_CONF_OFF) return 0; - r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc); + r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL); if (r < 0) { log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); return 0; @@ -1856,7 +1856,7 @@ static int setup_resolv_conf(const char *dest) { _cleanup_free_ char *resolved = NULL; int found; - found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved); + found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL); if (found < 0) { log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m"); return 0; @@ -2733,12 +2733,11 @@ static int chase_symlinks_and_update(char **p, unsigned flags) { if (!*p) return 0; - r = chase_symlinks(*p, NULL, flags, &chased); + r = chase_symlinks(*p, NULL, flags, &chased, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve path %s: %m", *p); - free_and_replace(*p, chased); - return r; /* r might be an fd here in case we ever use CHASE_OPEN in flags */ + return free_and_replace(*p, chased); } static int determine_uid_shift(const char *directory) { diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c index 2f8b0254c8..06ab7735ad 100644 --- a/src/portable/portablectl.c +++ b/src/portable/portablectl.c @@ -67,7 +67,7 @@ static int determine_image(const char *image, bool permit_non_existing, char **r return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Operations on images by path not supported when connecting to remote systems."); - r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret); + r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret, NULL); if (r < 0) return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index a54714169e..3e75464966 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -833,7 +833,7 @@ static int mount_partition( rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY); if (directory) { - r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased); + r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL); if (r < 0) return r; @@ -909,7 +909,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, /* Mount the ESP to /efi if it exists. If it doesn't exist, use /boot instead, but only if it * exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */ - r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL); + r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL, NULL); if (r >= 0) { r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags); if (r < 0) @@ -918,7 +918,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, } else if (boot_mounted <= 0) { _cleanup_free_ char *p = NULL; - r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p); + r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p, NULL); if (r >= 0 && dir_is_empty(p) > 0) { r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags); if (r < 0) diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 2f67a44bf0..7328b7adde 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -106,7 +106,7 @@ static int unit_file_add_dir( /* This adds [original_root]/path to dirs, if it exists. */ - r = chase_symlinks(path, original_root, 0, &chased); + r = chase_symlinks(path, original_root, 0, &chased, NULL); if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */ return 0; if (r == -ENAMETOOLONG) { diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 7007374192..cceed58f74 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -1113,7 +1113,7 @@ int image_read_metadata(Image *i) { _cleanup_free_ char *hostname = NULL; _cleanup_free_ char *path = NULL; - r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path); + r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name); else if (r >= 0) { @@ -1124,7 +1124,7 @@ int image_read_metadata(Image *i) { path = mfree(path); - r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path); + r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name); else if (r >= 0) { @@ -1142,7 +1142,7 @@ int image_read_metadata(Image *i) { path = mfree(path); - r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path); + r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name); else if (r >= 0) { diff --git a/src/shared/os-util.c b/src/shared/os-util.c index 2191a610ae..b2af8535f9 100644 --- a/src/shared/os-util.c +++ b/src/shared/os-util.c @@ -33,22 +33,24 @@ int path_is_os_tree(const char *path) { int open_os_release(const char *root, char **ret_path, int *ret_fd) { _cleanup_free_ char *q = NULL; const char *p; - int k; + int r, fd; FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") { - k = chase_symlinks(p, root, CHASE_PREFIX_ROOT|(ret_fd ? CHASE_OPEN : 0), (ret_path ? &q : NULL)); - if (k != -ENOENT) + r = chase_symlinks(p, root, CHASE_PREFIX_ROOT, + ret_path ? &q : NULL, + ret_fd ? &fd : NULL); + if (r != -ENOENT) break; } - if (k < 0) - return k; + if (r < 0) + return r; if (ret_fd) { int real_fd; /* Convert the O_PATH fd into a proper, readable one */ - real_fd = fd_reopen(k, O_RDONLY|O_CLOEXEC|O_NOCTTY); - safe_close(k); + real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY); + safe_close(fd); if (real_fd < 0) return real_fd; diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index f721aff760..a807826378 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -52,7 +52,7 @@ int switch_root(const char *new_root, } /* Determine where we shall place the old root after the transition */ - r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after); + r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, old_root_after); if (r == 0) /* Doesn't exist yet. Let's create it */ @@ -68,7 +68,7 @@ int switch_root(const char *new_root, FOREACH_STRING(i, "/sys", "/dev", "/run", "/proc") { _cleanup_free_ char *chased = NULL; - r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased); + r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased, NULL); if (r < 0) return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, i); if (r > 0) { diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c index b015ff9338..28cd3c8600 100644 --- a/src/shared/unit-file.c +++ b/src/shared/unit-file.c @@ -303,7 +303,7 @@ int unit_file_build_name_map( } /* Get rid of "." and ".." components in target path */ - r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified); + r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified, NULL); if (r < 0) { log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m", filename, target); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index e4b85d906c..05013484ad 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2520,7 +2520,7 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **re if (!path) return log_oom(); - r = chase_symlinks(path, arg_root, 0, &lpath); + r = chase_symlinks(path, arg_root, 0, &lpath, NULL); if (r == -ENOENT) continue; if (r == -ENOMEM) diff --git a/src/test/test-chase-symlinks.c b/src/test/test-chase-symlinks.c index 013b36e2a7..0b7dd8764f 100644 --- a/src/test/test-chase-symlinks.c +++ b/src/test/test-chase-symlinks.c @@ -8,21 +8,23 @@ static char *arg_root = NULL; static int arg_flags = 0; +static bool arg_open = false; static int parse_argv(int argc, char *argv[]) { enum { ARG_ROOT = 0x1000, + ARG_OPEN, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "root", required_argument, NULL, ARG_ROOT }, + { "open", no_argument, NULL, ARG_OPEN }, { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT }, { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT }, { "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS }, { "safe", no_argument, NULL, CHASE_SAFE }, - { "open", no_argument, NULL, CHASE_OPEN }, { "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH }, { "step", no_argument, NULL, CHASE_STEP }, { "nofollow", no_argument, NULL, CHASE_NOFOLLOW }, @@ -51,11 +53,14 @@ static int parse_argv(int argc, char *argv[]) { arg_root = optarg; break; + case ARG_OPEN: + arg_open = true; + break; + case CHASE_PREFIX_ROOT: case CHASE_NONEXISTENT: case CHASE_NO_AUTOFS: case CHASE_SAFE: - case CHASE_OPEN: case CHASE_TRAIL_SLASH: case CHASE_STEP: case CHASE_NOFOLLOW: @@ -89,18 +94,21 @@ static int run(int argc, char **argv) { for (int i = optind; i < argc; i++) { _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; printf("%s ", argv[i]); fflush(stdout); - r = chase_symlinks(argv[i], arg_root, arg_flags, &p); + r = chase_symlinks(argv[i], arg_root, arg_flags, &p, arg_open ? &fd : NULL); if (r < 0) log_error_errno(r, "failed: %m"); - else + else { log_info("→ %s", p); - - if (FLAGS_SET(arg_flags, CHASE_OPEN)) - safe_close(r); + if (arg_open) + assert(fd >= 0); + else + assert(fd == -1); + } } return 0; diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 5f7b9e5ce8..ffabf95663 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -130,7 +130,7 @@ static void test_copy_tree(void) { assert_se(f = strjoin(original_dir, *p)); assert_se(l = strjoin(copy_dir, *link)); - assert_se(chase_symlinks(l, NULL, 0, &target) == 1); + assert_se(chase_symlinks(l, NULL, 0, &target, NULL) == 1); assert_se(path_equal(f, target)); } diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 7cf4f4976b..ac8b95aece 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -61,45 +61,45 @@ static void test_chase_symlinks(void) { /* Paths that use symlinks underneath the "root" */ - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, "/usr")); result = mfree(result); pslash = strjoina(p, "/"); - r = chase_symlinks(pslash, NULL, 0, &result); + r = chase_symlinks(pslash, NULL, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, "/usr/")); result = mfree(result); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r == -ENOENT); - r = chase_symlinks(pslash, temp, 0, &result); + r = chase_symlinks(pslash, temp, 0, &result, NULL); assert_se(r == -ENOENT); q = strjoina(temp, "/usr"); - r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result); + r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result, NULL); assert_se(r == 0); assert_se(path_equal(result, q)); result = mfree(result); qslash = strjoina(q, "/"); - r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result); + r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result, NULL); assert_se(r == 0); assert_se(path_equal(result, qslash)); result = mfree(result); assert_se(mkdir(q, 0700) >= 0); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, q)); result = mfree(result); - r = chase_symlinks(pslash, temp, 0, &result); + r = chase_symlinks(pslash, temp, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, qslash)); result = mfree(result); @@ -107,12 +107,12 @@ static void test_chase_symlinks(void) { p = strjoina(temp, "/slash"); assert_se(symlink("/", p) >= 0); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, "/")); result = mfree(result); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, temp)); result = mfree(result); @@ -122,21 +122,21 @@ static void test_chase_symlinks(void) { p = strjoina(temp, "/6dots"); assert_se(symlink("../../..", p) >= 0); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r > 0 && path_equal(result, temp)); result = mfree(result); p = strjoina(temp, "/6dotsusr"); assert_se(symlink("../../../usr", p) >= 0); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r > 0 && path_equal(result, q)); result = mfree(result); p = strjoina(temp, "/top/8dotsusr"); assert_se(symlink("../../../../usr", p) >= 0); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r > 0 && path_equal(result, q)); result = mfree(result); @@ -145,12 +145,12 @@ static void test_chase_symlinks(void) { p = strjoina(temp, "/slashslash"); assert_se(symlink("///usr///", p) >= 0); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, "/usr")); result = mfree(result); - r = chase_symlinks(p, temp, 0, &result); + r = chase_symlinks(p, temp, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, q)); result = mfree(result); @@ -169,48 +169,48 @@ static void test_chase_symlinks(void) { assert_se(symlink("/", p) >= 0); /* Fail when user-owned directories contain root-owned subdirectories. */ - r = chase_symlinks(p, temp, CHASE_SAFE, &result); + r = chase_symlinks(p, temp, CHASE_SAFE, &result, NULL); assert_se(r == -ENOLINK); result = mfree(result); /* Allow this when the user-owned directories are all in the "root". */ - r = chase_symlinks(p, q, CHASE_SAFE, &result); + r = chase_symlinks(p, q, CHASE_SAFE, &result, NULL); assert_se(r > 0); result = mfree(result); } /* Paths using . */ - r = chase_symlinks("/etc/./.././", NULL, 0, &result); + r = chase_symlinks("/etc/./.././", NULL, 0, &result, NULL); assert_se(r > 0); assert_se(path_equal(result, "/")); result = mfree(result); - r = chase_symlinks("/etc/./.././", "/etc", 0, &result); + r = chase_symlinks("/etc/./.././", "/etc", 0, &result, NULL); assert_se(r > 0 && path_equal(result, "/etc")); result = mfree(result); - r = chase_symlinks("/../.././//../../etc", NULL, 0, &result); + r = chase_symlinks("/../.././//../../etc", NULL, 0, &result, NULL); assert_se(r > 0); assert_se(streq(result, "/etc")); result = mfree(result); - r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result); + r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result, NULL); assert_se(r == 0); assert_se(streq(result, "/test-chase.fsldajfl")); result = mfree(result); - r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result); + r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result, NULL); assert_se(r > 0); assert_se(streq(result, "/etc")); result = mfree(result); - r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result); + r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result, NULL); assert_se(r == 0); assert_se(streq(result, "/test-chase.fsldajfl")); result = mfree(result); - r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result); + r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result, NULL); assert_se(r == -ENOTDIR); result = mfree(result); @@ -218,25 +218,25 @@ static void test_chase_symlinks(void) { p = strjoina(temp, "/recursive-symlink"); assert_se(symlink("recursive-symlink", p) >= 0); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r == -ELOOP); /* Path which doesn't exist */ p = strjoina(temp, "/idontexist"); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r == -ENOENT); - r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result); + r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); assert_se(r == 0); assert_se(path_equal(result, p)); result = mfree(result); p = strjoina(temp, "/idontexist/meneither"); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r == -ENOENT); - r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result); + r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); assert_se(r == 0); assert_se(path_equal(result, p)); result = mfree(result); @@ -244,17 +244,17 @@ static void test_chase_symlinks(void) { /* Path which doesn't exist, but contains weird stuff */ p = strjoina(temp, "/idontexist/.."); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r == -ENOENT); - r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result); + r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); assert_se(r == -ENOENT); p = strjoina(temp, "/target"); q = strjoina(temp, "/top"); assert_se(symlink(q, p) >= 0); p = strjoina(temp, "/target/idontexist"); - r = chase_symlinks(p, NULL, 0, &result); + r = chase_symlinks(p, NULL, 0, &result, NULL); assert_se(r == -ENOENT); if (geteuid() == 0) { @@ -264,30 +264,30 @@ static void test_chase_symlinks(void) { q = strjoina(p, "/priv2"); assert_se(mkdir(q, 0755) >= 0); - assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chown(q, UID_NOBODY, GID_NOBODY) >= 0); - assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0); - assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); assert_se(chown(q, 0, 0) >= 0); - assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK); assert_se(rmdir(q) >= 0); assert_se(symlink("/etc/passwd", q) >= 0); - assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) == -ENOLINK); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK); assert_se(chown(p, 0, 0) >= 0); - assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); } p = strjoina(temp, "/machine-id-test"); assert_se(symlink("/usr/../etc/./machine-id", p) >= 0); - pfd = chase_symlinks(p, NULL, CHASE_OPEN, NULL); - if (pfd != -ENOENT) { + r = chase_symlinks(p, NULL, 0, NULL, &pfd); + if (r != -ENOENT) { _cleanup_close_ int fd = -1; sd_id128_t a, b; @@ -307,8 +307,9 @@ static void test_chase_symlinks(void) { p = strjoina(temp, "/target"); q = strjoina(temp, "/symlink"); assert_se(symlink(p, q) >= 0); - pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result); - assert_se(pfd > 0); + r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd); + assert_se(r >= 0); + assert_se(pfd >= 0); assert_se(path_equal(result, q)); assert_se(fstat(pfd, &st) >= 0); assert_se(S_ISLNK(st.st_mode)); @@ -319,8 +320,9 @@ static void test_chase_symlinks(void) { assert_se(symlink("s2", q) >= 0); p = strjoina(temp, "/s2"); assert_se(symlink("nonexistent", p) >= 0); - pfd = chase_symlinks(q, NULL, CHASE_OPEN|CHASE_NOFOLLOW, &result); - assert_se(pfd > 0); + r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd); + assert_se(r >= 0); + assert_se(pfd >= 0); assert_se(path_equal(result, q)); assert_se(fstat(pfd, &st) >= 0); assert_se(S_ISLNK(st.st_mode)); @@ -329,42 +331,42 @@ static void test_chase_symlinks(void) { /* Test CHASE_ONE */ p = strjoina(temp, "/start"); - r = chase_symlinks(p, NULL, CHASE_STEP, &result); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); assert_se(r == 0); p = strjoina(temp, "/top/dot/dotdota"); assert_se(streq(p, result)); result = mfree(result); - r = chase_symlinks(p, NULL, CHASE_STEP, &result); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); assert_se(r == 0); p = strjoina(temp, "/top/./dotdota"); assert_se(streq(p, result)); result = mfree(result); - r = chase_symlinks(p, NULL, CHASE_STEP, &result); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); assert_se(r == 0); p = strjoina(temp, "/top/../a"); assert_se(streq(p, result)); result = mfree(result); - r = chase_symlinks(p, NULL, CHASE_STEP, &result); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); assert_se(r == 0); p = strjoina(temp, "/a"); assert_se(streq(p, result)); result = mfree(result); - r = chase_symlinks(p, NULL, CHASE_STEP, &result); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); assert_se(r == 0); p = strjoina(temp, "/b"); assert_se(streq(p, result)); result = mfree(result); - r = chase_symlinks(p, NULL, CHASE_STEP, &result); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); assert_se(r == 0); assert_se(streq("/usr", result)); result = mfree(result); - r = chase_symlinks("/usr", NULL, CHASE_STEP, &result); + r = chase_symlinks("/usr", NULL, CHASE_STEP, &result, NULL); assert_se(r > 0); assert_se(streq("/usr", result)); result = mfree(result); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 19a2aa6f21..fae949863a 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -859,7 +859,7 @@ shortcut: static int path_open_parent_safe(const char *path) { _cleanup_free_ char *dn = NULL; - int fd; + int r, fd; if (path_equal(path, "/") || !path_is_normalized(path)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -870,15 +870,15 @@ static int path_open_parent_safe(const char *path) { if (!dn) return log_oom(); - fd = chase_symlinks(dn, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN, NULL); - if (fd < 0 && fd != -ENOLINK) - return log_error_errno(fd, "Failed to validate path %s: %m", path); + r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd); + if (r < 0 && r != -ENOLINK) + return log_error_errno(r, "Failed to validate path %s: %m", path); - return fd; + return r < 0 ? r : fd; } static int path_open_safe(const char *path) { - int fd; + int r, fd; /* path_open_safe() returns a file descriptor opened with O_PATH after * verifying that the path doesn't contain unsafe transitions, except @@ -891,11 +891,11 @@ static int path_open_safe(const char *path) { "Failed to open invalid path '%s'.", path); - fd = chase_symlinks(path, arg_root, CHASE_OPEN|CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL); - if (fd < 0 && fd != -ENOLINK) - return log_error_errno(fd, "Failed to validate path %s: %m", path); + r = chase_symlinks(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL, &fd); + if (r < 0 && r != -ENOLINK) + return log_error_errno(r, "Failed to validate path %s: %m", path); - return fd; + return r < 0 ? r : fd; } static int path_set_perms(Item *i, const char *path) { @@ -2257,7 +2257,7 @@ static int process_item(Item *i, OperationMask operation) { i->done |= operation; - r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL); + r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL, NULL); if (r == -EREMOTE) { log_notice_errno(r, "Skipping %s", i->path); return 0; diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index b82fd88497..e6d4659d9f 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -119,7 +119,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn /* Check if this is a virtual function. */ physfn_link_file = strjoina(syspath, "/physfn"); - r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath); + r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath, NULL); if (r < 0) return r; @@ -143,7 +143,7 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn if (!virtfn_link_file) return -ENOMEM; - if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath) < 0) + if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0) continue; if (streq(syspath, virtfn_pci_syspath)) { diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index d1193a7a24..af78a87d6f 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -21,7 +21,7 @@ static int make_volatile(const char *path) { assert(path); - r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr); + r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr, NULL); if (r < 0) return log_error_errno(r, "/usr not available in old root: %m");