mirror of
https://github.com/systemd/systemd.git
synced 2025-01-13 17:18:18 +03:00
chase-symlinks: add new flag for prohibiting any following of symlinks
This is useful when operating in the ESP, which is untrusted territory, and where under no circumstances we should be tricked by symlinks into doing anything we don't want to.
This commit is contained in:
parent
1c03f7f4ba
commit
d43e78b643
@ -57,6 +57,21 @@ static int log_autofs_mount_point(int fd, const char *path, ChaseSymlinksFlags f
|
||||
strna(n1), path);
|
||||
}
|
||||
|
||||
static int log_prohibited_symlink(int fd, ChaseSymlinksFlags flags) {
|
||||
_cleanup_free_ char *n1 = NULL;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if (!FLAGS_SET(flags, CHASE_WARN))
|
||||
return -EREMCHG;
|
||||
|
||||
(void) fd_get_path(fd, &n1);
|
||||
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EREMCHG),
|
||||
"Detected symlink where not symlink is allowed at %s, refusing.",
|
||||
strna(n1));
|
||||
}
|
||||
|
||||
int chase_symlinks_at(
|
||||
int dir_fd,
|
||||
const char *path,
|
||||
@ -291,6 +306,9 @@ int chase_symlinks_at(
|
||||
if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
|
||||
_cleanup_free_ char *destination = NULL;
|
||||
|
||||
if (flags & CHASE_PROHIBIT_SYMLINKS)
|
||||
return log_prohibited_symlink(child, flags);
|
||||
|
||||
/* This is a symlink, in this case read the destination. But let's make sure we
|
||||
* don't follow symlinks without bounds. */
|
||||
if (--max_follow <= 0)
|
||||
|
@ -19,6 +19,7 @@ typedef enum ChaseSymlinksFlags {
|
||||
* Note: this may do an NSS lookup, hence this flag cannot be used in PID 1. */
|
||||
CHASE_AT_RESOLVE_IN_ROOT = 1 << 8, /* Same as openat2()'s RESOLVE_IN_ROOT flag, symlinks are resolved
|
||||
* relative to the given directory fd instead of root. */
|
||||
CHASE_PROHIBIT_SYMLINKS = 1 << 9, /* Refuse all symlinks */
|
||||
} ChaseSymlinksFlags;
|
||||
|
||||
bool unsafe_transition(const struct stat *a, const struct stat *b);
|
||||
|
@ -386,6 +386,15 @@ TEST(chase_symlinks) {
|
||||
assert_se(path_equal(path_startswith(result, p), "usr"));
|
||||
result = mfree(result);
|
||||
|
||||
/* Test CHASE_PROHIBIT_SYMLINKS */
|
||||
|
||||
assert_se(chase_symlinks("top/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG);
|
||||
assert_se(chase_symlinks("top/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG);
|
||||
assert_se(chase_symlinks("top/dotdot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG);
|
||||
assert_se(chase_symlinks("top/dotdot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG);
|
||||
assert_se(chase_symlinks("top/dot/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS, NULL, NULL) == -EREMCHG);
|
||||
assert_se(chase_symlinks("top/dot/dot", temp, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_WARN, NULL, NULL) == -EREMCHG);
|
||||
|
||||
cleanup:
|
||||
assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user