mirror of
https://github.com/systemd/systemd
synced 2026-04-07 23:54:50 +02:00
Compare commits
15 Commits
1ccfb792e4
...
289a42304d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
289a42304d | ||
|
|
26bae8109d | ||
|
|
a50966416e | ||
|
|
7e570d575f | ||
|
|
963438a027 | ||
|
|
6fbb33f631 | ||
|
|
f0804759cf | ||
|
|
66e2bb282b | ||
|
|
368a14b67b | ||
|
|
363b2b9aaf | ||
|
|
b92d1eba31 | ||
|
|
d164ac771e | ||
|
|
86e68f3814 | ||
|
|
ceb4192df6 | ||
|
|
4cdb970b5b |
@ -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",
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user