journald.c revision 99add6fd0b8f4307ed79256e25f38da318e795c4
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering This file is part of systemd.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Copyright 2011 Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering (at your option) any later version.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is distributed in the hope that it will be useful, but
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
de97b26ac5e29063632312ec1a20eb6318ca924cLennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
9cfb57c989b62d11c073c77179df4bb7fa19f35dLennart Poettering#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart Poetteringstatic const char* const storage_table[] = {
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(storage, Storage);
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting");
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poetteringstatic uint64_t available_space(Server *s) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering const char *f;
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering uint64_t sum = 0, avail = 0, ss_avail = 0;
9cfb57c989b62d11c073c77179df4bb7fa19f35dLennart Poettering if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering p = strappend(f, sd_id128_to_string(machine, ids));
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering avail = sum >= m->max_use ? 0 : m->max_use - sum;
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
9cfb57c989b62d11c073c77179df4bb7fa19f35dLennart Poettering s->cached_available_space_timestamp = ts;
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poetteringstatic void server_read_file_gid(Server *s) {
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering log_warning("Failed to resolve 'adm' group: %s", strerror(-r));
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering /* if we couldn't read the gid, then it will be 0, but that's
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering * fine and we shouldn't try to resolve the group again, so
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering * let's just pretend it worked right-away. */
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poetteringstatic void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (acl_create_entry(&acl, &entry) < 0 ||
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering if (acl_get_permset(entry, &permset) < 0 ||
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poetteringstatic JournalFile* find_journal(Server *s, uid_t uid) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering /* We split up user logs only on /var, not on /run. If the
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering * runtime file is open, we write to it exclusively, in order
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering * to guarantee proper order as soon as we flush /run to
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering * /var and close the runtime file. */
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-%lu.journal",
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering SD_ID128_FORMAT_VAL(machine), (unsigned long) uid) < 0)
cab8ac60837b489b27a247990f741315c71cb389Lennart Poettering while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
cab8ac60837b489b27a247990f741315c71cb389Lennart Poettering /* Too many open? Then let's close one */
cab8ac60837b489b27a247990f741315c71cb389Lennart Poettering f = hashmap_steal_first(s->user_journals);
eb53b74f7e2f83d936b35107806a157fdffdbf5aLennart Poettering r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, s->system_journal, &f);
f4b4781191e8edfb5690e4447166e3ba7bcb48f5Lennart Poettering r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering r = journal_file_rotate(&s->runtime_journal, s->compress, false);
499fb2152f8518796607dd0406698cb6ce4c7098Sjoerd Simons log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
499fb2152f8518796607dd0406698cb6ce4c7098Sjoerd Simons log_error("Failed to create new runtime journal: %s", strerror(-r));
5e62067d08d989ab98b12497a9b27a877de8515bLennart Poettering server_fix_perms(s, s->runtime_journal, 0);
eb53b74f7e2f83d936b35107806a157fdffdbf5aLennart Poettering r = journal_file_rotate(&s->system_journal, s->compress, s->seal);
499fb2152f8518796607dd0406698cb6ce4c7098Sjoerd Simons log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
499fb2152f8518796607dd0406698cb6ce4c7098Sjoerd Simons log_error("Failed to create new system journal: %s", strerror(-r));
5e62067d08d989ab98b12497a9b27a877de8515bLennart Poettering server_fix_perms(s, s->system_journal, 0);
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
eb53b74f7e2f83d936b35107806a157fdffdbf5aLennart Poettering r = journal_file_rotate(&f, s->compress, s->seal);
499fb2152f8518796607dd0406698cb6ce4c7098Sjoerd Simons log_error("Failed to rotate %s: %s", f->path, strerror(-r));
499fb2152f8518796607dd0406698cb6ce4c7098Sjoerd Simons log_error("Failed to create user journal: %s", strerror(-r));
5e62067d08d989ab98b12497a9b27a877de8515bLennart Poettering server_fix_perms(s, s->system_journal, PTR_TO_UINT32(k));
bc85bfee87e11317fbcd1160c9003860dc6edde9Lennart Poettering log_error("Failed to get machine ID: %s", strerror(-r));
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free);
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering if (r < 0 && r != -ENOENT)
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering log_error("Failed to vacuum %s: %s", p, strerror(-r));
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free);
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering if (r < 0 && r != -ENOENT)
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering log_error("Failed to vacuum %s: %s", p, strerror(-r));
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poetteringstatic char *shortened_cgroup_path(pid_t pid) {
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &process_path);
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &init_path);
783d2675eff73d1937bf8f78b368b1004c2d28c5Lennart Poettering if (startswith(process_path, init_path)) {
783d2675eff73d1937bf8f78b368b1004c2d28c5Lennart Poettering p = strdup(process_path + strlen(init_path));
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poetteringstatic void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned n) {
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering log_info("Journal header limits reached or header out-of-date, rotating.");
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
71fa6f006f92831c0c02e844b4c35e4b7197c6d6Lennart Poettering r != -EPROTONOSUPPORT && /* unsupported feature */
71fa6f006f92831c0c02e844b4c35e4b7197c6d6Lennart Poettering r != -ESHUTDOWN /* already archived */)) {
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering log_error("Failed to write entry, ignoring: %s", strerror(-r));
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering if (r == -E2BIG || r == -EFBIG || r == EDQUOT || r == ENOSPC)
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering log_info("Allocation limit reached, rotating.");
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering else if (r == -EHOSTDOWN)
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering log_info("Journal file from other machine, rotating.");
71fa6f006f92831c0c02e844b4c35e4b7197c6d6Lennart Poettering else if (r == -EBUSY)
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering log_warning("Journal file corrupted, rotating.");
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering struct iovec *iovec, unsigned n, unsigned m,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char *pid = NULL, *uid = NULL, *gid = NULL,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering *source_time = NULL, *boot_id = NULL, *machine_id = NULL,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering *comm = NULL, *cmdline = NULL, *hostname = NULL,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering *audit_session = NULL, *audit_loginuid = NULL,
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering *exe = NULL, *cgroup = NULL, *session = NULL,
8a0f04e6a283cc6734ee09a20305c13e09ba0418Lennart Poettering *owner_uid = NULL, *unit = NULL, *selinux_context = NULL;
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&pid, "_PID=%lu", (unsigned long) ucred->pid) >= 0)
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&uid, "_UID=%lu", (unsigned long) ucred->uid) >= 0)
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&gid, "_GID=%lu", (unsigned long) ucred->gid) >= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering r = get_process_cmdline(ucred->pid, LINE_MAX, false, &t);
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering r = audit_session_from_pid(ucred->pid, &audit);
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit) >= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering IOVEC_SET_STRING(iovec[n++], audit_session);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering r = audit_loginuid_from_pid(ucred->pid, &loginuid);
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering IOVEC_SET_STRING(iovec[n++], audit_loginuid);
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering cgroup = strappend("_SYSTEMD_CGROUP=", t);
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering if (sd_pid_get_session(ucred->pid, &t) >= 0) {
85d83bf41c8bdf55c10b7f845d81e5787ef6c295Lennart Poettering session = strappend("_SYSTEMD_SESSION=", t);
ba1261bc02693ac8a7712ade14aab8e22989ba88Lennart Poettering if (sd_pid_get_owner_uid(ucred->uid, &owner) >= 0)
ba1261bc02693ac8a7712ade14aab8e22989ba88Lennart Poettering if (asprintf(&owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner) >= 0)
ba1261bc02693ac8a7712ade14aab8e22989ba88Lennart Poettering if (cg_pid_get_unit(ucred->pid, &t) >= 0) {
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering selinux_context = malloc(sizeof("_SELINUX_CONTEXT=") + label_len);
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering memcpy(selinux_context, "_SELINUX_CONTEXT=", sizeof("_SELINUX_CONTEXT=")-1);
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering memcpy(selinux_context+sizeof("_SELINUX_CONTEXT=")-1, label, label_len);
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering selinux_context[sizeof("_SELINUX_CONTEXT=")-1+label_len] = 0;
8a0f04e6a283cc6734ee09a20305c13e09ba0418Lennart Poettering IOVEC_SET_STRING(iovec[n++], selinux_context);
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering selinux_context = strappend("_SELINUX_CONTEXT=", con);
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering IOVEC_SET_STRING(iovec[n++], selinux_context);
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu",
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering (unsigned long long) timeval_load(tv)) >= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering IOVEC_SET_STRING(iovec[n++], source_time);
ed49ef3f349bcd4f0483ba8254a2537fe8e9cd17Lennart Poettering /* Note that strictly speaking storing the boot id here is
ed49ef3f349bcd4f0483ba8254a2537fe8e9cd17Lennart Poettering * redundant since the entry includes this in-line
ed49ef3f349bcd4f0483ba8254a2537fe8e9cd17Lennart Poettering * anyway. However, we need this indexed, too. */
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&boot_id, "_BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
de190aef08bb267b645205a747762df573b36834Lennart Poettering if (asprintf(&machine_id, "_MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering IOVEC_SET_STRING(iovec[n++], machine_id);
dca6219e04505e9fa10b32e71059ce2abfae1dadLennart Poettering write_to_journal(s, realuid == 0 ? 0 : loginuid, iovec, n);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringvoid server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
33eb8abfa51d5bffbf8819215fafdd1123a4a8c0Lennart Poettering struct iovec iovec[N_IOVEC_META_FIELDS + 4];
c51742d02981196f992aef5f3d72799f22ee89e0Lennart Poettering IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
33eb8abfa51d5bffbf8819215fafdd1123a4a8c0Lennart Poettering IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering snprintf(mid, sizeof(mid), "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(message_id));
62bca2c657bf95fd1f69935eef09915afa5c69d9Eelco Dolstra dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering struct iovec *iovec, unsigned n, unsigned m,
213ba152fdf7978773be5b8a72e040584765137fLennart Poettering if (LOG_PRI(priority) > s->max_level_store)
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering path = shortened_cgroup_path(ucred->pid);
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering /* example: /user/lennart/3/foobar
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering * So let's cut of everything past the third /, since that is
6e409ce10d134625626d1eddfd6152755ef1908dLennart Poettering * wher user directories start */
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available_space(s));
224f2ee221e77c326d1d7761abb6e812432b2163Lennart Poettering /* Write a suppression message if we suppressed something */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, "Suppressed %u messages from %s", rl - 1, path);
62bca2c657bf95fd1f69935eef09915afa5c69d9Eelco Dolstra dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poetteringstatic int system_journal_open(Server *s) {
b8156be03f71c53072c7126bb418410acbef6c81Lennart Poettering (s->storage == STORAGE_PERSISTENT || s->storage == STORAGE_AUTO) &&
b8156be03f71c53072c7126bb418410acbef6c81Lennart Poettering access("/run/systemd/journal/flushed", F_OK) >= 0) {
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart Poettering /* If in auto mode: first try to create the machine
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart Poettering * path, but not the prefix.
205c4d1d6a3f5343f970abf20283d69dcec359edLennart Poettering * If in persistent mode: create /var/log/journal and
e156d769c3ee756cdb20f8522ace9ea459a82655Lennart Poettering * the machine path */
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering fn = strappend("/var/log/journal/", ids);
b7def684941808600c344f0be7a2b9fcdda97e0fLennart Poettering fn = strjoin("/var/log/journal/", ids, "/system.journal", NULL);
eb53b74f7e2f83d936b35107806a157fdffdbf5aLennart Poettering r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, s->seal, &s->system_metrics, s->mmap, NULL, &s->system_journal);
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering server_fix_perms(s, s->system_journal, 0);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering else if (r < 0) {
adf7d506b50af9ba398a9925c8cd47ba328e720cLennart Poettering log_warning("Failed to open system journal: %s", strerror(-r));
b7def684941808600c344f0be7a2b9fcdda97e0fLennart Poettering fn = strjoin("/run/log/journal/", ids, "/system.journal", NULL);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering /* Try to open the runtime journal, but only
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering * if it already exists, so that we can flush
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering * it into the system journal */
16e9f408fa9a9626059bdd6c89dc175e06b9e976Lennart Poettering r = journal_file_open(fn, O_RDWR, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
adf7d506b50af9ba398a9925c8cd47ba328e720cLennart Poettering log_warning("Failed to open runtime journal: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering /* OK, we really need the runtime journal, so create
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering * it if necessary. */
16e9f408fa9a9626059bdd6c89dc175e06b9e976Lennart Poettering r = journal_file_open_reliably(fn, O_RDWR|O_CREAT, 0640, s->compress, false, &s->runtime_metrics, s->mmap, NULL, &s->runtime_journal);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Failed to open runtime journal: %s", strerror(-r));
5e41cfec83aa47af12e469bc62e336f8213ee066Lennart Poettering server_fix_perms(s, s->runtime_journal, 0);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poetteringstatic int server_flush_to_var(Server *s) {
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Failed to get machine id: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Failed to read runtime journal: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Can't read entry: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering journal_file_post_change(s->system_journal);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset, NULL, NULL, NULL);
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering log_error("Can't write entry: %s", strerror(-r));
cf244689e9d1ab50082c9ddd0f3c4d1eb982badcLennart Poettering journal_file_post_change(s->system_journal);
4a299a7ad547becb70e8271eaf8cdc27e8e6836aLennart Poettering rm_rf("/run/log/journal", false, true, false);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poetteringstatic int process_event(Server *s, struct epoll_event *ev) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_info("Got invalid event from epoll.");
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering n = read(s->signal_fd, &sfsi, sizeof(sfsi));
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering if (n != sizeof(sfsi)) {
3146a302d184d64a5c75237129f9e4f54ce46cd3Lennart Poettering log_info("Received SIG%s", signal_to_string(sfsi.ssi_signo));
51abe64c859c01ffad4f80840396ad9f6d5c9e62Lennart Poettering } else if (ev->data.fd == s->dev_kmsg_fd) {
6c1e6b98bde8288d65d7cddf87ff9bedf94a3e1cLennart Poettering log_info("Got invalid event from epoll.");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering } else if (ev->data.fd == s->native_fd ||
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_info("Got invalid event from epoll.");
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering /* We use NAME_MAX space for the
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * SELinux label here. The kernel
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * currently enforces no limit, but
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * according to suggestions from the
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * SELinux people this will change and
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * it will probably be identical to
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * NAME_MAX. For now we use that, but
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * this should be updated one day when
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering * the final limit is known.*/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
7264278fbbdc1dc6c30fedc902d1337594aa6ff6Lennart Poettering CMSG_SPACE(NAME_MAX)]; /* selinux label */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (ioctl(ev->data.fd, SIOCINQ, &v) < 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering l = MAX(LINE_MAX + (size_t) v, s->buffer_size * 2);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering n = recvmsg(ev->data.fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering else if (cmsg->cmsg_level == SOL_SOCKET &&
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering label_len = cmsg->cmsg_len - CMSG_LEN(0);
7f2c63cbf47c89ec56f50469f6551df473dd65d8Lennart Poettering } else if (cmsg->cmsg_level == SOL_SOCKET &&
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering else if (cmsg->cmsg_level == SOL_SOCKET &&
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (n > 0 && n_fds == 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering } else if (n_fds > 0)
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering log_warning("Got file descriptors via syslog socket. Ignoring.");
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (n > 0 && n_fds == 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering server_process_native_file(s, fds[0], ucred, tv, label, label_len);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering log_warning("Got too many file descriptors via native socket. Ignoring.");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering } else if (ev->data.fd == s->stdout_fd) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_info("Got invalid event from epoll.");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if ((ev->events|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_info("Got invalid event from epoll.");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering /* If it is none of the well-known fds, it must be an
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering * stdout stream fd. Note that this is a bit ugly here
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering * (since we rely that none of the well-known fds
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering * could be interpreted as pointer), but nonetheless
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering * safe, since the well-known fds would never get an
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering * fd > 4096, i.e. beyond the first memory page */
ba6b3039531a70466dd955c6faa9bf521b3dfbacLennart Poettering sigset_add_many(&mask, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, -1);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering s->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->signal_fd, &ev) < 0) {
effb1102d3f1d6bc2d0bda5328d3ce2139af9850Lennart Poetteringstatic int server_parse_proc_cmdline(Server *s) {
effb1102d3f1d6bc2d0bda5328d3ce2139af9850Lennart Poettering r = read_one_line_file("/proc/cmdline", &line);
effb1102d3f1d6bc2d0bda5328d3ce2139af9850Lennart Poettering log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
c66e7bc7a19c068ca1c414f2f8bd5dc13c20907fLennart Poettering if (startswith(word, "systemd.journald.forward_to_syslog=")) {
effb1102d3f1d6bc2d0bda5328d3ce2139af9850Lennart Poettering log_warning("Failed to parse forward to syslog switch %s. Ignoring.", word + 35);
c66e7bc7a19c068ca1c414f2f8bd5dc13c20907fLennart Poettering } else if (startswith(word, "systemd.journald.forward_to_kmsg=")) {
effb1102d3f1d6bc2d0bda5328d3ce2139af9850Lennart Poettering log_warning("Failed to parse forward to kmsg switch %s. Ignoring.", word + 33);
c66e7bc7a19c068ca1c414f2f8bd5dc13c20907fLennart Poettering } else if (startswith(word, "systemd.journald.forward_to_console=")) {
effb1102d3f1d6bc2d0bda5328d3ce2139af9850Lennart Poettering log_warning("Failed to parse forward to console switch %s. Ignoring.", word + 36);
66a78c2b95ba6cc0be15dab68c5af816fb5b7a33Lennart Poettering } else if (startswith(word, "systemd.journald"))
66a78c2b95ba6cc0be15dab68c5af816fb5b7a33Lennart Poettering log_warning("Invalid systemd.journald parameter. Ignoring.");
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poetteringstatic int server_parse_config_file(Server *s) {
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poettering log_warning("Failed to open configuration file %s: %m", fn);
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poettering r = config_parse(fn, f, "Journal\0", config_item_perf_lookup, (void*) journald_gperf_lookup, false, s);
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poettering log_warning("Failed to parse configuration file: %s", strerror(-r));
51abe64c859c01ffad4f80840396ad9f6d5c9e62Lennart Poettering s->syslog_fd = s->native_fd = s->stdout_fd = s->signal_fd = s->epoll_fd = s->dev_kmsg_fd = -1;
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poettering s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poettering s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering memset(&s->system_metrics, 0xFF, sizeof(s->system_metrics));
babfc09177c1e71cec6c1ef9602e265ed40cfe4fLennart Poettering memset(&s->runtime_metrics, 0xFF, sizeof(s->runtime_metrics));
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering s->user_journals = hashmap_new(trivial_hash_func, trivial_compare_func);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_error("Failed to create epoll object: %m");
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering log_error("Failed to read listening file descriptors from environment: %s", strerror(-n));
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
259d2e762041d8d50c2a17bfea90b1a96f6b880bLennart Poettering if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/socket", 0) > 0) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("Too many native sockets passed.");
259d2e762041d8d50c2a17bfea90b1a96f6b880bLennart Poettering } else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, "/run/systemd/journal/stdout", 0) > 0) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("Too many stdout sockets passed.");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering } else if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_error("Too many /dev/log sockets passed.");
e6960940b6dc5ab81eb2fca4061c333e1795f38dLennart Poettering s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst);
99add6fd0b8f4307ed79256e25f38da318e795c4Lennart Poetteringstatic void server_maybe_append_tags(Server *s) {
671e021c92c835c6c701dc61463149d05b6f31afLennart Poettering journal_file_maybe_append_tag(s->system_journal, n);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering while ((f = hashmap_steal_first(s->user_journals)))
cee5e9a7ca75f05d4a0f7759566e657587a500d5Lennart Poettering munmap(s->kernel_seqnum, sizeof(uint64_t));
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering /* if (getppid() != 1) { */
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering /* log_error("This program should be invoked by init only."); */
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering /* return EXIT_FAILURE; */
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering log_error("This program does not take arguments.");
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering log_debug("systemd-journald running as pid %lu", (unsigned long) getpid());
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started");
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering "STATUS=Processing requests...");
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering journal_file_next_evolve_usec(server.system_journal, &u)) {
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering t = (int) ((u - n + USEC_PER_MSEC - 1) / USEC_PER_MSEC);
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering r = epoll_wait(server.epoll_fd, &event, 1, t);
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering else if (r == 0)
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering log_debug("systemd-journald stopped as pid %lu", (unsigned long) getpid());
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped");
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering "STATUS=Shutting down...");