diff options
Diffstat (limited to 'src/journal')
-rw-r--r-- | src/journal/audit-type.h | 3 | ||||
-rw-r--r-- | src/journal/cat.c | 50 | ||||
-rw-r--r-- | src/journal/catalog.c | 48 | ||||
-rw-r--r-- | src/journal/journal-def.h | 118 | ||||
-rw-r--r-- | src/journal/journal-send.c | 4 | ||||
-rw-r--r-- | src/journal/journald-audit.c | 2 | ||||
-rw-r--r-- | src/journal/journald-context.c | 72 | ||||
-rw-r--r-- | src/journal/journald-native.c | 74 | ||||
-rw-r--r-- | src/journal/journald-server.c | 29 | ||||
-rw-r--r-- | src/journal/journald-server.h | 2 | ||||
-rw-r--r-- | src/journal/journald-wall.h | 1 | ||||
-rw-r--r-- | src/journal/mmap-cache.c | 2 | ||||
-rw-r--r-- | src/journal/sd-journal.c | 1 |
13 files changed, 264 insertions, 142 deletions
diff --git a/src/journal/audit-type.h b/src/journal/audit-type.h index 069a883490..98e5c39420 100644 --- a/src/journal/audit-type.h +++ b/src/journal/audit-type.h @@ -4,6 +4,7 @@ #include <alloca.h> #include <stdio.h> +#include "alloc-util.h" #include "macro.h" const char *audit_type_to_string(int type); @@ -15,7 +16,7 @@ int audit_type_from_string(const char *s); const char *_s_; \ _s_ = audit_type_to_string(type); \ if (!_s_) { \ - _s_ = alloca(STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \ + _s_ = newa(char, STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \ sprintf((char*) _s_, "AUDIT%04i", type); \ } \ _s_; \ diff --git a/src/journal/cat.c b/src/journal/cat.c index a84350fbc9..9900bd2e86 100644 --- a/src/journal/cat.c +++ b/src/journal/cat.c @@ -20,6 +20,7 @@ static const char *arg_identifier = NULL; static int arg_priority = LOG_INFO; +static int arg_stderr_priority = -1; static bool arg_level_prefix = true; static int help(void) { @@ -32,11 +33,12 @@ static int help(void) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" "Execute process with stdout/stderr connected to the journal.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " -t --identifier=STRING Set syslog identifier\n" - " -p --priority=PRIORITY Set priority value (0..7)\n" - " --level-prefix=BOOL Control whether level prefix shall be parsed\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -t --identifier=STRING Set syslog identifier\n" + " -p --priority=PRIORITY Set priority value (0..7)\n" + " --stderr-priority=PRIORITY Set priority value (0..7) used for stderr\n" + " --level-prefix=BOOL Control whether level prefix shall be parsed\n" "\nSee the %s for details.\n" , program_invocation_short_name , link @@ -49,15 +51,17 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, + ARG_STDERR_PRIORITY, ARG_LEVEL_PREFIX }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "identifier", required_argument, NULL, 't' }, - { "priority", required_argument, NULL, 'p' }, - { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "identifier", required_argument, NULL, 't' }, + { "priority", required_argument, NULL, 'p' }, + { "stderr-priority", required_argument, NULL, ARG_STDERR_PRIORITY }, + { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX }, {} }; @@ -91,6 +95,13 @@ static int parse_argv(int argc, char *argv[]) { "Failed to parse priority value."); break; + case ARG_STDERR_PRIORITY: + arg_stderr_priority = log_level_from_string(optarg); + if (arg_stderr_priority < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse stderr priority value."); + break; + case ARG_LEVEL_PREFIX: { int k; @@ -113,7 +124,7 @@ static int parse_argv(int argc, char *argv[]) { } static int run(int argc, char *argv[]) { - _cleanup_close_ int fd = -1, saved_stderr = -1; + _cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1; int r; log_parse_environment(); @@ -123,14 +134,21 @@ static int run(int argc, char *argv[]) { if (r <= 0) return r; - fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix); - if (fd < 0) - return log_error_errno(fd, "Failed to create stream fd: %m"); + outfd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix); + if (outfd < 0) + return log_error_errno(outfd, "Failed to create stream fd: %m"); + + if (arg_stderr_priority >= 0 && arg_stderr_priority != arg_priority) { + errfd = sd_journal_stream_fd(arg_identifier, arg_stderr_priority, arg_level_prefix); + if (errfd < 0) + return log_error_errno(errfd, "Failed to create stream fd: %m"); + } saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3); - r = rearrange_stdio(STDIN_FILENO, fd, fd); /* Invalidates fd on succcess + error! */ - TAKE_FD(fd); + r = rearrange_stdio(STDIN_FILENO, outfd, errfd < 0 ? outfd : errfd); /* Invalidates fd on succcess + error! */ + TAKE_FD(outfd); + TAKE_FD(errfd); if (r < 0) return log_error_errno(r, "Failed to rearrange stdout/stderr: %m"); diff --git a/src/journal/catalog.c b/src/journal/catalog.c index 3556a101bf..4062f12c2d 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -46,7 +46,8 @@ typedef struct CatalogHeader { typedef struct CatalogItem { sd_id128_t id; - char language[32]; + char language[32]; /* One byte is used for termination, so the maximum allowed + * length of the string is actually 31 bytes. */ le64_t offset; } CatalogItem; @@ -556,25 +557,44 @@ static const char *find_id(void *p, sd_id128_t id) { const char *loc; loc = setlocale(LC_MESSAGES, NULL); - if (loc && loc[0] && !streq(loc, "C") && !streq(loc, "POSIX")) { - strncpy(key.language, loc, sizeof(key.language)); - key.language[strcspn(key.language, ".@")] = 0; - - f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func); - if (!f) { - char *e; - - e = strchr(key.language, '_'); - if (e) { - *e = 0; - f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func); + if (!isempty(loc) && !STR_IN_SET(loc, "C", "POSIX")) { + size_t len; + + len = strcspn(loc, ".@"); + if (len > sizeof(key.language) - 1) + log_debug("LC_MESSAGES value too long, ignoring: \"%.*s\"", (int) len, loc); + else { + strncpy(key.language, loc, len); + key.language[len] = '\0'; + + f = bsearch(&key, + (const uint8_t*) p + le64toh(h->header_size), + le64toh(h->n_items), + le64toh(h->catalog_item_size), + (comparison_fn_t) catalog_compare_func); + if (!f) { + char *e; + + e = strchr(key.language, '_'); + if (e) { + *e = 0; + f = bsearch(&key, + (const uint8_t*) p + le64toh(h->header_size), + le64toh(h->n_items), + le64toh(h->catalog_item_size), + (comparison_fn_t) catalog_compare_func); + } } } } if (!f) { zero(key.language); - f = bsearch(&key, (const uint8_t*) p + le64toh(h->header_size), le64toh(h->n_items), le64toh(h->catalog_item_size), (comparison_fn_t) catalog_compare_func); + f = bsearch(&key, + (const uint8_t*) p + le64toh(h->header_size), + le64toh(h->n_items), + le64toh(h->catalog_item_size), + (comparison_fn_t) catalog_compare_func); } if (!f) diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index e48260206f..d68ce3894b 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -59,16 +59,20 @@ struct ObjectHeader { uint8_t payload[]; } _packed_; -struct DataObject { - ObjectHeader object; - le64_t hash; - le64_t next_hash_offset; - le64_t next_field_offset; - le64_t entry_offset; /* the first array entry we store inline */ - le64_t entry_array_offset; - le64_t n_entries; - uint8_t payload[]; -} _packed_; +#define DataObject__contents { \ + ObjectHeader object; \ + le64_t hash; \ + le64_t next_hash_offset; \ + le64_t next_field_offset; \ + le64_t entry_offset; /* the first array entry we store inline */ \ + le64_t entry_array_offset; \ + le64_t n_entries; \ + uint8_t payload[]; \ + } + +struct DataObject DataObject__contents; +struct DataObject__packed DataObject__contents _packed_; +assert_cc(sizeof(struct DataObject) == sizeof(struct DataObject__packed)); struct FieldObject { ObjectHeader object; @@ -83,15 +87,20 @@ struct EntryItem { le64_t hash; } _packed_; -struct EntryObject { - ObjectHeader object; - le64_t seqnum; - le64_t realtime; - le64_t monotonic; - sd_id128_t boot_id; - le64_t xor_hash; - EntryItem items[]; -} _packed_; +#define EntryObject__contents { \ + ObjectHeader object; \ + le64_t seqnum; \ + le64_t realtime; \ + le64_t monotonic; \ + sd_id128_t boot_id; \ + le64_t xor_hash; \ + EntryItem items[]; \ + } + +struct EntryObject EntryObject__contents; +struct EntryObject__packed EntryObject__contents _packed_; +assert_cc(sizeof(struct EntryObject) == sizeof(struct EntryObject__packed)); + struct HashItem { le64_t head_hash_offset; @@ -166,40 +175,43 @@ enum { #define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }) -struct Header { - uint8_t signature[8]; /* "LPKSHHRH" */ - le32_t compatible_flags; - le32_t incompatible_flags; - uint8_t state; - uint8_t reserved[7]; - sd_id128_t file_id; - sd_id128_t machine_id; - sd_id128_t boot_id; /* last writer */ - sd_id128_t seqnum_id; - le64_t header_size; - le64_t arena_size; - le64_t data_hash_table_offset; - le64_t data_hash_table_size; - le64_t field_hash_table_offset; - le64_t field_hash_table_size; - le64_t tail_object_offset; - le64_t n_objects; - le64_t n_entries; - le64_t tail_entry_seqnum; - le64_t head_entry_seqnum; - le64_t entry_array_offset; - le64_t head_entry_realtime; - le64_t tail_entry_realtime; - le64_t tail_entry_monotonic; - /* Added in 187 */ - le64_t n_data; - le64_t n_fields; - /* Added in 189 */ - le64_t n_tags; - le64_t n_entry_arrays; - - /* Size: 240 */ -} _packed_; +#define struct_Header__contents { \ + uint8_t signature[8]; /* "LPKSHHRH" */ \ + le32_t compatible_flags; \ + le32_t incompatible_flags; \ + uint8_t state; \ + uint8_t reserved[7]; \ + sd_id128_t file_id; \ + sd_id128_t machine_id; \ + sd_id128_t boot_id; /* last writer */ \ + sd_id128_t seqnum_id; \ + le64_t header_size; \ + le64_t arena_size; \ + le64_t data_hash_table_offset; \ + le64_t data_hash_table_size; \ + le64_t field_hash_table_offset; \ + le64_t field_hash_table_size; \ + le64_t tail_object_offset; \ + le64_t n_objects; \ + le64_t n_entries; \ + le64_t tail_entry_seqnum; \ + le64_t head_entry_seqnum; \ + le64_t entry_array_offset; \ + le64_t head_entry_realtime; \ + le64_t tail_entry_realtime; \ + le64_t tail_entry_monotonic; \ + /* Added in 187 */ \ + le64_t n_data; \ + le64_t n_fields; \ + /* Added in 189 */ \ + le64_t n_tags; \ + le64_t n_entry_arrays; \ + } + +struct Header struct_Header__contents; +struct Header__packed struct_Header__contents _packed_; +assert_cc(sizeof(struct Header) == sizeof(struct Header__packed)); +assert_cc(sizeof(struct Header) == 240); #define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }) diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index 87056435fc..8618454131 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -30,7 +30,7 @@ const char *_func = (func); \ char **_f = &(f); \ _fl = strlen(_func) + 1; \ - *_f = alloca(_fl + 10); \ + *_f = newa(char, _fl + 10); \ memcpy(*_f, "CODE_FUNC=", 10); \ memcpy(*_f + 10, _func, _fl); \ } while (false) @@ -403,7 +403,7 @@ _public_ int sd_journal_stream_fd(const char *identifier, int priority, int leve identifier = strempty(identifier); l = strlen(identifier); - header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2); + header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2); memcpy(header, identifier, l); header[l++] = '\n'; diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index 345e43ef44..accbad4180 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -162,7 +162,7 @@ static int map_generic_field(const char *prefix, const char **p, struct iovec ** if (e <= *p || e >= *p + 16) return 0; - c = alloca(strlen(prefix) + (e - *p) + 2); + c = newa(char, strlen(prefix) + (e - *p) + 2); t = stpcpy(c, prefix); for (f = *p; f < e; f++) { diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c index 8253a45128..7c51f2f633 100644 --- a/src/journal/journald-context.c +++ b/src/journal/journald-context.c @@ -16,6 +16,7 @@ #include "parse-util.h" #include "path-util.h" #include "process-util.h" +#include "procfs-util.h" #include "string-util.h" #include "syslog-util.h" #include "unaligned.h" @@ -60,7 +61,37 @@ /* Keep at most 16K entries in the cache. (Note though that this limit may be violated if enough streams pin entries in * the cache, in which case we *do* permit this limit to be breached. That's safe however, as the number of stream * clients itself is limited.) */ -#define CACHE_MAX (16*1024) +#define CACHE_MAX_FALLBACK 128U +#define CACHE_MAX_MAX (16*1024U) +#define CACHE_MAX_MIN 64U + +static size_t cache_max(void) { + static size_t cached = -1; + + if (cached == (size_t) -1) { + uint64_t mem_total; + int r; + + r = procfs_memory_get(&mem_total, NULL); + if (r < 0) { + log_warning_errno(r, "Cannot query /proc/meminfo for MemTotal: %m"); + cached = CACHE_MAX_FALLBACK; + } else { + /* Cache entries are usually a few kB, but the process cmdline is controlled by the + * user and can be up to _SC_ARG_MAX, usually 2MB. Let's say that approximately up to + * 1/8th of memory may be used by the cache. + * + * In the common case, this formula gives 64 cache entries for each GB of RAM. + */ + long l = sysconf(_SC_ARG_MAX); + assert(l > 0); + + cached = CLAMP(mem_total / 8 / (uint64_t) l, CACHE_MAX_MIN, CACHE_MAX_MAX); + } + } + + return cached; +} static int client_context_compare(const void *a, const void *b) { const ClientContext *x = a, *y = b; @@ -246,7 +277,7 @@ static int client_context_read_label( } static int client_context_read_cgroup(Server *s, ClientContext *c, const char *unit_id) { - char *t = NULL; + _cleanup_free_ char *t = NULL; int r; assert(c); @@ -254,10 +285,9 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u /* Try to acquire the current cgroup path */ r = cg_pid_get_path_shifted(c->pid, s->cgroup_root, &t); if (r < 0 || empty_or_root(t)) { - /* We use the unit ID passed in as fallback if we have nothing cached yet and cg_pid_get_path_shifted() * failed or process is running in a root cgroup. Zombie processes are automatically migrated to root cgroup - * on cgroupsv1 and we want to be able to map log messages from them too. */ + * on cgroup v1 and we want to be able to map log messages from them too. */ if (unit_id && !c->unit) { c->unit = strdup(unit_id); if (c->unit) @@ -268,10 +298,8 @@ static int client_context_read_cgroup(Server *s, ClientContext *c, const char *u } /* Let's shortcut this if the cgroup path didn't change */ - if (streq_ptr(c->cgroup, t)) { - free(t); + if (streq_ptr(c->cgroup, t)) return 0; - } free_and_replace(c->cgroup, t); @@ -553,15 +581,39 @@ refresh: } static void client_context_try_shrink_to(Server *s, size_t limit) { + ClientContext *c; + usec_t t; + assert(s); + /* Flush any cache entries for PIDs that have already moved on. Don't do this + * too often, since it's a slow process. */ + t = now(CLOCK_MONOTONIC); + if (s->last_cache_pid_flush + MAX_USEC < t) { + unsigned n = prioq_size(s->client_contexts_lru), idx = 0; + + /* We do a number of iterations based on the initial size of the prioq. When we remove an + * item, a new item is moved into its places, and items to the right might be reshuffled. + */ + for (unsigned i = 0; i < n; i++) { + c = prioq_peek_by_index(s->client_contexts_lru, idx); + + assert(c->n_ref == 0); + + if (!pid_is_unwaited(c->pid)) + client_context_free(s, c); + else + idx ++; + } + + s->last_cache_pid_flush = t; + } + /* Bring the number of cache entries below the indicated limit, so that we can create a new entry without * breaching the limit. Note that we only flush out entries that aren't pinned here. This means the number of * cache entries may very well grow beyond the limit, if all entries stored remain pinned. */ while (hashmap_size(s->client_contexts) > limit) { - ClientContext *c; - c = prioq_pop(s->client_contexts_lru); if (!c) break; /* All remaining entries are pinned, give up */ @@ -630,7 +682,7 @@ static int client_context_get_internal( return 0; } - client_context_try_shrink_to(s, CACHE_MAX-1); + client_context_try_shrink_to(s, cache_max()-1); r = client_context_new(s, pid, &c); if (r < 0) diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index e86178ed77..221188db16 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -110,7 +110,7 @@ static int server_process_entry( int priority = LOG_INFO; pid_t object_pid = 0; const char *p; - int r = 0; + int r = 1; p = buffer; @@ -122,8 +122,7 @@ static int server_process_entry( if (!e) { /* Trailing noise, let's ignore it, and flush what we collected */ log_debug("Received message with trailing noise, ignoring."); - r = 1; /* finish processing of the message */ - break; + break; /* finish processing of the message */ } if (e == p) { @@ -133,14 +132,17 @@ static int server_process_entry( } if (IN_SET(*p, '.', '#')) { - /* Ignore control commands for now, and - * comments too. */ + /* Ignore control commands for now, and comments too. */ *remaining -= (e - p) + 1; p = e + 1; continue; } /* A property follows */ + if (n > ENTRY_FIELD_COUNT_MAX) { + log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry."); + goto finish; + } /* n existing properties, 1 new, +1 for _TRANSPORT */ if (!GREEDY_REALLOC(iovec, m, @@ -148,7 +150,7 @@ static int server_process_entry( N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS + client_context_extra_fields_n_iovec(context))) { r = log_oom(); - break; + goto finish; } q = memchr(p, '=', e - p); @@ -157,6 +159,16 @@ static int server_process_entry( size_t l; l = e - p; + if (l > DATA_SIZE_MAX) { + log_debug("Received text block of %zu bytes is too large, ignoring entry.", l); + goto finish; + } + + if (entry_size + l + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ + log_debug("Entry is too big (%zu bytes after processing %zu entries), ignoring entry.", + entry_size + l, n + 1); + goto finish; + } /* If the field name starts with an underscore, skip the variable, since that indicates * a trusted field */ @@ -174,7 +186,7 @@ static int server_process_entry( p = e + 1; continue; } else { - uint64_t l; + uint64_t l, total; char *k; if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) { @@ -183,10 +195,16 @@ static int server_process_entry( } l = unaligned_read_le64(e + 1); - if (l > DATA_SIZE_MAX) { - log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l); - break; + log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", l); + goto finish; + } + + total = (e - p) + 1 + l; + if (entry_size + total + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ + log_debug("Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.", + entry_size + total, n + 1); + goto finish; } if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || @@ -195,7 +213,7 @@ static int server_process_entry( break; } - k = malloc((e - p) + 1 + l); + k = malloc(total); if (!k) { log_oom(); break; @@ -223,15 +241,8 @@ static int server_process_entry( } } - if (n <= 0) { - r = 1; + if (n <= 0) goto finish; - } - - if (!client_context_test_priority(context, priority)) { - r = 0; - goto finish; - } tn = n++; iovec[tn] = IOVEC_MAKE_STRING("_TRANSPORT=journal"); @@ -242,6 +253,11 @@ static int server_process_entry( goto finish; } + r = 0; /* Success, we read the message. */ + + if (!client_context_test_priority(context, priority)) + goto finish; + if (message) { if (s->forward_to_syslog) server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv); @@ -313,15 +329,13 @@ void server_process_native_file( bool sealed; int r; - /* Data is in the passed fd, since it didn't fit in a - * datagram. */ + /* Data is in the passed fd, probably it didn't fit in a datagram. */ assert(s); assert(fd >= 0); /* If it's a memfd, check if it is sealed. If so, we can just - * use map it and use it, and do not need to copy the data - * out. */ + * mmap it and use it, and do not need to copy the data out. */ sealed = memfd_get_sealed(fd) > 0; if (!sealed && (!ucred || ucred->uid != 0)) { @@ -362,8 +376,10 @@ void server_process_native_file( if (st.st_size <= 0) return; - if (st.st_size > ENTRY_SIZE_MAX) { - log_error("File passed too large. Ignoring."); + /* When !sealed, set a lower memory limit. We have to read the file, + * effectively doubling memory use. */ + if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) { + log_error("File passed too large (%"PRIu64" bytes). Ignoring.", (uint64_t) st.st_size); return; } @@ -388,7 +404,7 @@ void server_process_native_file( ssize_t n; if (fstatvfs(fd, &vfs) < 0) { - log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m"); + log_error_errno(errno, "Failed to stat file system of passed file, not processing it: %m"); return; } @@ -398,7 +414,7 @@ void server_process_native_file( * https://github.com/systemd/systemd/issues/1822 */ if (vfs.f_flag & ST_MANDLOCK) { - log_error("Received file descriptor from file system with mandatory locking enabled, refusing."); + log_error("Received file descriptor from file system with mandatory locking enabled, not processing it."); return; } @@ -411,13 +427,13 @@ void server_process_native_file( * and so is SMB. */ r = fd_nonblock(fd, true); if (r < 0) { - log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m"); + log_error_errno(r, "Failed to make fd non-blocking, not processing it: %m"); return; } /* The file is not sealed, we can't map the file here, since * clients might then truncate it and trigger a SIGBUS for - * us. So let's stupidly read it */ + * us. So let's stupidly read it. */ p = malloc(st.st_size); if (!p) { diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 434325c179..2a960ebb3e 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -905,6 +905,7 @@ static void dispatch_message_real( pid_t object_pid) { char source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)]; + _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL; uid_t journal_uid; ClientContext *o; @@ -921,20 +922,23 @@ static void dispatch_message_real( IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->uid, uid_t, uid_is_valid, UID_FMT, "_UID"); IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->gid, gid_t, gid_is_valid, GID_FMT, "_GID"); - IOVEC_ADD_STRING_FIELD(iovec, n, c->comm, "_COMM"); - IOVEC_ADD_STRING_FIELD(iovec, n, c->exe, "_EXE"); - IOVEC_ADD_STRING_FIELD(iovec, n, c->cmdline, "_CMDLINE"); - IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE"); + IOVEC_ADD_STRING_FIELD(iovec, n, c->comm, "_COMM"); /* At most TASK_COMM_LENGTH (16 bytes) */ + IOVEC_ADD_STRING_FIELD(iovec, n, c->exe, "_EXE"); /* A path, so at most PATH_MAX (4096 bytes) */ - IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT"); + if (c->cmdline) + /* At most _SC_ARG_MAX (2MB usually), which is too much to put on stack. + * Let's use a heap allocation for this one. */ + cmdline1 = set_iovec_string_field(iovec, &n, "_CMDLINE=", c->cmdline); + IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE"); /* Read from /proc/.../status */ + IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT"); IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "_AUDIT_SESSION"); IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->loginuid, uid_t, uid_is_valid, UID_FMT, "_AUDIT_LOGINUID"); - IOVEC_ADD_STRING_FIELD(iovec, n, c->cgroup, "_SYSTEMD_CGROUP"); + IOVEC_ADD_STRING_FIELD(iovec, n, c->cgroup, "_SYSTEMD_CGROUP"); /* A path */ IOVEC_ADD_STRING_FIELD(iovec, n, c->session, "_SYSTEMD_SESSION"); IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->owner_uid, uid_t, uid_is_valid, UID_FMT, "_SYSTEMD_OWNER_UID"); - IOVEC_ADD_STRING_FIELD(iovec, n, c->unit, "_SYSTEMD_UNIT"); + IOVEC_ADD_STRING_FIELD(iovec, n, c->unit, "_SYSTEMD_UNIT"); /* Unit names are bounded by UNIT_NAME_MAX */ IOVEC_ADD_STRING_FIELD(iovec, n, c->user_unit, "_SYSTEMD_USER_UNIT"); IOVEC_ADD_STRING_FIELD(iovec, n, c->slice, "_SYSTEMD_SLICE"); IOVEC_ADD_STRING_FIELD(iovec, n, c->user_slice, "_SYSTEMD_USER_SLICE"); @@ -955,13 +959,14 @@ static void dispatch_message_real( IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_UID"); IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->gid, gid_t, gid_is_valid, GID_FMT, "OBJECT_GID"); + /* See above for size limits, only ->cmdline may be large, so use a heap allocation for it. */ IOVEC_ADD_STRING_FIELD(iovec, n, o->comm, "OBJECT_COMM"); IOVEC_ADD_STRING_FIELD(iovec, n, o->exe, "OBJECT_EXE"); - IOVEC_ADD_STRING_FIELD(iovec, n, o->cmdline, "OBJECT_CMDLINE"); - IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE"); + if (o->cmdline) + cmdline2 = set_iovec_string_field(iovec, &n, "OBJECT_CMDLINE=", o->cmdline); + IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE"); IOVEC_ADD_SIZED_FIELD(iovec, n, o->label, o->label_size, "OBJECT_SELINUX_CONTEXT"); - IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "OBJECT_AUDIT_SESSION"); IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->loginuid, uid_t, uid_is_valid, UID_FMT, "OBJECT_AUDIT_LOGINUID"); @@ -1276,8 +1281,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void return log_error_errno(errno, "recvmsg() failed: %m"); } - CMSG_FOREACH(cmsg, &msghdr) { - + CMSG_FOREACH(cmsg, &msghdr) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) @@ -1295,7 +1299,6 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void fds = (int*) CMSG_DATA(cmsg); n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); } - } /* And a trailing NUL, just in case */ s->buffer[n] = 0; diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 6d4847b0cd..3f6b42ddd5 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -161,6 +161,8 @@ struct Server { Hashmap *client_contexts; Prioq *client_contexts_lru; + usec_t last_cache_pid_flush; + ClientContext *my_context; /* the context of journald itself */ ClientContext *pid1_context; /* the context of PID 1 */ }; diff --git a/src/journal/journald-wall.h b/src/journal/journald-wall.h index d081c8254c..b73059af46 100644 --- a/src/journal/journald-wall.h +++ b/src/journal/journald-wall.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once - #include "journald-server.h" void server_forward_wall(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 90549f1c9f..0dc453e709 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -132,7 +132,7 @@ static void window_free(Window *w) { free(w); } -_pure_ static inline bool window_matches(Window *w, int prot, uint64_t offset, size_t size) { +_pure_ static bool window_matches(Window *w, int prot, uint64_t offset, size_t size) { assert(w); assert(size > 0); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index b5ff5b64f3..0f996283cd 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -36,7 +36,6 @@ #include "process-util.h" #include "replace-var.h" #include "stat-util.h" -#include "stat-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" |