journald-server.c revision a315ac4e076c4ce7ce3e5c95792cf916d5e918c5
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2011 Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersenstatic const char* const storage_table[_STORAGE_MAX] = {
b44cd8821087f2afebf85fec5b588f5720a9415cTom GundersenDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic const char* const split_mode_table[_SPLIT_MAX] = {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom GundersenDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom GundersenDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic uint64_t available_space(Server *s, bool verbose) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen const char *f;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen p = strappend(f, sd_id128_to_string(machine, ids));
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen /* If we reached a high mark, we will always allow this much
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen * again, unless usage goes above max_use. This watermark
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen * value is cached so that we don't give up space on pressure,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen * but hover below the maximum usage. */
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen s->cached_available_space = LESS_BY(MIN(m->max_use, avail), sum);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "%s journal is using %s (max allowed %s, "
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "trying to leave %s free of %s available → current limit %s).",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen format_bytes(fb5, sizeof(fb5), s->cached_available_space + sum));
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenvoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen log_warning_errno(r, "Failed to fix access mode on %s, ignoring: %m", f->path);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_warning_errno(errno, "Failed to read ACL on %s, ignoring: %m", f->path);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (r <= 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* We do not recalculate the mask unconditionally here,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen * so that the fchmod() mask above stays intact. */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning_errno(errno, "Failed to patch ACL on %s, ignoring: %m", f->path);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_warning_errno(errno, "Failed to set ACL on %s, ignoring: %m", f->path);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersenstatic JournalFile* find_journal(Server *s, uid_t uid) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* We split up user logs only on /var, not on /run. If the
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen * runtime file is open, we write to it exclusively, in order
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen * to guarantee proper order as soon as we flush /run to
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen * /var and close the runtime file. */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen f = ordered_hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-"UID_FMT".journal",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen while (ordered_hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Too many open? Then let's close one */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen f = ordered_hashmap_steal_first(s->user_journals);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = ordered_hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = journal_file_rotate(f, s->compress, seal);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_errno(r, "Failed to create new %s journal: %m", name);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen do_rotate(s, &s->runtime_journal, "runtime", false, 0);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen do_rotate(s, &s->system_journal, "system", s->seal, 0);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = do_rotate(s, &f, "user", s->seal, PTR_TO_UINT32(k));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen ordered_hashmap_replace(s->user_journals, k, f);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Old file has been closed and deallocated */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = journal_file_set_offline(s->system_journal);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_errno(r, "Failed to sync system journal: %m");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_errno(r, "Failed to sync user journal: %m");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error_errno(r, "Failed to disable sync timer source: %m");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen const char *id,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen const char *p;
1231c4d238844e77018caf5b5852f01d96373c47Tom Gundersen r = journal_directory_vacuum(p, metrics->max_use, s->max_retention_usec, &s->oldest_file_usec, false);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r < 0 && r != -ENOENT)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_error_errno(r, "Failed to vacuum %s: %m", p);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_error_errno(r, "Failed to get machine ID: %m");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen do_vacuum(s, ids, s->system_journal, "/var/log/journal/", &s->system_metrics);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen do_vacuum(s, ids, s->runtime_journal, "/run/log/journal/", &s->runtime_metrics);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic void server_cache_machine_id(Server *s) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID="));
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID="));
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic bool shall_try_append_again(JournalFile *f, int r) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen /* -E2BIG Hit configured limit
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -EFBIG Hit fs limit
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -EDQUOT Quota limit hit
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -ENOSPC Disk full
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -EIO I/O error of some kind (mmap)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -EHOSTDOWN Other machine
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen -EBUSY Unclean shutdown
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -EPROTONOSUPPORT Unsupported feature
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen -EBADMSG Corrupted
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen -ENODATA Truncated
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -ESHUTDOWN Already archived
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen -EIDRM Journal file has been deleted */
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen log_debug("%s: Allocation limit reached, rotating.", f->path);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen else if (r == -EHOSTDOWN)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen log_info("%s: Journal file from other machine, rotating.", f->path);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen else if (r == -EBUSY)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen log_info("%s: Unclean shutdown, rotating.", f->path);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen else if (r == -EPROTONOSUPPORT)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen log_info("%s: Unsupported feature, rotating.", f->path);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen log_warning("%s: Journal file corrupted, rotating.", f->path);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering else if (r == -EIO)
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering log_warning("%s: IO error, rotating.", f->path);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering else if (r == -EIDRM)
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering log_warning("%s: Journal file has been deleted, rotating.", f->path);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (journal_file_rotate_suggested(f, s->max_file_usec)) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (r >= 0) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (vacuumed || !shall_try_append_again(f, r)) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen log_error_errno(r, "Failed to write entry (%d items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen struct iovec *iovec, unsigned n, unsigned m,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)],
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)],
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = get_process_cmdline(ucred->pid, 0, false, &t);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = audit_session_from_pid(ucred->pid, &audit);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen sprintf(audit_session, "_AUDIT_SESSION=%"PRIu32, audit);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = audit_loginuid_from_pid(ucred->pid, &loginuid);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r >= 0) {
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen sprintf(audit_loginuid, "_AUDIT_LOGINUID="UID_FMT, loginuid);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r >= 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen sprintf(owner_uid, "_SYSTEMD_OWNER_UID="UID_FMT, owner);
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen if (cg_path_get_unit(c, &t) >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (cg_path_get_user_unit(c, &t) >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (cg_path_get_slice(c, &t) >= 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen } else if (unit_id) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen *((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r >= 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen sprintf(o_uid, "OBJECT_UID="UID_FMT, object_uid);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r >= 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen sprintf(o_gid, "OBJECT_GID="GID_FMT, object_gid);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r >= 0) {
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen if (r >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = get_process_cmdline(object_pid, 0, false, &t);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (r >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = audit_session_from_pid(object_pid, &audit);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%"PRIu32, audit);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen IOVEC_SET_STRING(iovec[n++], o_audit_session);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = audit_loginuid_from_pid(object_pid, &loginuid);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID="UID_FMT, loginuid);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r >= 0) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID="UID_FMT, owner);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (cg_path_get_unit(c, &t) >= 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (cg_path_get_user_unit(c, &t) >= 0) {
a7f7d1bde43fc825c49afea3f946f5b4b3d563e0Harald Hoyer sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv));
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen /* Note that strictly speaking storing the boot id here is
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen * redundant since the entry includes this in-line
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen * anyway. However, we need this indexed, too. */
02557f973aed0fed7154fefe53d67e2935f918dcThomas Hindoe Paaboel Andersen if (!isempty(s->boot_id_field))
02557f973aed0fed7154fefe53d67e2935f918dcThomas Hindoe Paaboel Andersen IOVEC_SET_STRING(iovec[n++], s->boot_id_field);
02557f973aed0fed7154fefe53d67e2935f918dcThomas Hindoe Paaboel Andersen if (!isempty(s->machine_id_field))
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen IOVEC_SET_STRING(iovec[n++], s->machine_id_field);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen IOVEC_SET_STRING(iovec[n++], s->hostname_field);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (s->split_mode == SPLIT_UID && realuid > 0)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen /* Split up strictly by any UID */
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0)
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani /* Split up by login UIDs. We do this only if the
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani * realuid is not root, in order not to accidentally
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering * leak privileged information to the user that is
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani * logged by a privileged process that is part of an
bff92d2c2f913c368d80066ee89855665818edc8Susant Sahani * unprivileged session. */
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen write_to_journal(s, journal_uid, iovec, n, priority);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenvoid server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id));
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen /* Stop early in case the information will not be stored
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen * in a journal. */
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &path);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen /* example: /user/lennart/3/foobar
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen * So let's cut of everything past the third /, since that is
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen * where user directories start */
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen rl = journal_rate_limit_test(s->rate_limit, path,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen priority & LOG_PRIMASK, available_space(s, false));
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen /* Write a suppression message if we suppressed something */
a38d99451f2bf8026ec51aee91662292e823c6a8Lennart Poettering server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen "Suppressed %u messages from %s", rl - 1, path);
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersenstatic int system_journal_open(Server *s, bool flush_requested) {
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen return log_error_errno(r, "Failed to get machine id: %m");
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen || access("/run/systemd/journal/flushed", F_OK) >= 0)) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen /* If in auto mode: first try to create the machine
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen * path, but not the prefix.
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen * If in persistent mode: create /var/log/journal and
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen * the machine path */
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen else if (r < 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_warning_errno(r, "Failed to open system journal: %m");
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen /* Try to open the runtime journal, but only
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen * if it already exists, so that we can flush
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen * it into the system journal */
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen log_warning_errno(r, "Failed to open runtime journal: %m");
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen /* OK, we really need the runtime journal, so create
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen * it if necessary. */
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen return log_error_errno(r, "Failed to open runtime journal: %m");
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering unsigned n = 0;
if (!s->runtime_journal)
system_journal_open(s, true);
if (!s->system_journal)
SD_JOURNAL_FOREACH(j) {
JournalFile *f;
f = j->current_file;
goto finish;
goto finish;
server_rotate(s);
server_vacuum(s);
if (!s->system_journal) {
r = -EIO;
goto finish;
goto finish;
sd_journal_close(j);
server_driver_message(s, SD_ID128_NULL, "Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n);
ssize_t n;
unsigned n_fds = 0;
} control = {};
assert(s);
return -EIO;
return log_oom();
s->buffer[n] = 0;
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
server_sync(s);
server_vacuum(s);
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
server_rotate(s);
server_vacuum(s);
static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
assert(s);
assert(s);
const char *w, *state;
size_t l;
if (!word)
return -ENOMEM;
s->forward_to_syslog = r;
s->forward_to_kmsg = r;
s->forward_to_console = r;
s->forward_to_wall = r;
assert(s);
assert(s);
server_sync(s);
assert(s);
server_sync(s);
if (s->sync_scheduled)
if (s->sync_interval_usec > 0) {
if (!s->sync_event_source) {
r = sd_event_add_time(
s->event,
&s->sync_event_source,
when, 0,
server_dispatch_sync, s);
s->sync_scheduled = true;
static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
assert(s);
assert(s);
if (s->hostname_fd < 0)
r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s);
if (r == -EPERM) {
strerror(-r));
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->seal = true;
s->sync_scheduled = false;
s->forward_to_wall = true;
if (!s->user_journals)
return log_oom();
if (!s->mmap)
return log_oom();
n = sd_listen_fds(true);
if (s->native_fd >= 0) {
return -EINVAL;
if (s->stdout_fd >= 0) {
return -EINVAL;
if (s->syslog_fd >= 0) {
return -EINVAL;
if (s->audit_fd >= 0) {
return -EINVAL;
if (!fds) {
if (!fds)
return log_oom();
return log_oom();
r = server_open_syslog_socket(s);
r = server_open_native_socket(s);
r = server_open_dev_kmsg(s);
r = server_open_audit(s);
r = server_open_kernel_seqnum(s);
r = server_open_hostname(s);
r = setup_signals(s);
if (!s->udev)
return -ENOMEM;
if (!s->rate_limit)
return -ENOMEM;
r = system_journal_open(s, false);
#ifdef HAVE_GCRYPT
JournalFile *f;
Iterator i;
usec_t n;
if (s->system_journal)
JournalFile *f;
assert(s);
while (s->stdout_streams)
if (s->system_journal)
if (s->runtime_journal)
if (s->rate_limit)
if (s->kernel_seqnum)
if (s->mmap)
if (s->udev)