1
0
mirror of https://github.com/systemd/systemd synced 2026-04-07 23:54:50 +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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
@ -941,49 +941,49 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_start,
bus_unit_method_start,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Stop",
"s",
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_stop,
bus_unit_method_stop,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Reload",
"s",
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_reload,
bus_unit_method_reload,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("Restart",
"s",
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_restart,
bus_unit_method_restart,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("TryRestart",
"s",
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_try_restart,
bus_unit_method_try_restart,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ReloadOrRestart",
"s",
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_reload_or_restart,
bus_unit_method_reload_or_restart,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("ReloadOrTryRestart",
"s",
SD_BUS_PARAM(mode),
"o",
SD_BUS_PARAM(job),
method_reload_or_try_restart,
bus_unit_method_reload_or_try_restart,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("EnqueueJob",
"ss",

View File

@ -31,6 +31,7 @@ struct audit_info {
sd_bus_creds *creds;
const char *path;
const char *cmdline;
const char *function;
};
/*
@ -58,10 +59,11 @@ static int audit_callback(
xsprintf(gid_buf, GID_FMT, gid);
(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,
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;
}
@ -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
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,
const char *path,
const char *permission,
const char *function,
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
@ -191,6 +194,7 @@ int mac_selinux_generic_access_check(
assert(message);
assert(permission);
assert(function);
assert(error);
r = access_init(error);
@ -263,6 +267,7 @@ int mac_selinux_generic_access_check(
.creds = creds,
.path = path,
.cmdline = cl,
.function = function,
};
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,
"SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s path=%s cmdline=%s: %m",
scon, fcon, tclass, permission, enforce ? "enforcing" : "permissive", path, cl);
"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", function, strna(path), isempty(cl) ? "n/a" : cl);
return enforce ? r : 0;
}
#else /* HAVE_SELINUX */
int mac_selinux_generic_access_check(
int mac_selinux_access_check_internal(
sd_bus_message *message,
const char *path,
const char *permission,
const char *function,
sd_bus_error *error) {
return 0;

View File

@ -5,10 +5,14 @@
#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) \
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) \
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 {
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(

View File

@ -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);

View File

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

View File

@ -30,6 +30,7 @@
#include "set.h"
#include "sort-util.h"
#include "stat-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "sync-util.h"
@ -497,7 +498,7 @@ static bool warn_wrong_flags(const JournalFile *f, bool compatible) {
flags = (flags & any) & ~supported;
if (flags) {
const char* strv[5];
unsigned n = 0;
size_t n = 0;
_cleanup_free_ char *t = NULL;
if (compatible) {
@ -2148,7 +2149,7 @@ int journal_file_append_entry(
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;
Object *o;
@ -2170,8 +2171,10 @@ int journal_file_append_entry(
else
xor_hash ^= le64toh(o->data.hash);
items[i].object_offset = htole64(p);
items[i].hash = o->data.hash;
items[i] = (EntryItem) {
.object_offset = htole64(p),
.hash = o->data.hash,
};
}
/* 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));
while (p != 0) {
const char *s;
r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
if (r < 0)
goto fail;
s = journal_object_type_to_string(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:
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.monotonic),
le64toh(o->entry.realtime));
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:
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.epoch));
break;
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;
}
@ -3867,8 +3860,10 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
if (!to->writable)
return -EPERM;
ts.monotonic = le64toh(o->entry.monotonic);
ts.realtime = le64toh(o->entry.realtime);
ts = (dual_timestamp) {
.monotonic = le64toh(o->entry.monotonic),
.realtime = le64toh(o->entry.realtime),
};
boot_id = &o->entry.boot_id;
n = journal_file_entry_n_items(o);
@ -3931,8 +3926,10 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
else
xor_hash ^= le64toh(u->data.hash);
items[i].object_offset = htole64(h);
items[i].hash = u->data.hash;
items[i] = (EntryItem) {
.object_offset = htole64(h),
.hash = u->data.hash,
};
r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o);
if (r < 0)
@ -4189,3 +4186,16 @@ bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec, int log
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);
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;
}
static int verify_hash_table(
static int verify_data_hash_table(
JournalFile *f,
MMapFileDescriptor *cache_data_fd, uint64_t n_data,
MMapFileDescriptor *cache_entry_fd, uint64_t n_entries,
@ -824,6 +824,43 @@ static int verify_entry_array(
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(
JournalFile *f,
const char *key,
@ -1069,37 +1106,20 @@ int journal_file_verify(
break;
case OBJECT_DATA_HASH_TABLE:
if (n_data_hash_tables > 1) {
error(p, "More than one data hash table");
r = -EBADMSG;
r = verify_hash_table(o, p, &n_data_hash_tables,
le64toh(f->header->data_hash_table_offset),
le64toh(f->header->data_hash_table_size));
if (r < 0)
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;
case OBJECT_FIELD_HASH_TABLE:
if (n_field_hash_tables > 1) {
error(p, "More than one field hash table");
r = -EBADMSG;
r = verify_hash_table(o, p, &n_field_hash_tables,
le64toh(f->header->field_hash_table_offset),
le64toh(f->header->field_hash_table_size));
if (r < 0)
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;
case OBJECT_ENTRY_ARRAY:
@ -1325,12 +1345,12 @@ int journal_file_verify(
if (r < 0)
goto fail;
r = verify_hash_table(f,
cache_data_fd, n_data,
cache_entry_fd, n_entries,
cache_entry_array_fd, n_entry_arrays,
&last_usec,
show_progress);
r = verify_data_hash_table(f,
cache_data_fd, n_data,
cache_entry_fd, n_entries,
cache_entry_array_fd, n_entry_arrays,
&last_usec,
show_progress);
if (r < 0)
goto fail;

View File

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