journald-server.c revision ff82c36c792a23a03994af2ae40cbd441e128bb4
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2011 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#ifdef HAVE_SELINUX
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <selinux/selinux.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#endif
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/ioctl.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/mman.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/signalfd.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <sys/statvfs.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <linux/sockios.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "libudev.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "sd-daemon.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "sd-journal.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "sd-messages.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "acl-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "alloc-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "audit-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "cgroup-util.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "conf-parser.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "dirent-util.h"
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek#include "extract-word.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "fd-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "fileio.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "formats-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "fs-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "hashmap.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "hostname-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "io-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journal-authenticate.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journal-file.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journal-internal.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journal-vacuum.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "journald-audit.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "journald-kmsg.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "journald-native.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journald-rate-limit.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journald-server.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journald-stream.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "journald-syslog.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "missing.h"
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering#include "mkdir.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "parse-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "proc-cmdline.h"
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt#include "process-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "rm-rf.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "selinux-util.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "signal-util.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "socket-util.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "string-table.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "string-util.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#include "user-util.h"
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#define USER_JOURNALS_MAX 1024
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#define DEFAULT_RATE_LIMIT_BURST 1000
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define RECHECK_SPACE_USEC (30*USEC_PER_SEC)
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define NOTIFY_SNDBUF_SIZE (8*1024*1024)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int determine_space_for(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Server *s,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering JournalMetrics *metrics,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *path,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *name,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool verbose,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool patch_min_use,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t *available,
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek uint64_t *limit) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint64_t sum = 0, ss_avail, avail;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt _cleanup_closedir_ DIR *d = NULL;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt struct dirent *de;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt struct statvfs ss;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt const char *p;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt usec_t ts;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(metrics);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(name);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ts = now(CLOCK_MONOTONIC);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek if (!verbose && s->cached_space_timestamp + RECHECK_SPACE_USEC > ts) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (available)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *available = s->cached_space_available;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (limit)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *limit = s->cached_space_limit;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering p = strjoina(path, SERVER_MACHINE_ID(s));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering d = opendir(p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!d)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open %s: %m", p);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (fstatvfs(dirfd(d), &ss) < 0)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return log_error_errno(errno, "Failed to fstatvfs(%s): %m", p);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek FOREACH_DIRENT_ALL(de, d, break) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek struct stat st;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!endswith(de->d_name, ".journal") &&
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering !endswith(de->d_name, ".journal~"))
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek continue;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", p, de->d_name);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek continue;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek if (!S_ISREG(st.st_mode))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering continue;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sum += (uint64_t) st.st_blocks * 512UL;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek /* If request, then let's bump the min_use limit to the
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * current usage on disk. We do this when starting up and
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * first opening the journal files. This way sudden spikes in
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * disk usage will not cause journald to vacuum files without
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * bounds. Note that this means that only a restart of
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * journald will make it reset this value. */
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (patch_min_use)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek metrics->min_use = MAX(metrics->min_use, sum);
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek ss_avail = ss.f_bsize * ss.f_bavail;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek avail = LESS_BY(ss_avail, metrics->keep_free);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek s->cached_space_limit = MIN(MAX(sum + avail, metrics->min_use), metrics->max_use);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek s->cached_space_available = LESS_BY(s->cached_space_limit, sum);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek s->cached_space_timestamp = ts;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (verbose) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX];
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "%s (%s) is currently using %s.\n"
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "Maximum allowed usage is set to %s.\n"
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "Leaving at least %s free (of currently available %s of space).\n"
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "Enforced usage limit is thus %s, of which %s are still available.",
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek name, path,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek format_bytes(fb1, sizeof(fb1), sum),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek format_bytes(fb2, sizeof(fb2), metrics->max_use),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek format_bytes(fb3, sizeof(fb3), metrics->keep_free),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek format_bytes(fb4, sizeof(fb4), ss_avail),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek format_bytes(fb5, sizeof(fb5), s->cached_space_limit),
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek format_bytes(fb6, sizeof(fb6), s->cached_space_available));
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek }
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (available)
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek *available = s->cached_space_available;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (limit)
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek *limit = s->cached_space_limit;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return 1;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek}
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic int determine_space(Server *s, bool verbose, bool patch_min_use, uint64_t *available, uint64_t *limit) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek JournalMetrics *metrics;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek const char *path, *name;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert(s);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (s->system_journal) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek path = "/var/log/journal/";
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek metrics = &s->system_metrics;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering name = "System journal";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering path = "/run/log/journal/";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering metrics = &s->runtime_metrics;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek name = "Runtime journal";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return determine_space_for(s, metrics, path, name, verbose, patch_min_use, available, limit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void server_add_acls(JournalFile *f, uid_t uid) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#ifdef HAVE_ACL
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt#endif
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt assert(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek#ifdef HAVE_ACL
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (uid <= SYSTEM_UID_MAX)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt return;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = add_acls_for_user(f->fd, uid);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning_errno(r, "Failed to set ACL on %s, ignoring: %m", f->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#endif
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic JournalFile* find_journal(Server *s, uid_t uid) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_free_ char *p = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering JournalFile *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_id128_t machine;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We split up user logs only on /var, not on /run. If the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * runtime file is open, we write to it exclusively, in order
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * to guarantee proper order as soon as we flush /run to
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * /var and close the runtime file. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (s->runtime_journal)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return s->runtime_journal;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (uid <= SYSTEM_UID_MAX)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return s->system_journal;
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_id128_get_machine(&machine);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return s->system_journal;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return f;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-"UID_FMT".journal",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SD_ID128_FORMAT_VAL(machine), uid) < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return s->system_journal;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while (ordered_hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Too many open? Then let's close one */
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek f = ordered_hashmap_steal_first(s->user_journals);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek assert(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering journal_file_close(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return s->system_journal;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek server_add_acls(f, uid);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering journal_file_close(f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return s->system_journal;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return f;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek}
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekstatic int do_rotate(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Server *s,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering JournalFile **f,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char* name,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool seal,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint32_t uid) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!*f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -EINVAL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = journal_file_rotate(f, s->compress, seal);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (*f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_errno(r, "Failed to create new %s journal: %m", name);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering server_add_acls(*f, uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid server_rotate(Server *s) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering JournalFile *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering void *k;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Iterator i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Rotating...");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (void) do_rotate(s, &s->runtime_journal, "runtime", false, 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (void) do_rotate(s, &s->system_journal, "system", s->seal, 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = do_rotate(s, &f, "user", s->seal, PTR_TO_UID(k));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ordered_hashmap_replace(s->user_journals, k, f);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Old file has been closed and deallocated */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ordered_hashmap_remove(s->user_journals, k);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid server_sync(Server *s) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering JournalFile *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Iterator i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (s->system_journal) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = journal_file_set_offline(s->system_journal);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning_errno(r, "Failed to sync system journal, ignoring: %m");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = journal_file_set_offline(f);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning_errno(r, "Failed to sync user journal, ignoring: %m");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (s->sync_event_source) {
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF);
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt if (r < 0)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to disable sync timer source: %m");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt s->sync_scheduled = false;
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic void do_vacuum(
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek Server *s,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek JournalFile *f,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek JournalMetrics *metrics,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek const char *path,
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek const char *name,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bool verbose,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek bool patch_min_use) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek const char *p;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek uint64_t limit;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(s);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(metrics);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(path);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(name);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (!f)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek p = strjoina(path, SERVER_MACHINE_ID(s));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek limit = metrics->max_use;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek (void) determine_space_for(s, metrics, path, name, verbose, patch_min_use, NULL, &limit);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = journal_directory_vacuum(p, limit, metrics->n_max_files, s->max_retention_usec, &s->oldest_file_usec, verbose);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0 && r != -ENOENT)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", p);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint server_vacuum(Server *s, bool verbose, bool patch_min_use) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(s);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_debug("Vacuuming...");
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek s->oldest_file_usec = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek do_vacuum(s, s->system_journal, &s->system_metrics, "/var/log/journal/", "System journal", verbose, patch_min_use);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek do_vacuum(s, s->runtime_journal, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", verbose, patch_min_use);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek s->cached_space_limit = 0;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering s->cached_space_available = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek s->cached_space_timestamp = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void server_cache_machine_id(Server *s) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_id128_t id;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_id128_get_machine(&id);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID="));
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void server_cache_boot_id(Server *s) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_id128_t id;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = sd_id128_get_boot(&id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID="));
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek}
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekstatic void server_cache_hostname(Server *s) {
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek _cleanup_free_ char *t = NULL;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek char *x;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering t = gethostname_malloc();
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!t)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek x = strappend("_HOSTNAME=", t);
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek if (!x)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(s->hostname_field);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering s->hostname_field = x;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool shall_try_append_again(JournalFile *f, int r) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* -E2BIG Hit configured limit
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EFBIG Hit fs limit
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EDQUOT Quota limit hit
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek -ENOSPC Disk full
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek -EIO I/O error of some kind (mmap)
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek -EHOSTDOWN Other machine
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EBUSY Unclean shutdown
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EPROTONOSUPPORT Unsupported feature
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EBADMSG Corrupted
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -ENODATA Truncated
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmek -ESHUTDOWN Already archived
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EIDRM Journal file has been deleted */
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_debug("%s: Allocation limit reached, rotating.", f->path);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else if (r == -EHOSTDOWN)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_info("%s: Journal file from other machine, rotating.", f->path);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else if (r == -EBUSY)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("%s: Unclean shutdown, rotating.", f->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (r == -EPROTONOSUPPORT)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_info("%s: Unsupported feature, rotating.", f->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s: Journal file corrupted, rotating.", f->path);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek else if (r == -EIO)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_warning("%s: IO error, rotating.", f->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (r == -EIDRM)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_warning("%s: Journal file has been deleted, rotating.", f->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering JournalFile *f;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool vacuumed = false;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(iovec);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(n > 0);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = find_journal(s, uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering if (journal_file_rotate_suggested(f, s->max_file_usec)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering server_rotate(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering server_vacuum(s, false, false);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering vacuumed = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering f = find_journal(s, uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (r >= 0) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering server_schedule_sync(s, priority);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering if (vacuumed || !shall_try_append_again(f, r)) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_errno(r, "Failed to write entry (%d items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering server_rotate(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering server_vacuum(s, false, false);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering f = find_journal(s, uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!f)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_debug("Retrying write.");
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_error_errno(r, "Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering server_schedule_sync(s, priority);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void dispatch_message_real(
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Server *s,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct iovec *iovec, unsigned n, unsigned m,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const struct ucred *ucred,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const struct timeval *tv,
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering const char *label, size_t label_len,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const char *unit_id,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int priority,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pid_t object_pid) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)],
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uid_t object_uid;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering gid_t object_gid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *x;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char *t, *c;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uid_t realuid = 0, owner = 0, journal_uid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering bool owner_valid = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#ifdef HAVE_AUDIT
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)],
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek uint32_t audit;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uid_t loginuid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#endif
a7f7d1bde43fc825c49afea3f946f5b4b3d563e0Harald Hoyer
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(s);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(iovec);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(n > 0);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (ucred) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek realuid = ucred->uid;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(pid, "_PID="PID_FMT, ucred->pid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], pid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(uid, "_UID="UID_FMT, ucred->uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(gid, "_GID="GID_FMT, ucred->gid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], gid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = get_process_comm(ucred->pid, &t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_COMM=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = get_process_exe(ucred->pid, &t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_EXE=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = get_process_cmdline(ucred->pid, 0, false, &t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_CMDLINE=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = get_process_capeff(ucred->pid, &t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_CAP_EFFECTIVE=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#ifdef HAVE_AUDIT
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = audit_session_from_pid(ucred->pid, &audit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(audit_session, "_AUDIT_SESSION=%"PRIu32, audit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], audit_session);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = audit_loginuid_from_pid(ucred->pid, &loginuid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(audit_loginuid, "_AUDIT_LOGINUID="UID_FMT, loginuid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], audit_loginuid);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek#endif
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r >= 0) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek char *session = NULL;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek x = strjoina("_SYSTEMD_CGROUP=", c);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iovec[n++], x);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = cg_path_get_session(c, &t);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r >= 0) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek session = strjoina("_SYSTEMD_SESSION=", t);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek free(t);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iovec[n++], session);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (cg_path_get_owner_uid(c, &owner) >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering owner_valid = true;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(owner_uid, "_SYSTEMD_OWNER_UID="UID_FMT, owner);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], owner_uid);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (cg_path_get_unit(c, &t) >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_SYSTEMD_UNIT=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (unit_id && !session) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_SYSTEMD_UNIT=", unit_id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (cg_path_get_user_unit(c, &t) >= 0) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering x = strjoina("_SYSTEMD_USER_UNIT=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (unit_id && session) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_SYSTEMD_USER_UNIT=", unit_id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (cg_path_get_slice(c, &t) >= 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_SYSTEMD_SLICE=", t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(t);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(c);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (unit_id) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering x = strjoina("_SYSTEMD_UNIT=", unit_id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IOVEC_SET_STRING(iovec[n++], x);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek#ifdef HAVE_SELINUX
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (mac_selinux_have()) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (label) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek x = alloca(strlen("_SELINUX_CONTEXT=") + label_len + 1);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek *((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer IOVEC_SET_STRING(iovec[n++], x);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek } else {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek security_context_t con;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
c33b329709ebe2755181980a050d02ec7c81ed87Michal Schmidt if (getpidcon(ucred->pid, &con) >= 0) {
c33b329709ebe2755181980a050d02ec7c81ed87Michal Schmidt x = strjoina("_SELINUX_CONTEXT=", con);
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek freecon(con);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iovec[n++], x);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek#endif
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(n <= m);
2e8fb7026d3c560194cfe9f83935ce0b16263da0Lukas Nykryn
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn if (object_pid) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = get_process_uid(object_pid, &object_uid);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r >= 0) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek sprintf(o_uid, "OBJECT_UID="UID_FMT, object_uid);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iovec[n++], o_uid);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek }
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = get_process_gid(object_pid, &object_gid);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (r >= 0) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek sprintf(o_gid, "OBJECT_GID="GID_FMT, object_gid);
IOVEC_SET_STRING(iovec[n++], o_gid);
}
r = get_process_comm(object_pid, &t);
if (r >= 0) {
x = strjoina("OBJECT_COMM=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_exe(object_pid, &t);
if (r >= 0) {
x = strjoina("OBJECT_EXE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
r = get_process_cmdline(object_pid, 0, false, &t);
if (r >= 0) {
x = strjoina("OBJECT_CMDLINE=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
#ifdef HAVE_AUDIT
r = audit_session_from_pid(object_pid, &audit);
if (r >= 0) {
sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%"PRIu32, audit);
IOVEC_SET_STRING(iovec[n++], o_audit_session);
}
r = audit_loginuid_from_pid(object_pid, &loginuid);
if (r >= 0) {
sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID="UID_FMT, loginuid);
IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
}
#endif
r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
if (r >= 0) {
x = strjoina("OBJECT_SYSTEMD_CGROUP=", c);
IOVEC_SET_STRING(iovec[n++], x);
r = cg_path_get_session(c, &t);
if (r >= 0) {
x = strjoina("OBJECT_SYSTEMD_SESSION=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_owner_uid(c, &owner) >= 0) {
sprintf(o_owner_uid, "OBJECT_SYSTEMD_OWNER_UID="UID_FMT, owner);
IOVEC_SET_STRING(iovec[n++], o_owner_uid);
}
if (cg_path_get_unit(c, &t) >= 0) {
x = strjoina("OBJECT_SYSTEMD_UNIT=", t);
free(t);
IOVEC_SET_STRING(iovec[n++], x);
}
if (cg_path_get_user_unit(c, &t) >= 0) {
x = strjoina("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. 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 + 6];
int n = 0;
va_list ap;
struct ucred ucred = {};
assert(s);
assert(format);
IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3");
IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald");
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);
IOVEC_SET_STRING(iovec[n++], buffer);
if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id));
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,
const struct ucred *ucred,
const struct timeval *tv,
const char *label, size_t label_len,
const char *unit_id,
int priority,
pid_t object_pid) {
int rl, r;
_cleanup_free_ char *path = NULL;
uint64_t available = 0;
char *c;
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;
}
}
(void) determine_space(s, false, false, &available, NULL);
rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available);
if (rl == 0)
return;
/* Write a suppression message if we suppressed something */
if (rl > 1)
server_driver_message(s, 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, bool flush_requested) {
const char *fn;
int r = 0;
if (!s->system_journal &&
(s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
(flush_requested
|| 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_p("/var/log/journal/", 0755);
fn = strjoina("/var/log/journal/", SERVER_MACHINE_ID(s));
(void) mkdir(fn, 0755);
fn = strjoina(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_add_acls(s->system_journal, 0);
(void) determine_space_for(s, &s->system_metrics, "/var/log/journal/", "System journal", true, true, NULL, NULL);
} else if (r < 0) {
if (r != -ENOENT && r != -EROFS)
log_warning_errno(r, "Failed to open system journal: %m");
r = 0;
}
}
if (!s->runtime_journal &&
(s->storage != STORAGE_NONE)) {
fn = strjoina("/run/log/journal/", SERVER_MACHINE_ID(s), "/system.journal");
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);
if (r < 0) {
if (r != -ENOENT)
log_warning_errno(r, "Failed to open runtime journal: %m");
r = 0;
}
} else {
/* OK, we really need the runtime journal, so create
* it if necessary. */
(void) mkdir("/run/log", 0755);
(void) mkdir("/run/log/journal", 0755);
(void) mkdir_parents(fn, 0750);
r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
if (r < 0)
return log_error_errno(r, "Failed to open runtime journal: %m");
}
if (s->runtime_journal) {
server_add_acls(s->runtime_journal, 0);
(void) determine_space_for(s, &s->runtime_metrics, "/run/log/journal/", "Runtime journal", true, true, NULL, NULL);
}
}
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;
(void) system_journal_open(s, true);
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)
return log_error_errno(r, "Failed to read runtime journal: %m");
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_errno(r, "Can't read entry: %m");
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_errno(r, "Can't write entry: %m");
goto finish;
}
server_rotate(s);
server_vacuum(s, false, false);
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_errno(r, "Can't write entry: %m");
goto finish;
}
}
r = 0;
finish:
journal_file_post_change(s->system_journal);
s->runtime_journal = journal_file_close(s->runtime_journal);
if (r >= 0)
(void) rm_rf("/run/log/journal", REMOVE_ROOT);
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 server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Server *s = userdata;
struct ucred *ucred = NULL;
struct timeval *tv = NULL;
struct cmsghdr *cmsg;
char *label = NULL;
size_t label_len = 0, m;
struct iovec iovec;
ssize_t n;
int *fds = NULL, v = 0;
unsigned n_fds = 0;
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 = {};
union sockaddr_union sa = {};
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
.msg_control = &control,
.msg_controllen = sizeof(control),
.msg_name = &sa,
.msg_namelen = sizeof(sa),
};
assert(s);
assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd);
if (revents != EPOLLIN) {
log_error("Got invalid event from epoll for datagram fd: %"PRIx32, revents);
return -EIO;
}
/* Try to get the right size, if we can. (Not all
* sockets support SIOCINQ, hence we just try, but
* don't rely on it. */
(void) ioctl(fd, SIOCINQ, &v);
/* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
m = PAGE_ALIGN(MAX3((size_t) v + 1,
(size_t) LINE_MAX,
ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
return log_oom();
iovec.iov_base = s->buffer;
iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (n < 0) {
if (errno == EINTR || errno == EAGAIN)
return 0;
return log_error_errno(errno, "recvmsg() failed: %m");
}
CMSG_FOREACH(cmsg, &msghdr) {
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);
}
}
/* And a trailing NUL, just in case */
s->buffer[n] = 0;
if (fd == s->syslog_fd) {
if (n > 0 && n_fds == 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 (fd == s->native_fd) {
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.");
} else {
assert(fd == s->audit_fd);
if (n > 0 && n_fds == 0)
server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
else if (n_fds > 0)
log_warning("Got file descriptors via audit 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;
int r;
assert(s);
log_info("Received request to flush runtime journal from PID " PID_FMT, si->ssi_pid);
server_flush_to_var(s);
server_sync(s);
server_vacuum(s, false, false);
r = touch("/run/systemd/journal/flushed");
if (r < 0)
log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
return 0;
}
static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
int r;
assert(s);
log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid);
server_rotate(s);
server_vacuum(s, true, true);
/* Let clients know when the most recent rotation happened. */
r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC));
if (r < 0)
log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m");
return 0;
}
static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
assert(s);
log_received_signal(LOG_INFO, si);
sd_event_exit(s->event, 0);
return 0;
}
static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
Server *s = userdata;
int r;
assert(s);
log_debug("Received request to sync from PID " PID_FMT, si->ssi_pid);
server_sync(s);
/* Let clients know when the most recent sync happened. */
r = write_timestamp_file_atomic("/run/systemd/journal/synced", now(CLOCK_MONOTONIC));
if (r < 0)
log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m");
return 0;
}
static int setup_signals(Server *s) {
int r;
assert(s);
assert(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, &s->sigusr2_event_source, SIGUSR2, dispatch_sigusr2, s);
if (r < 0)
return r;
r = sd_event_add_signal(s->event, &s->sigterm_event_source, SIGTERM, dispatch_sigterm, s);
if (r < 0)
return r;
/* Let's process SIGTERM late, so that we flush all queued
* messages to disk before we exit */
r = sd_event_source_set_priority(s->sigterm_event_source, SD_EVENT_PRIORITY_NORMAL+20);
if (r < 0)
return r;
/* When journald is invoked on the terminal (when debugging),
* it's useful if C-c is handled equivalent to SIGTERM. */
r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s);
if (r < 0)
return r;
r = sd_event_source_set_priority(s->sigint_event_source, SD_EVENT_PRIORITY_NORMAL+20);
if (r < 0)
return r;
/* SIGRTMIN+1 causes an immediate sync. We process this very
* late, so that everything else queued at this point is
* really written to disk. Clients can watch
* /run/systemd/journal/synced with inotify until its mtime
* changes to see when a sync happened. */
r = sd_event_add_signal(s->event, &s->sigrtmin1_event_source, SIGRTMIN+1, dispatch_sigrtmin1, s);
if (r < 0)
return r;
r = sd_event_source_set_priority(s->sigrtmin1_event_source, SD_EVENT_PRIORITY_NORMAL+15);
if (r < 0)
return r;
return 0;
}
static int server_parse_proc_cmdline(Server *s) {
_cleanup_free_ char *line = NULL;
const char *p;
int r;
r = proc_cmdline(&line);
if (r < 0) {
log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m");
return 0;
}
p = line;
for(;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r < 0)
return log_error_errno(r, "Failed to parse journald syntax \"%s\": %m", line);
if (r == 0)
break;
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.forward_to_wall=")) {
r = parse_boolean(word + 33);
if (r < 0)
log_warning("Failed to parse forward to wall switch %s. Ignoring.", word + 33);
else
s->forward_to_wall = r;
} else if (startswith(word, "systemd.journald"))
log_warning("Invalid systemd.journald parameter. Ignoring.");
}
/* do not warn about state here, since probably systemd already did */
return 0;
}
static int server_parse_config_file(Server *s) {
assert(s);
return config_parse_many(PKGSYSCONFDIR "/journald.conf",
CONF_PATHS_NULSTR("systemd/journald.conf.d"),
"Journal\0",
config_item_perf_lookup, journald_gperf_lookup,
false, s);
}
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_now(s->event, CLOCK_MONOTONIC, &when);
if (r < 0)
return r;
when += s->sync_interval_usec;
if (!s->sync_event_source) {
r = sd_event_add_time(
s->event,
&s->sync_event_source,
CLOCK_MONOTONIC,
when, 0,
server_dispatch_sync, s);
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)
return log_error_errno(errno, "Failed to open /proc/sys/kernel/hostname: %m");
r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s);
if (r < 0) {
/* kernels prior to 3.2 don't support polling this file. Ignore
* the failure. */
if (r == -EPERM) {
log_warning_errno(r, "Failed to register hostname fd in event loop, ignoring: %m");
s->hostname_fd = safe_close(s->hostname_fd);
return 0;
}
return log_error_errno(r, "Failed to register hostname fd in event loop: %m");
}
r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10);
if (r < 0)
return log_error_errno(r, "Failed to adjust priority of host name event source: %m");
return 0;
}
static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
Server *s = userdata;
int r;
assert(s);
assert(s->notify_event_source == es);
assert(s->notify_fd == fd);
/* The $NOTIFY_SOCKET is writable again, now send exactly one
* message on it. Either it's the wtachdog event, the initial
* READY=1 event or an stdout stream event. If there's nothing
* to write anymore, turn our event source off. The next time
* there's something to send it will be turned on again. */
if (!s->sent_notify_ready) {
static const char p[] =
"READY=1\n"
"STATUS=Processing requests...";
ssize_t l;
l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT);
if (l < 0) {
if (errno == EAGAIN)
return 0;
return log_error_errno(errno, "Failed to send READY=1 notification message: %m");
}
s->sent_notify_ready = true;
log_debug("Sent READY=1 notification.");
} else if (s->send_watchdog) {
static const char p[] =
"WATCHDOG=1";
ssize_t l;
l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT);
if (l < 0) {
if (errno == EAGAIN)
return 0;
return log_error_errno(errno, "Failed to send WATCHDOG=1 notification message: %m");
}
s->send_watchdog = false;
log_debug("Sent WATCHDOG=1 notification.");
} else if (s->stdout_streams_notify_queue)
/* Dispatch one stream notification event */
stdout_stream_send_notify(s->stdout_streams_notify_queue);
/* Leave us enabled if there's still more to to do. */
if (s->send_watchdog || s->stdout_streams_notify_queue)
return 0;
/* There was nothing to do anymore, let's turn ourselves off. */
r = sd_event_source_set_enabled(es, SD_EVENT_OFF);
if (r < 0)
return log_error_errno(r, "Failed to turn off notify event source: %m");
return 0;
}
static int dispatch_watchdog(sd_event_source *es, uint64_t usec, void *userdata) {
Server *s = userdata;
int r;
assert(s);
s->send_watchdog = true;
r = sd_event_source_set_enabled(s->notify_event_source, SD_EVENT_ON);
if (r < 0)
log_warning_errno(r, "Failed to turn on notify event source: %m");
r = sd_event_source_set_time(s->watchdog_event_source, usec + s->watchdog_usec / 2);
if (r < 0)
return log_error_errno(r, "Failed to restart watchdog event source: %m");
r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON);
if (r < 0)
return log_error_errno(r, "Failed to enable watchdog event source: %m");
return 0;
}
static int server_connect_notify(Server *s) {
union sockaddr_union sa = {
.un.sun_family = AF_UNIX,
};
const char *e;
int r;
assert(s);
assert(s->notify_fd < 0);
assert(!s->notify_event_source);
/*
So here's the problem: we'd like to send notification
messages to PID 1, but we cannot do that via sd_notify(),
since that's synchronous, and we might end up blocking on
it. Specifically: given that PID 1 might block on
dbus-daemon during IPC, and dbus-daemon is logging to us,
and might hence block on us, we might end up in a deadlock
if we block on sending PID 1 notification messages -- by
generating a full blocking circle. To avoid this, let's
create a non-blocking socket, and connect it to the
notification socket, and then wait for POLLOUT before we
send anything. This should efficiently avoid any deadlocks,
as we'll never block on PID 1, hence PID 1 can safely block
on dbus-daemon which can safely block on us again.
Don't think that this issue is real? It is, see:
https://github.com/systemd/systemd/issues/1505
*/
e = getenv("NOTIFY_SOCKET");
if (!e)
return 0;
if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
log_error("NOTIFY_SOCKET set to an invalid value: %s", e);
return -EINVAL;
}
if (strlen(e) > sizeof(sa.un.sun_path)) {
log_error("NOTIFY_SOCKET path too long: %s", e);
return -EINVAL;
}
s->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (s->notify_fd < 0)
return log_error_errno(errno, "Failed to create notify socket: %m");
(void) fd_inc_sndbuf(s->notify_fd, NOTIFY_SNDBUF_SIZE);
strncpy(sa.un.sun_path, e, sizeof(sa.un.sun_path));
if (sa.un.sun_path[0] == '@')
sa.un.sun_path[0] = 0;
r = connect(s->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(e));
if (r < 0)
return log_error_errno(errno, "Failed to connect to notify socket: %m");
r = sd_event_add_io(s->event, &s->notify_event_source, s->notify_fd, EPOLLOUT, dispatch_notify_event, s);
if (r < 0)
return log_error_errno(r, "Failed to watch notification socket: %m");
if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) {
s->send_watchdog = true;
r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s);
if (r < 0)
return log_error_errno(r, "Failed to add watchdog time event: %m");
}
/* This should fire pretty soon, which we'll use to send the
* READY=1 event. */
return 0;
}
int server_init(Server *s) {
_cleanup_fdset_free_ FDSet *fds = NULL;
int n, r, fd;
bool no_sockets;
assert(s);
zero(*s);
s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1;
s->compress = true;
s->seal = true;
s->watchdog_usec = USEC_INFINITY;
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_wall = true;
s->max_file_usec = DEFAULT_MAX_FILE_USEC;
s->max_level_store = LOG_DEBUG;
s->max_level_syslog = LOG_DEBUG;
s->max_level_kmsg = LOG_NOTICE;
s->max_level_console = LOG_INFO;
s->max_level_wall = LOG_EMERG;
journal_reset_metrics(&s->system_metrics);
journal_reset_metrics(&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 "USEC_FMT",%u to 0,0",
s->rate_limit_interval, s->rate_limit_burst);
s->rate_limit_interval = s->rate_limit_burst = 0;
}
(void) mkdir_p("/run/systemd/journal", 0755);
s->user_journals = ordered_hashmap_new(NULL);
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)
return log_error_errno(r, "Failed to create event loop: %m");
n = sd_listen_fds(true);
if (n < 0)
return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
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 ||
sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/dev-log", 0) > 0) {
if (s->syslog_fd >= 0) {
log_error("Too many /dev/log sockets passed.");
return -EINVAL;
}
s->syslog_fd = fd;
} else if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
if (s->audit_fd >= 0) {
log_error("Too many audit sockets passed.");
return -EINVAL;
}
s->audit_fd = fd;
} else {
if (!fds) {
fds = fdset_new();
if (!fds)
return log_oom();
}
r = fdset_put(fds, fd);
if (r < 0)
return log_oom();
}
}
/* Try to restore streams, but don't bother if this fails */
(void) server_restore_streams(s, fds);
if (fdset_size(fds) > 0) {
log_warning("%u unknown file descriptors passed, closing.", fdset_size(fds));
fds = fdset_free(fds);
}
no_sockets = s->native_fd < 0 && s->stdout_fd < 0 && s->syslog_fd < 0 && s->audit_fd < 0;
/* always open stdout, syslog, native, and kmsg sockets */
/* systemd-journald.socket: /run/systemd/journal/stdout */
r = server_open_stdout_socket(s);
if (r < 0)
return r;
/* systemd-journald-dev-log.socket: /run/systemd/journal/dev-log */
r = server_open_syslog_socket(s);
if (r < 0)
return r;
/* systemd-journald.socket: /run/systemd/journal/socket */
r = server_open_native_socket(s);
if (r < 0)
return r;
/* /dev/ksmg */
r = server_open_dev_kmsg(s);
if (r < 0)
return r;
/* Unless we got *some* sockets and not audit, open audit socket */
if (s->audit_fd >= 0 || no_sockets) {
r = server_open_audit(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);
(void) server_connect_notify(s);
return system_journal_open(s, false);
}
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);
ORDERED_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 = ordered_hashmap_steal_first(s->user_journals)))
journal_file_close(f);
ordered_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->audit_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->sigrtmin1_event_source);
sd_event_source_unref(s->hostname_event_source);
sd_event_source_unref(s->notify_event_source);
sd_event_source_unref(s->watchdog_event_source);
sd_event_unref(s->event);
safe_close(s->syslog_fd);
safe_close(s->native_fd);
safe_close(s->stdout_fd);
safe_close(s->dev_kmsg_fd);
safe_close(s->audit_fd);
safe_close(s->hostname_fd);
safe_close(s->notify_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);
free(s->hostname_field);
if (s->mmap)
mmap_cache_unref(s->mmap);
udev_unref(s->udev);
}
static const char* const storage_table[_STORAGE_MAX] = {
[STORAGE_AUTO] = "auto",
[STORAGE_VOLATILE] = "volatile",
[STORAGE_PERSISTENT] = "persistent",
[STORAGE_NONE] = "none"
};
DEFINE_STRING_TABLE_LOOKUP(storage, Storage);
DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
static const char* const split_mode_table[_SPLIT_MAX] = {
[SPLIT_LOGIN] = "login",
[SPLIT_UID] = "uid",
[SPLIT_NONE] = "none",
};
DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");