Merge pull request #23061 from poettering/chase-symlinks-tweaks,-new

some chase_symlinks() tweaks
This commit is contained in:
Lennart Poettering
2022-04-12 22:57:17 +02:00
committed by GitHub
2 changed files with 41 additions and 29 deletions
+34 -22
View File
@@ -24,7 +24,7 @@ bool unsafe_transition(const struct stat *a, const struct stat *b) {
return a->st_uid != b->st_uid; /* Otherwise we need to stay within the same UID */
}
static int log_unsafe_transition(int a, int b, const char *path, unsigned flags) {
static int log_unsafe_transition(int a, int b, const char *path, ChaseSymlinksFlags flags) {
_cleanup_free_ char *n1 = NULL, *n2 = NULL, *user_a = NULL, *user_b = NULL;
struct stat st;
@@ -44,7 +44,7 @@ static int log_unsafe_transition(int a, int b, const char *path, unsigned flags)
strna(n1), strna(user_a), special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), strna(n2), strna(user_b), path);
}
static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
static int log_autofs_mount_point(int fd, const char *path, ChaseSymlinksFlags flags) {
_cleanup_free_ char *n1 = NULL;
if (!FLAGS_SET(flags, CHASE_WARN))
@@ -57,7 +57,13 @@ static int log_autofs_mount_point(int fd, const char *path, unsigned flags) {
strna(n1), path);
}
int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) {
int chase_symlinks(
const char *path,
const char *original_root,
ChaseSymlinksFlags 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 */
@@ -78,6 +84,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (isempty(path))
return -EINVAL;
/* We don't support relative paths in combination with a root directory */
if (FLAGS_SET(flags, CHASE_PREFIX_ROOT) && !path_is_absolute(path))
return -EINVAL;
/* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
* symlinks relative to a root directory, instead of the root of the host.
*
@@ -155,19 +165,19 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
path_simplify(root);
if (flags & CHASE_PREFIX_ROOT) {
/* We don't support relative paths in combination with a root directory */
if (!path_is_absolute(path))
return -EINVAL;
path = prefix_roota(root, path);
buffer = path_join(root, path);
if (!buffer)
return -ENOMEM;
}
}
r = path_make_absolute_cwd(path, &buffer);
if (r < 0)
return r;
if (!buffer) {
r = path_make_absolute_cwd(path, &buffer);
if (r < 0)
return r;
}
fd = open(root ?: "/", O_CLOEXEC|O_DIRECTORY|O_PATH);
fd = open(empty_to_root(root), O_CLOEXEC|O_DIRECTORY|O_PATH);
if (fd < 0)
return -errno;
@@ -193,6 +203,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
todo = buffer;
done = strdup("/");
}
if (!done)
return -ENOMEM;
for (;;) {
_cleanup_free_ char *first = NULL;
@@ -200,7 +212,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
struct stat st;
const char *e;
r = path_find_first_component(&todo, true, &e);
r = path_find_first_component(&todo, /* accept_dot_dot= */ true, &e);
if (r < 0)
return r;
if (r == 0) { /* We reached the end. */
@@ -224,9 +236,9 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (empty_or_root(done))
continue;
parent = dirname_malloc(done);
if (!parent)
return -ENOMEM;
r = path_extract_directory(done, &parent);
if (r < 0)
return r;
/* Don't allow this to leave the root dir. */
if (root &&
@@ -311,7 +323,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* directory as base. */
safe_close(fd);
fd = open(root ?: "/", O_CLOEXEC|O_DIRECTORY|O_PATH);
fd = open(empty_to_root(root), O_CLOEXEC|O_DIRECTORY|O_PATH);
if (fd < 0)
return -errno;
@@ -375,7 +387,7 @@ chased_one:
const char *e;
/* todo may contain slashes at the beginning. */
r = path_find_first_component(&todo, true, &e);
r = path_find_first_component(&todo, /* accept_dot_dot= */ true, &e);
if (r < 0)
return r;
if (r == 0)
@@ -397,7 +409,7 @@ chased_one:
int chase_symlinks_and_open(
const char *path,
const char *root,
unsigned chase_flags,
ChaseSymlinksFlags chase_flags,
int open_flags,
char **ret_path) {
@@ -435,7 +447,7 @@ int chase_symlinks_and_open(
int chase_symlinks_and_opendir(
const char *path,
const char *root,
unsigned chase_flags,
ChaseSymlinksFlags chase_flags,
char **ret_path,
DIR **ret_dir) {
@@ -478,7 +490,7 @@ int chase_symlinks_and_opendir(
int chase_symlinks_and_stat(
const char *path,
const char *root,
unsigned chase_flags,
ChaseSymlinksFlags chase_flags,
char **ret_path,
struct stat *ret_stat,
int *ret_fd) {
@@ -520,7 +532,7 @@ int chase_symlinks_and_stat(
int chase_symlinks_and_fopen_unlocked(
const char *path,
const char *root,
unsigned chase_flags,
ChaseSymlinksFlags chase_flags,
const char *open_flags,
char **ret_path,
FILE **ret_file) {
+7 -7
View File
@@ -6,7 +6,7 @@
#include "stat-util.h"
enum {
typedef enum ChaseSymlinksFlags {
CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */
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 */
@@ -16,17 +16,17 @@ enum {
CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most component. 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 */
};
} ChaseSymlinksFlags;
bool unsafe_transition(const struct stat *a, const struct stat *b);
/* 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_path, int *ret_fd);
int chase_symlinks(const char *path_with_prefix, const char *root, ChaseSymlinksFlags chase_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 *ret_fd);
int chase_symlinks_and_open(const char *path, const char *root, ChaseSymlinksFlags chase_flags, int open_flags, char **ret_path);
int chase_symlinks_and_opendir(const char *path, const char *root, ChaseSymlinksFlags chase_flags, char **ret_path, DIR **ret_dir);
int chase_symlinks_and_stat(const char *path, const char *root, ChaseSymlinksFlags chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd);
int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, unsigned chase_flags, const char *open_flags, char **ret_path, FILE **ret_file);
int chase_symlinks_and_fopen_unlocked(const char *path, const char *root, ChaseSymlinksFlags chase_flags, const char *open_flags, char **ret_path, FILE **ret_file);