journald-server.c revision fc7b7e2e74ed0c4ce2bda91d693240c9dcd0d526
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Copyright 2011 Lennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic const char* const storage_table[] = {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik FlyktDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic const char* const split_mode_table[] = {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik FlyktDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik FlyktDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const char *f;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt p = strappend(f, sd_id128_to_string(machine, ids));
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt avail = sum >= m->max_use ? 0 : m->max_use - sum;
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen log_warning("Failed to resolve 'adm' group: %s", strerror(-r));
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen /* if we couldn't read the gid, then it will be 0, but that's
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen * fine and we shouldn't try to resolve the group again, so
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen * let's just pretend it worked right-away. */
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersenvoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r <= 0) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic JournalFile* find_journal(Server *s, uid_t uid) {
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt /* We split up user logs only on /var, not on /run. If the
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt * runtime file is open, we write to it exclusively, in order
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt * to guarantee proper order as soon as we flush /run to
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt * /var and close the runtime file. */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal",
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0)
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt /* Too many open? Then let's close one */
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, s->system_journal, &f);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt r = journal_file_rotate(&s->runtime_journal, s->compress, false);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Failed to create new runtime journal: %s", strerror(-r));
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = journal_file_rotate(&s->system_journal, s->compress, s->seal);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Failed to create new system journal: %s", strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = journal_file_rotate(&f, s->compress, s->seal);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_error("Failed to rotate %s: %s", f->path, strerror(-r));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_error("Failed to create user journal: %s", strerror(-r));
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Failed to get machine ID: %s", strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0 && r != -ENOENT)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Failed to vacuum %s: %s", p, strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0 && r != -ENOENT)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Failed to vacuum %s: %s", p, strerror(-r));
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Hallerstatic char *shortened_cgroup_path(pid_t pid) {
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams char _cleanup_free_ *process_path = NULL, *init_path = NULL;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &process_path);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &init_path);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt path = strdup(process_path + strlen(init_path));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktbool shall_try_append_again(JournalFile *f, int r) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt /* -E2BIG Hit configured limit
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -EFBIG Hit fs limit
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -EDQUOT Quota limit hit
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -ENOSPC Disk full
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -EHOSTDOWN Other machine
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -EBUSY Unclean shutdown
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -EPROTONOSUPPORT Unsupported feature
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -EBADMSG Corrupted
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt -ENODATA Truncated
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt -ESHUTDOWN Already archived */
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_debug("%s: Allocation limit reached, rotating.", f->path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (r == -EHOSTDOWN)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_info("%s: Journal file from other machine, rotating.", f->path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (r == -EBUSY)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_info("%s: Unclean shutdown, rotating.", f->path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (r == -EPROTONOSUPPORT)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_info("%s: Unsupported feature, rotating.", f->path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_warning("%s: Journal file corrupted, rotating.", f->path);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return false;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return true;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flyktstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt bool vacuumed = false;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (journal_file_rotate_suggested(f, s->max_file_usec)) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (vacuumed || !shall_try_append_again(f, r)) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Failed to write entry, ignoring: %s", strerror(-r));
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Failed to write entry, ignoring: %s", strerror(-r));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt const char *unit_id) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt char _cleanup_free_ *pid = NULL, *uid = NULL, *gid = NULL,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt *source_time = NULL, *boot_id = NULL, *machine_id = NULL,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt *comm = NULL, *cmdline = NULL, *hostname = NULL,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt *owner_uid = NULL, *unit = NULL, *selinux_context = NULL;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (asprintf(&pid, "_PID=%lu", (unsigned long) ucred->pid) >= 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (asprintf(&uid, "_UID=%lu", (unsigned long) ucred->uid) >= 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (asprintf(&gid, "_GID=%lu", (unsigned long) ucred->gid) >= 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r >= 0) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r >= 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = get_process_cmdline(ucred->pid, 0, false, &t);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r >= 0) {
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = audit_session_from_pid(ucred->pid, &audit);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit) >= 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = audit_loginuid_from_pid(ucred->pid, &loginuid);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (sd_pid_get_owner_uid(ucred->uid, &owner) >= 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (asprintf(&owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner) >= 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen } else if (cg_pid_get_user_unit(ucred->pid, &t) >= 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt } else if (unit_id) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt unit = strappend("_SYSTEMD_USER_UNIT=", unit_id);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt selinux_context = malloc(sizeof("_SELINUX_CONTEXT=") + label_len);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt *((char*) mempcpy(stpcpy(selinux_context, "_SELINUX_CONTEXT="), label, label_len)) = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt selinux_context = strappend("_SELINUX_CONTEXT=", con);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (asprintf(&source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu",
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt /* Note that strictly speaking storing the boot id here is
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt * redundant since the entry includes this in-line
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen * anyway. However, we need this indexed, too. */
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (asprintf(&boot_id, "_BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (asprintf(&machine_id, "_MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Split up strictly by any UID */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Split up by login UIDs, this avoids creation of
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * individual journals for system UIDs. We do this
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * only if the realuid is not root, in order not to
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * accidentally leak privileged information to the
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * user that is logged by a privileged process that is
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams * part of an unprivileged session.*/
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktvoid server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt snprintf(mid, sizeof(mid), MESSAGE_ID(message_id));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt /* example: /user/lennart/3/foobar
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt * So let's cut of everything past the third /, since that is
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt * where user directories start */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt rl = journal_rate_limit_test(s->rate_limit, path,
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Write a suppression message if we suppressed something */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "Suppressed %u messages from %s", rl - 1, path);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt access("/run/systemd/journal/flushed", F_OK) >= 0) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt /* If in auto mode: first try to create the machine
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt * path, but not the prefix.
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt * If in persistent mode: create /var/log/journal and
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt * the machine path */
5364f729ba9616cd9fdab8d5413fbc25a1af3a57Lennart Poettering fn = strappend("/var/log/journal/", ids);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt fn = strjoin("/var/log/journal/", ids, "/system.journal", NULL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r >= 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt server_driver_message(s, SD_ID128_NULL, "Allowing system journal files to grow to %s.",
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt format_bytes(fb, sizeof(fb), s->system_metrics.max_use));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt } else if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_warning("Failed to open system journal: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Try to open the runtime journal, but only
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * if it already exists, so that we can flush
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * it into the system journal */
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_warning("Failed to open runtime journal: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* OK, we really need the runtime journal, so create
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * it if necessary. */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_error("Failed to open runtime journal: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt server_driver_message(s, SD_ID128_NULL, "Allowing runtime journal files to grow to %s.",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt format_bytes(fb, sizeof(fb), s->runtime_metrics.max_use));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_error("Failed to get machine id: %s", strerror(-r));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_error("Failed to read runtime journal: %s", strerror(-r));
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Can't read entry: %s", strerror(-r));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (!shall_try_append_again(s->system_journal, r)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Can't write entry: %s", strerror(-r));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Can't write entry: %s", strerror(-r));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktint process_event(Server *s, struct epoll_event *ev) {
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering if (n != sizeof(sfsi)) {
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen log_info("Received SIG%s", signal_to_string(sfsi.ssi_signo));
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen /* We use NAME_MAX space for the
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen * SELinux label here. The kernel
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen * currently enforces no limit, but
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * according to suggestions from the
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * SELinux people this will change and
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * it will probably be identical to
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * NAME_MAX. For now we use that, but
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * this should be updated one day when
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt * the final limit is known.*/
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt unsigned n_fds = 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt l = MAX(LINE_MAX + (size_t) v, s->buffer_size * 2);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (n < 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek label = (char*) CMSG_DATA(cmsg);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (n > 0 && n_fds == 0) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt } else if (n_fds > 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_warning("Got file descriptors via syslog socket. Ignoring.");
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (n > 0 && n_fds == 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt server_process_native_file(s, fds[0], ucred, tv, label, label_len);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt else if (n_fds > 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_warning("Got too many file descriptors via native socket. Ignoring.");
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* If it is none of the well-known fds, it must be an
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * stdout stream fd. Note that this is a bit ugly here
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * (since we rely that none of the well-known fds
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * could be interpreted as pointer), but nonetheless
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * safe, since the well-known fds would never get an
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * fd > 4096, i.e. beyond the first memory page */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->signal_fd, &ev) < 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int server_parse_proc_cmdline(Server *s) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = read_one_line_file("/proc/cmdline", &line);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (startswith(word, "systemd.journald.forward_to_syslog=")) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt } else if (startswith(word, "systemd.journald.forward_to_kmsg=")) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33);
s->forward_to_console = r;
assert(s);
return -errno;
(void*) journald_gperf_lookup, false, s);
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->seal = true;
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 = 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->rate_limit)
if (s->kernel_seqnum)
if (s->mmap)
if (s->udev)