summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-04-28 18:33:17 +0200
committerLennart Poettering <lennart@poettering.net>2023-05-03 17:55:55 +0200
commit8aefedce147bfc99cf96090e3bd7f4d2c6468fd7 (patch)
treecaac826a7beca2560e3689fc3506a586f5c0c9e5 /src/shared
parentf2c1d491a539035d6cc1fa53a7cef0cbc8d52902 (diff)
downloadsystemd-8aefedce147bfc99cf96090e3bd7f4d2c6468fd7.tar.gz
base-filesystem: add new helper base_filesystem_create_fd() that operates on an fd, instead of a path
This also changes the open flags from O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW to O_DIRECTORY|O_CLOEXEC. O_RDONLY is redundant, since O_RDONLY is zero anyway, and O_DIRECTORY pins the acces mode enough: it doesn't allow read()/write() anyway when specified. O_NONBLOCK is also pointless given that O_DIRECTORY is specified, it has no meaning on directories. (It is useful if we don't know much about the inode we are opening, and could be a device node or fifo, but the O_DIRECTORY excludes that case.) O_NOFOLLOW is dropped since there's really no point in blocking out the initial entrypoint being a symlink. Once we pinned the the root of the tree it might make sense to restrict symlink use below it, but for the entrypoint itself it doesn't matter.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/base-filesystem.c20
-rw-r--r--src/shared/base-filesystem.h1
-rw-r--r--src/shared/switch-root.c2
3 files changed, 17 insertions, 6 deletions
diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c
index f2161041c8..37293cdb6d 100644
--- a/src/shared/base-filesystem.c
+++ b/src/shared/base-filesystem.c
@@ -130,13 +130,13 @@ static const BaseFilesystem table[] = {
# pragma message "Please add an entry above specifying whether your architecture uses /lib64/, /lib32/, or no such links."
#endif
-int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
- _cleanup_close_ int fd = -EBADF;
+int base_filesystem_create_fd(int fd, const char *root, uid_t uid, gid_t gid) {
int r;
- fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
- if (fd < 0)
- return log_error_errno(errno, "Failed to open root file system: %m");
+ assert(fd >= 0);
+ assert(root);
+
+ /* The "root" parameter is decoration only – it's only used as part of log messages */
for (size_t i = 0; i < ELEMENTSOF(table); i++) {
if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
@@ -205,3 +205,13 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
return 0;
}
+
+int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
+ _cleanup_close_ int fd = -EBADF;
+
+ fd = open(ASSERT_PTR(root), O_DIRECTORY|O_CLOEXEC);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open root file system: %m");
+
+ return base_filesystem_create_fd(fd, root, uid, gid);
+}
diff --git a/src/shared/base-filesystem.h b/src/shared/base-filesystem.h
index a33975f3b5..a1ccf451c4 100644
--- a/src/shared/base-filesystem.h
+++ b/src/shared/base-filesystem.h
@@ -3,4 +3,5 @@
#include <sys/types.h>
+int base_filesystem_create_fd(int fd, const char *root, uid_t uid, gid_t gid);
int base_filesystem_create(const char *root, uid_t uid, gid_t gid);
diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c
index 33e918b7d0..fa438b3c06 100644
--- a/src/shared/switch-root.c
+++ b/src/shared/switch-root.c
@@ -94,7 +94,7 @@ int switch_root(const char *new_root,
/* Do not fail if base_filesystem_create() fails. Not all switch roots are like base_filesystem_create() wants
* them to look like. They might even boot, if they are RO and don't have the FS layout. Just ignore the error
* and switch_root() nevertheless. */
- (void) base_filesystem_create(new_root, UID_INVALID, GID_INVALID);
+ (void) base_filesystem_create_fd(new_root_fd, new_root, UID_INVALID, GID_INVALID);
if (fchdir(new_root_fd) < 0)
return log_error_errno(errno, "Failed to change directory to %s: %m", new_root);