journald-server.c revision fe1abefcd3bf1718dde3b5b835db56142c9f7082
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer This file is part of systemd.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Copyright 2011 Lennart Poettering
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer systemd is free software; you can redistribute it and/or modify it
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer under the terms of the GNU Lesser General Public License as published by
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer the Free Software Foundation; either version 2.1 of the License, or
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt (at your option) any later version.
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt systemd is distributed in the hope that it will be useful, but
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt WITHOUT ANY WARRANTY; without even the implied warranty of
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1c36b4a73b876258fbe01fbe9bc9b750b7dcc9ceEvgeny Vereshchagin Lesser General Public License for more details.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier You should have received a copy of the GNU Lesser General Public License
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierstatic const char* const storage_table[] = {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny ChevalierDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny ChevalierDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierstatic const char* const split_mode_table[] = {
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-SzmekDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-SzmekDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
24be78d72b931b0175f08cee12fd23d631c024bfEvgeny Vereshchagin const char *f;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
a2fbff31c9c319da51528f85ae97d019f1e61a86Evgeny Vereshchagin p = strappend(f, sd_id128_to_string(machine, ids));
cb2f9d3f296bc80b55f09880d61dfdf47fc98212Evgeny Vereshchagin if (!endswith(de->d_name, ".journal") &&
cb2f9d3f296bc80b55f09880d61dfdf47fc98212Evgeny Vereshchagin if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier avail = sum >= m->max_use ? 0 : m->max_use - sum;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek ss_avail = ss.f_bsize * ss.f_bavail;
2375607039517c88df51ef16ddbb624ec1c10654Kay Sievers ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic void server_read_file_gid(Server *s) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *g = "systemd-journal";
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to resolve '%s' group: %s", g, strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* if we couldn't read the gid, then it will be 0, but that's
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek * fine and we shouldn't try to resolve the group again, so
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * let's just pretend it worked right-away. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevaliervoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
c7eda0133b6bf13a182337cbe8a61bf2faf9b32eEvgeny Vereshchagin if (acl_create_entry(&acl, &entry) < 0 ||
c7eda0133b6bf13a182337cbe8a61bf2faf9b32eEvgeny Vereshchagin acl_set_tag_type(entry, ACL_USER) < 0 ||
c7eda0133b6bf13a182337cbe8a61bf2faf9b32eEvgeny Vereshchagin log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* We do not recalculate the mask unconditionally here,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * so that the fchmod() mask above stays intact. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic JournalFile* find_journal(Server *s, uid_t uid) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* We split up user logs only on /var, not on /run. If the
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * runtime file is open, we write to it exclusively, in order
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * to guarantee proper order as soon as we flush /run to
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * /var and close the runtime file. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal",
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Too many open? Then let's close one */
7d023341c765c205068e33d23d63a4000ec211dfMartin Pitt r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, s->system_journal, &f);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
0fe15dc8ddddeb39a5cad1f4f4afa25fa074a5d1Evgeny Vereshchagin r = journal_file_rotate(&s->runtime_journal, s->compress, false);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to create new runtime journal: %s", strerror(-r));
0fe15dc8ddddeb39a5cad1f4f4afa25fa074a5d1Evgeny Vereshchagin server_fix_perms(s, s->runtime_journal, 0);
417491f122b346a31cf8dc406c4f9195a5900cecEvgeny Vereshchagin r = journal_file_rotate(&s->system_journal, s->compress, s->seal);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to create new system journal: %s", strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = journal_file_rotate(&f, s->compress, s->seal);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to rotate %s: %s", f->path, strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to create user journal: %s", strerror(-r));
53d90f9582f96208b3674da823ad1a3d2c3b1aa4Martin Pitt static const struct itimerspec sync_timer_disable = {};
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = journal_file_set_offline(s->system_journal);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to sync system journal: %s", strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to sync user journal: %s", strerror(-r));
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = timerfd_settime(s->sync_timer_fd, 0, &sync_timer_disable, NULL);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to disable max timer: %m");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to get machine ID: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0 && r != -ENOENT)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to vacuum %s: %s", p, strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0 && r != -ENOENT)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to vacuum %s: %s", p, strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerbool shall_try_append_again(JournalFile *f, int r) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* -E2BIG Hit configured limit
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier -EFBIG Hit fs limit
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier -EDQUOT Quota limit hit
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier -ENOSPC Disk full
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier -EHOSTDOWN Other machine
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier -EBUSY Unclean shutdown
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer -EPROTONOSUPPORT Unsupported feature
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer -EBADMSG Corrupted
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer -ENODATA Truncated
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer -ESHUTDOWN Already archived */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("%s: Allocation limit reached, rotating.", f->path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (r == -EHOSTDOWN)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_info("%s: Journal file from other machine, rotating.", f->path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (r == -EBUSY)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_info("%s: Unclean shutdown, rotating.", f->path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (r == -EPROTONOSUPPORT)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_info("%s: Unsupported feature, rotating.", f->path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_warning("%s: Journal file corrupted, rotating.", f->path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return false;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return true;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bool vacuumed = false;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (journal_file_rotate_suggested(f, s->max_file_usec)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (vacuumed || !shall_try_append_again(f, r)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to write entry, ignoring: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_error("Failed to write entry, ignoring: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *unit_id) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer boot_id[sizeof("_BOOT_ID=") + 32] = "_BOOT_ID=",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer machine_id[sizeof("_MACHINE_ID=") + 32] = "_MACHINE_ID=";
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *comm, *exe, *cmdline, *cgroup, *session, *unit, *hostname;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *t, *c;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(pid, "_PID=%lu", (unsigned long) ucred->pid);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(uid, "_UID=%lu", (unsigned long) ucred->uid);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(gid, "_GID=%lu", (unsigned long) ucred->gid);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = get_process_cmdline(ucred->pid, 0, false, &t);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = audit_session_from_pid(ucred->pid, &audit);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = audit_loginuid_from_pid(ucred->pid, &loginuid);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = cg_pid_get_path_shifted(ucred->pid, NULL, &c);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (cg_path_get_unit(c, &t) >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else if (cg_path_get_user_unit(c, &t) >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else if (unit_id) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unit = strappenda("_SYSTEMD_USER_UNIT=", unit_id);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *selinux_context = alloca(sizeof("_SELINUX_CONTEXT=") + label_len);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer *((char*) mempcpy(stpcpy(selinux_context, "_SELINUX_CONTEXT="), label, label_len)) = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer char *selinux_context = strappenda("_SELINUX_CONTEXT=", con);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Note that strictly speaking storing the boot id here is
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * redundant since the entry includes this in-line
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * anyway. However, we need this indexed, too. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_id128_to_string(id, boot_id + sizeof("_BOOT_ID=") - 1);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sd_id128_to_string(id, machine_id + sizeof("_MACHINE_ID=") - 1);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Split up strictly by any UID */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Split up by login UIDs, this avoids creation of
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * individual journals for system UIDs. We do this
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * only if the realuid is not root, in order not to
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * accidentally leak privileged information to the
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * user that is logged by a privileged process that is
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * part of an unprivileged session.*/
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyervoid server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer snprintf(mid, sizeof(mid), MESSAGE_ID(message_id));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = cg_pid_get_path_shifted(ucred->pid, NULL, &path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* example: /user/lennart/3/foobar
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * So let's cut of everything past the third /, since that is
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * where user directories start */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer rl = journal_rate_limit_test(s->rate_limit, path,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Write a suppression message if we suppressed something */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer "Suppressed %u messages from %s", rl - 1, path);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer access("/run/systemd/journal/flushed", F_OK) >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* If in auto mode: first try to create the machine
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * path, but not the prefix.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * If in persistent mode: create /var/log/journal and
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * the machine path */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fn = strjoin("/var/log/journal/", ids, "/system.journal", NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r >= 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_driver_message(s, SD_ID128_NULL, "Allowing system journal files to grow to %s.",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer format_bytes(fb, sizeof(fb), s->system_metrics.max_use));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_driver_message(s, SD_ID128_NULL, "Journal size currently limited to %s due to SystemKeepFree.",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_warning("Failed to open system journal: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* Try to open the runtime journal, but only
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * if it already exists, so that we can flush
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * it into the system journal */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_warning("Failed to open runtime journal: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* OK, we really need the runtime journal, so create
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * it if necessary. */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to open runtime journal: %s", strerror(-r));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_driver_message(s, SD_ID128_NULL, "Allowing runtime journal files to grow to %s.",
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer format_bytes(fb, sizeof(fb), s->runtime_metrics.max_use));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_driver_message(s, SD_ID128_NULL, "Journal size currently limited to %s due to RuntimeKeepFree.",
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_error("Failed to get machine id: %s", strerror(-r));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_error("Failed to read runtime journal: %s", strerror(-r));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_error("Can't read entry: %s", strerror(-r));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (!shall_try_append_again(s->system_journal, r)) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_error("Can't write entry: %s", strerror(-r));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful.");
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (r < 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_error("Can't write entry: %s", strerror(-r));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyerint process_event(Server *s, struct epoll_event *ev) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (n != sizeof(sfsi)) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer log_info("Received SIG%s", signal_to_string(sfsi.ssi_signo));
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer /* We use NAME_MAX space for the
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * SELinux label here. The kernel
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * currently enforces no limit, but
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * according to suggestions from the
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * SELinux people this will change and
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * it will probably be identical to
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * NAME_MAX. For now we use that, but
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * this should be updated one day when
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer * the final limit is known.*/
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer unsigned n_fds = 0;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer l = MAX(LINE_MAX + (size_t) v, s->buffer_size * 2);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (n < 0) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (n > 0 && n_fds == 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else if (n_fds > 0)
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer log_warning("Got file descriptors via syslog socket. Ignoring.");
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer if (n > 0 && n_fds == 0)
1ecf6a2b4960229ad1d06c591b4776ddf065e834Harald Hoyer server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer server_process_native_file(s, fds[0], ucred, tv, label, label_len);
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer else if (n_fds > 0)
33a5e20ffaa2cbb2853f14265566bac66a7f9026Harald Hoyer log_warning("Got too many file descriptors via native socket. Ignoring.");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer /* If it is none of the well-known fds, it must be an
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * stdout stream fd. Note that this is a bit ugly here
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * (since we rely that none of the well-known fds
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * could be interpreted as pointer), but nonetheless
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * safe, since the well-known fds would never get an
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer * fd > 4096, i.e. beyond the first memory page */
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
return -errno;
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;
assert(s);
return -errno;
(void*) journald_gperf_lookup, false, false, s);
assert(s);
if (s->sync_timer_fd < 0)
return -errno;
return -errno;
assert(s);
if (s->sync_scheduled)
if (s->sync_interval_usec) {
return -errno;
s->sync_scheduled = true;
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->seal = true;
s->sync_scheduled = false;
s->forward_to_syslog = true;
(long long unsigned) s->rate_limit_interval,
s->rate_limit_burst);
if (!s->user_journals)
return log_oom();
if (!s->mmap)
return log_oom();
if (s->epoll_fd < 0) {
return -errno;
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;
return -EINVAL;
r = server_open_syslog_socket(s);
r = server_open_native_socket(s);
r = server_open_stdout_socket(s);
r = server_open_dev_kmsg(s);
r = server_open_kernel_seqnum(s);
r = server_open_sync_timer(s);
r = open_signalfd(s);
if (!s->udev)
return -ENOMEM;
s->rate_limit_burst);
if (!s->rate_limit)
return -ENOMEM;
r = system_journal_open(s);
#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->epoll_fd >= 0)
if (s->signal_fd >= 0)
if (s->syslog_fd >= 0)
if (s->native_fd >= 0)
if (s->stdout_fd >= 0)
if (s->dev_kmsg_fd >= 0)
if (s->sync_timer_fd >= 0)
if (s->rate_limit)
if (s->kernel_seqnum)
if (s->mmap)
if (s->udev)