diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2021-11-18 12:37:04 +0000 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2021-11-19 18:50:59 +0000 |
commit | 66e2bb282b44fceec0a495ff94208761fb2b7ceb (patch) | |
tree | 7d3881029d97894f66323cfcf0e502e1da1dcf1a | |
parent | ceb4192df6e38538e94e45e84a2d37f6187d7d27 (diff) | |
download | systemd-66e2bb282b44fceec0a495ff94208761fb2b7ceb.tar.gz |
journal: Limit the number of audit fields per log message
Similar to the kmsg handler, let's also limit the number of fields
we parse from audit messages.
Fixes #19799
-rw-r--r-- | src/journal/journald-audit.c | 54 | ||||
-rw-r--r-- | src/journal/journald-server.h | 3 |
2 files changed, 25 insertions, 32 deletions
diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index e31e5453b8..a8e3b175ac 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -15,13 +15,13 @@ typedef struct MapField { const char *audit_field; const char *journal_field; - int (*map)(const char *field, const char **p, struct iovec **iovec, size_t *n); + int (*map)(const char *field, const char **p, struct iovec *iovec, size_t *n); } MapField; static int map_simple_field( const char *field, const char **p, - struct iovec **iovec, + struct iovec *iovec, size_t *n) { _cleanup_free_ char *c = NULL; @@ -48,10 +48,7 @@ static int map_simple_field( c[l] = 0; - if (!GREEDY_REALLOC(*iovec, *n + 1)) - return -ENOMEM; - - (*iovec)[(*n)++] = IOVEC_MAKE(c, l); + iovec[(*n)++] = IOVEC_MAKE(c, l); *p = e; c = NULL; @@ -62,7 +59,7 @@ static int map_simple_field( static int map_string_field_internal( const char *field, const char **p, - struct iovec **iovec, + struct iovec *iovec, size_t *n, bool filter_printable) { @@ -128,10 +125,7 @@ static int map_string_field_internal( } else return 0; - if (!GREEDY_REALLOC(*iovec, *n + 1)) - return -ENOMEM; - - (*iovec)[(*n)++] = IOVEC_MAKE(c, l); + iovec[(*n)++] = IOVEC_MAKE(c, l); *p = e; c = NULL; @@ -139,18 +133,18 @@ static int map_string_field_internal( return 1; } -static int map_string_field(const char *field, const char **p, struct iovec **iovec, size_t *n) { +static int map_string_field(const char *field, const char **p, struct iovec *iovec, size_t *n) { return map_string_field_internal(field, p, iovec, n, false); } -static int map_string_field_printable(const char *field, const char **p, struct iovec **iovec, size_t *n) { +static int map_string_field_printable(const char *field, const char **p, struct iovec *iovec, size_t *n) { return map_string_field_internal(field, p, iovec, n, true); } static int map_generic_field( const char *prefix, const char **p, - struct iovec **iovec, + struct iovec *iovec, size_t *n) { const char *e, *f; @@ -255,8 +249,9 @@ static int map_all_fields( const MapField map_fields[], const char *prefix, bool handle_msg, - struct iovec **iovec, - size_t *n) { + struct iovec *iovec, + size_t *n, + size_t m) { int r; @@ -269,6 +264,13 @@ static int map_all_fields( const MapField *mf; const char *v; + if (*n >= m) { + log_debug( + "More fields in audit message than audit field limit (%i), skipping remaining fields", + N_IOVEC_AUDIT_FIELDS); + return 0; + } + p += strspn(p, WHITESPACE); if (*p == 0) @@ -296,7 +298,7 @@ static int map_all_fields( if (!c) return -ENOMEM; - return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iovec, n); + return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iovec, n, m); } } @@ -331,12 +333,12 @@ static int map_all_fields( void process_audit_string(Server *s, int type, const char *data, size_t size) { size_t n = 0, z; - _cleanup_free_ struct iovec *iovec = NULL; uint64_t seconds, msec, id; const char *p, *type_name; char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)], type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)], source_time_field[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)]; + struct iovec iovec[N_IOVEC_META_FIELDS + 8 + N_IOVEC_AUDIT_FIELDS]; char *m, *type_field_name; int k; @@ -371,12 +373,6 @@ void process_audit_string(Server *s, int type, const char *data, size_t size) { if (isempty(p)) return; - iovec = new(struct iovec, N_IOVEC_META_FIELDS + 8); - if (!iovec) { - log_oom(); - return; - } - iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=audit"); sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64, @@ -403,16 +399,10 @@ void process_audit_string(Server *s, int type, const char *data, size_t size) { z = n; - map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, &iovec, &n); - - if (!GREEDY_REALLOC(iovec, n + N_IOVEC_META_FIELDS)) { - log_oom(); - goto finish; - } + map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, iovec, &n, ELEMENTSOF(iovec)); - server_dispatch_message(s, iovec, n, MALLOC_ELEMENTSOF(iovec), NULL, NULL, LOG_NOTICE, 0); + server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, LOG_NOTICE, 0); -finish: /* free() all entries that map_all_fields() added. All others * are allocated on the stack or are constant. */ diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 53e75ff3b0..87d39de3ae 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -191,6 +191,9 @@ struct Server { /* kmsg: Maximum number of extra fields we'll import from udev's devices */ #define N_IOVEC_UDEV_FIELDS 32 +/* audit: Maximum number of extra fields we'll import from audit messages */ +#define N_IOVEC_AUDIT_FIELDS 64 + void server_dispatch_message(Server *s, struct iovec *iovec, size_t n, size_t m, ClientContext *c, const struct timeval *tv, int priority, pid_t object_pid); void server_driver_message(Server *s, pid_t object_pid, const char *message_id, const char *format, ...) _sentinel_ _printf_(4,0); |