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