journald.c revision 66a78c2b95ba6cc0be15dab68c5af816fb5b7a33
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2011 Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is free software; you can redistribute it and/or modify it
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering under the terms of the GNU Lesser General Public License as published by
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (at your option) any later version.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is distributed in the hope that it will be useful, but
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Lesser General Public License for more details.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering You should have received a copy of the GNU Lesser General Public License
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#define RECHECK_VAR_AVAILABLE_USEC (30*USEC_PER_SEC)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering LIST_FIELDS(StdoutStream, stdout_stream);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic int server_flush_to_var(Server *s);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic uint64_t available_space(Server *s) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering const char *f;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering uint64_t sum = 0, avail = 0, ss_avail = 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (s->cached_available_space_timestamp + RECHECK_AVAILABLE_SPACE_USEC > ts)
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering p = strappend(f, sd_id128_to_string(machine, ids));
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering avail = sum >= m->max_use ? 0 : m->max_use - sum;
d57c365bf8f09fbcc649e00f7060ff30809f67c2Lennart Poettering ss_avail = ss_avail < m->keep_free ? 0 : ss_avail - m->keep_free;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s->cached_available_space_timestamp = ts;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_warning("Failed to resolve 'adm' group: %s", strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* if we couldn't read the gid, then it will be 0, but that's
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering * fine and we shouldn't try to resolve the group again, so
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt * let's just pretend it worked right-away. */
3e3db0ee860025ad663b13b0ace4e6d627611332Lennart Poetteringstatic void server_fix_perms(Server *s, JournalFile *f, uid_t uid) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = fchmod_and_fchown(f->fd, 0640, 0, s->file_gid);
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (acl_create_entry(&acl, &entry) < 0 ||
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic JournalFile* find_journal(Server *s, uid_t uid) {
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen /* We split up user logs only on /var, not on /run. If the
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen * runtime file is open, we write to it exclusively, in order
81fd1dd3a2cf4cc90a6898d562c9bb0fb238cbd7Tom Gundersen * to guarantee proper order as soon as we flush /run to
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen * /var and close the runtime file. */
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (asprintf(&p, "/var/log/journal/%s/user-%lu.journal", sd_id128_to_string(machine, ids), (unsigned long) uid) < 0)
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen while (hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen /* Too many open? Then let's close one */
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = journal_file_open_reliably(p, O_RDWR|O_CREAT, 0640, s->system_journal, &f);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to rotate %s: %s", s->runtime_journal->path, strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to create new runtime journal: %s", strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to rotate %s: %s", s->system_journal->path, strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to create new system journal: %s", strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to rotate %s: %s", f->path, strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to create user journal: %s", strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen server_fix_perms(s, s->system_journal, PTR_TO_UINT32(k));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen log_error("Failed to get machine ID: %s", strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (asprintf(&p, "/var/log/journal/%s", ids) < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = journal_directory_vacuum(p, s->system_metrics.max_use, s->system_metrics.keep_free);
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen if (r < 0 && r != -ENOENT)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering log_error("Failed to vacuum %s: %s", p, strerror(-r));
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen if (asprintf(&p, "/run/log/journal/%s", ids) < 0) {
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersen r = journal_directory_vacuum(p, s->runtime_metrics.max_use, s->runtime_metrics.keep_free);
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen if (r < 0 && r != -ENOENT)
b6a3ca6d876ab59b4f29ed67f54ef87005177906Tom Gundersen log_error("Failed to vacuum %s: %s", p, strerror(-r));
c09da72900b03fcddade06643f24c6357f3e0482Tom Gundersenstatic char *shortened_cgroup_path(pid_t pid) {
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &process_path);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &init_path);
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering if (startswith(process_path, init_path)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct iovec *iovec, unsigned n, unsigned m,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char *pid = NULL, *uid = NULL, *gid = NULL,
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering *source_time = NULL, *boot_id = NULL, *machine_id = NULL,
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering *comm = NULL, *cmdline = NULL, *hostname = NULL,
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering *audit_session = NULL, *audit_loginuid = NULL,
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering *exe = NULL, *cgroup = NULL, *session = NULL,
1693a943ca581aca2beebb4c812ec6c9f17b8164Lennart Poettering *owner_uid = NULL, *unit = NULL, *selinux_context = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (asprintf(&pid, "_PID=%lu", (unsigned long) ucred->pid) >= 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (asprintf(&uid, "_UID=%lu", (unsigned long) ucred->uid) >= 0)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering if (asprintf(&gid, "_GID=%lu", (unsigned long) ucred->gid) >= 0)
6c03d27d9f7e831194dbd8bd6bcdeef9273edb6eThomas Hindoe Paaboel Andersen r = get_process_comm(ucred->pid, &t);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = get_process_cmdline(ucred->pid, LINE_MAX, false, &t);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering r = audit_session_from_pid(ucred->pid, &audit);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit) >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering IOVEC_SET_STRING(iovec[n++], audit_session);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt r = audit_loginuid_from_pid(ucred->pid, &loginuid);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering IOVEC_SET_STRING(iovec[n++], audit_loginuid);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering cgroup = strappend("_SYSTEMD_CGROUP=", t);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (sd_pid_get_session(ucred->pid, &t) >= 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering session = strappend("_SYSTEMD_SESSION=", t);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (sd_pid_get_owner_uid(ucred->uid, &owner) >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (asprintf(&owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner) >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (cg_pid_get_unit(ucred->pid, &t) >= 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering unit = strappend("_SYSTEMD_UNIT=", unit_id);
d6731e4c7964ee2860d4f5abdb0b52acd7a66960Tom Gundersen selinux_context = malloc(sizeof("_SELINUX_CONTEXT=") + label_len);
2301cb9fdb774d0a1b3d8f5e95c5d358721ccacbLennart Poettering memcpy(selinux_context, "_SELINUX_CONTEXT=", sizeof("_SELINUX_CONTEXT=")-1);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen memcpy(selinux_context+sizeof("_SELINUX_CONTEXT=")-1, label, label_len);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen selinux_context[sizeof("_SELINUX_CONTEXT=")-1+label_len] = 0;
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen IOVEC_SET_STRING(iovec[n++], selinux_context);
1405434b6986d3c3d6ccaaa2e472bad843cbbfa1Lennart Poettering selinux_context = strappend("_SELINUX_CONTEXT=", con);
67272d157a35e5cda4e5c904eafdcc23d20541d1Tom Gundersen IOVEC_SET_STRING(iovec[n++], selinux_context);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (asprintf(&source_time, "_SOURCE_REALTIME_TIMESTAMP=%llu",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering (unsigned long long) timeval_load(tv)) >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering IOVEC_SET_STRING(iovec[n++], source_time);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering /* Note that strictly speaking storing the boot id here is
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering * redundant since the entry includes this in-line
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering * anyway. However, we need this indexed, too. */
b1acce80cd60fe95f16df2f1ad23ff2ad82d08e5Lennart Poettering if (asprintf(&boot_id, "_BOOT_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
af5effc4220dab6c4c87a130bae7be441f6967caTom Gundersen if (asprintf(&machine_id, "_MACHINE_ID=%s", sd_id128_to_string(id, idbuf)) >= 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering f = find_journal(s, realuid == 0 ? 0 : loginuid);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_warning("Dropping message, as we can't find a place to store the data.");
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
db73295accbec0c6513817f0a64a92018592bb26Lennart Poettering r == -EPROTONOSUPPORT) && /* unsupported feature */
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_info("Allocation limit reached, rotating.");
888943fc6246b2917168fff59380b58b678ba157Lennart Poettering log_warning("Journal file corrupted, rotating.");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_error("Failed to write entry, ignoring: %s", strerror(-r));
c627729fc49d59ffcecc09555a34d9dd139927ceLennart Poetteringstatic void driver_message(Server *s, sd_id128_t message_id, const char *format, ...) {
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering struct iovec iovec[N_IOVEC_META_FIELDS + 4];
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering IOVEC_SET_STRING(iovec[n++], "PRIORITY=5");
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
03cc0fd1431b82e59c11ae12a274c1f2df23169dLennart Poettering vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap);
ddb7f7fc07a31937989afad53edb87b50e2cad72Zbigniew Jędrzejewski-Szmek snprintf(mid, sizeof(mid), "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(message_id));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct iovec *iovec, unsigned n, unsigned m,
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (LOG_PRI(priority) > s->max_level_store)
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering path = shortened_cgroup_path(ucred->pid);
266b538958932e6fc27dfce4917336e70e17e29eTom Gundersen /* example: /user/lennart/3/foobar
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering * So let's cut of everything past the third /, since that is
69fb1176c403e437c4fba763ba242b540c73898fLennart Poettering * wher user directories start */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available_space(s));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Write a suppression message if we suppressed something */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, "Suppressed %u messages from %s", rl - 1, path);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahanistatic void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) {
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani strncpy(sa.un.sun_path, "/run/systemd/journal/syslog", sizeof(sa.un.sun_path));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani msghdr.msg_namelen = offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Forward the syslog message we received via /dev/log to
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani * /run/systemd/syslog. Unfortunately we currently can't set
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani * the SO_TIMESTAMP auxiliary data, and hence we don't. */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* The socket is full? I guess the syslog implementation is
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani * too slow, and we shouldn't wait for that... */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Hmm, presumably the sender process vanished
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani * by now, so let's fix it as good as we
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani * can, and retry */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani log_debug("Failed to forward syslog message: %m");
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahanistatic void forward_syslog_raw(Server *s, int priority, const char *buffer, struct ucred *ucred, struct timeval *tv) {
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani forward_syslog_iovec(s, &iovec, 1, ucred, tv);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahanistatic void forward_syslog(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred, struct timeval *tv) {
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani char header_priority[6], header_time[64], header_pid[16];
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* First: priority field */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani IOVEC_SET_STRING(iovec[n++], header_priority);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Second: timestamp */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Third: identifier and PID */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Fourth: message */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahanistatic void forward_kmsg(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred) {
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Never allow messages with kernel facility to be written to
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani * kmsg, regardless where the data comes from. */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* First: priority field */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani IOVEC_SET_STRING(iovec[n++], header_priority);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Second: identifier and PID */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* Fourth: message */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani log_debug("Failed to open /dev/kmsg for logging: %s", strerror(errno));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno));
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahanistatic void forward_console(Server *s, int priority, const char *identifier, const char *message, struct ucred *ucred) {
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani const char *tty;
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani /* First: identifier and PID */
49699bac94d24b444274f91f85c82e6fad04d029Susant Sahani snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering IOVEC_SET_STRING(iovec[n++], header_pid);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Third: message */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering tty = s->tty_path ? s->tty_path : "/dev/console";
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_debug("Failed to open %s for logging: %s", tty, strerror(errno));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_debug("Failed to write to %s for logging: %s", tty, strerror(errno));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void read_identifier(const char **buf, char **identifier, char **pid) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering const char *p;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (p[k] == '[') {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic void process_syslog_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv, const char *label, size_t label_len) {
266b538958932e6fc27dfce4917336e70e17e29eTom Gundersen char *message = NULL, *syslog_priority = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *syslog_pid = NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering struct iovec iovec[N_IOVEC_META_FIELDS + 6];
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering unsigned n = 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering parse_syslog_priority((char**) &buf, &priority);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering forward_syslog_raw(s, priority, orig, ucred, tv);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering read_identifier(&buf, &identifier, &pid);
if (s->forward_to_console)
if (identifier) {
if (syslog_identifier)
if (pid) {
if (syslog_pid)
if (message)
static void process_native_message(
Server *s,
assert(s);
p = buffer;
while (remaining > 0) {
remaining--;
if (n+N_IOVEC_META_FIELDS >= m) {
struct iovec *c;
iovec = c;
if (valid_user_field(p, q - p)) {
size_t l;
identifier = t;
message = t;
uint64_t l;
memcpy(k, p, e - p);
if (valid_user_field(p, e - p)) {
free(k);
goto finish;
tn = n++;
if (message) {
if (s->forward_to_syslog)
if (s->forward_to_kmsg)
if (s->forward_to_console)
if (j == tn)
static void process_native_file(
Server *s,
int fd,
ssize_t n;
assert(s);
free(p);
int priority;
assert(s);
assert(p);
if (isempty(p))
if (s->level_prefix)
if (s->identifier) {
if (syslog_identifier)
if (message)
#ifdef HAVE_SELINUX
if (s->security_context) {
dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority);
assert(s);
assert(p);
p = strstrip(p);
switch (s->state) {
case STDOUT_STREAM_IDENTIFIER:
if (isempty(p))
if (!s->identifier) {
return -ENOMEM;
case STDOUT_STREAM_UNIT_ID:
if (isempty(p))
if (!s->unit_id) {
return -ENOMEM;
case STDOUT_STREAM_PRIORITY:
return -EINVAL;
r = parse_boolean(p);
return -EINVAL;
s->level_prefix = !!r;
r = parse_boolean(p);
return -EINVAL;
s->forward_to_syslog = !!r;
r = parse_boolean(p);
return -EINVAL;
s->forward_to_kmsg = !!r;
r = parse_boolean(p);
return -EINVAL;
s->forward_to_console = !!r;
case STDOUT_STREAM_RUNNING:
return stdout_stream_log(s, p);
assert(s);
p = s->buffer;
char *end;
if (end)
*end = 0;
r = stdout_stream_line(s, p);
p += skip;
p[remaining] = 0;
r = stdout_stream_line(s, p);
p += remaining;
remaining = 0;
if (p > s->buffer) {
ssize_t l;
assert(s);
return -errno;
r = stdout_stream_scan(s, true);
s->length += l;
r = stdout_stream_scan(s, false);
assert(s);
if (s->server) {
if (s->fd >= 0) {
if (s->server)
#ifdef HAVE_SELINUX
if (s->security_context)
free(s);
int fd, r;
assert(s);
if (fd < 0) {
return -errno;
if (!stream) {
return -ENOMEM;
r = -errno;
goto fail;
#ifdef HAVE_SELINUX
r = -errno;
goto fail;
r = -errno;
goto fail;
s->n_stdout_streams ++;
fail:
usec_t r;
assert(t);
p = *_p;
k = undecchar(p[i]);
k = undecchar(p[i]);
pid_t t;
return t == getpid();
char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL;
assert(s);
assert(p);
if (isempty(p))
(unsigned long long) usec) >= 0)
if (s->forward_to_syslog)
goto finish;
if (s->forward_to_syslog)
if (identifier) {
if (syslog_identifier)
if (pid) {
if (syslog_pid)
if (message)
assert(s);
p = s->proc_kmsg_buffer;
char *end;
if (end)
*end = 0;
proc_kmsg_line(s, p);
p += skip;
if (p > s->proc_kmsg_buffer) {
char *fn;
if (!s->system_journal) {
if (!fn)
return -ENOMEM;
if (!fn)
return -ENOMEM;
if (!s->runtime_journal) {
if (!fn)
return -ENOMEM;
if (s->system_journal) {
if (r != -ENOENT)
if (s->runtime_journal) {
sd_journal *j;
assert(s);
if (!s->runtime_journal)
if (!s->system_journal)
SD_JOURNAL_FOREACH(j) {
JournalFile *f;
f = j->current_file;
goto finish;
if (r == -E2BIG) {
server_rotate(s);
server_vacuum(s);
goto finish;
ssize_t l;
assert(s);
l = read(s->proc_kmsg_fd, s->proc_kmsg_buffer + s->proc_kmsg_length, sizeof(s->proc_kmsg_buffer) - 1 - s->proc_kmsg_length);
return -errno;
s->proc_kmsg_length += l;
proc_kmsg_scan(s);
assert(s);
if (s->proc_kmsg_fd < 0)
r = server_read_proc_kmsg(s);
assert(s);
ssize_t n;
return -EIO;
if (n != sizeof(sfsi)) {
return -EIO;
return -errno;
server_rotate(s);
server_vacuum(s);
return -EIO;
r = server_read_proc_kmsg(s);
return -EIO;
} control;
ssize_t n;
unsigned n_fds = 0;
return -errno;
size_t l;
return -ENOMEM;
s->buffer_size = l;
s->buffer = b;
return -errno;
if (n > 0 && n_fds == 0) {
s->buffer[n] = 0;
} else if (n_fds > 0)
if (n > 0 && n_fds == 0)
else if (n_fds > 0)
return -EIO;
return -EIO;
int one, r;
assert(s);
if (s->syslog_fd < 0) {
if (s->syslog_fd < 0) {
return -errno;
r = bind(s->syslog_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
#ifdef HAVE_SELINUX
return -errno;
return -errno;
int one, r;
assert(s);
if (s->native_fd < 0) {
if (s->native_fd < 0) {
return -errno;
r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
#ifdef HAVE_SELINUX
return -errno;
return -errno;
assert(s);
if (s->stdout_fd < 0) {
if (s->stdout_fd < 0) {
return -errno;
r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
return -errno;
return -errno;
return -errno;
assert(s);
if (!s->import_proc_kmsg)
if (s->proc_kmsg_fd < 0) {
return -errno;
assert(s);
if (s->signal_fd < 0) {
return -errno;
return -errno;
size_t l;
char *word;
if (!word) {
r = -ENOMEM;
goto finish;
s->forward_to_syslog = r;
s->forward_to_kmsg = r;
s->forward_to_console = r;
FILE *f;
const char *fn;
assert(s);
return -errno;
r = config_parse(fn, f, "Journal\0", config_item_perf_lookup, (void*) journald_gperf_lookup, false, s);
fclose(f);
int n, r, fd;
assert(s);
zero(*s);
s->compress = true;
s->forward_to_syslog = true;
s->import_proc_kmsg = true;
if (!s->user_journals) {
return -ENOMEM;
if (s->epoll_fd < 0) {
return -errno;
n = sd_listen_fds(true);
if (s->native_fd >= 0) {
return -EINVAL;
if (s->stdout_fd >= 0) {
return -EINVAL;
if (s->syslog_fd >= 0) {
return -EINVAL;
return -EINVAL;
r = open_syslog_socket(s);
r = open_native_socket(s);
r = open_stdout_socket(s);
r = open_proc_kmsg(s);
r = open_signalfd(s);
if (!s->rate_limit)
return -ENOMEM;
r = system_journal_open(s);
JournalFile *f;
assert(s);
while (s->stdout_streams)
if (s->system_journal)
if (s->runtime_journal)
if (s->epoll_fd >= 0)
if (s->signal_fd >= 0)
if (s->syslog_fd >= 0)
if (s->native_fd >= 0)
if (s->stdout_fd >= 0)
if (s->proc_kmsg_fd >= 0)
if (s->rate_limit)
return EXIT_FAILURE;
log_open();
goto finish;
sd_notify(false,
r = -errno;
goto finish;
goto finish;
sd_notify(false,