diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml index 8f62c966ea..8b7035fcc2 100644 --- a/man/sd_journal_open.xml +++ b/man/sd_journal_open.xml @@ -32,6 +32,7 @@ SD_JOURNAL_OS_ROOT SD_JOURNAL_ALL_NAMESPACES SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE + SD_JOURNAL_TAKE_DIRECTORY_FD Open the system journal for reading @@ -136,7 +137,13 @@ sd_journal_open_directory_fd() is similar to sd_journal_open_directory(), but takes a file descriptor referencing a directory in the file - system instead of an absolute file system path. + system instead of an absolute file system path. In addtion to the flags accepted by + sd_journal_open_directory(), this function also accepts + SD_JOURNAL_TAKE_DIRECTORY_FD. If SD_JOURNAL_TAKE_DIRECTORY_FD is + specified, the function will take the ownership of the specified file descriptor on success, and it will be + closed by sd_journal_close(), hence the caller of the function must not close the file + descriptor. When the flag is not specified, sd_journal_close() will not close the file + descriptor, so the caller should close it after sd_journal_close(). sd_journal_open_files() is similar to sd_journal_open() but takes a NULL-terminated list of file paths to open. All files will be opened and interleaved diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 22f318f314..db74355842 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -21,6 +21,7 @@ #include "fs-util.h" #include "glob-util.h" #include "journal-upload.h" +#include "journal-util.h" #include "log.h" #include "main-func.h" #include "mkdir.h" @@ -769,21 +770,17 @@ static int parse_argv(int argc, char *argv[]) { static int open_journal(sd_journal **j) { int r; + assert(j); + if (arg_directory) r = sd_journal_open_directory(j, arg_directory, arg_journal_type); else if (arg_file) r = sd_journal_open_files(j, (const char**) arg_file, 0); - else if (arg_machine) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - /* FIXME: replace with D-Bus call OpenMachineRootDirectory() so that things also work with raw disk images */ - r = sd_journal_open_container(j, arg_machine, 0); -#pragma GCC diagnostic pop - } else if (arg_namespace) - r = sd_journal_open_namespace(j, arg_namespace, (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | - arg_namespace_flags | arg_journal_type); + else if (arg_machine) + r = journal_open_machine(j, arg_machine); else - r = sd_journal_open(j, (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | arg_journal_type); + r = sd_journal_open_namespace(j, arg_namespace, + (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | arg_namespace_flags | arg_journal_type); if (r < 0) log_error_errno(r, "Failed to open %s: %m", arg_directory ?: (arg_file ? "files" : "journal")); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 8b36e2bbd2..c70b98a3b1 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -2348,7 +2348,6 @@ static int run(int argc, char *argv[]) { _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; _cleanup_(umount_and_freep) char *mounted_dir = NULL; _cleanup_(sd_journal_closep) sd_journal *j = NULL; - _cleanup_close_ int machine_fd = -EBADF; int n_shown, r, poll_fd = -EBADF; setlocale(LC_ALL, ""); @@ -2467,35 +2466,9 @@ static int run(int argc, char *argv[]) { r = sd_journal_open_files_fd(&j, (int[]) { STDIN_FILENO }, 1, 0); else if (arg_file) r = sd_journal_open_files(&j, (const char**) arg_file, 0); - else if (arg_machine) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - int fd; - - if (geteuid() != 0) - /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of - * the container, thus we need root privileges to override them. */ - return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Using the --machine= switch requires root privileges."); - - r = sd_bus_open_system(&bus); - if (r < 0) - return log_error_errno(r, "Failed to open system bus: %m"); - - r = bus_call_method(bus, bus_machine_mgr, "OpenMachineRootDirectory", &error, &reply, "s", arg_machine); - if (r < 0) - return log_error_errno(r, "Failed to open root directory: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "h", &fd); - if (r < 0) - return bus_log_parse_error(r); - - machine_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); - if (machine_fd < 0) - return log_error_errno(errno, "Failed to duplicate file descriptor: %m"); - - r = sd_journal_open_directory_fd(&j, machine_fd, SD_JOURNAL_OS_ROOT); - } else + else if (arg_machine) + r = journal_open_machine(&j, arg_machine); + else r = sd_journal_open_namespace( &j, arg_namespace, diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c index 0124900517..d84b117783 100644 --- a/src/libsystemd/sd-journal/sd-journal.c +++ b/src/libsystemd/sd-journal/sd-journal.c @@ -2177,13 +2177,16 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla return 0; } -#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \ +#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \ (SD_JOURNAL_OS_ROOT | \ - SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER ) + SD_JOURNAL_SYSTEM | \ + SD_JOURNAL_CURRENT_USER | \ + SD_JOURNAL_TAKE_DIRECTORY_FD) _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { _cleanup_(sd_journal_closep) sd_journal *j = NULL; struct stat st; + bool take_fd; int r; assert_return(ret, -EINVAL); @@ -2196,7 +2199,8 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { if (!S_ISDIR(st.st_mode)) return -EBADFD; - j = journal_new(flags, NULL, NULL); + take_fd = FLAGS_SET(flags, SD_JOURNAL_TAKE_DIRECTORY_FD); + j = journal_new(flags & ~SD_JOURNAL_TAKE_DIRECTORY_FD, NULL, NULL); if (!j) return -ENOMEM; @@ -2209,6 +2213,8 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { if (r < 0) return r; + SET_FLAG(j->flags, SD_JOURNAL_TAKE_DIRECTORY_FD, take_fd); + *ret = TAKE_PTR(j); return 0; } @@ -2288,6 +2294,9 @@ _public_ void sd_journal_close(sd_journal *j) { hashmap_free(j->directories_by_path); hashmap_free(j->directories_by_wd); + if (FLAGS_SET(j->flags, SD_JOURNAL_TAKE_DIRECTORY_FD)) + safe_close(j->toplevel_fd); + safe_close(j->inotify_fd); if (j->mmap) { diff --git a/src/shared/journal-util.c b/src/shared/journal-util.c index ea396fcc9b..d73d7c47d0 100644 --- a/src/shared/journal-util.c +++ b/src/shared/journal-util.c @@ -1,6 +1,10 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "acl-util.h" +#include "bus-error.h" +#include "bus-locator.h" +#include "bus-util.h" +#include "fd-util.h" #include "fs-util.h" #include "hashmap.h" #include "journal-internal.h" @@ -140,3 +144,45 @@ int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_use return r; } + +int journal_open_machine(sd_journal **ret, const char *machine) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_close_ int machine_fd = -EBADF; + int fd, r; + + assert(ret); + assert(machine); + + if (geteuid() != 0) + /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of + * the container, thus we need root privileges to override them. */ + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Using the --machine= switch requires root privileges."); + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to open system bus: %m"); + + r = bus_call_method(bus, bus_machine_mgr, "OpenMachineRootDirectory", &error, &reply, "s", machine); + if (r < 0) + return log_error_errno(r, "Failed to open root directory of machine '%s': %s", + machine, bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "h", &fd); + if (r < 0) + return bus_log_parse_error(r); + + machine_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (machine_fd < 0) + return log_error_errno(errno, "Failed to duplicate file descriptor: %m"); + + r = sd_journal_open_directory_fd(&j, machine_fd, SD_JOURNAL_OS_ROOT | SD_JOURNAL_TAKE_DIRECTORY_FD); + if (r < 0) + return log_error_errno(r, "Failed to open journal in machine '%s': %m", machine); + + TAKE_FD(machine_fd); + *ret = TAKE_PTR(j); + return 0; +} diff --git a/src/shared/journal-util.h b/src/shared/journal-util.h index 86fcba058d..afad249c90 100644 --- a/src/shared/journal-util.h +++ b/src/shared/journal-util.h @@ -8,3 +8,4 @@ int journal_access_blocked(sd_journal *j); int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users); +int journal_open_machine(sd_journal **ret, const char *machine); diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index 4af540400d..7d2d75dd89 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -71,6 +71,7 @@ enum { SD_JOURNAL_OS_ROOT = 1 << 4, SD_JOURNAL_ALL_NAMESPACES = 1 << 5, /* Show all namespaces, not just the default or specified one */ SD_JOURNAL_INCLUDE_DEFAULT_NAMESPACE = 1 << 6, /* Show default namespace in addition to specified one */ + SD_JOURNAL_TAKE_DIRECTORY_FD = 1 << 7, /* sd_journal_open_directory_fd() will take ownership of the provided file descriptor. */ SD_JOURNAL_SYSTEM_ONLY _sd_deprecated_ = SD_JOURNAL_SYSTEM /* old name */ };