X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fjournal%2Fjournald-server.c;h=db6ca37d798e530962926c0688190f06d97ad7d9;hb=349cc4a507c4d84fcadf61f42159ea6412717896;hp=f391845ba9a9dc022cb02ddbbb54831841bc298a;hpb=52b1478414067eb9381b413408f920da7f162c6f;p=thirdparty%2Fsystemd.git
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index f391845ba9a..db6ca37d798 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -17,7 +17,7 @@
along with systemd; If not, see .
***/
-#ifdef HAVE_SELINUX
+#if HAVE_SELINUX
#include
#endif
#include
@@ -51,6 +51,7 @@
#include "journal-internal.h"
#include "journal-vacuum.h"
#include "journald-audit.h"
+#include "journald-context.h"
#include "journald-kmsg.h"
#include "journald-native.h"
#include "journald-rate-limit.h"
@@ -70,8 +71,8 @@
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
-#include "user-util.h"
#include "syslog-util.h"
+#include "user-util.h"
#define USER_JOURNALS_MAX 1024
@@ -87,6 +88,10 @@
/* The period to insert between posting changes for coalescing */
#define POST_CHANGE_TIMER_INTERVAL_USEC (250*USEC_PER_MSEC)
+/* Pick a good default that is likely to fit into AF_UNIX and AF_INET SOCK_DGRAM datagrams, and even leaves some room
+ * for a bit of additional metadata. */
+#define DEFAULT_LINE_MAX (48*1024)
+
static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, uint64_t *ret_free) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
@@ -235,12 +240,12 @@ void server_space_usage_message(Server *s, JournalStorage *storage) {
}
static void server_add_acls(JournalFile *f, uid_t uid) {
-#ifdef HAVE_ACL
+#if HAVE_ACL
int r;
#endif
assert(f);
-#ifdef HAVE_ACL
+#if HAVE_ACL
if (uid <= SYSTEM_UID_MAX)
return;
@@ -714,354 +719,140 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
server_schedule_sync(s, priority);
}
-static int get_invocation_id(const char *cgroup_root, const char *slice, const char *unit, char **ret) {
- _cleanup_free_ char *escaped = NULL, *slice_path = NULL, *p = NULL;
- char *copy, ids[SD_ID128_STRING_MAX];
- int r;
-
- /* Read the invocation ID of a unit off a unit. It's stored in the "trusted.invocation_id" extended attribute
- * on the cgroup path. */
-
- r = cg_slice_to_path(slice, &slice_path);
- if (r < 0)
- return r;
-
- escaped = cg_escape(unit);
- if (!escaped)
- return -ENOMEM;
-
- p = strjoin(cgroup_root, "/", slice_path, "/", escaped);
- if (!p)
- return -ENOMEM;
-
- r = cg_get_xattr(SYSTEMD_CGROUP_CONTROLLER, p, "trusted.invocation_id", ids, 32);
- if (r < 0)
- return r;
- if (r != 32)
- return -EINVAL;
- ids[32] = 0;
+#define IOVEC_ADD_NUMERIC_FIELD(iovec, n, value, type, isset, format, field) \
+ if (isset(value)) { \
+ char *k; \
+ k = newa(char, strlen(field "=") + DECIMAL_STR_MAX(type) + 1); \
+ sprintf(k, field "=" format, value); \
+ iovec[n++] = IOVEC_MAKE_STRING(k); \
+ }
- if (!id128_is_valid(ids))
- return -EINVAL;
+#define IOVEC_ADD_STRING_FIELD(iovec, n, value, field) \
+ if (!isempty(value)) { \
+ char *k; \
+ k = strjoina(field "=", value); \
+ iovec[n++] = IOVEC_MAKE_STRING(k); \
+ }
- copy = strdup(ids);
- if (!copy)
- return -ENOMEM;
+#define IOVEC_ADD_ID128_FIELD(iovec, n, value, field) \
+ if (!sd_id128_is_null(value)) { \
+ char *k; \
+ k = newa(char, strlen(field "=") + SD_ID128_STRING_MAX); \
+ sd_id128_to_string(value, stpcpy(k, field "=")); \
+ iovec[n++] = IOVEC_MAKE_STRING(k); \
+ }
- *ret = copy;
- return 0;
-}
+#define IOVEC_ADD_SIZED_FIELD(iovec, n, value, value_size, field) \
+ if (value_size > 0) { \
+ char *k; \
+ k = newa(char, strlen(field "=") + value_size + 1); \
+ *((char*) mempcpy(stpcpy(k, field "="), value, value_size)) = 0; \
+ iovec[n++] = IOVEC_MAKE_STRING(k); \
+ } \
static void dispatch_message_real(
Server *s,
struct iovec *iovec, unsigned n, unsigned m,
- const struct ucred *ucred,
+ const ClientContext *c,
const struct timeval *tv,
- const char *label, size_t label_len,
- const char *unit_id,
int priority,
- pid_t object_pid,
- char *cgroup) {
-
- char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
- uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)],
- gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
- owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
- source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
- o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
- o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
- o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
- uid_t object_uid;
- gid_t object_gid;
- char *x;
- int r;
- char *t, *c;
- uid_t realuid = 0, owner = 0, journal_uid;
- bool owner_valid = false;
-#ifdef HAVE_AUDIT
- char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
- audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)],
- o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
- o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
-
- uint32_t audit;
- uid_t loginuid;
-#endif
+ pid_t object_pid) {
+
+ char source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)];
+ uid_t journal_uid;
+ ClientContext *o;
assert(s);
assert(iovec);
assert(n > 0);
- assert(n + N_IOVEC_META_FIELDS + (object_pid > 0 ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
-
- if (ucred) {
- realuid = ucred->uid;
-
- sprintf(pid, "_PID="PID_FMT, ucred->pid);
- IOVEC_SET_STRING(iovec[n++], pid);
-
- sprintf(uid, "_UID="UID_FMT, ucred->uid);
- IOVEC_SET_STRING(iovec[n++], uid);
-
- sprintf(gid, "_GID="GID_FMT, ucred->gid);
- IOVEC_SET_STRING(iovec[n++], gid);
-
- r = get_process_comm(ucred->pid, &t);
- if (r >= 0) {
- x = strjoina("_COMM=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- r = get_process_exe(ucred->pid, &t);
- if (r >= 0) {
- x = strjoina("_EXE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- r = get_process_cmdline(ucred->pid, 0, false, &t);
- if (r >= 0) {
- x = strjoina("_CMDLINE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- r = get_process_capeff(ucred->pid, &t);
- if (r >= 0) {
- x = strjoina("_CAP_EFFECTIVE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
-#ifdef HAVE_AUDIT
- r = audit_session_from_pid(ucred->pid, &audit);
- if (r >= 0) {
- sprintf(audit_session, "_AUDIT_SESSION=%"PRIu32, audit);
- IOVEC_SET_STRING(iovec[n++], audit_session);
- }
-
- r = audit_loginuid_from_pid(ucred->pid, &loginuid);
- if (r >= 0) {
- sprintf(audit_loginuid, "_AUDIT_LOGINUID="UID_FMT, loginuid);
- IOVEC_SET_STRING(iovec[n++], audit_loginuid);
- }
-#endif
-
- r = 0;
- if (cgroup)
- c = cgroup;
- else
- r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
-
- if (r >= 0) {
- _cleanup_free_ char *raw_unit = NULL, *raw_slice = NULL;
- char *session = NULL;
-
- x = strjoina("_SYSTEMD_CGROUP=", c);
- IOVEC_SET_STRING(iovec[n++], x);
-
- r = cg_path_get_session(c, &t);
- if (r >= 0) {
- session = strjoina("_SYSTEMD_SESSION=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], session);
- }
-
- if (cg_path_get_owner_uid(c, &owner) >= 0) {
- owner_valid = true;
-
- sprintf(owner_uid, "_SYSTEMD_OWNER_UID="UID_FMT, owner);
- IOVEC_SET_STRING(iovec[n++], owner_uid);
- }
-
- if (cg_path_get_unit(c, &raw_unit) >= 0) {
- x = strjoina("_SYSTEMD_UNIT=", raw_unit);
- IOVEC_SET_STRING(iovec[n++], x);
- } else if (unit_id && !session) {
- x = strjoina("_SYSTEMD_UNIT=", unit_id);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- if (cg_path_get_user_unit(c, &t) >= 0) {
- x = strjoina("_SYSTEMD_USER_UNIT=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- } else if (unit_id && session) {
- x = strjoina("_SYSTEMD_USER_UNIT=", unit_id);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- if (cg_path_get_slice(c, &raw_slice) >= 0) {
- x = strjoina("_SYSTEMD_SLICE=", raw_slice);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- if (cg_path_get_user_slice(c, &t) >= 0) {
- x = strjoina("_SYSTEMD_USER_SLICE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ assert(n + N_IOVEC_META_FIELDS + (pid_is_valid(object_pid) ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
- if (raw_slice && raw_unit) {
- if (get_invocation_id(s->cgroup_root, raw_slice, raw_unit, &t) >= 0) {
- x = strjoina("_SYSTEMD_INVOCATION_ID=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
- }
+ if (c) {
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->pid, pid_t, pid_is_valid, PID_FMT, "_PID");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->uid, uid_t, uid_is_valid, UID_FMT, "_UID");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->gid, gid_t, gid_is_valid, GID_FMT, "_GID");
- if (!cgroup)
- free(c);
- } else if (unit_id) {
- x = strjoina("_SYSTEMD_UNIT=", unit_id);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->comm, "_COMM");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->exe, "_EXE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->cmdline, "_CMDLINE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE");
-#ifdef HAVE_SELINUX
- if (mac_selinux_use()) {
- if (label) {
- x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
+ IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT");
- *((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
- IOVEC_SET_STRING(iovec[n++], x);
- } else {
- char *con;
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "_AUDIT_SESSION");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->loginuid, uid_t, uid_is_valid, UID_FMT, "_AUDIT_LOGINUID");
- if (getpidcon(ucred->pid, &con) >= 0) {
- x = strjoina("_SELINUX_CONTEXT=", con);
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->cgroup, "_SYSTEMD_CGROUP");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->session, "_SYSTEMD_SESSION");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->owner_uid, uid_t, uid_is_valid, UID_FMT, "_SYSTEMD_OWNER_UID");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->unit, "_SYSTEMD_UNIT");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->user_unit, "_SYSTEMD_USER_UNIT");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->slice, "_SYSTEMD_SLICE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, c->user_slice, "_SYSTEMD_USER_SLICE");
- freecon(con);
- IOVEC_SET_STRING(iovec[n++], x);
- }
- }
- }
-#endif
+ IOVEC_ADD_ID128_FIELD(iovec, n, c->invocation_id, "_SYSTEMD_INVOCATION_ID");
}
- assert(n <= m);
-
- if (object_pid) {
- r = get_process_uid(object_pid, &object_uid);
- if (r >= 0) {
- sprintf(o_uid, "OBJECT_UID="UID_FMT, object_uid);
- IOVEC_SET_STRING(iovec[n++], o_uid);
- }
-
- r = get_process_gid(object_pid, &object_gid);
- if (r >= 0) {
- sprintf(o_gid, "OBJECT_GID="GID_FMT, object_gid);
- IOVEC_SET_STRING(iovec[n++], o_gid);
- }
-
- r = get_process_comm(object_pid, &t);
- if (r >= 0) {
- x = strjoina("OBJECT_COMM=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- r = get_process_exe(object_pid, &t);
- if (r >= 0) {
- x = strjoina("OBJECT_EXE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-
- r = get_process_cmdline(object_pid, 0, false, &t);
- if (r >= 0) {
- x = strjoina("OBJECT_CMDLINE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
-#ifdef HAVE_AUDIT
- r = audit_session_from_pid(object_pid, &audit);
- if (r >= 0) {
- sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%"PRIu32, audit);
- IOVEC_SET_STRING(iovec[n++], o_audit_session);
- }
-
- r = audit_loginuid_from_pid(object_pid, &loginuid);
- if (r >= 0) {
- sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID="UID_FMT, loginuid);
- IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
- }
-#endif
+ assert(n <= m);
- r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
- if (r >= 0) {
- x = strjoina("OBJECT_SYSTEMD_CGROUP=", c);
- IOVEC_SET_STRING(iovec[n++], x);
-
- r = cg_path_get_session(c, &t);
- if (r >= 0) {
- x = strjoina("OBJECT_SYSTEMD_SESSION=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ if (pid_is_valid(object_pid) && client_context_get(s, object_pid, NULL, NULL, 0, NULL, &o) >= 0) {
- if (cg_path_get_owner_uid(c, &owner) >= 0) {
- sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID="UID_FMT, owner);
- IOVEC_SET_STRING(iovec[n++], o_owner_uid);
- }
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->pid, pid_t, pid_is_valid, PID_FMT, "OBJECT_PID");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_UID");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->gid, gid_t, gid_is_valid, GID_FMT, "OBJECT_GID");
- if (cg_path_get_unit(c, &t) >= 0) {
- x = strjoina("OBJECT_SYSTEMD_UNIT=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->comm, "OBJECT_COMM");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->exe, "OBJECT_EXE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->cmdline, "OBJECT_CMDLINE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE");
- if (cg_path_get_user_unit(c, &t) >= 0) {
- x = strjoina("OBJECT_SYSTEMD_USER_UNIT=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ IOVEC_ADD_SIZED_FIELD(iovec, n, o->label, o->label_size, "OBJECT_SELINUX_CONTEXT");
- if (cg_path_get_slice(c, &t) >= 0) {
- x = strjoina("OBJECT_SYSTEMD_SLICE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "OBJECT_AUDIT_SESSION");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->loginuid, uid_t, uid_is_valid, UID_FMT, "OBJECT_AUDIT_LOGINUID");
- if (cg_path_get_user_slice(c, &t) >= 0) {
- x = strjoina("OBJECT_SYSTEMD_USER_SLICE=", t);
- free(t);
- IOVEC_SET_STRING(iovec[n++], x);
- }
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->cgroup, "OBJECT_SYSTEMD_CGROUP");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->session, "OBJECT_SYSTEMD_SESSION");
+ IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->owner_uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_SYSTEMD_OWNER_UID");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->unit, "OBJECT_SYSTEMD_UNIT");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->user_unit, "OBJECT_SYSTEMD_USER_UNIT");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->slice, "OBJECT_SYSTEMD_SLICE");
+ IOVEC_ADD_STRING_FIELD(iovec, n, o->user_slice, "OBJECT_SYSTEMD_USER_SLICE");
- free(c);
- }
+ IOVEC_ADD_ID128_FIELD(iovec, n, o->invocation_id, "OBJECT_SYSTEMD_INVOCATION_ID=");
}
+
assert(n <= m);
if (tv) {
sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=" USEC_FMT, timeval_load(tv));
- IOVEC_SET_STRING(iovec[n++], source_time);
+ iovec[n++] = IOVEC_MAKE_STRING(source_time);
}
/* Note that strictly speaking storing the boot id here is
* redundant since the entry includes this in-line
* anyway. However, we need this indexed, too. */
if (!isempty(s->boot_id_field))
- IOVEC_SET_STRING(iovec[n++], s->boot_id_field);
+ iovec[n++] = IOVEC_MAKE_STRING(s->boot_id_field);
if (!isempty(s->machine_id_field))
- IOVEC_SET_STRING(iovec[n++], s->machine_id_field);
+ iovec[n++] = IOVEC_MAKE_STRING(s->machine_id_field);
if (!isempty(s->hostname_field))
- IOVEC_SET_STRING(iovec[n++], s->hostname_field);
+ iovec[n++] = IOVEC_MAKE_STRING(s->hostname_field);
assert(n <= m);
- if (s->split_mode == SPLIT_UID && realuid > 0)
- /* Split up strictly by any UID */
- journal_uid = realuid;
- else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0)
+ if (s->split_mode == SPLIT_UID && c && uid_is_valid(c->uid))
+ /* Split up strictly by (non-root) UID */
+ journal_uid = c->uid;
+ else if (s->split_mode == SPLIT_LOGIN && c && c->uid > 0 && uid_is_valid(c->owner_uid))
/* Split up by login UIDs. We do this only if the
* realuid is not root, in order not to accidentally
* leak privileged information to the user that is
* logged by a privileged process that is part of an
* unprivileged session. */
- journal_uid = owner;
+ journal_uid = c->owner_uid;
else
journal_uid = 0;
@@ -1069,25 +860,25 @@ static void dispatch_message_real(
}
void server_driver_message(Server *s, const char *message_id, const char *format, ...) {
+
struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS];
unsigned n = 0, m;
- int r;
va_list ap;
- struct ucred ucred = {};
+ int r;
assert(s);
assert(format);
assert_cc(3 == LOG_FAC(LOG_DAEMON));
- IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3");
- IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald");
+ iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=3");
+ iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=systemd-journald");
- IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
+ iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=driver");
assert_cc(6 == LOG_INFO);
- IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
+ iovec[n++] = IOVEC_MAKE_STRING("PRIORITY=6");
if (message_id)
- IOVEC_SET_STRING(iovec[n++], message_id);
+ iovec[n++] = IOVEC_MAKE_STRING(message_id);
m = n;
va_start(ap, format);
@@ -1095,12 +886,8 @@ void server_driver_message(Server *s, const char *message_id, const char *format
/* Error handling below */
va_end(ap);
- ucred.pid = getpid_cached();
- ucred.uid = getuid();
- ucred.gid = getgid();
-
if (r >= 0)
- dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0, NULL);
+ dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), s->my_context, NULL, LOG_INFO, 0);
while (m < n)
free(iovec[m++].iov_base);
@@ -1112,26 +899,22 @@ void server_driver_message(Server *s, const char *message_id, const char *format
xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror(-r));
n = 3;
- IOVEC_SET_STRING(iovec[n++], "PRIORITY=4");
- IOVEC_SET_STRING(iovec[n++], buf);
- dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0, NULL);
+ iovec[n++] = IOVEC_MAKE_STRING("PRIORITY=4");
+ iovec[n++] = IOVEC_MAKE_STRING(buf);
+ dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), s->my_context, NULL, LOG_INFO, 0);
}
}
void server_dispatch_message(
Server *s,
struct iovec *iovec, unsigned n, unsigned m,
- const struct ucred *ucred,
+ ClientContext *c,
const struct timeval *tv,
- const char *label, size_t label_len,
- const char *unit_id,
int priority,
pid_t object_pid) {
- int rl, r;
- _cleanup_free_ char *path = NULL;
uint64_t available = 0;
- char *c = NULL;
+ int rl;
assert(s);
assert(iovec || n == 0);
@@ -1147,45 +930,21 @@ void server_dispatch_message(
if (s->storage == STORAGE_NONE)
return;
- if (!ucred)
- goto finish;
+ if (c && c->unit) {
+ (void) determine_space(s, &available, NULL);
- r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &path);
- if (r < 0)
- goto finish;
-
- /* example: /user/lennart/3/foobar
- * /system/dbus.service/foobar
- *
- * So let's cut of everything past the third /, since that is
- * where user directories start */
+ rl = journal_rate_limit_test(s->rate_limit, c->unit, priority & LOG_PRIMASK, available);
+ if (rl == 0)
+ return;
- c = strchr(path, '/');
- if (c) {
- c = strchr(c+1, '/');
- if (c) {
- c = strchr(c+1, '/');
- if (c)
- *c = 0;
- }
+ /* Write a suppression message if we suppressed something */
+ if (rl > 1)
+ server_driver_message(s, "MESSAGE_ID=" SD_MESSAGE_JOURNAL_DROPPED_STR,
+ LOG_MESSAGE("Suppressed %u messages from %s", rl - 1, c->unit),
+ NULL);
}
- (void) determine_space(s, &available, NULL);
- rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available);
- if (rl == 0)
- return;
-
- /* Write a suppression message if we suppressed something */
- if (rl > 1)
- server_driver_message(s, "MESSAGE_ID=" SD_MESSAGE_JOURNAL_DROPPED_STR,
- LOG_MESSAGE("Suppressed %u messages from %s", rl - 1, path),
- NULL);
-
-finish:
- /* restore cgroup path for logging */
- if (c)
- *c = '/';
- dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid, path);
+ dispatch_message_real(s, iovec, n, m, c, tv, priority, object_pid);
}
int server_flush_to_var(Server *s, bool require_flag_file) {
@@ -1335,9 +1094,8 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
return -EIO;
}
- /* Try to get the right size, if we can. (Not all
- * sockets support SIOCINQ, hence we just try, but
- * don't rely on it. */
+ /* Try to get the right size, if we can. (Not all sockets support SIOCINQ, hence we just try, but don't rely on
+ * it.) */
(void) ioctl(fd, SIOCINQ, &v);
/* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
@@ -1353,7 +1111,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
- if (errno == EINTR || errno == EAGAIN)
+ if (IN_SET(errno, EINTR, EAGAIN))
return 0;
return log_error_errno(errno, "recvmsg() failed: %m");
@@ -1935,6 +1693,8 @@ int server_init(Server *s) {
s->max_level_console = LOG_INFO;
s->max_level_wall = LOG_EMERG;
+ s->line_max = DEFAULT_LINE_MAX;
+
journal_reset_metrics(&s->system_storage.metrics);
journal_reset_metrics(&s->runtime_storage.metrics);
@@ -2102,11 +1862,13 @@ int server_init(Server *s) {
(void) server_connect_notify(s);
+ (void) client_context_acquire_default(s);
+
return system_journal_open(s, false);
}
void server_maybe_append_tags(Server *s) {
-#ifdef HAVE_GCRYPT
+#if HAVE_GCRYPT
JournalFile *f;
Iterator i;
usec_t n;
@@ -2133,6 +1895,8 @@ void server_done(Server *s) {
while (s->stdout_streams)
stdout_stream_free(s->stdout_streams);
+ client_context_flush_all(s);
+
if (s->system_journal)
(void) journal_file_close(s->system_journal);
@@ -2205,3 +1969,55 @@ static const char* const split_mode_table[_SPLIT_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
+
+int config_parse_line_max(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ size_t *sz = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue))
+ /* Empty assignment means default */
+ *sz = DEFAULT_LINE_MAX;
+ else {
+ uint64_t v;
+
+ r = parse_size(rvalue, 1024, &v);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (v < 79) {
+ /* Why specify 79 here as minimum line length? Simply, because the most common traditional
+ * terminal size is 80ch, and it might make sense to break one character before the natural
+ * line break would occur on that. */
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too small, clamping to 79: %s", rvalue);
+ *sz = 79;
+ } else if (v > (uint64_t) (SSIZE_MAX-1)) {
+ /* So, why specify SSIZE_MAX-1 here? Because that's one below the largest size value read()
+ * can return, and we need one extra byte for the trailing NUL byte. Of course IRL such large
+ * memory allocations will fail anyway, hence this limit is mostly theoretical anyway, as we'll
+ * fail much earlier anyway. */
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too large, clamping to %" PRIu64 ": %s", (uint64_t) (SSIZE_MAX-1), rvalue);
+ *sz = SSIZE_MAX-1;
+ } else
+ *sz = (size_t) v;
+ }
+
+ return 0;
+}