journald-server.c revision 6203e07a83214a55bb1f88508fcda2005c601dea
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/signalfd.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/ioctl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <linux/sockios.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/statvfs.h>
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering#include <sys/mman.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/timerfd.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <libudev.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-journal.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-messages.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "sd-daemon.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fileio.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "mkdir.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "hashmap.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journal-file.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "socket-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "cgroup-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "list.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "missing.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "conf-parser.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "selinux-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journal-internal.h"
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering#include "journal-vacuum.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journal-authenticate.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-rate-limit.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-kmsg.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-syslog.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-stream.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-console.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-native.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "journald-server.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#ifdef HAVE_ACL
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/acl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <acl/libacl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "acl-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#ifdef HAVE_SELINUX
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <selinux/selinux.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define USER_JOURNALS_MAX 1024
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define DEFAULT_RATE_LIMIT_BURST 1000
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic const char* const storage_table[] = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering [STORAGE_AUTO] = "auto",
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen [STORAGE_VOLATILE] = "volatile",
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen [STORAGE_PERSISTENT] = "persistent",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering [STORAGE_NONE] = "none"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic const char* const split_mode_table[] = {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering [SPLIT_NONE] = "none",
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering [SPLIT_UID] = "uid",
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering [SPLIT_LOGIN] = "login"
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen};
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic uint64_t available_space(Server *s, bool verbose) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char ids[33];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_free_ char *p = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sd_id128_t machine;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering struct statvfs ss;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint64_t sum = 0, ss_avail = 0, avail = 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_closedir_ DIR *d = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering usec_t ts;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering const char *f;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering JournalMetrics *m;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering ts = now(CLOCK_MONOTONIC);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering && !verbose)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return s->cached_available_space;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_id128_get_machine(&machine);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s->system_journal) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering f = "/var/log/journal/";
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m = &s->system_metrics;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering } else {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering f = "/run/log/journal/";
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering m = &s->runtime_metrics;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = strappend(f, sd_id128_to_string(machine, ids));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!p)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering d = opendir(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!d)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fstatvfs(dirfd(d), &ss) < 0)
c5ed93163e6ef51a7462aa558a7e0912b17c4951Lennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering for (;;) {
cc7844e78751916acb639443c119763cafe2c684Lennart Poettering struct stat st;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct dirent *de;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union dirent_storage buf;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = readdir_r(d, &buf.de, &de);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r != 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!de)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen if (!endswith(de->d_name, ".journal") &&
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen !endswith(de->d_name, ".journal~"))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen if (!S_ISREG(st.st_mode))
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sum += (uint64_t) st.st_blocks * 512UL;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering ss_avail = ss.f_bsize * ss.f_bavail;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen avail = ss_avail > m->keep_free ? ss_avail - m->keep_free : 0;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen s->cached_available_space = MIN(m->max_use, avail) > sum ? MIN(m->max_use, avail) - sum : 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->cached_available_space_timestamp = ts;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen if (verbose) {
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX];
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "%s journal is using %s (max %s, leaving %s of free %s, current limit %s).",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->system_journal ? "Permanent" : "Runtime",
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering format_bytes(fb1, sizeof(fb1), sum),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering format_bytes(fb2, sizeof(fb2), m->max_use),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering format_bytes(fb3, sizeof(fb3), m->keep_free),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering format_bytes(fb4, sizeof(fb4), ss_avail),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering format_bytes(fb5, sizeof(fb5), MIN(m->max_use, avail)));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return s->cached_available_space;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringvoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#ifdef HAVE_ACL
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen acl_t acl;
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen acl_entry_t entry;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering acl_permset_t permset;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#endif
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(f);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering r = fchmod(f->fd, 0640);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (r < 0)
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering log_warning("Failed to fix access mode on %s, ignoring: %s", f->path, strerror(-r));
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering#ifdef HAVE_ACL
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (uid <= 0)
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering return;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering acl = acl_get_fd(f->fd);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (!acl) {
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering return;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering }
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering r = acl_find_uid(acl, uid, &entry);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (r <= 0) {
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (acl_create_entry(&acl, &entry) < 0 ||
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering acl_set_tag_type(entry, ACL_USER) < 0 ||
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering acl_set_qualifier(entry, &uid) < 0) {
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering goto finish;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering }
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering }
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering /* We do not recalculate the mask unconditionally here,
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering * so that the fchmod() mask above stays intact. */
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (acl_get_permset(entry, &permset) < 0 ||
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering acl_add_perm(permset, ACL_READ) < 0 ||
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering calc_acl_mask_if_needed(&acl) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen goto finish;
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (acl_set_fd(f->fd, acl) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfinish:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering acl_free(acl);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering#endif
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic JournalFile* find_journal(Server *s, uid_t uid) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *p = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering JournalFile *f;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering sd_id128_t machine;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(s);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering /* We split up user logs only on /var, not on /run. If the
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * runtime file is open, we write to it exclusively, in order
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering * to guarantee proper order as soon as we flush /run to
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * /var and close the runtime file. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (s->runtime_journal)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return s->runtime_journal;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (uid <= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return s->system_journal;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_id128_get_machine(&machine);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return s->system_journal;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (f)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return f;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return s->system_journal;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Too many open? Then let's close one */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering f = hashmap_steal_first(s->user_journals);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering journal_file_close(f);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return s->system_journal;
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering server_fix_perms(s, f, uid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering journal_file_close(f);
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering return s->system_journal;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return f;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringvoid server_rotate(Server *s) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering JournalFile *f;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering void *k;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering Iterator i;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering int r;
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_debug("Rotating...");
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering if (s->runtime_journal) {
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering r = journal_file_rotate(&s->runtime_journal, s->compress, false);
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering if (r < 0)
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering if (s->runtime_journal)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering else
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_error("Failed to create new runtime journal: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering server_fix_perms(s, s->runtime_journal, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (s->system_journal) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_rotate(&s->system_journal, s->compress, s->seal);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s->system_journal)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to create new system journal: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering server_fix_perms(s, s->system_journal, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_rotate(&f, s->compress, s->seal);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (f)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_error("Failed to rotate %s: %s", f->path, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to create user journal: %s", strerror(-r));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering hashmap_remove(s->user_journals, k);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering hashmap_replace(s->user_journals, k, f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering server_fix_perms(s, f, PTR_TO_UINT32(k));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringvoid server_sync(Server *s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering JournalFile *f;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *k;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s->system_journal) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_set_offline(s->system_journal);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to sync system journal: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_set_offline(f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to sync user journal: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s->sync_event_source) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_error("Failed to disable sync timer source: %s", strerror(-r));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering s->sync_scheduled = false;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringvoid server_vacuum(Server *s) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering char ids[33];
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering sd_id128_t machine;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_debug("Vacuuming...");
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering s->oldest_file_usec = 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_id128_get_machine(&machine);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to get machine ID: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering sd_id128_to_string(machine, ids);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (s->system_journal) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering char *p = strappenda("/var/log/journal/", ids);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0 && r != -ENOENT)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_error("Failed to vacuum %s: %s", p, strerror(-r));
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering if (s->runtime_journal) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering char *p = strappenda("/run/log/journal/", ids);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free, s->max_retention_usec, &s->oldest_file_usec);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0 && r != -ENOENT)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering log_error("Failed to vacuum %s: %s", p, strerror(-r));
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering s->cached_available_space_timestamp = 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic void server_cache_machine_id(Server *s) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering sd_id128_t id;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(s);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_id128_get_machine(&id);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID="));
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic void server_cache_boot_id(Server *s) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering sd_id128_t id;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_id128_get_boot(&id);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
cc7844e78751916acb639443c119763cafe2c684Lennart Poettering return;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID="));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
cc7844e78751916acb639443c119763cafe2c684Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic void server_cache_hostname(Server *s) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering _cleanup_free_ char *t = NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering char *x;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(s);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering t = gethostname_malloc();
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (!t)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering x = strappend("_HOSTNAME=", t);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (!x)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering free(s->hostname_field);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering s->hostname_field = x;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringbool shall_try_append_again(JournalFile *f, int r) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
19b50b5ba7ee8c1bfb330377309e4bab7a7531d8Lennart Poettering /* -E2BIG Hit configured limit
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering -EFBIG Hit fs limit
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering -EDQUOT Quota limit hit
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering -ENOSPC Disk full
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering -EHOSTDOWN Other machine
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering -EBUSY Unclean shutdown
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering -EPROTONOSUPPORT Unsupported feature
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering -EBADMSG Corrupted
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering -ENODATA Truncated
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering -ESHUTDOWN Already archived */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering log_debug("%s: Allocation limit reached, rotating.", f->path);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering else if (r == -EHOSTDOWN)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering log_info("%s: Journal file from other machine, rotating.", f->path);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering else if (r == -EBUSY)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering log_info("%s: Unclean shutdown, rotating.", f->path);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering else if (r == -EPROTONOSUPPORT)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering log_info("%s: Unsupported feature, rotating.", f->path);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_warning("%s: Journal file corrupted, rotating.", f->path);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering else
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return false;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return true;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering JournalFile *f;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering bool vacuumed = false;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(iovec);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(n > 0);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering f = find_journal(s, uid);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!f)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (journal_file_rotate_suggested(f, s->max_file_usec)) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering server_rotate(s);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering server_vacuum(s);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering vacuumed = true;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering f = find_journal(s, uid);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (!f)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r >= 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering server_schedule_sync(s, priority);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (vacuumed || !shall_try_append_again(f, r)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t size = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < n; i++)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size += iovec[i].iov_len;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to write entry (%d items, %zu bytes), ignoring: %s", n, size, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering server_rotate(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering server_vacuum(s);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering f = find_journal(s, uid);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!f)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Retrying write.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size_t size = 0;
7b85d72f824cdf34554b349712b6b8e39095dbd4Lennart Poettering unsigned i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < n; i++)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering size += iovec[i].iov_len;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %s", n, size, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering server_schedule_sync(s, priority);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
static void dispatch_message_real(
Server *s,
struct iovec *iovec, unsigned n, unsigned m,
struct ucred *ucred,
struct timeval *tv,
const char *label, size_t label_len,
const char *unit_id,
int priority,
pid_t object_pid) {
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
assert(s);
assert(iovec);
assert(n > 0);
assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
if (ucred) {
realuid = ucred->uid;
sprintf(pid, "_PID=%lu", (unsigned long) ucred->pid);
IOVEC_SET_STRING(iovec[n++], pid);
sprintf(uid, "_UID=%lu", (unsigned long) ucred->uid);
IOVEC_SET_STRING(iovec[n++], uid);
sprintf(gid, "_GID=%lu", (unsigned long) ucred->gid);
IOVEC_SET_STRING(iovec[n++], gid);
r = get_process_comm(ucred->pid, &t);
if (r >= 0) {
x = strappenda("_COMM=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_exe(ucred->pid, &t);
if (r >= 0) {
x = strappenda("_EXE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_cmdline(ucred->pid, 0, false, &t);
if (r >= 0) {
x = strappenda("_CMDLINE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_capeff(ucred->pid, &t);
if (r >= 0) {
x = strappenda("_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=%lu", (unsigned long) audit);
IOVEC_SET_STRING(iovec[n++], audit_session);
}
r = audit_loginuid_from_pid(ucred->pid, &loginuid);
if (r >= 0) {
sprintf(audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid);
IOVEC_SET_STRING(iovec[n++], audit_loginuid);
}
#endif
r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
if (r >= 0) {
char *session = NULL;
x = strappenda("_SYSTEMD_CGROUP=", c);
IOVEC_SET_STRING(iovec[n++], x);
r = cg_path_get_session(c, &t);
if (r >= 0) {
session = strappenda("_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=%lu", (unsigned long) owner);
IOVEC_SET_STRING(iovec[n++], owner_uid);
}
if (cg_path_get_unit(c, &t) >= 0) {
x = strappenda("_SYSTEMD_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
} else if (unit_id && !session) {
x = strappenda("_SYSTEMD_UNIT=", unit_id);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_user_unit(c, &t) >= 0) {
x = strappenda("_SYSTEMD_USER_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
} else if (unit_id && session) {
x = strappenda("_SYSTEMD_USER_UNIT=", unit_id);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_slice(c, &t) >= 0) {
x = strappenda("_SYSTEMD_SLICE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
free(c);
} else if (unit_id) {
x = strappenda("_SYSTEMD_UNIT=", unit_id);
IOVEC_SET_STRING(iovec[n++], x);
}
#ifdef HAVE_SELINUX
if (use_selinux()) {
if (label) {
x = alloca(sizeof("_SELINUX_CONTEXT=") + label_len);
*((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
IOVEC_SET_STRING(iovec[n++], x);
} else {
security_context_t con;
if (getpidcon(ucred->pid, &con) >= 0) {
x = strappenda("_SELINUX_CONTEXT=", con);
freecon(con);
IOVEC_SET_STRING(iovec[n++], x);
}
}
}
#endif
}
assert(n <= m);
if (object_pid) {
r = get_process_uid(object_pid, &object_uid);
if (r >= 0) {
sprintf(o_uid, "OBJECT_UID=%lu", (unsigned long) 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=%lu", (unsigned long) object_gid);
IOVEC_SET_STRING(iovec[n++], o_gid);
}
r = get_process_comm(object_pid, &t);
if (r >= 0) {
x = strappenda("OBJECT_COMM=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_exe(object_pid, &t);
if (r >= 0) {
x = strappenda("OBJECT_EXE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_cmdline(object_pid, 0, false, &t);
if (r >= 0) {
x = strappenda("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=%lu", (unsigned long) 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=%lu", (unsigned long) loginuid);
IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
}
#endif
r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
if (r >= 0) {
x = strappenda("OBJECT_SYSTEMD_CGROUP=", c);
IOVEC_SET_STRING(iovec[n++], x);
r = cg_path_get_session(c, &t);
if (r >= 0) {
x = strappenda("OBJECT_SYSTEMD_SESSION=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_owner_uid(c, &owner) >= 0) {
sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner);
IOVEC_SET_STRING(iovec[n++], o_owner_uid);
}
if (cg_path_get_unit(c, &t) >= 0) {
x = strappenda("OBJECT_SYSTEMD_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_user_unit(c, &t) >= 0) {
x = strappenda("OBJECT_SYSTEMD_USER_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
free(c);
}
}
assert(n <= m);
if (tv) {
sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu", (unsigned long long) timeval_load(tv));
IOVEC_SET_STRING(iovec[n++], 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);
if (!isempty(s->machine_id_field))
IOVEC_SET_STRING(iovec[n++], s->machine_id_field);
if (!isempty(s->hostname_field))
IOVEC_SET_STRING(iovec[n++], 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)
/* Split up by login UIDs, this avoids creation of
* individual journals for system 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;
else
journal_uid = 0;
write_to_journal(s, journal_uid, iovec, n, priority);
}
void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
char mid[11 + 32 + 1];
char buffer[16 + LINE_MAX + 1];
struct iovec iovec[N_IOVEC_META_FIELDS + 4];
int n = 0;
va_list ap;
struct ucred ucred = {};
assert(s);
assert(format);
IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
memcpy(buffer, "MESSAGE=", 8);
va_start(ap, format);
vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
va_end(ap);
char_array_0(buffer);
IOVEC_SET_STRING(iovec[n++], buffer);
if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
snprintf(mid, sizeof(mid), MESSAGE_ID(message_id));
char_array_0(mid);
IOVEC_SET_STRING(iovec[n++], mid);
}
ucred.pid = getpid();
ucred.uid = getuid();
ucred.gid = getgid();
dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0);
}
void server_dispatch_message(
Server *s,
struct iovec *iovec, unsigned n, unsigned m,
struct ucred *ucred,
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;
char *c;
assert(s);
assert(iovec || n == 0);
if (n == 0)
return;
if (LOG_PRI(priority) > s->max_level_store)
return;
/* Stop early in case the information will not be stored
* in a journal. */
if (s->storage == STORAGE_NONE)
return;
if (!ucred)
goto finish;
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 */
c = strchr(path, '/');
if (c) {
c = strchr(c+1, '/');
if (c) {
c = strchr(c+1, '/');
if (c)
*c = 0;
}
}
rl = journal_rate_limit_test(s->rate_limit, path,
priority & LOG_PRIMASK, available_space(s, false));
if (rl == 0)
return;
/* Write a suppression message if we suppressed something */
if (rl > 1)
server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED,
"Suppressed %u messages from %s", rl - 1, path);
finish:
dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid);
}
static int system_journal_open(Server *s) {
int r;
char *fn;
sd_id128_t machine;
char ids[33];
r = sd_id128_get_machine(&machine);
if (r < 0) {
log_error("Failed to get machine id: %s", strerror(-r));
return r;
}
sd_id128_to_string(machine, ids);
if (!s->system_journal &&
(s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
access("/run/systemd/journal/flushed", F_OK) >= 0) {
/* If in auto mode: first try to create the machine
* path, but not the prefix.
*
* If in persistent mode: create /var/log/journal and
* the machine path */
if (s->storage == STORAGE_PERSISTENT)
(void) mkdir("/var/log/journal/", 0755);
fn = strappenda("/var/log/journal/", ids);
(void) mkdir(fn, 0755);
fn = strappenda(fn, "/system.journal");
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
if (r >= 0)
server_fix_perms(s, s->system_journal, 0);
else if (r < 0) {
if (r != -ENOENT && r != -EROFS)
log_warning("Failed to open system journal: %s", strerror(-r));
r = 0;
}
}
if (!s->runtime_journal &&
(s->storage != STORAGE_NONE)) {
fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
if (!fn)
return -ENOMEM;
if (s->system_journal) {
/* Try to open the runtime journal, but only
* if it already exists, so that we can flush
* it into the system journal */
r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
free(fn);
if (r < 0) {
if (r != -ENOENT)
log_warning("Failed to open runtime journal: %s", strerror(-r));
r = 0;
}
} else {
/* OK, we really need the runtime journal, so create
* it if necessary. */
(void) mkdir_parents(fn, 0755);
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
free(fn);
if (r < 0) {
log_error("Failed to open runtime journal: %s", strerror(-r));
return r;
}
}
if (s->runtime_journal)
server_fix_perms(s, s->runtime_journal, 0);
}
available_space(s, true);
return r;
}
int server_flush_to_var(Server *s) {
sd_id128_t machine;
sd_journal *j = NULL;
char ts[FORMAT_TIMESPAN_MAX];
usec_t start;
unsigned n = 0;
int r;
assert(s);
if (s->storage != STORAGE_AUTO &&
s->storage != STORAGE_PERSISTENT)
return 0;
if (!s->runtime_journal)
return 0;
system_journal_open(s);
if (!s->system_journal)
return 0;
log_debug("Flushing to /var...");
start = now(CLOCK_MONOTONIC);
r = sd_id128_get_machine(&machine);
if (r < 0)
return r;
r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
if (r < 0) {
log_error("Failed to read runtime journal: %s", strerror(-r));
return r;
}
sd_journal_set_data_threshold(j, 0);
SD_JOURNAL_FOREACH(j) {
Object *o = NULL;
JournalFile *f;
f = j->current_file;
assert(f && f->current_offset > 0);
n++;
r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
if (r < 0) {
log_error("Can't read entry: %s", strerror(-r));
goto finish;
}
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
if (r >= 0)
continue;
if (!shall_try_append_again(s->system_journal, r)) {
log_error("Can't write entry: %s", strerror(-r));
goto finish;
}
server_rotate(s);
server_vacuum(s);
if (!s->system_journal) {
log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful.");
r = -EIO;
goto finish;
}
log_debug("Retrying write.");
r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
if (r < 0) {
log_error("Can't write entry: %s", strerror(-r));
goto finish;
}
}
finish:
journal_file_post_change(s->system_journal);
journal_file_close(s->runtime_journal);
s->runtime_journal = NULL;
if (r >= 0)
rm_rf("/run/log/journal", false, true, false);
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);
return r;
}
int process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Server *s = userdata;
assert(s);
assert(fd == s->native_fd || fd == s->syslog_fd);
if (revents != EPOLLIN) {
log_error("Got invalid event from epoll for datagram fd: %"PRIx32, revents);
return -EIO;
}
for (;;) {
struct ucred *ucred = NULL;
struct timeval *tv = NULL;
struct cmsghdr *cmsg;
char *label = NULL;
size_t label_len = 0;
struct iovec iovec;
union {
struct cmsghdr cmsghdr;
/* We use NAME_MAX space for the
* SELinux label here. The kernel
* currently enforces no limit, but
* according to suggestions from the
* SELinux people this will change and
* it will probably be identical to
* NAME_MAX. For now we use that, but
* this should be updated one day when
* the final limit is known.*/
uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(sizeof(struct timeval)) +
CMSG_SPACE(sizeof(int)) + /* fd */
CMSG_SPACE(NAME_MAX)]; /* selinux label */
} control = {};
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
};
ssize_t n;
int v;
int *fds = NULL;
unsigned n_fds = 0;
if (ioctl(fd, SIOCINQ, &v) < 0) {
log_error("SIOCINQ failed: %m");
return -errno;
}
if (!GREEDY_REALLOC(s->buffer, s->buffer_size, LINE_MAX + (size_t) v))
return log_oom();
iovec.iov_base = s->buffer;
iovec.iov_len = s->buffer_size;
n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
return 0;
log_error("recvmsg() failed: %m");
return -errno;
}
for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_SECURITY) {
label = (char*) CMSG_DATA(cmsg);
label_len = cmsg->cmsg_len - CMSG_LEN(0);
} else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
tv = (struct timeval*) CMSG_DATA(cmsg);
else if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
fds = (int*) CMSG_DATA(cmsg);
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
}
}
if (fd == s->syslog_fd) {
if (n > 0 && n_fds == 0) {
s->buffer[n] = 0;
server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
} else if (n_fds > 0)
log_warning("Got file descriptors via syslog socket. Ignoring.");
} else {
if (n > 0 && n_fds == 0)
server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
else if (n == 0 && n_fds == 1)
server_process_native_file(s, fds[0], ucred, tv, label, label_len);
else if (n_fds > 0)
log_warning("Got too many file descriptors via native socket. Ignoring.");
}
close_many(fds, n_fds);
}
return 0;
}
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_info("Received request to flush runtime journal from PID %"PRIu32, si->ssi_pid);
touch("/run/systemd/journal/flushed");
server_flush_to_var(s);
server_sync(s);
return 0;
}
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_info("Received request to rotate journal from PID %"PRIu32, si->ssi_pid);
server_rotate(s);
server_vacuum(s);
return 0;
}
static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_info("Received SIG%s", signal_to_string(si->ssi_signo));
sd_event_exit(s->event, 0);
return 0;
}
static int setup_signals(Server *s) {
sigset_t mask;
int r;
assert(s);
assert_se(sigemptyset(&mask) == 0);
sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
r = sd_event_add_signal(s->event, SIGUSR1, dispatch_sigusr1, s, &s->sigusr1_event_source);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, SIGUSR2, dispatch_sigusr2, s, &s->sigusr2_event_source);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, SIGTERM, dispatch_sigterm, s, &s->sigterm_event_source);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, SIGINT, dispatch_sigterm, s, &s->sigint_event_source);
if (r < 0)
return r;
return 0;
}
static int server_parse_proc_cmdline(Server *s) {
_cleanup_free_ char *line = NULL;
char *w, *state;
size_t l;
int r;
r = proc_cmdline(&line);
if (r < 0)
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
if (r <= 0)
return 0;
FOREACH_WORD_QUOTED(w, l, line, state) {
_cleanup_free_ char *word;
word = strndup(w, l);
if (!word)
return -ENOMEM;
if (startswith(word, "systemd.journald.forward_to_syslog=")) {
r = parse_boolean(word + 35);
if (r < 0)
log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35);
else
s->forward_to_syslog = r;
} else if (startswith(word, "systemd.journald.forward_to_kmsg=")) {
r = parse_boolean(word + 33);
if (r < 0)
log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33);
else
s->forward_to_kmsg = r;
} else if (startswith(word, "systemd.journald.forward_to_console=")) {
r = parse_boolean(word + 36);
if (r < 0)
log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
else
s->forward_to_console = r;
} else if (startswith(word, "systemd.journald"))
log_warning("Invalid systemd.journald parameter. Ignoring.");
}
return 0;
}
static int server_parse_config_file(Server *s) {
static const char fn[] = "/etc/systemd/journald.conf";
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(s);
f = fopen(fn, "re");
if (!f) {
if (errno == ENOENT)
return 0;
log_warning("Failed to open configuration file %s: %m", fn);
return -errno;
}
r = config_parse(NULL, fn, f, "Journal\0", config_item_perf_lookup,
(void*) journald_gperf_lookup, false, false, s);
if (r < 0)
log_warning("Failed to parse configuration file: %s", strerror(-r));
return r;
}
static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) {
Server *s = userdata;
assert(s);
server_sync(s);
return 0;
}
int server_schedule_sync(Server *s, int priority) {
int r;
assert(s);
if (priority <= LOG_CRIT) {
/* Immediately sync to disk when this is of priority CRIT, ALERT, EMERG */
server_sync(s);
return 0;
}
if (s->sync_scheduled)
return 0;
if (s->sync_interval_usec > 0) {
usec_t when;
r = sd_event_get_now_monotonic(s->event, &when);
if (r < 0)
return r;
when += s->sync_interval_usec;
if (!s->sync_event_source) {
r = sd_event_add_monotonic(s->event, when, 0, server_dispatch_sync, s, &s->sync_event_source);
if (r < 0)
return r;
r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT);
} else {
r = sd_event_source_set_time(s->sync_event_source, when);
if (r < 0)
return r;
r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_ONESHOT);
}
if (r < 0)
return r;
s->sync_scheduled = true;
}
return 0;
}
static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Server *s = userdata;
assert(s);
server_cache_hostname(s);
return 0;
}
static int server_open_hostname(Server *s) {
int r;
assert(s);
s->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
if (s->hostname_fd < 0) {
log_error("Failed to open /proc/sys/kernel/hostname: %m");
return -errno;
}
r = sd_event_add_io(s->event, s->hostname_fd, 0, dispatch_hostname_change, s, &s->hostname_event_source);
if (r < 0) {
log_error("Failed to register hostname fd in event loop: %s", strerror(-r));
return r;
}
r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10);
if (r < 0) {
log_error("Failed to adjust priority of host name event source: %s", strerror(-r));
return r;
}
return 0;
}
int server_init(Server *s) {
int n, r, fd;
assert(s);
zero(*s);
s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->hostname_fd = -1;
s->compress = true;
s->seal = true;
s->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
s->sync_scheduled = false;
s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
s->forward_to_syslog = true;
s->max_level_store = LOG_DEBUG;
s->max_level_syslog = LOG_DEBUG;
s->max_level_kmsg = LOG_NOTICE;
s->max_level_console = LOG_INFO;
memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
server_parse_config_file(s);
server_parse_proc_cmdline(s);
if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) {
log_debug("Setting both rate limit interval and burst from %llu,%u to 0,0",
(long long unsigned) s->rate_limit_interval,
s->rate_limit_burst);
s->rate_limit_interval = s->rate_limit_burst = 0;
}
mkdir_p("/run/systemd/journal", 0755);
s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func);
if (!s->user_journals)
return log_oom();
s->mmap = mmap_cache_new();
if (!s->mmap)
return log_oom();
r = sd_event_default(&s->event);
if (r < 0) {
log_error("Failed to create event loop: %s", strerror(-r));
return r;
}
sd_event_set_watchdog(s->event, true);
n = sd_listen_fds(true);
if (n < 0) {
log_error("Failed to read listening file descriptors from environment: %s", strerror(-n));
return n;
}
for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/socket", 0) > 0) {
if (s->native_fd >= 0) {
log_error("Too many native sockets passed.");
return -EINVAL;
}
s->native_fd = fd;
} else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, "/run/systemd/journal/stdout", 0) > 0) {
if (s->stdout_fd >= 0) {
log_error("Too many stdout sockets passed.");
return -EINVAL;
}
s->stdout_fd = fd;
} else if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0) {
if (s->syslog_fd >= 0) {
log_error("Too many /dev/log sockets passed.");
return -EINVAL;
}
s->syslog_fd = fd;
} else {
log_error("Unknown socket passed.");
return -EINVAL;
}
}
r = server_open_syslog_socket(s);
if (r < 0)
return r;
r = server_open_native_socket(s);
if (r < 0)
return r;
r = server_open_stdout_socket(s);
if (r < 0)
return r;
r = server_open_dev_kmsg(s);
if (r < 0)
return r;
r = server_open_kernel_seqnum(s);
if (r < 0)
return r;
r = server_open_hostname(s);
if (r < 0)
return r;
r = setup_signals(s);
if (r < 0)
return r;
s->udev = udev_new();
if (!s->udev)
return -ENOMEM;
s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst);
if (!s->rate_limit)
return -ENOMEM;
r = cg_get_root_path(&s->cgroup_root);
if (r < 0)
return r;
server_cache_hostname(s);
server_cache_boot_id(s);
server_cache_machine_id(s);
r = system_journal_open(s);
if (r < 0)
return r;
return 0;
}
void server_maybe_append_tags(Server *s) {
#ifdef HAVE_GCRYPT
JournalFile *f;
Iterator i;
usec_t n;
n = now(CLOCK_REALTIME);
if (s->system_journal)
journal_file_maybe_append_tag(s->system_journal, n);
HASHMAP_FOREACH(f, s->user_journals, i)
journal_file_maybe_append_tag(f, n);
#endif
}
void server_done(Server *s) {
JournalFile *f;
assert(s);
while (s->stdout_streams)
stdout_stream_free(s->stdout_streams);
if (s->system_journal)
journal_file_close(s->system_journal);
if (s->runtime_journal)
journal_file_close(s->runtime_journal);
while ((f = hashmap_steal_first(s->user_journals)))
journal_file_close(f);
hashmap_free(s->user_journals);
sd_event_source_unref(s->syslog_event_source);
sd_event_source_unref(s->native_event_source);
sd_event_source_unref(s->stdout_event_source);
sd_event_source_unref(s->dev_kmsg_event_source);
sd_event_source_unref(s->sync_event_source);
sd_event_source_unref(s->sigusr1_event_source);
sd_event_source_unref(s->sigusr2_event_source);
sd_event_source_unref(s->sigterm_event_source);
sd_event_source_unref(s->sigint_event_source);
sd_event_source_unref(s->hostname_event_source);
sd_event_unref(s->event);
if (s->syslog_fd >= 0)
close_nointr_nofail(s->syslog_fd);
if (s->native_fd >= 0)
close_nointr_nofail(s->native_fd);
if (s->stdout_fd >= 0)
close_nointr_nofail(s->stdout_fd);
if (s->dev_kmsg_fd >= 0)
close_nointr_nofail(s->dev_kmsg_fd);
if (s->hostname_fd >= 0)
close_nointr_nofail(s->hostname_fd);
if (s->rate_limit)
journal_rate_limit_free(s->rate_limit);
if (s->kernel_seqnum)
munmap(s->kernel_seqnum, sizeof(uint64_t));
free(s->buffer);
free(s->tty_path);
free(s->cgroup_root);
if (s->mmap)
mmap_cache_unref(s->mmap);
if (s->udev)
udev_unref(s->udev);
}