]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
base-filesystem: add new helper base_filesystem_create_fd() that operates on an fd...
authorLennart Poettering <lennart@poettering.net>
Fri, 28 Apr 2023 16:33:17 +0000 (18:33 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 3 May 2023 15:55:55 +0000 (17:55 +0200)
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.

src/shared/base-filesystem.c
src/shared/base-filesystem.h
src/shared/switch-root.c

index f2161041c831ebb73131a77bf986b20b485da38c..37293cdb6d2f43a2dc0e71af8c9cfba29b0b11b5 100644 (file)
@@ -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);
+}
index a33975f3b5b36164282528540887797884c927ef..a1ccf451c4752c80a36429fc0725b429716b633a 100644 (file)
@@ -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);
index 33e918b7d02d3db4eaabf52ccec67b7769e4f01b..fa438b3c065f5a55328f427550cd916b3c23703e 100644 (file)
@@ -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);