summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaan De Meyer <daan.j.demeyer@gmail.com>2021-11-18 12:37:04 +0000
committerDaan De Meyer <daan.j.demeyer@gmail.com>2021-11-19 18:50:59 +0000
commit66e2bb282b44fceec0a495ff94208761fb2b7ceb (patch)
tree7d3881029d97894f66323cfcf0e502e1da1dcf1a
parentceb4192df6e38538e94e45e84a2d37f6187d7d27 (diff)
downloadsystemd-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.c54
-rw-r--r--src/journal/journald-server.h3
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);