X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fjournal%2Fjournald-audit.c;h=345e43ef44f7d3627be1b50cf922c24d397345fb;hb=1dab14aba749b9c5ab8176c5730107b70834240b;hp=869c996aefe5616b74ec6b9b575588efc9d7218f;hpb=0cde65e263643cf00a6b29c3178c9a73724da812;p=thirdparty%2Fsystemd.git diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c index 869c996aefe..345e43ef44f 100644 --- a/src/journal/journald-audit.c +++ b/src/journal/journald-audit.c @@ -1,21 +1,4 @@ -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see . -***/ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include "alloc-util.h" #include "audit-type.h" @@ -29,10 +12,10 @@ 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_allocated, unsigned *n_iov); + int (*map)(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov); } MapField; -static int map_simple_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { +static int map_simple_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { _cleanup_free_ char *c = NULL; size_t l = 0, allocated = 0; const char *e; @@ -49,7 +32,7 @@ static int map_simple_field(const char *field, const char **p, struct iovec **io return -ENOMEM; memcpy(c, field, l); - for (e = *p; *e != ' ' && *e != 0; e++) { + for (e = *p; !IN_SET(*e, 0, ' '); e++) { if (!GREEDY_REALLOC(c, allocated, l+2)) return -ENOMEM; @@ -61,9 +44,7 @@ static int map_simple_field(const char *field, const char **p, struct iovec **io if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1)) return -ENOMEM; - (*iov)[*n_iov].iov_base = c; - (*iov)[*n_iov].iov_len = l; - (*n_iov)++; + (*iov)[(*n_iov)++] = IOVEC_MAKE(c, l); *p = e; c = NULL; @@ -71,7 +52,7 @@ static int map_simple_field(const char *field, const char **p, struct iovec **io return 1; } -static int map_string_field_internal(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov, bool filter_printable) { +static int map_string_field_internal(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov, bool filter_printable) { _cleanup_free_ char *c = NULL; const char *s, *e; size_t l; @@ -110,7 +91,7 @@ static int map_string_field_internal(const char *field, const char **p, struct i return -ENOMEM; memcpy(c, field, l); - for (e = *p; *e != ' ' && *e != 0; e += 2) { + for (e = *p; !IN_SET(*e, 0, ' '); e += 2) { int a, b; uint8_t x; @@ -140,9 +121,7 @@ static int map_string_field_internal(const char *field, const char **p, struct i if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1)) return -ENOMEM; - (*iov)[*n_iov].iov_base = c; - (*iov)[*n_iov].iov_len = l; - (*n_iov)++; + (*iov)[(*n_iov)++] = IOVEC_MAKE(c, l); *p = e; c = NULL; @@ -150,15 +129,15 @@ static int map_string_field_internal(const char *field, const char **p, struct i return 1; } -static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { +static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, false); } -static int map_string_field_printable(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { +static int map_string_field_printable(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, true); } -static int map_generic_field(const char *prefix, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) { +static int map_generic_field(const char *prefix, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { const char *e, *f; char *c, *t; int r; @@ -167,7 +146,7 @@ static int map_generic_field(const char *prefix, const char **p, struct iovec ** for (e = *p; e < *p + 16; e++) { - if (*e == 0 || *e == ' ') + if (IN_SET(*e, 0, ' ')) return 0; if (*e == '=') @@ -176,7 +155,7 @@ static int map_generic_field(const char *prefix, const char **p, struct iovec ** if (!((*e >= 'a' && *e <= 'z') || (*e >= 'A' && *e <= 'Z') || (*e >= '0' && *e <= '9') || - *e == '_' || *e == '-')) + IN_SET(*e, '_', '-'))) return 0; } @@ -218,29 +197,29 @@ static const MapField map_fields_kernel[] = { /* First, we map certain well-known audit fields into native * well-known fields */ - { "pid=", "_PID=", map_simple_field }, - { "ppid=", "_PPID=", map_simple_field }, - { "uid=", "_UID=", map_simple_field }, - { "euid=", "_EUID=", map_simple_field }, - { "fsuid=", "_FSUID=", map_simple_field }, - { "gid=", "_GID=", map_simple_field }, - { "egid=", "_EGID=", map_simple_field }, - { "fsgid=", "_FSGID=", map_simple_field }, - { "tty=", "_TTY=", map_simple_field }, - { "ses=", "_AUDIT_SESSION=", map_simple_field }, - { "auid=", "_AUDIT_LOGINUID=", map_simple_field }, - { "subj=", "_SELINUX_CONTEXT=", map_simple_field }, - { "comm=", "_COMM=", map_string_field }, - { "exe=", "_EXE=", map_string_field }, - { "proctitle=", "_CMDLINE=", map_string_field_printable }, + { "pid=", "_PID=", map_simple_field }, + { "ppid=", "_PPID=", map_simple_field }, + { "uid=", "_UID=", map_simple_field }, + { "euid=", "_EUID=", map_simple_field }, + { "fsuid=", "_FSUID=", map_simple_field }, + { "gid=", "_GID=", map_simple_field }, + { "egid=", "_EGID=", map_simple_field }, + { "fsgid=", "_FSGID=", map_simple_field }, + { "tty=", "_TTY=", map_simple_field }, + { "ses=", "_AUDIT_SESSION=", map_simple_field }, + { "auid=", "_AUDIT_LOGINUID=", map_simple_field }, + { "subj=", "_SELINUX_CONTEXT=", map_simple_field }, + { "comm=", "_COMM=", map_string_field }, + { "exe=", "_EXE=", map_string_field }, + { "proctitle=", "_CMDLINE=", map_string_field_printable }, /* Some fields don't map to native well-known fields. However, * we know that they are string fields, hence let's undo * string field escaping for them, though we stick to the * generic field names. */ - { "path=", "_AUDIT_FIELD_PATH=", map_string_field }, - { "dev=", "_AUDIT_FIELD_DEV=", map_string_field }, - { "name=", "_AUDIT_FIELD_NAME=", map_string_field }, + { "path=", "_AUDIT_FIELD_PATH=", map_string_field }, + { "dev=", "_AUDIT_FIELD_DEV=", map_string_field }, + { "name=", "_AUDIT_FIELD_NAME=", map_string_field }, {} }; @@ -248,11 +227,11 @@ static const MapField map_fields_kernel[] = { * msg='. All of these fields are untrusted, hence carry no "_" * prefix. We map the fields we don't know to AUDIT_FIELD_XYZ= */ static const MapField map_fields_userspace[] = { - { "cwd=", "AUDIT_FIELD_CWD=", map_string_field }, - { "cmd=", "AUDIT_FIELD_CMD=", map_string_field }, - { "acct=", "AUDIT_FIELD_ACCT=", map_string_field }, - { "exe=", "AUDIT_FIELD_EXE=", map_string_field }, - { "comm=", "AUDIT_FIELD_COMM=", map_string_field }, + { "cwd=", "AUDIT_FIELD_CWD=", map_string_field }, + { "cmd=", "AUDIT_FIELD_CMD=", map_string_field }, + { "acct=", "AUDIT_FIELD_ACCT=", map_string_field }, + { "exe=", "AUDIT_FIELD_EXE=", map_string_field }, + { "comm=", "AUDIT_FIELD_COMM=", map_string_field }, {} }; @@ -263,7 +242,7 @@ static int map_all_fields( bool handle_msg, struct iovec **iov, size_t *n_iov_allocated, - unsigned *n_iov) { + size_t *n_iov) { int r; @@ -334,17 +313,16 @@ static int map_all_fields( } } -static void process_audit_string(Server *s, int type, const char *data, size_t size) { +void process_audit_string(Server *s, int type, const char *data, size_t size) { + size_t n_iov_allocated = 0, n_iov = 0, z; _cleanup_free_ struct iovec *iov = NULL; - size_t n_iov_allocated = 0; - unsigned n_iov = 0, k; uint64_t seconds, msec, id; const char *p, *type_name; - unsigned z; 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)]; - char *m; + char *m, *type_field_name; + int k; assert(s); @@ -363,11 +341,12 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s if (!p) return; + k = 0; if (sscanf(p, "(%" PRIu64 ".%" PRIu64 ":%" PRIu64 "):%n", &seconds, &msec, &id, - &k) != 3) + &k) != 3 || k == 0) return; p += k; @@ -376,7 +355,7 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s if (isempty(p)) return; - n_iov_allocated = N_IOVEC_META_FIELDS + 7; + n_iov_allocated = N_IOVEC_META_FIELDS + 8; iov = new(struct iovec, n_iov_allocated); if (!iov) { log_oom(); @@ -401,6 +380,9 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s 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); + m = strjoina("MESSAGE=", type_name, " ", p); iov[n_iov++] = IOVEC_MAKE_STRING(m); @@ -463,8 +445,8 @@ void server_process_audit_message( if (IN_SET(nl->nlmsg_type, NLMSG_NOOP, NLMSG_ERROR)) return; - /* Below AUDIT_FIRST_USER_MSG theer are only control messages, let's ignore those */ - if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG) + /* Except AUDIT_USER, all messsages below AUDIT_FIRST_USER_MSG are control messages, let's ignore those */ + if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG && nl->nlmsg_type != AUDIT_USER) return; process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr))); @@ -516,7 +498,6 @@ static int enable_audit(int fd, bool b) { } int server_open_audit(Server *s) { - static const int one = 1; int r; if (s->audit_fd < 0) { @@ -528,7 +509,7 @@ int server_open_audit(Server *s) { s->audit_fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); if (s->audit_fd < 0) { - if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) + if (IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT)) log_debug("Audit not supported in the kernel."); else log_warning_errno(errno, "Failed to create audit socket, ignoring: %m"); @@ -545,11 +526,11 @@ int server_open_audit(Server *s) { return 0; } } else - fd_nonblock(s->audit_fd, 1); + (void) fd_nonblock(s->audit_fd, true); - r = setsockopt(s->audit_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); + r = setsockopt_int(s->audit_fd, SOL_SOCKET, SO_PASSCRED, true); if (r < 0) - return log_error_errno(errno, "Failed to set SO_PASSCRED on audit socket: %m"); + return log_error_errno(r, "Failed to set SO_PASSCRED on audit socket: %m"); r = sd_event_add_io(s->event, &s->audit_event_source, s->audit_fd, EPOLLIN, server_process_datagram, s); if (r < 0)