Merge pull request #8708 from poettering/namespace-repeat

pid1 namespacing fixes
This commit is contained in:
Lennart Poettering
2018-04-18 18:46:44 +02:00
committed by GitHub
4 changed files with 222 additions and 53 deletions
+62 -3
View File
@@ -578,7 +578,7 @@ static bool safe_transition(const struct stat *a, const struct stat *b) {
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
_cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1;
unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */
struct stat previous_stat;
bool exists = true;
char *todo;
@@ -590,6 +590,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if ((flags & (CHASE_NONEXISTENT|CHASE_OPEN)) == (CHASE_NONEXISTENT|CHASE_OPEN))
return -EINVAL;
if ((flags & (CHASE_STEP|CHASE_OPEN)) == (CHASE_STEP|CHASE_OPEN))
return -EINVAL;
if (isempty(path))
return -EINVAL;
@@ -611,13 +614,34 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
* as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
* function what to do when encountering a symlink with an absolute path as directory: prefix it by the
* specified path. */
* specified path.
*
* There are three 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 doesn't.
*
* 2. With CHASE_OPEN: 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
* CHASE_NONEXISTENT.
*
* 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first
* symlink or ".." component of the path is resolved, and the resulting path is returned. This is useful if
* a caller wants to trace the a path through the file system verbosely. Returns < 0 on error, > 0 if the
* path is fully normalized, and == 0 for each normalization step. This may be combined with
* CHASE_NONEXISTENT, in which case 1 is returned when a component is not found.
*
* */
/* 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_OPEN) {
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
* and doesn't care about any of the other special features we provide either. */
r = open(path, O_PATH|O_CLOEXEC);
@@ -714,6 +738,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
free_and_replace(done, parent);
if (flags & CHASE_STEP)
goto chased_one;
fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
if (fd_parent < 0)
return -errno;
@@ -830,6 +857,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
free(buffer);
todo = buffer = joined;
if (flags & CHASE_STEP)
goto chased_one;
continue;
}
@@ -868,7 +898,36 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
return TAKE_FD(fd);
}
if (flags & CHASE_STEP)
return 1;
return exists;
chased_one:
if (ret) {
char *c;
if (done) {
if (todo) {
c = strjoin(done, todo);
if (!c)
return -ENOMEM;
} else
c = TAKE_PTR(done);
} else {
if (todo)
c = strdup(todo);
else
c = strdup("/");
if (!c)
return -ENOMEM;
}
*ret = c;
}
return 0;
}
int chase_symlinks_and_open(
+4
View File
@@ -75,8 +75,12 @@ enum {
CHASE_SAFE = 1U << 3, /* If set, return EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_OPEN = 1U << 4, /* If set, return an O_PATH object to the final component */
CHASE_TRAIL_SLASH = 1U << 5, /* If set, any trailing slash will be preserved */
CHASE_STEP = 1U << 6, /* If set, just execute a single step of the normalization */
};
/* 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_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path);