Compare commits
2 Commits
1048436869
...
a5648b8094
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | a5648b8094 | |
Zbigniew Jędrzejewski-Szmek | 58ce85f6a1 |
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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? */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -66,7 +66,7 @@ static void test_socket_address_parse_one(const char *in, int ret, int family, c
|
|||
}
|
||||
|
||||
#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path))
|
||||
assert_cc(sizeof(((struct sockaddr_un){}).sun_path) == 108);
|
||||
assert_cc(SUN_PATH_LEN == 108);
|
||||
|
||||
static void test_socket_address_parse(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
@ -126,6 +126,7 @@ static void test_socket_address_parse(void) {
|
|||
static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) {
|
||||
_cleanup_free_ char *out = NULL, *c = NULL;
|
||||
|
||||
assert(len_in <= SUN_PATH_LEN);
|
||||
SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } },
|
||||
.size = offsetof(struct sockaddr_un, sun_path) + len_in,
|
||||
.type = SOCK_STREAM,
|
||||
|
@ -152,8 +153,6 @@ static void test_socket_print_unix(void) {
|
|||
"@_________________________there\\'s 108 characters in this string_____________________________________________");
|
||||
test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108,
|
||||
"////////////////////////////////////////////////////////////////////////////////////////////////////////////");
|
||||
test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 109,
|
||||
"////////////////////////////////////////////////////////////////////////////////////////////////////////////");
|
||||
test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue