journald-kmsg.c revision b2e6df73aa508cc09b1b536a2fb9f90f152b89fa
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering This file is part of systemd.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Copyright 2011 Lennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering systemd is free software; you can redistribute it and/or modify it
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering under the terms of the GNU Lesser General Public License as published by
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering (at your option) any later version.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering systemd is distributed in the hope that it will be useful, but
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Lesser General Public License for more details.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering You should have received a copy of the GNU Lesser General Public License
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg))
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Never allow messages with kernel facility to be written to
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * kmsg, regardless where the data comes from. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering priority = syslog_fixup_facility(priority);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* First: priority field */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], header_priority);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Second: identifier and PID */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering get_process_comm(ucred->pid, &ident_buf);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], header_pid);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], identifier);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Fourth: message */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno));
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering return t == getpid();
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic void dev_kmsg_record(Server *s, char *p, size_t l) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS];
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL;
e9f600f2fb4b0df55c7a8fb4b4d09f9979997223Lennart Poettering unsigned n = 0, z = 0, j;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering char *identifier = NULL, *pid = NULL, *e, *f, *k;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (r < 0 || priority < 0 || priority > 999)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering l -= (e - p) + 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* We already read this one? */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Did we lose any? */
b9c488f60050248b35640f28e4d00958702ba1c3Eelco Dolstra server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %llu kernel messages", (unsigned long long) serial - *s->kernel_seqnum - 1);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Make sure we never read this one again. Note that
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * we always store the next message serial we expect
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * here, simply because this makes handling the first
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * message with serial 0 easy. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering l -= (e - p) + 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (!e || f < e)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering l -= (f - p) + 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering l -= (e - p) + 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Meta data fields attached */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (*k != ' ')
527b7a421ff3927d4f3f170b1b143452e88ae1dcLennart Poettering m = cunescape_length_with_prefix(k, e - k, "_KERNEL_");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering l -= (e - k) + 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering ud = udev_device_new_from_device_id(s->udev, kernel_device);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering const char *g;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering ll = udev_device_get_devlinks_list_entry(ud);
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek b = strappend("_UDEV_DEVLINK=", g);
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek IOVEC_SET_STRING(iovec[n++], b);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu",
e9f600f2fb4b0df55c7a8fb4b4d09f9979997223Lennart Poettering (unsigned long long) usec) >= 0)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], source_time);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_priority);
36dd072cdf03dcac0fcd2d6b42f261444dc7ac88Michal Sekletar IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering syslog_parse_identifier((const char**) &p, &identifier, &pid);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Avoid any messages we generated ourselves via
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek * log_info() and friends. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_identifier);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering syslog_pid = strappend("SYSLOG_PID=", pid);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_pid);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_facility);
527b7a421ff3927d4f3f170b1b143452e88ae1dcLennart Poettering message = cunescape_length_with_prefix(p, pl, "MESSAGE=");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering for (j = 0; j < z; j++)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Old kernels who don't allow reading from /dev/kmsg
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * return EINVAL when we try. So handle this cleanly,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * but don' try to ever read from it again. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering epoll_ctl(s->epoll_fd, EPOLL_CTL_DEL, s->dev_kmsg_fd, NULL);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (errno == EAGAIN || errno == EINTR || errno == EPIPE)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Failed to read from kernel: %m");
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering log_warning("Failed to open /dev/kmsg, ignoring: %m");
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->dev_kmsg_fd, &ev) < 0) {
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering /* This will fail with EPERM on older kernels where
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * /dev/kmsg is not readable. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Failed to add /dev/kmsg fd to epoll object: %m");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringint server_open_kernel_seqnum(Server *s) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* We store the seqnum we last read in an mmaped file. That
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt * way we can just use it like a variable, but it is
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering * persistent and automatically flushed at reboot. */
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering log_error("Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (posix_fallocate(fd, 0, sizeof(uint64_t)) < 0) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Failed to allocate sequential number file, ignoring: %m");
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
c0f71f469fef3f3a0822e0021085e6d165df2b46Lennart Poettering log_error("Failed to map sequential number file, ignoring: %m");