97 lines
4.5 KiB
Diff
97 lines
4.5 KiB
Diff
From a5486de446d4312b9bebdcb3ab8d6325187930f6 Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Mon, 13 Jan 2025 13:12:23 +0100
|
|
Subject: [PATCH] chase: introduce flags that verify that chased inode is
|
|
regular file or dir
|
|
|
|
This also implies the new CHASE_MUST_BE_DIRECTORY flag in case the
|
|
specified path ends in a slash. This makes the rules stricter, it means
|
|
we'll be closer to how this is handled in kernel: if a path ends in a
|
|
slash it can never refer to a non-directory.
|
|
|
|
(cherry picked from commit 90b9f7a07e6f57825f416f6ce2db0a9f2086754b)
|
|
|
|
Resolves: RHEL-75774
|
|
---
|
|
src/basic/chase.c | 20 +++++++++++++++++---
|
|
src/basic/chase.h | 2 ++
|
|
src/shared/machine-id-setup.c | 2 +-
|
|
3 files changed, 20 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/basic/chase.c b/src/basic/chase.c
|
|
index 8eac356665..e5a6fb1587 100644
|
|
--- a/src/basic/chase.c
|
|
+++ b/src/basic/chase.c
|
|
@@ -89,6 +89,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
|
|
int r;
|
|
|
|
assert(!FLAGS_SET(flags, CHASE_PREFIX_ROOT));
|
|
+ assert(!FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY|CHASE_MUST_BE_REGULAR));
|
|
assert(!FLAGS_SET(flags, CHASE_STEP|CHASE_EXTRACT_FILENAME));
|
|
assert(!FLAGS_SET(flags, CHASE_TRAIL_SLASH|CHASE_EXTRACT_FILENAME));
|
|
assert(!FLAGS_SET(flags, CHASE_MKDIR_0755) || (flags & (CHASE_NONEXISTENT | CHASE_PARENT)) != 0);
|
|
@@ -244,8 +245,15 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
|
|
if (root_fd < 0)
|
|
return -errno;
|
|
|
|
- if (FLAGS_SET(flags, CHASE_TRAIL_SLASH))
|
|
- append_trail_slash = ENDSWITH_SET(buffer, "/", "/.");
|
|
+ if (ENDSWITH_SET(buffer, "/", "/.")) {
|
|
+ flags |= CHASE_MUST_BE_DIRECTORY;
|
|
+ if (FLAGS_SET(flags, CHASE_TRAIL_SLASH))
|
|
+ append_trail_slash = true;
|
|
+ } else if (dot_or_dot_dot(buffer) || endswith(buffer, "/.."))
|
|
+ flags |= CHASE_MUST_BE_DIRECTORY;
|
|
+
|
|
+ if (FLAGS_SET(flags, CHASE_PARENT))
|
|
+ flags |= CHASE_MUST_BE_DIRECTORY;
|
|
|
|
for (todo = buffer;;) {
|
|
_cleanup_free_ char *first = NULL;
|
|
@@ -477,12 +485,18 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
|
|
close_and_replace(fd, child);
|
|
}
|
|
|
|
- if (FLAGS_SET(flags, CHASE_PARENT)) {
|
|
+ if (FLAGS_SET(flags, CHASE_MUST_BE_DIRECTORY)) {
|
|
r = stat_verify_directory(&st);
|
|
if (r < 0)
|
|
return r;
|
|
}
|
|
|
|
+ if (FLAGS_SET(flags, CHASE_MUST_BE_REGULAR)) {
|
|
+ r = stat_verify_regular(&st);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
+ }
|
|
+
|
|
if (ret_path) {
|
|
if (FLAGS_SET(flags, CHASE_EXTRACT_FILENAME) && done) {
|
|
_cleanup_free_ char *f = NULL;
|
|
diff --git a/src/basic/chase.h b/src/basic/chase.h
|
|
index cfc714b9f7..2d708b4bae 100644
|
|
--- a/src/basic/chase.h
|
|
+++ b/src/basic/chase.h
|
|
@@ -33,6 +33,8 @@ typedef enum ChaseFlags {
|
|
* when internally call chase(), hence CHASE_MKDIR_0755 can be
|
|
* safely set without CHASE_NONEXISTENT and CHASE_PARENT. */
|
|
CHASE_EXTRACT_FILENAME = 1 << 12, /* Only return the last component of the resolved path */
|
|
+ CHASE_MUST_BE_DIRECTORY = 1 << 13, /* Fail if returned inode fd is not a dir */
|
|
+ CHASE_MUST_BE_REGULAR = 1 << 14, /* Fail if returned inode fd is not a regular file */
|
|
} ChaseFlags;
|
|
|
|
bool unsafe_transition(const struct stat *a, const struct stat *b);
|
|
diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c
|
|
index f5e1b9ee72..4e355d8144 100644
|
|
--- a/src/shared/machine-id-setup.c
|
|
+++ b/src/shared/machine-id-setup.c
|
|
@@ -74,7 +74,7 @@ static int acquire_machine_id(const char *root, bool machine_id_from_firmware, s
|
|
}
|
|
|
|
/* Then, try reading the D-Bus machine ID, unless it is a symlink */
|
|
- fd = chase_and_open("/var/lib/dbus/machine-id", root, CHASE_PREFIX_ROOT | CHASE_NOFOLLOW, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
|
+ fd = chase_and_open("/var/lib/dbus/machine-id", root, CHASE_PREFIX_ROOT|CHASE_NOFOLLOW|CHASE_MUST_BE_REGULAR, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
|
if (fd >= 0 && id128_read_fd(fd, ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, ret) >= 0) {
|
|
log_info("Initializing machine ID from D-Bus machine ID.");
|
|
return 0;
|