1
0
mirror of https://github.com/systemd/systemd synced 2026-04-07 15:44:49 +02:00

Compare commits

...

15 Commits

Author SHA1 Message Date
Luca Boccassi
289a42304d
Merge pull request #21432 from DaanDeMeyer/journal-trivial-fixes
Journal trivial fixes
2021-11-20 18:00:35 +00:00
Luca Boccassi
26bae8109d
Merge pull request #21431 from DaanDeMeyer/issue-19799
journal: Limit the number of audit fields we add to a message
2021-11-20 17:58:51 +00:00
Lennart Poettering
a50966416e nspawn: use FOREACH_STRING() more 2021-11-20 17:54:53 +00:00
Christian Göttsche
7e570d575f core: prefix functions to avoid identical static function names
The function name `method_reload` is used both in dbus-unit.c and
dbus-manager.c for static functions.
With the previous addition of adding the function name to the audit
information on SELinux denials, rename the one (and its relatives) in
dbus-unit.c as most of the functions in src/core/dbus-unit.c are already
prefixed with `bus_unit_`.
2021-11-20 16:38:03 +00:00
Christian Göttsche
963438a027 selinux: name mac_selinux_generic_access_check as internal function
`mac_selinux_generic_access_check()` should not be called directly, only
via the wrapper macros `mac_selinux_access_check` and
`mac_selinux_unit_access_check`.
2021-11-20 16:38:03 +00:00
Christian Göttsche
6fbb33f631 selinux: improve debug log format
path might be NULL when checking against the system permissions, so wrap
with strna().

The command line might not be available over D-Bus and thus cl might be
empty. Print "n/a" instead of the empty string.
2021-11-20 16:38:03 +00:00
Christian Göttsche
f0804759cf selinux: add function name to audit data
Include the systemd C function name in the audit message to improve the
debug ability on denials.
Similar like kernel denial messages include the syscall name.
2021-11-20 16:38:03 +00:00
Daan De Meyer
66e2bb282b 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
2021-11-19 18:50:59 +00:00
Daan De Meyer
368a14b67b journal: Add verify_hash_table()
The existing verify_hash_table() function is renamed to
verify_data_hash_table() since it only verifies the data hash table.

The verify information is also made a little more detailed by splitting
one of the checks in two.
2021-11-19 17:12:29 +00:00
Daan De Meyer
363b2b9aaf journal: Add journal_file_object_to_string() 2021-11-19 17:12:27 +00:00
Daan De Meyer
b92d1eba31 journal: Simplify definition of HEADER_INCOMPATIBLE_SUPPORTED 2021-11-19 17:06:57 +00:00
Daan De Meyer
d164ac771e journal: Use more structured initialization 2021-11-19 17:06:57 +00:00
Daan De Meyer
86e68f3814 journal: Use size_t instead of unsigned for array sizes 2021-11-19 17:06:55 +00:00
Daan De Meyer
ceb4192df6 journal: Use mf as variable name for MapField
So we can have a variable m for the max iovec size in the next
commit like we do in the rest of the journal logic.
2021-11-18 13:28:14 +00:00
Daan De Meyer
4cdb970b5b journal: Use consistent naming for iovec in audit logic
Let's use iovec and n for the iovec variable and it's size just like
we do in the rest of the journal code.
2021-11-18 13:28:08 +00:00
10 changed files with 199 additions and 176 deletions

View File

@ -422,31 +422,31 @@ int bus_unit_method_start_generic(
reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0, error); reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0, error);
} }
static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_START, false, error); return bus_unit_method_start_generic(message, userdata, JOB_START, false, error);
} }
static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error); return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error);
} }
static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error); return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error);
} }
static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error); return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error);
} }
static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error); return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error);
} }
static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error); return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error);
} }
static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int bus_unit_method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error); return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error);
} }
@ -941,49 +941,49 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_start, bus_unit_method_start,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Stop", SD_BUS_METHOD_WITH_NAMES("Stop",
"s", "s",
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_stop, bus_unit_method_stop,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Reload", SD_BUS_METHOD_WITH_NAMES("Reload",
"s", "s",
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_reload, bus_unit_method_reload,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Restart", SD_BUS_METHOD_WITH_NAMES("Restart",
"s", "s",
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_restart, bus_unit_method_restart,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("TryRestart", SD_BUS_METHOD_WITH_NAMES("TryRestart",
"s", "s",
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_try_restart, bus_unit_method_try_restart,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ReloadOrRestart", SD_BUS_METHOD_WITH_NAMES("ReloadOrRestart",
"s", "s",
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_reload_or_restart, bus_unit_method_reload_or_restart,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ReloadOrTryRestart", SD_BUS_METHOD_WITH_NAMES("ReloadOrTryRestart",
"s", "s",
SD_BUS_PARAM(mode), SD_BUS_PARAM(mode),
"o", "o",
SD_BUS_PARAM(job), SD_BUS_PARAM(job),
method_reload_or_try_restart, bus_unit_method_reload_or_try_restart,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("EnqueueJob", SD_BUS_METHOD_WITH_NAMES("EnqueueJob",
"ss", "ss",

View File

@ -31,6 +31,7 @@ struct audit_info {
sd_bus_creds *creds; sd_bus_creds *creds;
const char *path; const char *path;
const char *cmdline; const char *cmdline;
const char *function;
}; };
/* /*
@ -58,10 +59,11 @@ static int audit_callback(
xsprintf(gid_buf, GID_FMT, gid); xsprintf(gid_buf, GID_FMT, gid);
(void) snprintf(msgbuf, msgbufsize, (void) snprintf(msgbuf, msgbufsize,
"auid=%s uid=%s gid=%s%s%s%s%s%s%s", "auid=%s uid=%s gid=%s%s%s%s%s%s%s%s%s%s",
login_uid_buf, uid_buf, gid_buf, login_uid_buf, uid_buf, gid_buf,
audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "", audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "",
audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : ""); audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : "",
audit->function ? " function=\"" : "", strempty(audit->function), audit->function ? "\"" : "");
return 0; return 0;
} }
@ -175,10 +177,11 @@ static int access_init(sd_bus_error *error) {
If the machine is in permissive mode it will return ok. Audit messages will If the machine is in permissive mode it will return ok. Audit messages will
still be generated if the access would be denied in enforcing mode. still be generated if the access would be denied in enforcing mode.
*/ */
int mac_selinux_generic_access_check( int mac_selinux_access_check_internal(
sd_bus_message *message, sd_bus_message *message,
const char *path, const char *path,
const char *permission, const char *permission,
const char *function,
sd_bus_error *error) { sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@ -191,6 +194,7 @@ int mac_selinux_generic_access_check(
assert(message); assert(message);
assert(permission); assert(permission);
assert(function);
assert(error); assert(error);
r = access_init(error); r = access_init(error);
@ -263,6 +267,7 @@ int mac_selinux_generic_access_check(
.creds = creds, .creds = creds,
.path = path, .path = path,
.cmdline = cl, .cmdline = cl,
.function = function,
}; };
r = selinux_check_access(scon, fcon, tclass, permission, &audit_info); r = selinux_check_access(scon, fcon, tclass, permission, &audit_info);
@ -274,17 +279,18 @@ int mac_selinux_generic_access_check(
} }
log_full_errno_zerook(LOG_DEBUG, r, log_full_errno_zerook(LOG_DEBUG, r,
"SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s path=%s cmdline=%s: %m", "SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s function=%s path=%s cmdline=%s: %m",
scon, fcon, tclass, permission, enforce ? "enforcing" : "permissive", path, cl); scon, fcon, tclass, permission, enforce ? "enforcing" : "permissive", function, strna(path), isempty(cl) ? "n/a" : cl);
return enforce ? r : 0; return enforce ? r : 0;
} }
#else /* HAVE_SELINUX */ #else /* HAVE_SELINUX */
int mac_selinux_generic_access_check( int mac_selinux_access_check_internal(
sd_bus_message *message, sd_bus_message *message,
const char *path, const char *path,
const char *permission, const char *permission,
const char *function,
sd_bus_error *error) { sd_bus_error *error) {
return 0; return 0;

View File

@ -5,10 +5,14 @@
#include "manager.h" #include "manager.h"
int mac_selinux_generic_access_check(sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error); int mac_selinux_access_check_internal(sd_bus_message *message,
const char *path,
const char *permission,
const char *function,
sd_bus_error *error);
#define mac_selinux_access_check(message, permission, error) \ #define mac_selinux_access_check(message, permission, error) \
mac_selinux_generic_access_check((message), NULL, (permission), (error)) mac_selinux_access_check_internal((message), NULL, (permission), __func__, (error))
#define mac_selinux_unit_access_check(unit, message, permission, error) \ #define mac_selinux_unit_access_check(unit, message, permission, error) \
mac_selinux_generic_access_check((message), unit_label_path(unit), (permission), (error)) mac_selinux_access_check_internal((message), unit_label_path(unit), (permission), __func__, (error))

View File

@ -15,14 +15,14 @@
typedef struct MapField { typedef struct MapField {
const char *audit_field; const char *audit_field;
const char *journal_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; } MapField;
static int map_simple_field( static int map_simple_field(
const char *field, const char *field,
const char **p, const char **p,
struct iovec **iov, struct iovec *iovec,
size_t *n_iov) { size_t *n) {
_cleanup_free_ char *c = NULL; _cleanup_free_ char *c = NULL;
size_t l = 0; size_t l = 0;
@ -30,8 +30,8 @@ static int map_simple_field(
assert(field); assert(field);
assert(p); assert(p);
assert(iov); assert(iovec);
assert(n_iov); assert(n);
l = strlen(field); l = strlen(field);
c = malloc(l + 1); c = malloc(l + 1);
@ -48,10 +48,7 @@ static int map_simple_field(
c[l] = 0; c[l] = 0;
if (!GREEDY_REALLOC(*iov, *n_iov + 1)) iovec[(*n)++] = IOVEC_MAKE(c, l);
return -ENOMEM;
(*iov)[(*n_iov)++] = IOVEC_MAKE(c, l);
*p = e; *p = e;
c = NULL; c = NULL;
@ -62,8 +59,8 @@ static int map_simple_field(
static int map_string_field_internal( static int map_string_field_internal(
const char *field, const char *field,
const char **p, const char **p,
struct iovec **iov, struct iovec *iovec,
size_t *n_iov, size_t *n,
bool filter_printable) { bool filter_printable) {
_cleanup_free_ char *c = NULL; _cleanup_free_ char *c = NULL;
@ -72,8 +69,8 @@ static int map_string_field_internal(
assert(field); assert(field);
assert(p); assert(p);
assert(iov); assert(iovec);
assert(n_iov); assert(n);
/* The kernel formats string fields in one of two formats. */ /* The kernel formats string fields in one of two formats. */
@ -128,10 +125,7 @@ static int map_string_field_internal(
} else } else
return 0; return 0;
if (!GREEDY_REALLOC(*iov, *n_iov + 1)) iovec[(*n)++] = IOVEC_MAKE(c, l);
return -ENOMEM;
(*iov)[(*n_iov)++] = IOVEC_MAKE(c, l);
*p = e; *p = e;
c = NULL; c = NULL;
@ -139,19 +133,19 @@ static int map_string_field_internal(
return 1; return 1;
} }
static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov) { static int map_string_field(const char *field, const char **p, struct iovec *iovec, size_t *n) {
return map_string_field_internal(field, p, iov, n_iov, false); 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) { 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, iov, n_iov, true); return map_string_field_internal(field, p, iovec, n, true);
} }
static int map_generic_field( static int map_generic_field(
const char *prefix, const char *prefix,
const char **p, const char **p,
struct iovec **iov, struct iovec *iovec,
size_t *n_iov) { size_t *n) {
const char *e, *f; const char *e, *f;
char *c, *t; char *c, *t;
@ -196,7 +190,7 @@ static int map_generic_field(
e++; e++;
r = map_simple_field(c, &e, iov, n_iov); r = map_simple_field(c, &e, iovec, n);
if (r < 0) if (r < 0)
return r; return r;
@ -255,20 +249,28 @@ static int map_all_fields(
const MapField map_fields[], const MapField map_fields[],
const char *prefix, const char *prefix,
bool handle_msg, bool handle_msg,
struct iovec **iov, struct iovec *iovec,
size_t *n_iov) { size_t *n,
size_t m) {
int r; int r;
assert(p); assert(p);
assert(iov); assert(iovec);
assert(n_iov); assert(n);
for (;;) { for (;;) {
bool mapped = false; bool mapped = false;
const MapField *m; const MapField *mf;
const char *v; 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); p += strspn(p, WHITESPACE);
if (*p == 0) if (*p == 0)
@ -296,17 +298,17 @@ static int map_all_fields(
if (!c) if (!c)
return -ENOMEM; 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 */ /* Try to map the kernel fields to our own names */
for (m = map_fields; m->audit_field; m++) { for (mf = map_fields; mf->audit_field; mf++) {
v = startswith(p, m->audit_field); v = startswith(p, mf->audit_field);
if (!v) if (!v)
continue; continue;
r = m->map(m->journal_field, &v, iov, n_iov); r = mf->map(mf->journal_field, &v, iovec, n);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to parse audit array: %m"); return log_debug_errno(r, "Failed to parse audit array: %m");
@ -318,7 +320,7 @@ static int map_all_fields(
} }
if (!mapped) { if (!mapped) {
r = map_generic_field(prefix, &p, iov, n_iov); r = map_generic_field(prefix, &p, iovec, n);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to parse audit array: %m"); 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) { void process_audit_string(Server *s, int type, const char *data, size_t size) {
size_t n_iov = 0, z; size_t n = 0, z;
_cleanup_free_ struct iovec *iov = NULL;
uint64_t seconds, msec, id; uint64_t seconds, msec, id;
const char *p, *type_name; const char *p, *type_name;
char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)], char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)],
type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)], type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)],
source_time_field[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)]; 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; char *m, *type_field_name;
int k; int k;
@ -371,53 +373,41 @@ void process_audit_string(Server *s, int type, const char *data, size_t size) {
if (isempty(p)) if (isempty(p))
return; return;
iov = new(struct iovec, N_IOVEC_META_FIELDS + 8); iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=audit");
if (!iov) {
log_oom();
return;
}
iov[n_iov++] = IOVEC_MAKE_STRING("_TRANSPORT=audit");
sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64, sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64,
(usec_t) seconds * USEC_PER_SEC + (usec_t) msec * USEC_PER_MSEC); (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); 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); 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)); assert_cc(4 == LOG_FAC(LOG_AUTH));
iov[n_iov++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=4"); iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=4");
iov[n_iov++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=audit"); iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=audit");
type_name = audit_type_name_alloca(type); type_name = audit_type_name_alloca(type);
type_field_name = strjoina("_AUDIT_TYPE_NAME=", type_name); 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); 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)) { server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, LOG_NOTICE, 0);
log_oom();
goto finish;
}
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 /* free() all entries that map_all_fields() added. All others
* are allocated on the stack or are constant. */ * are allocated on the stack or are constant. */
for (; z < n_iov; z++) for (; z < n; z++)
free(iov[z].iov_base); free(iovec[z].iov_base);
} }
void server_process_audit_message( void server_process_audit_message(

View File

@ -193,6 +193,9 @@ struct Server {
/* kmsg: Maximum number of extra fields we'll import from udev's devices */ /* kmsg: Maximum number of extra fields we'll import from udev's devices */
#define N_IOVEC_UDEV_FIELDS 32 #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_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); void server_driver_message(Server *s, pid_t object_pid, const char *message_id, const char *format, ...) _sentinel_ _printf_(4,0);

View File

@ -161,23 +161,11 @@ enum {
HEADER_INCOMPATIBLE_KEYED_HASH | \ HEADER_INCOMPATIBLE_KEYED_HASH | \
HEADER_INCOMPATIBLE_COMPRESSED_ZSTD) HEADER_INCOMPATIBLE_COMPRESSED_ZSTD)
#if HAVE_XZ && HAVE_LZ4 && HAVE_ZSTD #define HEADER_INCOMPATIBLE_SUPPORTED \
# define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_ANY ((HAVE_XZ ? HEADER_INCOMPATIBLE_COMPRESSED_XZ : 0) | \
#elif HAVE_XZ && HAVE_LZ4 (HAVE_LZ4 ? HEADER_INCOMPATIBLE_COMPRESSED_LZ4 : 0) | \
# define HEADER_INCOMPATIBLE_SUPPORTED (HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_LZ4|HEADER_INCOMPATIBLE_KEYED_HASH) (HAVE_ZSTD ? HEADER_INCOMPATIBLE_COMPRESSED_ZSTD : 0) | \
#elif HAVE_XZ && HAVE_ZSTD HEADER_INCOMPATIBLE_KEYED_HASH)
# define HEADER_INCOMPATIBLE_SUPPORTED (HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_ZSTD|HEADER_INCOMPATIBLE_KEYED_HASH)
#elif HAVE_LZ4 && HAVE_ZSTD
# define HEADER_INCOMPATIBLE_SUPPORTED (HEADER_INCOMPATIBLE_COMPRESSED_LZ4|HEADER_INCOMPATIBLE_COMPRESSED_ZSTD|HEADER_INCOMPATIBLE_KEYED_HASH)
#elif HAVE_XZ
# define HEADER_INCOMPATIBLE_SUPPORTED (HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_KEYED_HASH)
#elif HAVE_LZ4
# define HEADER_INCOMPATIBLE_SUPPORTED (HEADER_INCOMPATIBLE_COMPRESSED_LZ4|HEADER_INCOMPATIBLE_KEYED_HASH)
#elif HAVE_ZSTD
# define HEADER_INCOMPATIBLE_SUPPORTED (HEADER_INCOMPATIBLE_COMPRESSED_ZSTD|HEADER_INCOMPATIBLE_KEYED_HASH)
#else
# define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_KEYED_HASH
#endif
enum { enum {
HEADER_COMPATIBLE_SEALED = 1 << 0, HEADER_COMPATIBLE_SEALED = 1 << 0,

View File

@ -30,6 +30,7 @@
#include "set.h" #include "set.h"
#include "sort-util.h" #include "sort-util.h"
#include "stat-util.h" #include "stat-util.h"
#include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "sync-util.h" #include "sync-util.h"
@ -497,7 +498,7 @@ static bool warn_wrong_flags(const JournalFile *f, bool compatible) {
flags = (flags & any) & ~supported; flags = (flags & any) & ~supported;
if (flags) { if (flags) {
const char* strv[5]; const char* strv[5];
unsigned n = 0; size_t n = 0;
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
if (compatible) { if (compatible) {
@ -2148,7 +2149,7 @@ int journal_file_append_entry(
items = newa(EntryItem, n_iovec); items = newa(EntryItem, n_iovec);
for (unsigned i = 0; i < n_iovec; i++) { for (size_t i = 0; i < n_iovec; i++) {
uint64_t p; uint64_t p;
Object *o; Object *o;
@ -2170,8 +2171,10 @@ int journal_file_append_entry(
else else
xor_hash ^= le64toh(o->data.hash); xor_hash ^= le64toh(o->data.hash);
items[i].object_offset = htole64(p); items[i] = (EntryItem) {
items[i].hash = o->data.hash; .object_offset = htole64(p),
.hash = o->data.hash,
};
} }
/* Order by the position on disk, in order to improve seek /* Order by the position on disk, in order to improve seek
@ -3204,51 +3207,41 @@ void journal_file_dump(JournalFile *f) {
p = le64toh(READ_NOW(f->header->header_size)); p = le64toh(READ_NOW(f->header->header_size));
while (p != 0) { while (p != 0) {
const char *s;
r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
if (r < 0) if (r < 0)
goto fail; goto fail;
s = journal_object_type_to_string(o->object.type);
switch (o->object.type) { switch (o->object.type) {
case OBJECT_UNUSED:
printf("Type: OBJECT_UNUSED\n");
break;
case OBJECT_DATA:
printf("Type: OBJECT_DATA\n");
break;
case OBJECT_FIELD:
printf("Type: OBJECT_FIELD\n");
break;
case OBJECT_ENTRY: case OBJECT_ENTRY:
printf("Type: OBJECT_ENTRY seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n", assert(s);
printf("Type: %s seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n",
s,
le64toh(o->entry.seqnum), le64toh(o->entry.seqnum),
le64toh(o->entry.monotonic), le64toh(o->entry.monotonic),
le64toh(o->entry.realtime)); le64toh(o->entry.realtime));
break; break;
case OBJECT_FIELD_HASH_TABLE:
printf("Type: OBJECT_FIELD_HASH_TABLE\n");
break;
case OBJECT_DATA_HASH_TABLE:
printf("Type: OBJECT_DATA_HASH_TABLE\n");
break;
case OBJECT_ENTRY_ARRAY:
printf("Type: OBJECT_ENTRY_ARRAY\n");
break;
case OBJECT_TAG: case OBJECT_TAG:
printf("Type: OBJECT_TAG seqnum=%"PRIu64" epoch=%"PRIu64"\n", assert(s);
printf("Type: %s seqnum=%"PRIu64" epoch=%"PRIu64"\n",
s,
le64toh(o->tag.seqnum), le64toh(o->tag.seqnum),
le64toh(o->tag.epoch)); le64toh(o->tag.epoch));
break; break;
default: default:
printf("Type: unknown (%i)\n", o->object.type); if (s)
printf("Type: %s \n", s);
else
printf("Type: unknown (%i)", o->object.type);
break; break;
} }
@ -3867,8 +3860,10 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
if (!to->writable) if (!to->writable)
return -EPERM; return -EPERM;
ts.monotonic = le64toh(o->entry.monotonic); ts = (dual_timestamp) {
ts.realtime = le64toh(o->entry.realtime); .monotonic = le64toh(o->entry.monotonic),
.realtime = le64toh(o->entry.realtime),
};
boot_id = &o->entry.boot_id; boot_id = &o->entry.boot_id;
n = journal_file_entry_n_items(o); n = journal_file_entry_n_items(o);
@ -3931,8 +3926,10 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
else else
xor_hash ^= le64toh(u->data.hash); xor_hash ^= le64toh(u->data.hash);
items[i].object_offset = htole64(h); items[i] = (EntryItem) {
items[i].hash = u->data.hash; .object_offset = htole64(h),
.hash = u->data.hash,
};
r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o); r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o);
if (r < 0) if (r < 0)
@ -4189,3 +4186,16 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log
return false; return false;
} }
static const char * const journal_object_type_table[] = {
[OBJECT_UNUSED] = "unused",
[OBJECT_DATA] = "data",
[OBJECT_FIELD] = "field",
[OBJECT_ENTRY] = "entry",
[OBJECT_DATA_HASH_TABLE] = "data hash table",
[OBJECT_FIELD_HASH_TABLE] = "field hash table",
[OBJECT_ENTRY_ARRAY] = "entry array",
[OBJECT_TAG] = "tag",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(journal_object_type, ObjectType);

View File

@ -272,3 +272,5 @@ static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) {
uint64_t journal_file_hash_data(JournalFile *f, const void *data, size_t sz); uint64_t journal_file_hash_data(JournalFile *f, const void *data, size_t sz);
bool journal_field_valid(const char *p, size_t l, bool allow_protected); bool journal_field_valid(const char *p, size_t l, bool allow_protected);
const char* journal_object_type_to_string(ObjectType type) _const_;

View File

@ -591,7 +591,7 @@ static int verify_data(
return 0; return 0;
} }
static int verify_hash_table( static int verify_data_hash_table(
JournalFile *f, JournalFile *f,
MMapFileDescriptor *cache_data_fd, uint64_t n_data, MMapFileDescriptor *cache_data_fd, uint64_t n_data,
MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
@ -824,6 +824,43 @@ static int verify_entry_array(
return 0; return 0;
} }
static int verify_hash_table(
Object *o, uint64_t p, uint64_t *n_hash_tables, uint64_t header_offset, uint64_t header_size) {
assert(o);
assert(n_hash_tables);
if (*n_hash_tables > 1) {
error(p,
"More than one %s: %" PRIu64,
journal_object_type_to_string(o->object.type),
*n_hash_tables);
return -EBADMSG;
}
if (header_offset != p + offsetof(HashTableObject, items)) {
error(p,
"Header offset for %s invalid (%" PRIu64 " != %" PRIu64 ")",
journal_object_type_to_string(o->object.type),
header_offset,
p + offsetof(HashTableObject, items));
return -EBADMSG;
}
if (header_size != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
error(p,
"Header size for %s invalid (%" PRIu64 " != %" PRIu64 ")",
journal_object_type_to_string(o->object.type),
header_size,
le64toh(o->object.size) - offsetof(HashTableObject, items));
return -EBADMSG;
}
(*n_hash_tables)++;
return 0;
}
int journal_file_verify( int journal_file_verify(
JournalFile *f, JournalFile *f,
const char *key, const char *key,
@ -1069,37 +1106,20 @@ int journal_file_verify(
break; break;
case OBJECT_DATA_HASH_TABLE: case OBJECT_DATA_HASH_TABLE:
if (n_data_hash_tables > 1) { r = verify_hash_table(o, p, &n_data_hash_tables,
error(p, "More than one data hash table"); le64toh(f->header->data_hash_table_offset),
r = -EBADMSG; le64toh(f->header->data_hash_table_size));
if (r < 0)
goto fail; goto fail;
}
if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) ||
le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
error(p, "header fields for data hash table invalid");
r = -EBADMSG;
goto fail;
}
n_data_hash_tables++;
break; break;
case OBJECT_FIELD_HASH_TABLE: case OBJECT_FIELD_HASH_TABLE:
if (n_field_hash_tables > 1) { r = verify_hash_table(o, p, &n_field_hash_tables,
error(p, "More than one field hash table"); le64toh(f->header->field_hash_table_offset),
r = -EBADMSG; le64toh(f->header->field_hash_table_size));
if (r < 0)
goto fail; goto fail;
}
if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
error(p, "Header fields for field hash table invalid");
r = -EBADMSG;
goto fail;
}
n_field_hash_tables++;
break; break;
case OBJECT_ENTRY_ARRAY: case OBJECT_ENTRY_ARRAY:
@ -1325,7 +1345,7 @@ int journal_file_verify(
if (r < 0) if (r < 0)
goto fail; goto fail;
r = verify_hash_table(f, r = verify_data_hash_table(f,
cache_data_fd, n_data, cache_data_fd, n_data,
cache_entry_fd, n_entries, cache_entry_fd, n_entries,
cache_entry_array_fd, n_entry_arrays, cache_entry_array_fd, n_entry_arrays,

View File

@ -3513,6 +3513,7 @@ static int inner_child(
(void) fdset_close_others(fds); (void) fdset_close_others(fds);
if (arg_start_mode == START_BOOT) { if (arg_start_mode == START_BOOT) {
const char *init;
char **a; char **a;
size_t m; size_t m;
@ -3523,14 +3524,13 @@ static int inner_child(
memcpy_safe(a + 1, arg_parameters, m * sizeof(char*)); memcpy_safe(a + 1, arg_parameters, m * sizeof(char*));
a[1 + m] = NULL; a[1 + m] = NULL;
a[0] = (char*) "/usr/lib/systemd/systemd"; FOREACH_STRING(init,
execve(a[0], a, env_use); "/usr/lib/systemd/systemd",
"/lib/systemd/systemd",
a[0] = (char*) "/lib/systemd/systemd"; "/sbin/init") {
execve(a[0], a, env_use); a[0] = (char*) init;
a[0] = (char*) "/sbin/init";
execve(a[0], a, env_use); execve(a[0], a, env_use);
}
exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init"; exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init";
} else if (!strv_isempty(arg_parameters)) { } else if (!strv_isempty(arg_parameters)) {