chase: check root path in more detail
In chaseat() we call dir_fd_is_root() several places, and the final result depends on it. If the root path specified to `chase()` is not normalized but points to "/", e.g. "/../", assertions in `chaseat()` or `chase()` may be triggered.
This commit is contained in:
+35
-1
@@ -518,6 +518,27 @@ chased_one:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int empty_or_root_to_null(const char **path) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
/* This nullifies the input path when the path is empty or points to "/". */
|
||||
|
||||
if (empty_or_root(*path)) {
|
||||
*path = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = path_is_root(*path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
*path = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chase(const char *path, const char *root, ChaseFlags flags, char **ret_path, int *ret_fd) {
|
||||
_cleanup_free_ char *root_abs = NULL, *absolute = NULL, *p = NULL;
|
||||
_cleanup_close_ int fd = -EBADF, pfd = -EBADF;
|
||||
@@ -528,6 +549,10 @@ int chase(const char *path, const char *root, ChaseFlags flags, char **ret_path,
|
||||
if (isempty(path))
|
||||
return -EINVAL;
|
||||
|
||||
r = empty_or_root_to_null(&root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* A root directory of "/" or "" is identical to "/". */
|
||||
if (empty_or_root(root)) {
|
||||
root = "/";
|
||||
@@ -624,8 +649,13 @@ int chaseat_prefix_root(const char *path, const char *root, char **ret) {
|
||||
if (!path_is_absolute(path)) {
|
||||
_cleanup_free_ char *root_abs = NULL;
|
||||
|
||||
r = empty_or_root_to_null(&root);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
/* If the dir_fd points to the root directory, chaseat() always returns an absolute path. */
|
||||
assert(!empty_or_root(root));
|
||||
if (empty_or_root(root))
|
||||
return -EINVAL;
|
||||
|
||||
r = path_make_absolute_cwd(root, &root_abs);
|
||||
if (r < 0)
|
||||
@@ -658,6 +688,10 @@ int chase_extract_filename(const char *path, const char *root, char **ret) {
|
||||
if (!path_is_absolute(path))
|
||||
return -EINVAL;
|
||||
|
||||
r = empty_or_root_to_null(&root);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
if (!empty_or_root(root)) {
|
||||
_cleanup_free_ char *root_abs = NULL;
|
||||
|
||||
|
||||
@@ -102,6 +102,9 @@ int read_nr_open(void);
|
||||
int fd_get_diskseq(int fd, uint64_t *ret);
|
||||
|
||||
int path_is_root_at(int dir_fd, const char *path);
|
||||
static inline int path_is_root(const char *path) {
|
||||
return path_is_root_at(AT_FDCWD, path);
|
||||
}
|
||||
static inline int dir_fd_is_root(int dir_fd) {
|
||||
return path_is_root_at(dir_fd, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user