]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/journald-kmsg.c
bus: check return value from bus_type_get_alignment/size
[thirdparty/systemd.git] / src / journal / journald-kmsg.c
CommitLineData
ef63833d
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <sys/epoll.h>
24#include <fcntl.h>
25#include <sys/mman.h>
4871690d 26#include <sys/socket.h>
ef63833d
LP
27
28#include <systemd/sd-messages.h>
29#include <libudev.h>
30
d025f1e4 31#include "journald-server.h"
ef63833d 32#include "journald-kmsg.h"
35e2e347 33#include "journald-syslog.h"
ef63833d
LP
34
35void server_forward_kmsg(
36 Server *s,
37 int priority,
38 const char *identifier,
39 const char *message,
40 struct ucred *ucred) {
41
42 struct iovec iovec[5];
43 char header_priority[6], header_pid[16];
44 int n = 0;
45 char *ident_buf = NULL;
46
47 assert(s);
48 assert(priority >= 0);
49 assert(priority <= 999);
50 assert(message);
51
52 if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg))
53 return;
54
55 if (_unlikely_(s->dev_kmsg_fd < 0))
56 return;
57
58 /* Never allow messages with kernel facility to be written to
59 * kmsg, regardless where the data comes from. */
60 priority = syslog_fixup_facility(priority);
61
62 /* First: priority field */
63 snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
64 char_array_0(header_priority);
65 IOVEC_SET_STRING(iovec[n++], header_priority);
66
67 /* Second: identifier and PID */
68 if (ucred) {
69 if (!identifier) {
70 get_process_comm(ucred->pid, &ident_buf);
71 identifier = ident_buf;
72 }
73
74 snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) ucred->pid);
75 char_array_0(header_pid);
76
77 if (identifier)
78 IOVEC_SET_STRING(iovec[n++], identifier);
79
80 IOVEC_SET_STRING(iovec[n++], header_pid);
81 } else if (identifier) {
82 IOVEC_SET_STRING(iovec[n++], identifier);
83 IOVEC_SET_STRING(iovec[n++], ": ");
84 }
85
86 /* Fourth: message */
87 IOVEC_SET_STRING(iovec[n++], message);
88 IOVEC_SET_STRING(iovec[n++], "\n");
89
90 if (writev(s->dev_kmsg_fd, iovec, n) < 0)
91 log_debug("Failed to write to /dev/kmsg for logging: %s", strerror(errno));
92
93 free(ident_buf);
94}
95
96static bool is_us(const char *pid) {
97 pid_t t;
98
99 assert(pid);
100
101 if (parse_pid(pid, &t) < 0)
102 return false;
103
104 return t == getpid();
105}
106
107static void dev_kmsg_record(Server *s, char *p, size_t l) {
108 struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS];
109 char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL;
110 int priority, r;
111 unsigned n = 0, z = 0, j;
e9f600f2 112 unsigned long long usec;
ef63833d
LP
113 char *identifier = NULL, *pid = NULL, *e, *f, *k;
114 uint64_t serial;
115 size_t pl;
116 char *kernel_device = NULL;
117
118 assert(s);
119 assert(p);
120
121 if (l <= 0)
122 return;
123
124 e = memchr(p, ',', l);
125 if (!e)
126 return;
127 *e = 0;
128
129 r = safe_atoi(p, &priority);
130 if (r < 0 || priority < 0 || priority > 999)
131 return;
132
133 if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN)
134 return;
135
136 l -= (e - p) + 1;
137 p = e + 1;
138 e = memchr(p, ',', l);
139 if (!e)
140 return;
141 *e = 0;
142
143 r = safe_atou64(p, &serial);
144 if (r < 0)
145 return;
146
147 if (s->kernel_seqnum) {
148 /* We already read this one? */
149 if (serial < *s->kernel_seqnum)
150 return;
151
152 /* Did we lose any? */
153 if (serial > *s->kernel_seqnum)
154 server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %llu kernel messages", (unsigned long long) serial - *s->kernel_seqnum - 1);
155
156 /* Make sure we never read this one again. Note that
157 * we always store the next message serial we expect
158 * here, simply because this makes handling the first
159 * message with serial 0 easy. */
160 *s->kernel_seqnum = serial + 1;
161 }
162
163 l -= (e - p) + 1;
164 p = e + 1;
165 f = memchr(p, ';', l);
166 if (!f)
167 return;
168 /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */
169 e = memchr(p, ',', l);
170 if (!e || f < e)
171 e = f;
172 *e = 0;
173
e9f600f2 174 r = safe_atollu(p, &usec);
ef63833d
LP
175 if (r < 0)
176 return;
177
178 l -= (f - p) + 1;
179 p = f + 1;
180 e = memchr(p, '\n', l);
181 if (!e)
182 return;
183 *e = 0;
184
185 pl = e - p;
186 l -= (e - p) + 1;
187 k = e + 1;
188
189 for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) {
190 char *m;
191 /* Meta data fields attached */
192
193 if (*k != ' ')
194 break;
195
196 k ++, l --;
197
198 e = memchr(k, '\n', l);
199 if (!e)
200 return;
201
202 *e = 0;
203
204 m = cunescape_length_with_prefix(k, e - k, "_KERNEL_");
205 if (!m)
206 break;
207
208 if (startswith(m, "_KERNEL_DEVICE="))
209 kernel_device = m + 15;
210
211 IOVEC_SET_STRING(iovec[n++], m);
212 z++;
213
214 l -= (e - k) + 1;
215 k = e + 1;
216 }
217
218 if (kernel_device) {
219 struct udev_device *ud;
220
221 ud = udev_device_new_from_device_id(s->udev, kernel_device);
222 if (ud) {
223 const char *g;
224 struct udev_list_entry *ll;
225 char *b;
226
227 g = udev_device_get_devnode(ud);
228 if (g) {
229 b = strappend("_UDEV_DEVNODE=", g);
230 if (b) {
231 IOVEC_SET_STRING(iovec[n++], b);
232 z++;
233 }
234 }
235
236 g = udev_device_get_sysname(ud);
237 if (g) {
238 b = strappend("_UDEV_SYSNAME=", g);
239 if (b) {
240 IOVEC_SET_STRING(iovec[n++], b);
241 z++;
242 }
243 }
244
245 j = 0;
246 ll = udev_device_get_devlinks_list_entry(ud);
247 udev_list_entry_foreach(ll, ll) {
248
249 if (j > N_IOVEC_UDEV_FIELDS)
250 break;
251
252 g = udev_list_entry_get_name(ll);
253 b = strappend("_UDEV_DEVLINK=", g);
254 if (g) {
255 IOVEC_SET_STRING(iovec[n++], b);
256 z++;
257 }
258
259 j++;
260 }
261
262 udev_device_unref(ud);
263 }
264 }
265
e9f600f2 266 if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0)
ef63833d
LP
267 IOVEC_SET_STRING(iovec[n++], source_time);
268
269 IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel");
270
271 if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0)
272 IOVEC_SET_STRING(iovec[n++], syslog_priority);
273
274 if ((priority & LOG_FACMASK) == LOG_KERN)
275 IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel");
276 else {
e88baee8 277 pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid);
ef63833d
LP
278
279 /* Avoid any messages we generated ourselves via
280 * log_info() and friends. */
281 if (pid && is_us(pid))
282 goto finish;
283
284 if (identifier) {
285 syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier);
286 if (syslog_identifier)
287 IOVEC_SET_STRING(iovec[n++], syslog_identifier);
288 }
289
290 if (pid) {
291 syslog_pid = strappend("SYSLOG_PID=", pid);
292 if (syslog_pid)
293 IOVEC_SET_STRING(iovec[n++], syslog_pid);
294 }
295
296 if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0)
297 IOVEC_SET_STRING(iovec[n++], syslog_facility);
298 }
299
300 message = cunescape_length_with_prefix(p, pl, "MESSAGE=");
301 if (message)
302 IOVEC_SET_STRING(iovec[n++], message);
303
304 server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority);
305
306finish:
307 for (j = 0; j < z; j++)
308 free(iovec[j].iov_base);
309
310 free(message);
311 free(syslog_priority);
312 free(syslog_identifier);
313 free(syslog_pid);
314 free(syslog_facility);
315 free(source_time);
316 free(identifier);
317 free(pid);
318}
319
320int server_read_dev_kmsg(Server *s) {
321 char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */
322 ssize_t l;
323
324 assert(s);
325 assert(s->dev_kmsg_fd >= 0);
326
327 l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1);
328 if (l == 0)
329 return 0;
330 if (l < 0) {
331 /* Old kernels who don't allow reading from /dev/kmsg
332 * return EINVAL when we try. So handle this cleanly,
333 * but don' try to ever read from it again. */
334 if (errno == EINVAL) {
335 epoll_ctl(s->epoll_fd, EPOLL_CTL_DEL, s->dev_kmsg_fd, NULL);
336 return 0;
337 }
338
339 if (errno == EAGAIN || errno == EINTR || errno == EPIPE)
340 return 0;
341
342 log_error("Failed to read from kernel: %m");
343 return -errno;
344 }
345
346 dev_kmsg_record(s, buffer, l);
347 return 1;
348}
349
350int server_flush_dev_kmsg(Server *s) {
351 int r;
352
353 assert(s);
354
355 if (s->dev_kmsg_fd < 0)
356 return 0;
357
358 if (!s->dev_kmsg_readable)
359 return 0;
360
2b43f939 361 log_debug("Flushing /dev/kmsg...");
ef63833d
LP
362
363 for (;;) {
364 r = server_read_dev_kmsg(s);
365 if (r < 0)
366 return r;
367
368 if (r == 0)
369 break;
370 }
371
372 return 0;
373}
374
375int server_open_dev_kmsg(Server *s) {
376 struct epoll_event ev;
377
378 assert(s);
379
380 s->dev_kmsg_fd = open("/dev/kmsg", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
381 if (s->dev_kmsg_fd < 0) {
382 log_warning("Failed to open /dev/kmsg, ignoring: %m");
383 return 0;
384 }
385
386 zero(ev);
387 ev.events = EPOLLIN;
388 ev.data.fd = s->dev_kmsg_fd;
389 if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->dev_kmsg_fd, &ev) < 0) {
390
391 /* This will fail with EPERM on older kernels where
392 * /dev/kmsg is not readable. */
393 if (errno == EPERM)
394 return 0;
395
396 log_error("Failed to add /dev/kmsg fd to epoll object: %m");
397 return -errno;
398 }
399
400 s->dev_kmsg_readable = true;
401
402 return 0;
403}
404
405int server_open_kernel_seqnum(Server *s) {
406 int fd;
407 uint64_t *p;
408
409 assert(s);
410
411 /* We store the seqnum we last read in an mmaped file. That
412 * way we can just use it like a variable, but it is
b2e6df73 413 * persistent and automatically flushed at reboot. */
ef63833d
LP
414
415 fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
416 if (fd < 0) {
417 log_error("Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m");
418 return 0;
419 }
420
421 if (posix_fallocate(fd, 0, sizeof(uint64_t)) < 0) {
422 log_error("Failed to allocate sequential number file, ignoring: %m");
423 close_nointr_nofail(fd);
424 return 0;
425 }
426
427 p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
428 if (p == MAP_FAILED) {
429 log_error("Failed to map sequential number file, ignoring: %m");
430 close_nointr_nofail(fd);
431 return 0;
432 }
433
434 close_nointr_nofail(fd);
435 s->kernel_seqnum = p;
436
437 return 0;
438}