diff options
Diffstat (limited to 'src/journal-remote')
-rw-r--r-- | src/journal-remote/fuzz-journal-remote.c | 2 | ||||
-rw-r--r-- | src/journal-remote/journal-gatewayd.c | 207 | ||||
-rw-r--r-- | src/journal-remote/journal-remote-main.c | 28 | ||||
-rw-r--r-- | src/journal-remote/journal-remote.c | 15 | ||||
-rw-r--r-- | src/journal-remote/journal-remote.h | 5 | ||||
-rw-r--r-- | src/journal-remote/journal-upload-journal.c | 2 | ||||
-rw-r--r-- | src/journal-remote/journal-upload.c | 28 | ||||
-rw-r--r-- | src/journal-remote/journal-upload.h | 2 | ||||
-rw-r--r-- | src/journal-remote/meson.build | 10 |
9 files changed, 197 insertions, 102 deletions
diff --git a/src/journal-remote/fuzz-journal-remote.c b/src/journal-remote/fuzz-journal-remote.c index 557100b..774389d 100644 --- a/src/journal-remote/fuzz-journal-remote.c +++ b/src/journal-remote/fuzz-journal-remote.c @@ -67,7 +67,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Out */ - r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), 0); + r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), SD_JOURNAL_ASSUME_IMMUTABLE); if (r < 0) { log_error_errno(r, "sd_journal_open_files([\"%s\"]) failed: %m", name); assert_se(IN_SET(r, -ENOMEM, -EMFILE, -ENFILE, -ENODATA)); diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index aaa52c0..dd91f22 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -22,6 +22,8 @@ #include "fileio.h" #include "glob-util.h" #include "hostname-util.h" +#include "journal-internal.h" +#include "journal-remote.h" #include "log.h" #include "logs-show.h" #include "main-func.h" @@ -32,6 +34,7 @@ #include "pretty-print.h" #include "sigbus.h" #include "signal-util.h" +#include "time-util.h" #include "tmpfile-util.h" #define JOURNAL_WAIT_TIMEOUT (10*USEC_PER_SEC) @@ -55,9 +58,10 @@ typedef struct RequestMeta { OutputMode mode; char *cursor; + usec_t since, until; int64_t n_skip; uint64_t n_entries; - bool n_entries_set; + bool n_entries_set, since_set, until_set; FILE *tmp; uint64_t delta, size; @@ -212,6 +216,17 @@ static ssize_t request_reader_entries( return MHD_CONTENT_READER_END_OF_STREAM; } + if (m->until_set) { + usec_t usec; + + r = sd_journal_get_realtime_usec(m->journal, &usec); + if (r < 0) { + log_error_errno(r, "Failed to determine timestamp: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + if (usec > m->until) + return MHD_CONTENT_READER_END_OF_STREAM; + } pos -= m->size; m->delta += m->size; @@ -293,60 +308,59 @@ static int request_parse_accept( return 0; } -static int request_parse_range( +static int request_parse_range_skip_and_n_entries( RequestMeta *m, - struct MHD_Connection *connection) { + const char *colon) { - const char *range, *colon, *colon2; + const char *p, *colon2; int r; - assert(m); - assert(connection); + colon2 = strchr(colon + 1, ':'); + if (colon2) { + _cleanup_free_ char *t = NULL; - range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range"); - if (!range) - return 0; + t = strndup(colon + 1, colon2 - colon - 1); + if (!t) + return -ENOMEM; - if (!startswith(range, "entries=")) - return 0; + r = safe_atoi64(t, &m->n_skip); + if (r < 0) + return r; + } - range += 8; - range += strspn(range, WHITESPACE); + p = (colon2 ?: colon) + 1; + r = safe_atou64(p, &m->n_entries); + if (r < 0) + return r; - colon = strchr(range, ':'); - if (!colon) - m->cursor = strdup(range); - else { - const char *p; + if (m->n_entries <= 0) + return -EINVAL; - colon2 = strchr(colon + 1, ':'); - if (colon2) { - _cleanup_free_ char *t = NULL; + m->n_entries_set = true; - t = strndup(colon + 1, colon2 - colon - 1); - if (!t) - return -ENOMEM; + return 0; +} - r = safe_atoi64(t, &m->n_skip); - if (r < 0) - return r; - } +static int request_parse_range_entries( + RequestMeta *m, + const char *entries_request) { - p = (colon2 ?: colon) + 1; - if (*p) { - r = safe_atou64(p, &m->n_entries); - if (r < 0) - return r; + const char *colon; + int r; - if (m->n_entries <= 0) - return -EINVAL; + assert(m); + assert(entries_request); - m->n_entries_set = true; - } + colon = strchr(entries_request, ':'); + if (!colon) + m->cursor = strdup(entries_request); + else { + r = request_parse_range_skip_and_n_entries(m, colon); + if (r < 0) + return r; - m->cursor = strndup(range, colon - range); + m->cursor = strndup(entries_request, colon - entries_request); } - if (!m->cursor) return -ENOMEM; @@ -357,6 +371,93 @@ static int request_parse_range( return 0; } +static int request_parse_range_time( + RequestMeta *m, + const char *time_request) { + + _cleanup_free_ char *until = NULL; + const char *colon; + int r; + + assert(m); + assert(time_request); + + colon = strchr(time_request, ':'); + if (!colon) + return -EINVAL; + + if (colon - time_request > 0) { + _cleanup_free_ char *t = NULL; + + t = strndup(time_request, colon - time_request); + if (!t) + return -ENOMEM; + + r = parse_sec(t, &m->since); + if (r < 0) + return r; + + m->since_set = true; + } + + time_request = colon + 1; + colon = strchr(time_request, ':'); + if (!colon) + until = strdup(time_request); + else { + r = request_parse_range_skip_and_n_entries(m, colon); + if (r < 0) + return r; + + until = strndup(time_request, colon - time_request); + } + if (!until) + return -ENOMEM; + + if (!isempty(until)) { + r = parse_sec(until, &m->until); + if (r < 0) + return r; + + m->until_set = true; + if (m->until < m->since) + return -EINVAL; + } + + return 0; +} + +static int request_parse_range( + RequestMeta *m, + struct MHD_Connection *connection) { + + const char *range, *range_after_eq; + + assert(m); + assert(connection); + + range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range"); + if (!range) + return 0; + + /* Safety upper bound to make Coverity happy. Apache2 has a default limit of 8KB: + * https://httpd.apache.org/docs/2.2/mod/core.html#limitrequestfieldsize */ + if (strlen(range) > JOURNAL_SERVER_MEMORY_MAX) + return -EINVAL; + + m->n_skip = 0; + + range_after_eq = startswith(range, "entries="); + if (range_after_eq) + return request_parse_range_entries(m, skip_leading_chars(range_after_eq, /* bad = */ NULL)); + + range_after_eq = startswith(range, "realtime="); + if (range_after_eq) + return request_parse_range_time(m, skip_leading_chars(range_after_eq, /* bad = */ NULL)); + + return 0; +} + static mhd_result request_parse_arguments_iterator( void *cls, enum MHD_ValueKind kind, @@ -364,7 +465,6 @@ static mhd_result request_parse_arguments_iterator( const char *value) { RequestMeta *m = ASSERT_PTR(cls); - _cleanup_free_ char *p = NULL; int r; if (isempty(key)) { @@ -416,17 +516,7 @@ static mhd_result request_parse_arguments_iterator( } if (r) { - char match[9 + 32 + 1] = "_BOOT_ID="; - sd_id128_t bid; - - r = sd_id128_get_boot(&bid); - if (r < 0) { - log_error_errno(r, "Failed to get boot ID: %m"); - return MHD_NO; - } - - sd_id128_to_string(bid, match + 9); - r = sd_journal_add_match(m->journal, match, sizeof(match)-1); + r = add_match_boot_id(m->journal, SD_ID128_NULL); if (r < 0) { m->argument_parse_error = r; return MHD_NO; @@ -436,13 +526,7 @@ static mhd_result request_parse_arguments_iterator( return MHD_YES; } - p = strjoin(key, "=", strempty(value)); - if (!p) { - m->argument_parse_error = log_oom(); - return MHD_NO; - } - - r = sd_journal_add_match(m->journal, p, 0); + r = journal_add_match_pair(m->journal, key, strempty(value)); if (r < 0) { m->argument_parse_error = r; return MHD_NO; @@ -497,10 +581,15 @@ static int request_handler_entries( if (m->cursor) r = sd_journal_seek_cursor(m->journal, m->cursor); + else if (m->since_set) + r = sd_journal_seek_realtime_usec(m->journal, m->since); else if (m->n_skip >= 0) r = sd_journal_seek_head(m->journal); + else if (m->until_set && m->n_skip < 0) + r = sd_journal_seek_realtime_usec(m->journal, m->until); else if (m->n_skip < 0) r = sd_journal_seek_tail(m->journal); + if (r < 0) return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal."); @@ -778,7 +867,7 @@ static int request_handler_machine( SD_ID128_FORMAT_VAL(bid), hostname_cleanup(hostname), os_release_pretty_name(pretty_name, os_name), - v ? v : "bare", + v ?: "bare", usage, cutoff_from, cutoff_to); diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c index 294719b..34d4062 100644 --- a/src/journal-remote/journal-remote-main.c +++ b/src/journal-remote/journal-remote-main.c @@ -108,7 +108,7 @@ static int spawn_child(const char* child, char** argv) { r = fd_nonblock(fd[0], true); if (r < 0) - log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m"); + log_warning_errno(r, "Failed to set child pipe to non-blocking: %m"); return fd[0]; } @@ -374,7 +374,7 @@ static int setup_microhttpd_server(RemoteServer *s, { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger}, { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free}, { MHD_OPTION_LISTEN_SOCKET, fd}, - { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024}, + { MHD_OPTION_CONNECTION_MEMORY_LIMIT, JOURNAL_SERVER_MEMORY_MAX}, { MHD_OPTION_END}, { MHD_OPTION_END}, { MHD_OPTION_END}, @@ -451,7 +451,7 @@ static int setup_microhttpd_server(RemoteServer *s, if (epoll_fd < 0) return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "μhttp epoll fd is invalid"); - r = sd_event_add_io(s->events, &d->io_event, + r = sd_event_add_io(s->event, &d->io_event, epoll_fd, EPOLLIN, dispatch_http_event, d); if (r < 0) @@ -461,7 +461,7 @@ static int setup_microhttpd_server(RemoteServer *s, if (r < 0) return log_error_errno(r, "Failed to set source name: %m"); - r = sd_event_add_time(s->events, &d->timer_event, + r = sd_event_add_time(s->event, &d->timer_event, CLOCK_MONOTONIC, UINT64_MAX, 0, null_timer_event_handler, d); if (r < 0) @@ -562,7 +562,7 @@ static int create_remoteserver( if (r < 0) return r; - r = sd_event_set_signal_exit(s->events, true); + r = sd_event_set_signal_exit(s->event, true); if (r < 0) return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m"); @@ -728,9 +728,12 @@ static int parse_config(void) { {} }; - return config_parse_config_file("journal-remote.conf", "Remote\0", - config_item_table_lookup, items, - CONFIG_PARSE_WARN, NULL); + return config_parse_standard_file_with_dropins( + "systemd/journal-remote.conf", + "Remote\0", + config_item_table_lookup, items, + CONFIG_PARSE_WARN, + /* userdata= */ NULL); } static int help(void) { @@ -1067,8 +1070,7 @@ static int run(int argc, char **argv) { _cleanup_free_ char *cert = NULL, *trust = NULL; int r; - log_show_color(true); - log_parse_environment(); + log_setup(); /* The journal merging logic potentially needs a lot of fds. */ (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); @@ -1107,7 +1109,7 @@ static int run(int argc, char **argv) { if (r < 0) return r; - r = sd_event_set_watchdog(s.events, true); + r = sd_event_set_watchdog(s.event, true); if (r < 0) return log_error_errno(r, "Failed to enable watchdog: %m"); @@ -1119,13 +1121,13 @@ static int run(int argc, char **argv) { notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING); while (s.active) { - r = sd_event_get_state(s.events); + r = sd_event_get_state(s.event); if (r < 0) return r; if (r == SD_EVENT_FINISHED) break; - r = sd_event_run(s.events, -1); + r = sd_event_run(s.event, -1); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); } diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 9db686d..92187b7 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -86,7 +86,6 @@ static int open_output(RemoteServer *s, Writer *w, const char* host) { UINT64_MAX, &w->metrics, w->mmap, - NULL, &w->journal); if (r < 0) return log_error_errno(r, "Failed to open output journal %s: %m", filename); @@ -258,19 +257,19 @@ int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name return r; } - r = sd_event_add_io(s->events, &source->event, + r = sd_event_add_io(s->event, &source->event, fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI, dispatch_raw_source_event, source); if (r == 0) { /* Add additional source for buffer processing. It will be * enabled later. */ - r = sd_event_add_defer(s->events, &source->buffer_event, + r = sd_event_add_defer(s->event, &source->buffer_event, dispatch_raw_source_until_block, source); if (r == 0) r = sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF); } else if (r == -EPERM) { log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name); - r = sd_event_add_defer(s->events, &source->event, + r = sd_event_add_defer(s->event, &source->event, dispatch_blocking_source_event, source); if (r == 0) r = sd_event_source_set_enabled(source->event, SD_EVENT_ON); @@ -302,7 +301,7 @@ int journal_remote_add_raw_socket(RemoteServer *s, int fd) { assert(s); assert(fd >= 0); - r = sd_event_add_io(s->events, &s->listen_event, + r = sd_event_add_io(s->event, &s->listen_event, fd, EPOLLIN, dispatch_raw_connection_event, s); if (r < 0) @@ -348,7 +347,7 @@ int journal_remote_server_init( else assert_not_reached(); - r = sd_event_default(&s->events); + r = sd_event_default(&s->event); if (r < 0) return log_error_errno(r, "Failed to allocate event loop: %m"); @@ -377,7 +376,7 @@ void journal_remote_server_destroy(RemoteServer *s) { hashmap_free(s->writers); sd_event_source_unref(s->listen_event); - sd_event_unref(s->events); + sd_event_unref(s->event); if (s == journal_remote_server_global) journal_remote_server_global = NULL; @@ -525,7 +524,7 @@ static int accept_connection( if (r < 0) return log_error_errno(r, "socket_address_print(): %m"); - r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b); + r = socknameinfo_pretty(&addr->sockaddr.sa, addr->size, &b); if (r < 0) return log_error_errno(r, "Resolving hostname failed: %m"); diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h index 3d64db0..f1ec5d9 100644 --- a/src/journal-remote/journal-remote.h +++ b/src/journal-remote/journal-remote.h @@ -29,7 +29,7 @@ struct RemoteServer { RemoteSource **sources; size_t active; - sd_event *events; + sd_event *event; sd_event_source *listen_event; Hashmap *writers; @@ -48,6 +48,9 @@ struct RemoteServer { }; extern RemoteServer *journal_remote_server_global; +/* Used for MHD_OPTION_CONNECTION_MEMORY_LIMIT and header parsing cap */ +#define JOURNAL_SERVER_MEMORY_MAX 128U * 1024U + int journal_remote_server_init( RemoteServer *s, const char *output, diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c index 8206ca8..23ad3b2 100644 --- a/src/journal-remote/journal-upload-journal.c +++ b/src/journal-remote/journal-upload-journal.c @@ -388,7 +388,7 @@ int open_journal_for_upload(Uploader *u, else u->timeout = JOURNAL_UPLOAD_POLL_TIMEOUT; - r = sd_event_add_io(u->events, &u->input_event, + r = sd_event_add_io(u->event, &u->input_event, fd, events, dispatch_journal_input, u); if (r < 0) return log_error_errno(r, "Failed to register input event: %m"); diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index d70a049..f6b9351 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -366,7 +366,7 @@ static int open_file_for_upload(Uploader *u, const char *filename) { u->input = fd; if (arg_follow != 0) { - r = sd_event_add_io(u->events, &u->input_event, + r = sd_event_add_io(u->event, &u->input_event, fd, EPOLLIN, dispatch_fd_input, u); if (r < 0) { if (r != -EPERM || arg_follow > 0) @@ -415,11 +415,11 @@ static int setup_uploader(Uploader *u, const char *url, const char *state_file) u->state_file = state_file; - r = sd_event_default(&u->events); + r = sd_event_default(&u->event); if (r < 0) return log_error_errno(r, "sd_event_default failed: %m"); - r = sd_event_set_signal_exit(u->events, true); + r = sd_event_set_signal_exit(u->event, true); if (r < 0) return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m"); @@ -445,7 +445,7 @@ static void destroy_uploader(Uploader *u) { close_fd_input(u); close_journal_input(u); - sd_event_unref(u->events); + sd_event_unref(u->event); } static int perform_upload(Uploader *u) { @@ -499,9 +499,12 @@ static int parse_config(void) { {} }; - return config_parse_config_file("journal-upload.conf", "Upload\0", - config_item_table_lookup, items, - CONFIG_PARSE_WARN, NULL); + return config_parse_standard_file_with_dropins( + "systemd/journal-upload.conf", + "Upload\0", + config_item_table_lookup, items, + CONFIG_PARSE_WARN, + /* userdata= */ NULL); } static int help(void) { @@ -745,7 +748,7 @@ static int open_journal(sd_journal **j) { else if (arg_file) r = sd_journal_open_files(j, (const char**) arg_file, 0); else if (arg_machine) - r = journal_open_machine(j, arg_machine); + r = journal_open_machine(j, arg_machine, 0); else r = sd_journal_open_namespace(j, arg_namespace, (arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY) | arg_namespace_flags | arg_journal_type); @@ -761,8 +764,7 @@ static int run(int argc, char **argv) { bool use_journal; int r; - log_show_color(true); - log_parse_environment(); + log_setup(); /* The journal merging logic potentially needs a lot of fds. */ (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); @@ -781,7 +783,7 @@ static int run(int argc, char **argv) { if (r < 0) return r; - sd_event_set_watchdog(u.events, true); + sd_event_set_watchdog(u.event, true); r = check_cursor_updating(&u); if (r < 0) @@ -809,7 +811,7 @@ static int run(int argc, char **argv) { NOTIFY_STOPPING); for (;;) { - r = sd_event_get_state(u.events); + r = sd_event_get_state(u.event); if (r < 0) return r; if (r == SD_EVENT_FINISHED) @@ -836,7 +838,7 @@ static int run(int argc, char **argv) { return r; } - r = sd_event_run(u.events, u.timeout); + r = sd_event_run(u.event, u.timeout); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); } diff --git a/src/journal-remote/journal-upload.h b/src/journal-remote/journal-upload.h index 2007864..5ba3c4f 100644 --- a/src/journal-remote/journal-upload.h +++ b/src/journal-remote/journal-upload.h @@ -24,7 +24,7 @@ typedef enum { } entry_state; typedef struct Uploader { - sd_event *events; + sd_event *event; char *url; CURL *easy; diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build index 964a251..10a8275 100644 --- a/src/journal-remote/meson.build +++ b/src/journal-remote/meson.build @@ -22,9 +22,9 @@ libsystemd_journal_remote = static_library( libsystemd_journal_remote_sources, include_directories : includes, dependencies : [libgnutls, - liblz4, + liblz4_cflags, libmicrohttpd, - libxz, + libxz_cflags, threads, userspace], build_by_default : false) @@ -38,9 +38,9 @@ systemd_journal_gatewayd_sources = files( common_deps = [ libgnutls, - liblz4, - libxz, - libzstd, + liblz4_cflags, + libxz_cflags, + libzstd_cflags, threads, ] |