journald-server.c revision 2c5859afecee81e345fc9526b1083bf79990ffb8
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye/***
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye This file is part of systemd.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye Copyright 2011 Lennart Poettering
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye systemd is free software; you can redistribute it and/or modify it
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye under the terms of the GNU Lesser General Public License as published by
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye the Free Software Foundation; either version 2.1 of the License, or
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye (at your option) any later version.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye systemd is distributed in the hope that it will be useful, but
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye WITHOUT ANY WARRANTY; without even the implied warranty of
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye Lesser General Public License for more details.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye You should have received a copy of the GNU Lesser General Public License
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye along with systemd; If not, see <http://www.gnu.org/licenses/>.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye***/
fe80b749cd764b1f0f72b2f913b1fe10581911c3Knut Anders Hatlen
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <sys/signalfd.h>
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <sys/ioctl.h>
cf1f7b5e81583dfca30972cfef322266a6928e7fKnut Anders Hatlen#include <linux/sockios.h>
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <sys/statvfs.h>
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#include <sys/mman.h>
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#include <sys/timerfd.h>
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#include <libudev.h>
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "sd-journal.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "sd-messages.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "sd-daemon.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "fileio.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "mkdir.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "hashmap.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journal-file.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "socket-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "cgroup-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "list.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "missing.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "conf-parser.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "selinux-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journal-internal.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journal-vacuum.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journal-authenticate.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-rate-limit.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-kmsg.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-syslog.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-stream.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-console.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-native.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "journald-server.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#ifdef HAVE_ACL
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <sys/acl.h>
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <acl/libacl.h>
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "acl-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#endif
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#ifdef HAVE_SELINUX
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <selinux/selinux.h>
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#endif
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#define USER_JOURNALS_MAX 1024
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC)
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#define DEFAULT_RATE_LIMIT_BURST 1000
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbyestatic const char* const storage_table[_STORAGE_MAX] = {
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [STORAGE_AUTO] = "auto",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [STORAGE_VOLATILE] = "volatile",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [STORAGE_PERSISTENT] = "persistent",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [STORAGE_NONE] = "none"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye};
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond NorbyeDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
64b763950bf11e9357facbd2b5666631a895c085Trond NorbyeDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbyestatic const char* const split_mode_table[_SPLIT_MAX] = {
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [SPLIT_LOGIN] = "login",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [SPLIT_UID] = "uid",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye [SPLIT_NONE] = "none",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye};
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond NorbyeDEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
64b763950bf11e9357facbd2b5666631a895c085Trond NorbyeDEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting");
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbyestatic uint64_t available_space(Server *s, bool verbose) {
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye char ids[33];
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen _cleanup_free_ char *p = NULL;
b4c9214a3933505203cfad32e6a8d3ba86b0ada2Trond Norbye sd_id128_t machine;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen struct statvfs ss;
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner uint64_t sum = 0, ss_avail = 0, avail = 0;
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner int r;
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik _cleanup_closedir_ DIR *d = NULL;
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik usec_t ts;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik const char *f;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik JournalMetrics *m;
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik ts = now(CLOCK_MONOTONIC);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen && !verbose)
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen return s->cached_available_space;
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik r = sd_id128_get_machine(&machine);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen if (r < 0)
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco return 0;
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlen
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlen if (s->system_journal) {
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlen f = "/var/log/journal/";
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye m = &s->system_metrics;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye } else {
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco f = "/run/log/journal/";
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco m = &s->runtime_metrics;
1ed6b730409d4740e941142599767d5eac7e7d92Lubos Kosco }
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik assert(m);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye p = strappend(f, sd_id128_to_string(machine, ids));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (!p)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik return 0;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik d = opendir(p);
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik if (!d)
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco return 0;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (fstatvfs(dirfd(d), &ss) < 0)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik return 0;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik for (;;) {
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco struct stat st;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik struct dirent *de;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik errno = 0;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik de = readdir(d);
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco if (!de && errno != 0)
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik return 0;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik if (!de)
1ed6b730409d4740e941142599767d5eac7e7d92Lubos Kosco break;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
1ed6b730409d4740e941142599767d5eac7e7d92Lubos Kosco if (!endswith(de->d_name, ".journal") &&
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik !endswith(de->d_name, ".journal~"))
4d93e73b35c5009898b59c9bd7e6629ac5942c2cLubos Kosco continue;
4d93e73b35c5009898b59c9bd7e6629ac5942c2cLubos Kosco
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco continue;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco if (!S_ISREG(st.st_mode))
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco continue;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco sum += (uint64_t) st.st_blocks * 512UL;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco }
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco ss_avail = ss.f_bsize * ss.f_bavail;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
ecc9697029dc3bde02537b914756f7c49eb7cd1eLubos Kosco /* If we reached a high mark, we will always allow this much
ecc9697029dc3bde02537b914756f7c49eb7cd1eLubos Kosco * again, unless usage goes above max_use. This watermark
45909b3ef8c6e568a87482cb890fec7b5dbb7733Lubos Kosco * value is cached so that we don't give up space on pressure,
45909b3ef8c6e568a87482cb890fec7b5dbb7733Lubos Kosco * but hover below the maximum usage. */
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco if (m->use < sum)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye m->use = sum;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco avail = LESS_BY(ss_avail, m->keep_free);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco s->cached_available_space = LESS_BY(MIN(m->max_use, avail), sum);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco s->cached_available_space_timestamp = ts;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco if (verbose) {
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX],
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX];
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE,
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco "%s journal is using %s (max allowed %s, "
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco "trying to leave %s free of %s available → current limit %s).",
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco s->system_journal ? "Permanent" : "Runtime",
e3bec3188dc818cc194cd67e6871c6d0af0d6b26Felix Annan format_bytes(fb1, sizeof(fb1), sum),
e3bec3188dc818cc194cd67e6871c6d0af0d6b26Felix Annan format_bytes(fb2, sizeof(fb2), m->max_use),
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco format_bytes(fb3, sizeof(fb3), m->keep_free),
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco format_bytes(fb4, sizeof(fb4), ss_avail),
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye format_bytes(fb5, sizeof(fb5), s->cached_available_space + sum));
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye }
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen return s->cached_available_space;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen}
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlenvoid server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen int r;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen#ifdef HAVE_ACL
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye acl_t acl;
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye acl_entry_t entry;
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye acl_permset_t permset;
3d35131df8607ae05b064219b9448afc5c4b550aKnut Anders Hatlen#endif
3d35131df8607ae05b064219b9448afc5c4b550aKnut Anders Hatlen
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye assert(f);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye r = fchmod(f->fd, 0640);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen if (r < 0)
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen log_warning("Failed to fix access mode on %s, ignoring: %s", f->path, strerror(-r));
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen#ifdef HAVE_ACL
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (uid <= 0)
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen return;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen acl = acl_get_fd(f->fd);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen if (!acl) {
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen return;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen }
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen r = acl_find_uid(acl, uid, &entry);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r <= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (acl_create_entry(&acl, &entry) < 0 ||
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen acl_set_tag_type(entry, ACL_USER) < 0 ||
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen acl_set_qualifier(entry, &uid) < 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen goto finish;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen }
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen }
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye /* We do not recalculate the mask unconditionally here,
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye * so that the fchmod() mask above stays intact. */
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye if (acl_get_permset(entry, &permset) < 0 ||
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye acl_add_perm(permset, ACL_READ) < 0 ||
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye calc_acl_mask_if_needed(&acl) < 0) {
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye goto finish;
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye }
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik
d3aa2b921c67d952f62c82503575ea545e274d69Knut Anders Hatlen if (acl_set_fd(f->fd, acl) < 0)
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenfinish:
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik acl_free(acl);
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen#endif
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye}
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlenstatic JournalFile* find_journal(Server *s, uid_t uid) {
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen _cleanup_free_ char *p = NULL;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen int r;
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen JournalFile *f;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen sd_id128_t machine;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye assert(s);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen /* We split up user logs only on /var, not on /run. If the
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco * runtime file is open, we write to it exclusively, in order
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen * to guarantee proper order as soon as we flush /run to
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen * /var and close the runtime file. */
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (s->runtime_journal)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return s->runtime_journal;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (uid <= 0)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye return s->system_journal;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = sd_id128_get_machine(&machine);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r < 0)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye return s->system_journal;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (f)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return f;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal",
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0)
752fbd3cf33aada419c8258959ff5574d2d2047dTrond Norbye return s->system_journal;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen /* Too many open? Then let's close one */
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye f = hashmap_steal_first(s->user_journals);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen assert(f);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen journal_file_close(f);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen }
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &f);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (r < 0)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return s->system_journal;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye server_fix_perms(s, f, uid);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r < 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye journal_file_close(f);
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen return s->system_journal;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye }
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye return f;
2c2a50fade805afbf4a5a880a38648613d7e01aeLubos Kosco}
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye
20a0bde399487a651cdeb66fc8b44b2212036355Trond Norbyevoid server_rotate(Server *s) {
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye JournalFile *f;
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye void *k;
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye Iterator i;
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye int r;
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye log_debug("Rotating...");
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye if (s->runtime_journal) {
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye r = journal_file_rotate(&s->runtime_journal, s->compress, false);
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye if (r < 0)
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen if (s->runtime_journal)
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_error("Failed to create new runtime journal: %s", strerror(-r));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye server_fix_perms(s, s->runtime_journal, 0);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen if (s->system_journal) {
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen r = journal_file_rotate(&s->system_journal, s->compress, s->seal);
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen if (r < 0)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (s->system_journal)
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_error("Failed to create new system journal: %s", strerror(-r));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye server_fix_perms(s, s->system_journal, 0);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = journal_file_rotate(&f, s->compress, s->seal);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r < 0)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (f)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_error("Failed to rotate %s: %s", f->path, strerror(-r));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_error("Failed to create user journal: %s", strerror(-r));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye hashmap_remove(s->user_journals, k);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye hashmap_replace(s->user_journals, k, f);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye server_fix_perms(s, f, PTR_TO_UINT32(k));
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye}
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbyevoid server_sync(Server *s) {
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen JournalFile *f;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen void *k;
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen Iterator i;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye int r;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (s->system_journal) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = journal_file_set_offline(s->system_journal);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r < 0)
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco log_error("Failed to sync system journal: %s", strerror(-r));
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen r = journal_file_set_offline(f);
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik if (r < 0)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik log_error("Failed to sync user journal: %s", strerror(-r));
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik }
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (s->sync_event_source) {
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (r < 0)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik log_error("Failed to disable sync timer source: %s", strerror(-r));
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik }
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik s->sync_scheduled = false;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik}
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
52cf1d63b1f1b231ff1e86eca2058d88560579b5Lubos Koscovoid server_vacuum(Server *s) {
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik char ids[33];
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik sd_id128_t machine;
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik int r;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik log_debug("Vacuuming...");
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik s->oldest_file_usec = 0;
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik r = sd_id128_get_machine(&machine);
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik if (r < 0) {
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik log_error("Failed to get machine ID: %s", strerror(-r));
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik return;
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik }
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik sd_id128_to_string(machine, ids);
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik if (s->system_journal) {
52cf1d63b1f1b231ff1e86eca2058d88560579b5Lubos Kosco char *p = strappenda("/var/log/journal/", ids);
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik r = journal_directory_vacuum(p, s->system_metrics.max_use, s->max_retention_usec, &s->oldest_file_usec);
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik if (r < 0 && r != -ENOENT)
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye log_error("Failed to vacuum %s: %s", p, strerror(-r));
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye }
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik if (s->runtime_journal) {
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye char *p = strappenda("/run/log/journal/", ids);
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->max_retention_usec, &s->oldest_file_usec);
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye if (r < 0 && r != -ENOENT)
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye log_error("Failed to vacuum %s: %s", p, strerror(-r));
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye }
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye s->cached_available_space_timestamp = 0;
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye}
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvikstatic void server_cache_machine_id(Server *s) {
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik sd_id128_t id;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik int r;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik assert(s);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik r = sd_id128_get_machine(&id);
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik if (r < 0)
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik return;
45cf976b01987ad147e9edb54ffab0938dd6c016Trond Norbye
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID="));
54ba62a2c6e74332ffc742cb23faf21615b5d39fLubos Kosco}
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvikstatic void server_cache_boot_id(Server *s) {
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik sd_id128_t id;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik int r;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik assert(s);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik r = sd_id128_get_boot(&id);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik if (r < 0)
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik return;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID="));
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik}
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvikstatic void server_cache_hostname(Server *s) {
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik _cleanup_free_ char *t = NULL;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik char *x;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik assert(s);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
1e13442ac5687540ace78411d98155fca4b3791eKnut Anders Hatlen t = gethostname_malloc();
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik if (!t)
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik return;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco x = strappend("_HOSTNAME=", t);
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco if (!x)
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco return;
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
2ef63dc9adc693ddad2206d323b0a85a1afe70ecJorgen Austvik free(s->hostname_field);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik s->hostname_field = x;
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye}
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbyebool shall_try_append_again(JournalFile *f, int r) {
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco /* -E2BIG Hit configured limit
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -EFBIG Hit fs limit
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -EDQUOT Quota limit hit
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -ENOSPC Disk full
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -EHOSTDOWN Other machine
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -EBUSY Unclean shutdown
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -EPROTONOSUPPORT Unsupported feature
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -EBADMSG Corrupted
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -ENODATA Truncated
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye -ESHUTDOWN Already archived */
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco if (r == -E2BIG || r == -EFBIG || r == -EDQUOT || r == -ENOSPC)
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco log_debug("%s: Allocation limit reached, rotating.", f->path);
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco else if (r == -EHOSTDOWN)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_info("%s: Journal file from other machine, rotating.", f->path);
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco else if (r == -EBUSY)
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco log_info("%s: Unclean shutdown, rotating.", f->path);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else if (r == -EPROTONOSUPPORT)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_info("%s: Unsupported feature, rotating.", f->path);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else if (r == -EBADMSG || r == -ENODATA || r == ESHUTDOWN)
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye log_warning("%s: Journal file corrupted, rotating.", f->path);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye else
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye return false;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye return true;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye}
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Koscostatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n, int priority) {
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco JournalFile *f;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik bool vacuumed = false;
f09d46eefeb5e4db6dc11e02e417b448fa9362a9Jorgen Austvik int r;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik assert(s);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik assert(iovec);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik assert(n > 0);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik f = find_journal(s, uid);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (!f)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik return;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (journal_file_rotate_suggested(f, s->max_file_usec)) {
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik server_rotate(s);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik server_vacuum(s);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik vacuumed = true;
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik f = find_journal(s, uid);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik if (!f)
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik return;
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik }
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
63e0f31920b0818d6f471a066c12da991fb35346Trond Norbye if (r >= 0) {
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik server_schedule_sync(s, priority);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik return;
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik }
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik if (vacuumed || !shall_try_append_again(f, r)) {
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik size_t size = 0;
ede8ae04a015c7d2ae4916e5bb36813b81cb7c30Jorgen Austvik unsigned i;
49180e08afc7cf03413ab108bc71c14e9de1a880Jorgen Austvik for (i = 0; i < n; i++)
ede8ae04a015c7d2ae4916e5bb36813b81cb7c30Jorgen Austvik size += iovec[i].iov_len;
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen log_error("Failed to write entry (%d items, %zu bytes), ignoring: %s", n, size, strerror(-r));
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik return;
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik }
2f93a8465131cf5f18613f02f25a3663575bfe57Lubos Kosco
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye server_rotate(s);
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik server_vacuum(s);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik f = find_journal(s, uid);
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik if (!f)
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik return;
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye log_debug("Retrying write.");
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye if (r < 0) {
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye size_t size = 0;
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik unsigned i;
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik for (i = 0; i < n; i++)
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik size += iovec[i].iov_len;
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye log_error("Failed to write entry (%d items, %zu bytes) despite vacuuming, ignoring: %s", n, size, strerror(-r));
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen } else
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen server_schedule_sync(s, priority);
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen}
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlenstatic void dispatch_message_real(
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye Server *s,
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye struct iovec *iovec, unsigned n, unsigned m,
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye struct ucred *ucred,
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye struct timeval *tv,
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye const char *label, size_t label_len,
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye const char *unit_id,
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye int priority,
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlen pid_t object_pid) {
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlen
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye char pid[sizeof("_PID=") + DECIMAL_STR_MAX(pid_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye uid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye gid[sizeof("_GID=") + DECIMAL_STR_MAX(gid_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye owner_uid[sizeof("_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye uid_t object_uid;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye gid_t object_gid;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye char *x;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye int r;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye char *t, *c;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye uid_t realuid = 0, owner = 0, journal_uid;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye bool owner_valid = false;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#ifdef HAVE_AUDIT
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye char audit_session[sizeof("_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik audit_loginuid[sizeof("_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)],
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik o_audit_session[sizeof("OBJECT_AUDIT_SESSION=") + DECIMAL_STR_MAX(uint32_t)],
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen o_audit_loginuid[sizeof("OBJECT_AUDIT_LOGINUID=") + DECIMAL_STR_MAX(uid_t)];
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye uint32_t audit;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye uid_t loginuid;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#endif
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye assert(s);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye assert(iovec);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen assert(n > 0);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen assert(n + N_IOVEC_META_FIELDS + (object_pid ? N_IOVEC_OBJECT_FIELDS : 0) <= m);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen if (ucred) {
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen realuid = ucred->uid;
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen sprintf(pid, "_PID=%lu", (unsigned long) ucred->pid);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen IOVEC_SET_STRING(iovec[n++], pid);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen sprintf(uid, "_UID=%lu", (unsigned long) ucred->uid);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen IOVEC_SET_STRING(iovec[n++], uid);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen sprintf(gid, "_GID=%lu", (unsigned long) ucred->gid);
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen IOVEC_SET_STRING(iovec[n++], gid);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = get_process_comm(ucred->pid, &t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("_COMM=", t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(t);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen IOVEC_SET_STRING(iovec[n++], x);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen }
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik r = get_process_exe(ucred->pid, &t);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik if (r >= 0) {
4c0668d038ecec0f5f4f4cc3d7a177d8e118c955Knut Anders Hatlen x = strappenda("_EXE=", t);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik free(t);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik IOVEC_SET_STRING(iovec[n++], x);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik }
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik r = get_process_cmdline(ucred->pid, 0, false, &t);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik if (r >= 0) {
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik x = strappenda("_CMDLINE=", t);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik free(t);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik IOVEC_SET_STRING(iovec[n++], x);
4b08e2231abb7a3b44ab9255eca7963e6309aba4Jorgen Austvik }
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik r = get_process_capeff(ucred->pid, &t);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik if (r >= 0) {
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik x = strappenda("_CAP_EFFECTIVE=", t);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik free(t);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik IOVEC_SET_STRING(iovec[n++], x);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik }
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik#ifdef HAVE_AUDIT
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik r = audit_session_from_pid(ucred->pid, &audit);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik if (r >= 0) {
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik sprintf(audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik IOVEC_SET_STRING(iovec[n++], audit_session);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik }
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik r = audit_loginuid_from_pid(ucred->pid, &loginuid);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik if (r >= 0) {
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik sprintf(audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik IOVEC_SET_STRING(iovec[n++], audit_loginuid);
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik }
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik#endif
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik r = cg_pid_get_path_shifted(ucred->pid, s->cgroup_root, &c);
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen if (r >= 0) {
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen char *session = NULL;
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen x = strappenda("_SYSTEMD_CGROUP=", c);
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen IOVEC_SET_STRING(iovec[n++], x);
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen r = cg_path_get_session(c, &t);
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen if (r >= 0) {
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen session = strappenda("_SYSTEMD_SESSION=", t);
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen free(t);
d3aa2b921c67d952f62c82503575ea545e274d69Knut Anders Hatlen IOVEC_SET_STRING(iovec[n++], session);
d3aa2b921c67d952f62c82503575ea545e274d69Knut Anders Hatlen }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (cg_path_get_owner_uid(c, &owner) >= 0) {
6ba6a49186aff8de4dc5251195b9917021b5ee69Knut Anders Hatlen owner_valid = true;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye sprintf(owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], owner_uid);
d3aa2b921c67d952f62c82503575ea545e274d69Knut Anders Hatlen }
d3aa2b921c67d952f62c82503575ea545e274d69Knut Anders Hatlen
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner if (cg_path_get_unit(c, &t) >= 0) {
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner x = strappenda("_SYSTEMD_UNIT=", t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye } else if (unit_id && !session) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("_SYSTEMD_UNIT=", unit_id);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (cg_path_get_user_unit(c, &t) >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("_SYSTEMD_USER_UNIT=", t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner } else if (unit_id && session) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("_SYSTEMD_USER_UNIT=", unit_id);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (cg_path_get_slice(c, &t) >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("_SYSTEMD_SLICE=", t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
7c9ef1dc8277e4664577a4db666ec72024645c32Trond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(c);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye } else if (unit_id) {
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner x = strappenda("_SYSTEMD_UNIT=", unit_id);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#ifdef HAVE_SELINUX
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (use_selinux()) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (label) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = alloca(sizeof("_SELINUX_CONTEXT=") + label_len);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye *((char*) mempcpy(stpcpy(x, "_SELINUX_CONTEXT="), label, label_len)) = 0;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye } else {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye security_context_t con;
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (getpidcon(ucred->pid, &con) >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("_SELINUX_CONTEXT=", con);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye freecon(con);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#endif
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye assert(n <= m);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (object_pid) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = get_process_uid(object_pid, &object_uid);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye sprintf(o_uid, "OBJECT_UID=%lu", (unsigned long) object_uid);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], o_uid);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = get_process_gid(object_pid, &object_gid);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye sprintf(o_gid, "OBJECT_GID=%lu", (unsigned long) object_gid);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], o_gid);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = get_process_comm(object_pid, &t);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("OBJECT_COMM=", t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = get_process_exe(object_pid, &t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye x = strappenda("OBJECT_EXE=", t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye free(t);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner IOVEC_SET_STRING(iovec[n++], x);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner }
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner r = get_process_cmdline(object_pid, 0, false, &t);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner if (r >= 0) {
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner x = strappenda("OBJECT_CMDLINE=", t);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner free(t);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner IOVEC_SET_STRING(iovec[n++], x);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#ifdef HAVE_AUDIT
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner r = audit_session_from_pid(object_pid, &audit);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye sprintf(o_audit_session, "OBJECT_AUDIT_SESSION=%lu", (unsigned long) audit);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner IOVEC_SET_STRING(iovec[n++], o_audit_session);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = audit_loginuid_from_pid(object_pid, &loginuid);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner if (r >= 0) {
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye sprintf(o_audit_loginuid, "OBJECT_AUDIT_LOGINUID=%lu", (unsigned long) loginuid);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner IOVEC_SET_STRING(iovec[n++], o_audit_loginuid);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner }
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye#endif
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner r = cg_pid_get_path_shifted(object_pid, s->cgroup_root, &c);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner if (r >= 0) {
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner x = strappenda("OBJECT_SYSTEMD_CGROUP=", c);
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner IOVEC_SET_STRING(iovec[n++], x);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye r = cg_path_get_session(c, &t);
d4ce228a333ba2daa19ad8b0672a704c8e42a2dcTrond Norbye if (r >= 0) {
7e33e87b7d6c9a61ff11d23e37c02274b1223ce1Jens Elkner x = strappenda("OBJECT_SYSTEMD_SESSION=", t);
60776cc3939a32a5de92eed6808b45e38bbaff57Trond Norbye free(t);
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye 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);
}
}
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_received_signal(LOG_INFO, si);
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, &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;
r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s);
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, &s->sync_event_source, 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) {
log_error("Failed to open /proc/sys/kernel/hostname: %m");
return -errno;
}
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("Failed to register hostname fd in event loop: %s. Ignoring.",
strerror(-r));
close_nointr_nofail(s->hostname_fd);
s->hostname_fd = -1;
return 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);
}