mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #21431 from DaanDeMeyer/issue-19799
journal: Limit the number of audit fields we add to a message
This commit is contained in:
@@ -15,14 +15,14 @@
|
||||
typedef struct MapField {
|
||||
const char *audit_field;
|
||||
const char *journal_field;
|
||||
int (*map)(const char *field, const char **p, struct iovec **iov, size_t *n_iov);
|
||||
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 **iov,
|
||||
size_t *n_iov) {
|
||||
struct iovec *iovec,
|
||||
size_t *n) {
|
||||
|
||||
_cleanup_free_ char *c = NULL;
|
||||
size_t l = 0;
|
||||
@@ -30,8 +30,8 @@ static int map_simple_field(
|
||||
|
||||
assert(field);
|
||||
assert(p);
|
||||
assert(iov);
|
||||
assert(n_iov);
|
||||
assert(iovec);
|
||||
assert(n);
|
||||
|
||||
l = strlen(field);
|
||||
c = malloc(l + 1);
|
||||
@@ -48,10 +48,7 @@ static int map_simple_field(
|
||||
|
||||
c[l] = 0;
|
||||
|
||||
if (!GREEDY_REALLOC(*iov, *n_iov + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
(*iov)[(*n_iov)++] = IOVEC_MAKE(c, l);
|
||||
iovec[(*n)++] = IOVEC_MAKE(c, l);
|
||||
|
||||
*p = e;
|
||||
c = NULL;
|
||||
@@ -62,8 +59,8 @@ static int map_simple_field(
|
||||
static int map_string_field_internal(
|
||||
const char *field,
|
||||
const char **p,
|
||||
struct iovec **iov,
|
||||
size_t *n_iov,
|
||||
struct iovec *iovec,
|
||||
size_t *n,
|
||||
bool filter_printable) {
|
||||
|
||||
_cleanup_free_ char *c = NULL;
|
||||
@@ -72,8 +69,8 @@ static int map_string_field_internal(
|
||||
|
||||
assert(field);
|
||||
assert(p);
|
||||
assert(iov);
|
||||
assert(n_iov);
|
||||
assert(iovec);
|
||||
assert(n);
|
||||
|
||||
/* The kernel formats string fields in one of two formats. */
|
||||
|
||||
@@ -128,10 +125,7 @@ static int map_string_field_internal(
|
||||
} else
|
||||
return 0;
|
||||
|
||||
if (!GREEDY_REALLOC(*iov, *n_iov + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
(*iov)[(*n_iov)++] = IOVEC_MAKE(c, l);
|
||||
iovec[(*n)++] = IOVEC_MAKE(c, l);
|
||||
|
||||
*p = e;
|
||||
c = NULL;
|
||||
@@ -139,19 +133,19 @@ static int map_string_field_internal(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov) {
|
||||
return map_string_field_internal(field, p, iov, n_iov, false);
|
||||
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 **iov, size_t *n_iov) {
|
||||
return map_string_field_internal(field, p, iov, n_iov, true);
|
||||
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 **iov,
|
||||
size_t *n_iov) {
|
||||
struct iovec *iovec,
|
||||
size_t *n) {
|
||||
|
||||
const char *e, *f;
|
||||
char *c, *t;
|
||||
@@ -196,7 +190,7 @@ static int map_generic_field(
|
||||
|
||||
e++;
|
||||
|
||||
r = map_simple_field(c, &e, iov, n_iov);
|
||||
r = map_simple_field(c, &e, iovec, n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -255,20 +249,28 @@ static int map_all_fields(
|
||||
const MapField map_fields[],
|
||||
const char *prefix,
|
||||
bool handle_msg,
|
||||
struct iovec **iov,
|
||||
size_t *n_iov) {
|
||||
struct iovec *iovec,
|
||||
size_t *n,
|
||||
size_t m) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
assert(iov);
|
||||
assert(n_iov);
|
||||
assert(iovec);
|
||||
assert(n);
|
||||
|
||||
for (;;) {
|
||||
bool mapped = false;
|
||||
const MapField *m;
|
||||
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,17 +298,17 @@ static int map_all_fields(
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iov, n_iov);
|
||||
return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iovec, n, m);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to map the kernel fields to our own names */
|
||||
for (m = map_fields; m->audit_field; m++) {
|
||||
v = startswith(p, m->audit_field);
|
||||
for (mf = map_fields; mf->audit_field; mf++) {
|
||||
v = startswith(p, mf->audit_field);
|
||||
if (!v)
|
||||
continue;
|
||||
|
||||
r = m->map(m->journal_field, &v, iov, n_iov);
|
||||
r = mf->map(mf->journal_field, &v, iovec, n);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse audit array: %m");
|
||||
|
||||
@@ -318,7 +320,7 @@ static int map_all_fields(
|
||||
}
|
||||
|
||||
if (!mapped) {
|
||||
r = map_generic_field(prefix, &p, iov, n_iov);
|
||||
r = map_generic_field(prefix, &p, iovec, n);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse audit array: %m");
|
||||
|
||||
@@ -330,13 +332,13 @@ static int map_all_fields(
|
||||
}
|
||||
|
||||
void process_audit_string(Server *s, int type, const char *data, size_t size) {
|
||||
size_t n_iov = 0, z;
|
||||
_cleanup_free_ struct iovec *iov = NULL;
|
||||
size_t n = 0, z;
|
||||
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,53 +373,41 @@ void process_audit_string(Server *s, int type, const char *data, size_t size) {
|
||||
if (isempty(p))
|
||||
return;
|
||||
|
||||
iov = new(struct iovec, N_IOVEC_META_FIELDS + 8);
|
||||
if (!iov) {
|
||||
log_oom();
|
||||
return;
|
||||
}
|
||||
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING("_TRANSPORT=audit");
|
||||
iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=audit");
|
||||
|
||||
sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64,
|
||||
(usec_t) seconds * USEC_PER_SEC + (usec_t) msec * USEC_PER_MSEC);
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING(source_time_field);
|
||||
iovec[n++] = IOVEC_MAKE_STRING(source_time_field);
|
||||
|
||||
sprintf(type_field, "_AUDIT_TYPE=%i", type);
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING(type_field);
|
||||
iovec[n++] = IOVEC_MAKE_STRING(type_field);
|
||||
|
||||
sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING(id_field);
|
||||
iovec[n++] = IOVEC_MAKE_STRING(id_field);
|
||||
|
||||
assert_cc(4 == LOG_FAC(LOG_AUTH));
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=4");
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=audit");
|
||||
iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=4");
|
||||
iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=audit");
|
||||
|
||||
type_name = audit_type_name_alloca(type);
|
||||
|
||||
type_field_name = strjoina("_AUDIT_TYPE_NAME=", type_name);
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING(type_field_name);
|
||||
iovec[n++] = IOVEC_MAKE_STRING(type_field_name);
|
||||
|
||||
m = strjoina("MESSAGE=", type_name, " ", p);
|
||||
iov[n_iov++] = IOVEC_MAKE_STRING(m);
|
||||
iovec[n++] = IOVEC_MAKE_STRING(m);
|
||||
|
||||
z = n_iov;
|
||||
z = n;
|
||||
|
||||
map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, &iov, &n_iov);
|
||||
map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, iovec, &n, ELEMENTSOF(iovec));
|
||||
|
||||
if (!GREEDY_REALLOC(iov, n_iov + N_IOVEC_META_FIELDS)) {
|
||||
log_oom();
|
||||
goto finish;
|
||||
}
|
||||
server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, LOG_NOTICE, 0);
|
||||
|
||||
server_dispatch_message(s, iov, n_iov, MALLOC_ELEMENTSOF(iov), NULL, NULL, LOG_NOTICE, 0);
|
||||
|
||||
finish:
|
||||
/* free() all entries that map_all_fields() added. All others
|
||||
* are allocated on the stack or are constant. */
|
||||
|
||||
for (; z < n_iov; z++)
|
||||
free(iov[z].iov_base);
|
||||
for (; z < n; z++)
|
||||
free(iovec[z].iov_base);
|
||||
}
|
||||
|
||||
void server_process_audit_message(
|
||||
|
||||
@@ -193,6 +193,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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user