1
0
mirror of https://github.com/systemd/systemd synced 2026-04-25 16:34:50 +02:00

Compare commits

...

8 Commits

Author SHA1 Message Date
Lennart Poettering
5e9f594038
Merge pull request #23061 from poettering/chase-symlinks-tweaks,-new
some chase_symlinks() tweaks
2022-04-12 22:57:17 +02:00
Yu Watanabe
5180394b38 core: use assert_se() which takes side-effect
Fixes #23059.
2022-04-12 18:45:20 +02:00
Lennart Poettering
57f9ca3aa0 chase-symlinks: prefer path_extract_directory() over dirname() 2022-04-12 17:10:50 +02:00
Lennart Poettering
860f4c6aa6 chase-symlinks: add comment for opaque argument 2022-04-12 17:10:06 +02:00
Lennart Poettering
0ac6cdd6ae chase-symlinks: add missing OOM check 2022-04-12 17:09:21 +02:00
Lennart Poettering
69cf392f8e chase-symlinks: use empty_to_root() where appropriate 2022-04-12 17:08:33 +02:00
Lennart Poettering
7b9be862c7 chase-symlinks: avoid using stack allocation for potentially huge paths
let's better be safe and use heap allocation for paths which might be
unbounded.

In particular as previously we copied the stack memory to heap anyway,
via a noop path_make_absolute_cwd() call.
2022-04-12 17:07:49 +02:00
Lennart Poettering
8f47f880a4 chase-symlinks: use proper typedef for flags argument 2022-04-12 17:06:49 +02:00
3 changed files with 42 additions and 30 deletions

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 */ 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; _cleanup_free_ char *n1 = NULL, *n2 = NULL, *user_a = NULL, *user_b = NULL;
struct stat st; 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); 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; _cleanup_free_ char *n1 = NULL;
if (!FLAGS_SET(flags, CHASE_WARN)) 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); 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_free_ char *buffer = NULL, *done = NULL, *root = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
unsigned max_follow = CHASE_SYMLINKS_MAX; /* 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 */
@ -78,6 +84,10 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (isempty(path)) if (isempty(path))
return -EINVAL; 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 /* 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. * 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); path_simplify(root);
if (flags & CHASE_PREFIX_ROOT) { if (flags & CHASE_PREFIX_ROOT) {
/* We don't support relative paths in combination with a root directory */ buffer = path_join(root, path);
if (!path_is_absolute(path)) if (!buffer)
return -EINVAL; return -ENOMEM;
path = prefix_roota(root, path);
} }
} }
r = path_make_absolute_cwd(path, &buffer); if (!buffer) {
if (r < 0) r = path_make_absolute_cwd(path, &buffer);
return r; 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) if (fd < 0)
return -errno; return -errno;
@ -193,6 +203,8 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
todo = buffer; todo = buffer;
done = strdup("/"); done = strdup("/");
} }
if (!done)
return -ENOMEM;
for (;;) { for (;;) {
_cleanup_free_ char *first = NULL; _cleanup_free_ char *first = NULL;
@ -200,7 +212,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
struct stat st; struct stat st;
const char *e; 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) if (r < 0)
return r; return r;
if (r == 0) { /* We reached the end. */ 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)) if (empty_or_root(done))
continue; continue;
parent = dirname_malloc(done); r = path_extract_directory(done, &parent);
if (!parent) if (r < 0)
return -ENOMEM; return r;
/* Don't allow this to leave the root dir. */ /* Don't allow this to leave the root dir. */
if (root && if (root &&
@ -311,7 +323,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
* directory as base. */ * directory as base. */
safe_close(fd); 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) if (fd < 0)
return -errno; return -errno;
@ -375,7 +387,7 @@ chased_one:
const char *e; const char *e;
/* todo may contain slashes at the beginning. */ /* 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) if (r < 0)
return r; return r;
if (r == 0) if (r == 0)
@ -397,7 +409,7 @@ chased_one:
int chase_symlinks_and_open( int chase_symlinks_and_open(
const char *path, const char *path,
const char *root, const char *root,
unsigned chase_flags, ChaseSymlinksFlags chase_flags,
int open_flags, int open_flags,
char **ret_path) { char **ret_path) {
@ -435,7 +447,7 @@ int chase_symlinks_and_open(
int chase_symlinks_and_opendir( int chase_symlinks_and_opendir(
const char *path, const char *path,
const char *root, const char *root,
unsigned chase_flags, ChaseSymlinksFlags chase_flags,
char **ret_path, char **ret_path,
DIR **ret_dir) { DIR **ret_dir) {
@ -478,7 +490,7 @@ int chase_symlinks_and_opendir(
int chase_symlinks_and_stat( int chase_symlinks_and_stat(
const char *path, const char *path,
const char *root, const char *root,
unsigned chase_flags, ChaseSymlinksFlags chase_flags,
char **ret_path, char **ret_path,
struct stat *ret_stat, struct stat *ret_stat,
int *ret_fd) { int *ret_fd) {
@ -520,7 +532,7 @@ int chase_symlinks_and_stat(
int chase_symlinks_and_fopen_unlocked( int chase_symlinks_and_fopen_unlocked(
const char *path, const char *path,
const char *root, const char *root,
unsigned chase_flags, ChaseSymlinksFlags chase_flags,
const char *open_flags, const char *open_flags,
char **ret_path, char **ret_path,
FILE **ret_file) { FILE **ret_file) {

View File

@ -6,7 +6,7 @@
#include "stat-util.h" #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_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_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_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 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. */ * 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 */ 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); bool unsafe_transition(const struct stat *a, const struct stat *b);
/* How many iterations to execute before returning -ELOOP */ /* How many iterations to execute before returning -ELOOP */
#define CHASE_SYMLINKS_MAX 32 #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_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, unsigned chase_flags, char **ret_path, DIR **ret_dir); 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, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); 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);

View File

@ -2051,7 +2051,7 @@ static void log_execution_mode(bool *ret_first_boot) {
} }
} }
assert(uname(&uts) >= 0); assert_se(uname(&uts) >= 0);
if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0) if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0)
log_warning("Warning! Reported kernel version %s is older than systemd's required baseline kernel version %s. " log_warning("Warning! Reported kernel version %s is older than systemd's required baseline kernel version %s. "