Merge pull request #8708 from poettering/namespace-repeat
pid1 namespacing fixes
This commit is contained in:
+62
-3
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user