From: Lennart Poettering Date: Fri, 28 Apr 2023 16:33:17 +0000 (+0200) Subject: base-filesystem: add new helper base_filesystem_create_fd() that operates on an fd... X-Git-Tag: v254-rc1~564^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8aefedce147bfc99cf96090e3bd7f4d2c6468fd7;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index f2161041c83..37293cdb6d2 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 a33975f3b5b..a1ccf451c47 100644 --- a/src/shared/base-filesystem.h +++ b/src/shared/base-filesystem.h @@ -3,4 +3,5 @@ #include +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 33e918b7d02..fa438b3c065 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);