]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journalctl.c
journal: install sigbus handler for journal tools too
[thirdparty/systemd.git] / src / journal / journalctl.c
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 <locale.h>
23 #include <fcntl.h>
24 #include <fnmatch.h>
25 #include <errno.h>
26 #include <stddef.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <time.h>
32 #include <getopt.h>
33 #include <signal.h>
34 #include <poll.h>
35 #include <sys/stat.h>
36 #include <sys/ioctl.h>
37 #include <sys/inotify.h>
38 #include <linux/fs.h>
39
40 #ifdef HAVE_ACL
41 #include <sys/acl.h>
42 #include "acl-util.h"
43 #endif
44
45 #include "sd-journal.h"
46 #include "sd-bus.h"
47
48 #include "log.h"
49 #include "logs-show.h"
50 #include "util.h"
51 #include "path-util.h"
52 #include "fileio.h"
53 #include "build.h"
54 #include "pager.h"
55 #include "strv.h"
56 #include "set.h"
57 #include "sigbus.h"
58 #include "journal-internal.h"
59 #include "journal-def.h"
60 #include "journal-verify.h"
61 #include "journal-authenticate.h"
62 #include "journal-qrcode.h"
63 #include "journal-vacuum.h"
64 #include "fsprg.h"
65 #include "unit-name.h"
66 #include "catalog.h"
67 #include "mkdir.h"
68 #include "bus-util.h"
69 #include "bus-error.h"
70
71 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
72
73 enum {
74 /* Special values for arg_lines */
75 ARG_LINES_DEFAULT = -2,
76 ARG_LINES_ALL = -1,
77 };
78
79 static OutputMode arg_output = OUTPUT_SHORT;
80 static bool arg_utc = false;
81 static bool arg_pager_end = false;
82 static bool arg_follow = false;
83 static bool arg_full = true;
84 static bool arg_all = false;
85 static bool arg_no_pager = false;
86 static int arg_lines = ARG_LINES_DEFAULT;
87 static bool arg_no_tail = false;
88 static bool arg_quiet = false;
89 static bool arg_merge = false;
90 static bool arg_boot = false;
91 static sd_id128_t arg_boot_id = {};
92 static int arg_boot_offset = 0;
93 static bool arg_dmesg = false;
94 static const char *arg_cursor = NULL;
95 static const char *arg_after_cursor = NULL;
96 static bool arg_show_cursor = false;
97 static const char *arg_directory = NULL;
98 static char **arg_file = NULL;
99 static int arg_priorities = 0xFF;
100 static const char *arg_verify_key = NULL;
101 #ifdef HAVE_GCRYPT
102 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
103 static bool arg_force = false;
104 #endif
105 static usec_t arg_since, arg_until;
106 static bool arg_since_set = false, arg_until_set = false;
107 static char **arg_syslog_identifier = NULL;
108 static char **arg_system_units = NULL;
109 static char **arg_user_units = NULL;
110 static const char *arg_field = NULL;
111 static bool arg_catalog = false;
112 static bool arg_reverse = false;
113 static int arg_journal_type = 0;
114 static const char *arg_root = NULL;
115 static const char *arg_machine = NULL;
116 static off_t arg_vacuum_size = (off_t) -1;
117 static usec_t arg_vacuum_time = USEC_INFINITY;
118
119 static enum {
120 ACTION_SHOW,
121 ACTION_NEW_ID128,
122 ACTION_PRINT_HEADER,
123 ACTION_SETUP_KEYS,
124 ACTION_VERIFY,
125 ACTION_DISK_USAGE,
126 ACTION_LIST_CATALOG,
127 ACTION_DUMP_CATALOG,
128 ACTION_UPDATE_CATALOG,
129 ACTION_LIST_BOOTS,
130 ACTION_FLUSH,
131 ACTION_VACUUM,
132 } arg_action = ACTION_SHOW;
133
134 typedef struct boot_id_t {
135 sd_id128_t id;
136 uint64_t first;
137 uint64_t last;
138 } boot_id_t;
139
140 static void pager_open_if_enabled(void) {
141
142 if (arg_no_pager)
143 return;
144
145 pager_open(arg_pager_end);
146 }
147
148 static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) {
149
150 if (arg_utc)
151 return format_timestamp_utc(buf, l, t);
152
153 return format_timestamp(buf, l, t);
154 }
155
156 static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
157 sd_id128_t id = SD_ID128_NULL;
158 int off = 0, r;
159
160 if (strlen(x) >= 32) {
161 char *t;
162
163 t = strndupa(x, 32);
164 r = sd_id128_from_string(t, &id);
165 if (r >= 0)
166 x += 32;
167
168 if (*x != '-' && *x != '+' && *x != 0)
169 return -EINVAL;
170
171 if (*x != 0) {
172 r = safe_atoi(x, &off);
173 if (r < 0)
174 return r;
175 }
176 } else {
177 r = safe_atoi(x, &off);
178 if (r < 0)
179 return r;
180 }
181
182 if (boot_id)
183 *boot_id = id;
184
185 if (offset)
186 *offset = off;
187
188 return 0;
189 }
190
191 static void help(void) {
192
193 pager_open_if_enabled();
194
195 printf("%s [OPTIONS...] [MATCHES...]\n\n"
196 "Query the journal.\n\n"
197 "Flags:\n"
198 " --system Show the system journal\n"
199 " --user Show the user journal for the current user\n"
200 " -M --machine=CONTAINER Operate on local container\n"
201 " --since=DATE Start showing entries on or newer than the specified date\n"
202 " --until=DATE Stop showing entries on or newer than the specified date\n"
203 " -c --cursor=CURSOR Start showing entries from the specified cursor\n"
204 " --after-cursor=CURSOR Start showing entries from after the specified cursor\n"
205 " --show-cursor Print the cursor after all the entries\n"
206 " -b --boot[=ID] Show data only from ID or, if unspecified, the current boot\n"
207 " --list-boots Show terse information about recorded boots\n"
208 " -k --dmesg Show kernel message log from the current boot\n"
209 " -u --unit=UNIT Show data only from the specified unit\n"
210 " --user-unit=UNIT Show data only from the specified user session unit\n"
211 " -t --identifier=STRING Show only messages with the specified syslog identifier\n"
212 " -p --priority=RANGE Show only messages within the specified priority range\n"
213 " -e --pager-end Immediately jump to end of the journal in the pager\n"
214 " -f --follow Follow the journal\n"
215 " -n --lines[=INTEGER] Number of journal entries to show\n"
216 " --no-tail Show all lines, even in follow mode\n"
217 " -r --reverse Show the newest entries first\n"
218 " -o --output=STRING Change journal output mode (short, short-iso,\n"
219 " short-precise, short-monotonic, verbose,\n"
220 " export, json, json-pretty, json-sse, cat)\n"
221 " --utc Express time in Coordinated Universal Time (UTC)\n"
222 " -x --catalog Add message explanations where available\n"
223 " --no-full Ellipsize fields\n"
224 " -a --all Show all fields, including long and unprintable\n"
225 " -q --quiet Do not show privilege warning\n"
226 " --no-pager Do not pipe output into a pager\n"
227 " -m --merge Show entries from all available journals\n"
228 " -D --directory=PATH Show journal files from directory\n"
229 " --file=PATH Show journal file\n"
230 " --root=ROOT Operate on catalog files underneath the root ROOT\n"
231 #ifdef HAVE_GCRYPT
232 " --interval=TIME Time interval for changing the FSS sealing key\n"
233 " --verify-key=KEY Specify FSS verification key\n"
234 " --force Force overriding of the FSS key pair with --setup-keys\n"
235 #endif
236 "\nCommands:\n"
237 " -h --help Show this help text\n"
238 " --version Show package version\n"
239 " -F --field=FIELD List all values that a specified field takes\n"
240 " --new-id128 Generate a new 128-bit ID\n"
241 " --disk-usage Show total disk usage of all journal files\n"
242 " --vacuum-size=BYTES Remove old journals until disk space drops below size\n"
243 " --vacuum-time=TIME Remove old journals until none left older than\n"
244 " --flush Flush all journal data from /run into /var\n"
245 " --header Show journal header information\n"
246 " --list-catalog Show message IDs of all entries in the message catalog\n"
247 " --dump-catalog Show entries in the message catalog\n"
248 " --update-catalog Update the message catalog database\n"
249 #ifdef HAVE_GCRYPT
250 " --setup-keys Generate a new FSS key pair\n"
251 " --verify Verify journal file consistency\n"
252 #endif
253 , program_invocation_short_name);
254 }
255
256 static int parse_argv(int argc, char *argv[]) {
257
258 enum {
259 ARG_VERSION = 0x100,
260 ARG_NO_PAGER,
261 ARG_NO_FULL,
262 ARG_NO_TAIL,
263 ARG_NEW_ID128,
264 ARG_LIST_BOOTS,
265 ARG_USER,
266 ARG_SYSTEM,
267 ARG_ROOT,
268 ARG_HEADER,
269 ARG_SETUP_KEYS,
270 ARG_FILE,
271 ARG_INTERVAL,
272 ARG_VERIFY,
273 ARG_VERIFY_KEY,
274 ARG_DISK_USAGE,
275 ARG_SINCE,
276 ARG_UNTIL,
277 ARG_AFTER_CURSOR,
278 ARG_SHOW_CURSOR,
279 ARG_USER_UNIT,
280 ARG_LIST_CATALOG,
281 ARG_DUMP_CATALOG,
282 ARG_UPDATE_CATALOG,
283 ARG_FORCE,
284 ARG_UTC,
285 ARG_FLUSH,
286 ARG_VACUUM_SIZE,
287 ARG_VACUUM_TIME,
288 };
289
290 static const struct option options[] = {
291 { "help", no_argument, NULL, 'h' },
292 { "version" , no_argument, NULL, ARG_VERSION },
293 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
294 { "pager-end", no_argument, NULL, 'e' },
295 { "follow", no_argument, NULL, 'f' },
296 { "force", no_argument, NULL, ARG_FORCE },
297 { "output", required_argument, NULL, 'o' },
298 { "all", no_argument, NULL, 'a' },
299 { "full", no_argument, NULL, 'l' },
300 { "no-full", no_argument, NULL, ARG_NO_FULL },
301 { "lines", optional_argument, NULL, 'n' },
302 { "no-tail", no_argument, NULL, ARG_NO_TAIL },
303 { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
304 { "quiet", no_argument, NULL, 'q' },
305 { "merge", no_argument, NULL, 'm' },
306 { "boot", optional_argument, NULL, 'b' },
307 { "list-boots", no_argument, NULL, ARG_LIST_BOOTS },
308 { "this-boot", optional_argument, NULL, 'b' }, /* deprecated */
309 { "dmesg", no_argument, NULL, 'k' },
310 { "system", no_argument, NULL, ARG_SYSTEM },
311 { "user", no_argument, NULL, ARG_USER },
312 { "directory", required_argument, NULL, 'D' },
313 { "file", required_argument, NULL, ARG_FILE },
314 { "root", required_argument, NULL, ARG_ROOT },
315 { "header", no_argument, NULL, ARG_HEADER },
316 { "identifier", required_argument, NULL, 't' },
317 { "priority", required_argument, NULL, 'p' },
318 { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
319 { "interval", required_argument, NULL, ARG_INTERVAL },
320 { "verify", no_argument, NULL, ARG_VERIFY },
321 { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
322 { "disk-usage", no_argument, NULL, ARG_DISK_USAGE },
323 { "cursor", required_argument, NULL, 'c' },
324 { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR },
325 { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR },
326 { "since", required_argument, NULL, ARG_SINCE },
327 { "until", required_argument, NULL, ARG_UNTIL },
328 { "unit", required_argument, NULL, 'u' },
329 { "user-unit", required_argument, NULL, ARG_USER_UNIT },
330 { "field", required_argument, NULL, 'F' },
331 { "catalog", no_argument, NULL, 'x' },
332 { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG },
333 { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG },
334 { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG },
335 { "reverse", no_argument, NULL, 'r' },
336 { "machine", required_argument, NULL, 'M' },
337 { "utc", no_argument, NULL, ARG_UTC },
338 { "flush", no_argument, NULL, ARG_FLUSH },
339 { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE },
340 { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME },
341 {}
342 };
343
344 int c, r;
345
346 assert(argc >= 0);
347 assert(argv);
348
349 while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:t:u:F:xrM:", options, NULL)) >= 0)
350
351 switch (c) {
352
353 case 'h':
354 help();
355 return 0;
356
357 case ARG_VERSION:
358 puts(PACKAGE_STRING);
359 puts(SYSTEMD_FEATURES);
360 return 0;
361
362 case ARG_NO_PAGER:
363 arg_no_pager = true;
364 break;
365
366 case 'e':
367 arg_pager_end = true;
368
369 if (arg_lines == ARG_LINES_DEFAULT)
370 arg_lines = 1000;
371
372 break;
373
374 case 'f':
375 arg_follow = true;
376 break;
377
378 case 'o':
379 arg_output = output_mode_from_string(optarg);
380 if (arg_output < 0) {
381 log_error("Unknown output format '%s'.", optarg);
382 return -EINVAL;
383 }
384
385 if (arg_output == OUTPUT_EXPORT ||
386 arg_output == OUTPUT_JSON ||
387 arg_output == OUTPUT_JSON_PRETTY ||
388 arg_output == OUTPUT_JSON_SSE ||
389 arg_output == OUTPUT_CAT)
390 arg_quiet = true;
391
392 break;
393
394 case 'l':
395 arg_full = true;
396 break;
397
398 case ARG_NO_FULL:
399 arg_full = false;
400 break;
401
402 case 'a':
403 arg_all = true;
404 break;
405
406 case 'n':
407 if (optarg) {
408 if (streq(optarg, "all"))
409 arg_lines = ARG_LINES_ALL;
410 else {
411 r = safe_atoi(optarg, &arg_lines);
412 if (r < 0 || arg_lines < 0) {
413 log_error("Failed to parse lines '%s'", optarg);
414 return -EINVAL;
415 }
416 }
417 } else {
418 arg_lines = 10;
419
420 /* Hmm, no argument? Maybe the next
421 * word on the command line is
422 * supposed to be the argument? Let's
423 * see if there is one, and is
424 * parsable. */
425 if (optind < argc) {
426 int n;
427 if (streq(argv[optind], "all")) {
428 arg_lines = ARG_LINES_ALL;
429 optind++;
430 } else if (safe_atoi(argv[optind], &n) >= 0 && n >= 0) {
431 arg_lines = n;
432 optind++;
433 }
434 }
435 }
436
437 break;
438
439 case ARG_NO_TAIL:
440 arg_no_tail = true;
441 break;
442
443 case ARG_NEW_ID128:
444 arg_action = ACTION_NEW_ID128;
445 break;
446
447 case 'q':
448 arg_quiet = true;
449 break;
450
451 case 'm':
452 arg_merge = true;
453 break;
454
455 case 'b':
456 arg_boot = true;
457
458 if (optarg) {
459 r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
460 if (r < 0) {
461 log_error("Failed to parse boot descriptor '%s'", optarg);
462 return -EINVAL;
463 }
464 } else {
465
466 /* Hmm, no argument? Maybe the next
467 * word on the command line is
468 * supposed to be the argument? Let's
469 * see if there is one and is parsable
470 * as a boot descriptor... */
471
472 if (optind < argc &&
473 parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0)
474 optind++;
475 }
476
477 break;
478
479 case ARG_LIST_BOOTS:
480 arg_action = ACTION_LIST_BOOTS;
481 break;
482
483 case 'k':
484 arg_boot = arg_dmesg = true;
485 break;
486
487 case ARG_SYSTEM:
488 arg_journal_type |= SD_JOURNAL_SYSTEM;
489 break;
490
491 case ARG_USER:
492 arg_journal_type |= SD_JOURNAL_CURRENT_USER;
493 break;
494
495 case 'M':
496 arg_machine = optarg;
497 break;
498
499 case 'D':
500 arg_directory = optarg;
501 break;
502
503 case ARG_FILE:
504 r = glob_extend(&arg_file, optarg);
505 if (r < 0)
506 return log_error_errno(r, "Failed to add paths: %m");
507 break;
508
509 case ARG_ROOT:
510 arg_root = optarg;
511 break;
512
513 case 'c':
514 arg_cursor = optarg;
515 break;
516
517 case ARG_AFTER_CURSOR:
518 arg_after_cursor = optarg;
519 break;
520
521 case ARG_SHOW_CURSOR:
522 arg_show_cursor = true;
523 break;
524
525 case ARG_HEADER:
526 arg_action = ACTION_PRINT_HEADER;
527 break;
528
529 case ARG_VERIFY:
530 arg_action = ACTION_VERIFY;
531 break;
532
533 case ARG_DISK_USAGE:
534 arg_action = ACTION_DISK_USAGE;
535 break;
536
537 case ARG_VACUUM_SIZE:
538 r = parse_size(optarg, 1024, &arg_vacuum_size);
539 if (r < 0) {
540 log_error("Failed to parse vacuum size: %s", optarg);
541 return r;
542 }
543
544 arg_action = ACTION_VACUUM;
545 break;
546
547 case ARG_VACUUM_TIME:
548 r = parse_sec(optarg, &arg_vacuum_time);
549 if (r < 0) {
550 log_error("Failed to parse vacuum time: %s", optarg);
551 return r;
552 }
553
554 arg_action = ACTION_VACUUM;
555 break;
556
557 #ifdef HAVE_GCRYPT
558 case ARG_FORCE:
559 arg_force = true;
560 break;
561
562 case ARG_SETUP_KEYS:
563 arg_action = ACTION_SETUP_KEYS;
564 break;
565
566
567 case ARG_VERIFY_KEY:
568 arg_action = ACTION_VERIFY;
569 arg_verify_key = optarg;
570 arg_merge = false;
571 break;
572
573 case ARG_INTERVAL:
574 r = parse_sec(optarg, &arg_interval);
575 if (r < 0 || arg_interval <= 0) {
576 log_error("Failed to parse sealing key change interval: %s", optarg);
577 return -EINVAL;
578 }
579 break;
580 #else
581 case ARG_SETUP_KEYS:
582 case ARG_VERIFY_KEY:
583 case ARG_INTERVAL:
584 case ARG_FORCE:
585 log_error("Forward-secure sealing not available.");
586 return -ENOTSUP;
587 #endif
588
589 case 'p': {
590 const char *dots;
591
592 dots = strstr(optarg, "..");
593 if (dots) {
594 char *a;
595 int from, to, i;
596
597 /* a range */
598 a = strndup(optarg, dots - optarg);
599 if (!a)
600 return log_oom();
601
602 from = log_level_from_string(a);
603 to = log_level_from_string(dots + 2);
604 free(a);
605
606 if (from < 0 || to < 0) {
607 log_error("Failed to parse log level range %s", optarg);
608 return -EINVAL;
609 }
610
611 arg_priorities = 0;
612
613 if (from < to) {
614 for (i = from; i <= to; i++)
615 arg_priorities |= 1 << i;
616 } else {
617 for (i = to; i <= from; i++)
618 arg_priorities |= 1 << i;
619 }
620
621 } else {
622 int p, i;
623
624 p = log_level_from_string(optarg);
625 if (p < 0) {
626 log_error("Unknown log level %s", optarg);
627 return -EINVAL;
628 }
629
630 arg_priorities = 0;
631
632 for (i = 0; i <= p; i++)
633 arg_priorities |= 1 << i;
634 }
635
636 break;
637 }
638
639 case ARG_SINCE:
640 r = parse_timestamp(optarg, &arg_since);
641 if (r < 0) {
642 log_error("Failed to parse timestamp: %s", optarg);
643 return -EINVAL;
644 }
645 arg_since_set = true;
646 break;
647
648 case ARG_UNTIL:
649 r = parse_timestamp(optarg, &arg_until);
650 if (r < 0) {
651 log_error("Failed to parse timestamp: %s", optarg);
652 return -EINVAL;
653 }
654 arg_until_set = true;
655 break;
656
657 case 't':
658 r = strv_extend(&arg_syslog_identifier, optarg);
659 if (r < 0)
660 return log_oom();
661 break;
662
663 case 'u':
664 r = strv_extend(&arg_system_units, optarg);
665 if (r < 0)
666 return log_oom();
667 break;
668
669 case ARG_USER_UNIT:
670 r = strv_extend(&arg_user_units, optarg);
671 if (r < 0)
672 return log_oom();
673 break;
674
675 case 'F':
676 arg_field = optarg;
677 break;
678
679 case 'x':
680 arg_catalog = true;
681 break;
682
683 case ARG_LIST_CATALOG:
684 arg_action = ACTION_LIST_CATALOG;
685 break;
686
687 case ARG_DUMP_CATALOG:
688 arg_action = ACTION_DUMP_CATALOG;
689 break;
690
691 case ARG_UPDATE_CATALOG:
692 arg_action = ACTION_UPDATE_CATALOG;
693 break;
694
695 case 'r':
696 arg_reverse = true;
697 break;
698
699 case ARG_UTC:
700 arg_utc = true;
701 break;
702
703 case ARG_FLUSH:
704 arg_action = ACTION_FLUSH;
705 break;
706
707 case '?':
708 return -EINVAL;
709
710 default:
711 assert_not_reached("Unhandled option");
712 }
713
714 if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT)
715 arg_lines = 10;
716
717 if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
718 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
719 return -EINVAL;
720 }
721
722 if (arg_since_set && arg_until_set && arg_since > arg_until) {
723 log_error("--since= must be before --until=.");
724 return -EINVAL;
725 }
726
727 if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
728 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
729 return -EINVAL;
730 }
731
732 if (arg_follow && arg_reverse) {
733 log_error("Please specify either --reverse= or --follow=, not both.");
734 return -EINVAL;
735 }
736
737 if (arg_action != ACTION_SHOW && optind < argc) {
738 log_error("Extraneous arguments starting with '%s'", argv[optind]);
739 return -EINVAL;
740 }
741
742 return 1;
743 }
744
745 static int generate_new_id128(void) {
746 sd_id128_t id;
747 int r;
748 unsigned i;
749
750 r = sd_id128_randomize(&id);
751 if (r < 0)
752 return log_error_errno(r, "Failed to generate ID: %m");
753
754 printf("As string:\n"
755 SD_ID128_FORMAT_STR "\n\n"
756 "As UUID:\n"
757 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
758 "As macro:\n"
759 "#define MESSAGE_XYZ SD_ID128_MAKE(",
760 SD_ID128_FORMAT_VAL(id),
761 SD_ID128_FORMAT_VAL(id));
762 for (i = 0; i < 16; i++)
763 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
764 fputs(")\n\n", stdout);
765
766 printf("As Python constant:\n"
767 ">>> import uuid\n"
768 ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
769 SD_ID128_FORMAT_VAL(id));
770
771 return 0;
772 }
773
774 static int add_matches(sd_journal *j, char **args) {
775 char **i;
776 bool have_term = false;
777
778 assert(j);
779
780 STRV_FOREACH(i, args) {
781 int r;
782
783 if (streq(*i, "+")) {
784 if (!have_term)
785 break;
786 r = sd_journal_add_disjunction(j);
787 have_term = false;
788
789 } else if (path_is_absolute(*i)) {
790 _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
791 const char *path;
792 _cleanup_free_ char *interpreter = NULL;
793 struct stat st;
794
795 p = canonicalize_file_name(*i);
796 path = p ? p : *i;
797
798 if (stat(path, &st) < 0)
799 return log_error_errno(errno, "Couldn't stat file: %m");
800
801 if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
802 if (executable_is_script(path, &interpreter) > 0) {
803 _cleanup_free_ char *comm;
804
805 comm = strndup(basename(path), 15);
806 if (!comm)
807 return log_oom();
808
809 t = strappend("_COMM=", comm);
810
811 /* Append _EXE only if the interpreter is not a link.
812 Otherwise, it might be outdated often. */
813 if (lstat(interpreter, &st) == 0 &&
814 !S_ISLNK(st.st_mode)) {
815 t2 = strappend("_EXE=", interpreter);
816 if (!t2)
817 return log_oom();
818 }
819 } else
820 t = strappend("_EXE=", path);
821 } else if (S_ISCHR(st.st_mode)) {
822 if (asprintf(&t, "_KERNEL_DEVICE=c%u:%u",
823 major(st.st_rdev),
824 minor(st.st_rdev)) < 0)
825 return -ENOMEM;
826 } else if (S_ISBLK(st.st_mode)) {
827 if (asprintf(&t, "_KERNEL_DEVICE=b%u:%u",
828 major(st.st_rdev),
829 minor(st.st_rdev)) < 0)
830 return -ENOMEM;
831 } else {
832 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
833 return -EINVAL;
834 }
835
836 if (!t)
837 return log_oom();
838
839 r = sd_journal_add_match(j, t, 0);
840 if (t2)
841 r = sd_journal_add_match(j, t2, 0);
842 have_term = true;
843
844 } else {
845 r = sd_journal_add_match(j, *i, 0);
846 have_term = true;
847 }
848
849 if (r < 0)
850 return log_error_errno(r, "Failed to add match '%s': %m", *i);
851 }
852
853 if (!strv_isempty(args) && !have_term) {
854 log_error("\"+\" can only be used between terms");
855 return -EINVAL;
856 }
857
858 return 0;
859 }
860
861 static int boot_id_cmp(const void *a, const void *b) {
862 uint64_t _a, _b;
863
864 _a = ((const boot_id_t *)a)->first;
865 _b = ((const boot_id_t *)b)->first;
866
867 return _a < _b ? -1 : (_a > _b ? 1 : 0);
868 }
869
870 static int get_boots(sd_journal *j,
871 boot_id_t **boots,
872 unsigned int *count,
873 boot_id_t *query_ref_boot) {
874 int r;
875 const void *data;
876 size_t length, allocated = 0;
877
878 assert(j);
879 assert(boots);
880 assert(count);
881
882 r = sd_journal_query_unique(j, "_BOOT_ID");
883 if (r < 0)
884 return r;
885
886 *count = 0;
887 SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
888 boot_id_t *id;
889
890 assert(startswith(data, "_BOOT_ID="));
891
892 if (!GREEDY_REALLOC(*boots, allocated, *count + 1))
893 return log_oom();
894
895 id = *boots + *count;
896
897 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
898 if (r < 0)
899 continue;
900
901 r = sd_journal_add_match(j, data, length);
902 if (r < 0)
903 return r;
904
905 r = sd_journal_seek_head(j);
906 if (r < 0)
907 return r;
908
909 r = sd_journal_next(j);
910 if (r < 0)
911 return r;
912 else if (r == 0)
913 goto flush;
914
915 r = sd_journal_get_realtime_usec(j, &id->first);
916 if (r < 0)
917 return r;
918
919 if (query_ref_boot) {
920 id->last = 0;
921 if (sd_id128_equal(id->id, query_ref_boot->id))
922 *query_ref_boot = *id;
923 } else {
924 r = sd_journal_seek_tail(j);
925 if (r < 0)
926 return r;
927
928 r = sd_journal_previous(j);
929 if (r < 0)
930 return r;
931 else if (r == 0)
932 goto flush;
933
934 r = sd_journal_get_realtime_usec(j, &id->last);
935 if (r < 0)
936 return r;
937 }
938
939 (*count)++;
940 flush:
941 sd_journal_flush_matches(j);
942 }
943
944 qsort_safe(*boots, *count, sizeof(boot_id_t), boot_id_cmp);
945 return 0;
946 }
947
948 static int list_boots(sd_journal *j) {
949 int r, w, i;
950 unsigned int count;
951 boot_id_t *id;
952 _cleanup_free_ boot_id_t *all_ids = NULL;
953
954 assert(j);
955
956 r = get_boots(j, &all_ids, &count, NULL);
957 if (r < 0)
958 return r;
959
960 pager_open_if_enabled();
961
962 /* numbers are one less, but we need an extra char for the sign */
963 w = DECIMAL_STR_WIDTH(count - 1) + 1;
964
965 for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
966 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
967
968 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
969 w, i - count + 1,
970 SD_ID128_FORMAT_VAL(id->id),
971 format_timestamp_maybe_utc(a, sizeof(a), id->first),
972 format_timestamp_maybe_utc(b, sizeof(b), id->last));
973 }
974
975 return 0;
976 }
977
978 static int get_boot_id_by_offset(sd_journal *j, sd_id128_t *boot_id, int offset) {
979 int r;
980 unsigned int count;
981 boot_id_t ref_boot_id = {}, *id;
982 _cleanup_free_ boot_id_t *all_ids = NULL;
983
984 assert(j);
985 assert(boot_id);
986
987 ref_boot_id.id = *boot_id;
988 r = get_boots(j, &all_ids, &count, &ref_boot_id);
989 if (r < 0)
990 return r;
991
992 if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
993 if (offset > (int) count || offset <= -(int)count)
994 return -EADDRNOTAVAIL;
995
996 *boot_id = all_ids[(offset <= 0)*count + offset - 1].id;
997 } else {
998 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
999
1000 if (!id ||
1001 offset <= 0 ? (id - all_ids) + offset < 0 :
1002 (id - all_ids) + offset >= (int) count)
1003 return -EADDRNOTAVAIL;
1004
1005 *boot_id = (id + offset)->id;
1006 }
1007
1008 return 0;
1009 }
1010
1011 static int add_boot(sd_journal *j) {
1012 char match[9+32+1] = "_BOOT_ID=";
1013 int r;
1014
1015 assert(j);
1016
1017 if (!arg_boot)
1018 return 0;
1019
1020 if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
1021 return add_match_this_boot(j, arg_machine);
1022
1023 r = get_boot_id_by_offset(j, &arg_boot_id, arg_boot_offset);
1024 if (r < 0) {
1025 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
1026 log_error_errno(r, "Failed to look up boot %+i: %m", arg_boot_offset);
1027 else
1028 log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
1029 SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
1030 return r;
1031 }
1032
1033 sd_id128_to_string(arg_boot_id, match + 9);
1034
1035 r = sd_journal_add_match(j, match, sizeof(match) - 1);
1036 if (r < 0)
1037 return log_error_errno(r, "Failed to add match: %m");
1038
1039 r = sd_journal_add_conjunction(j);
1040 if (r < 0)
1041 return r;
1042
1043 return 0;
1044 }
1045
1046 static int add_dmesg(sd_journal *j) {
1047 int r;
1048 assert(j);
1049
1050 if (!arg_dmesg)
1051 return 0;
1052
1053 r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
1054 if (r < 0)
1055 return log_error_errno(r, "Failed to add match: %m");
1056
1057 r = sd_journal_add_conjunction(j);
1058 if (r < 0)
1059 return r;
1060
1061 return 0;
1062 }
1063
1064 static int get_possible_units(sd_journal *j,
1065 const char *fields,
1066 char **patterns,
1067 Set **units) {
1068 _cleanup_set_free_free_ Set *found;
1069 const char *field;
1070 int r;
1071
1072 found = set_new(&string_hash_ops);
1073 if (!found)
1074 return log_oom();
1075
1076 NULSTR_FOREACH(field, fields) {
1077 const void *data;
1078 size_t size;
1079
1080 r = sd_journal_query_unique(j, field);
1081 if (r < 0)
1082 return r;
1083
1084 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1085 char **pattern, *eq;
1086 size_t prefix;
1087 _cleanup_free_ char *u = NULL;
1088
1089 eq = memchr(data, '=', size);
1090 if (eq)
1091 prefix = eq - (char*) data + 1;
1092 else
1093 prefix = 0;
1094
1095 u = strndup((char*) data + prefix, size - prefix);
1096 if (!u)
1097 return log_oom();
1098
1099 STRV_FOREACH(pattern, patterns)
1100 if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) {
1101 log_debug("Matched %s with pattern %s=%s", u, field, *pattern);
1102
1103 r = set_consume(found, u);
1104 u = NULL;
1105 if (r < 0 && r != -EEXIST)
1106 return r;
1107
1108 break;
1109 }
1110 }
1111 }
1112
1113 *units = found;
1114 found = NULL;
1115 return 0;
1116 }
1117
1118 /* This list is supposed to return the superset of unit names
1119 * possibly matched by rules added with add_matches_for_unit... */
1120 #define SYSTEM_UNITS \
1121 "_SYSTEMD_UNIT\0" \
1122 "COREDUMP_UNIT\0" \
1123 "UNIT\0" \
1124 "OBJECT_SYSTEMD_UNIT\0" \
1125 "_SYSTEMD_SLICE\0"
1126
1127 /* ... and add_matches_for_user_unit */
1128 #define USER_UNITS \
1129 "_SYSTEMD_USER_UNIT\0" \
1130 "USER_UNIT\0" \
1131 "COREDUMP_USER_UNIT\0" \
1132 "OBJECT_SYSTEMD_USER_UNIT\0"
1133
1134 static int add_units(sd_journal *j) {
1135 _cleanup_strv_free_ char **patterns = NULL;
1136 int r, count = 0;
1137 char **i;
1138
1139 assert(j);
1140
1141 STRV_FOREACH(i, arg_system_units) {
1142 _cleanup_free_ char *u = NULL;
1143
1144 u = unit_name_mangle(*i, MANGLE_GLOB);
1145 if (!u)
1146 return log_oom();
1147
1148 if (string_is_glob(u)) {
1149 r = strv_push(&patterns, u);
1150 if (r < 0)
1151 return r;
1152 u = NULL;
1153 } else {
1154 r = add_matches_for_unit(j, u);
1155 if (r < 0)
1156 return r;
1157 r = sd_journal_add_disjunction(j);
1158 if (r < 0)
1159 return r;
1160 count ++;
1161 }
1162 }
1163
1164 if (!strv_isempty(patterns)) {
1165 _cleanup_set_free_free_ Set *units = NULL;
1166 Iterator it;
1167 char *u;
1168
1169 r = get_possible_units(j, SYSTEM_UNITS, patterns, &units);
1170 if (r < 0)
1171 return r;
1172
1173 SET_FOREACH(u, units, it) {
1174 r = add_matches_for_unit(j, u);
1175 if (r < 0)
1176 return r;
1177 r = sd_journal_add_disjunction(j);
1178 if (r < 0)
1179 return r;
1180 count ++;
1181 }
1182 }
1183
1184 strv_free(patterns);
1185 patterns = NULL;
1186
1187 STRV_FOREACH(i, arg_user_units) {
1188 _cleanup_free_ char *u = NULL;
1189
1190 u = unit_name_mangle(*i, MANGLE_GLOB);
1191 if (!u)
1192 return log_oom();
1193
1194 if (string_is_glob(u)) {
1195 r = strv_push(&patterns, u);
1196 if (r < 0)
1197 return r;
1198 u = NULL;
1199 } else {
1200 r = add_matches_for_user_unit(j, u, getuid());
1201 if (r < 0)
1202 return r;
1203 r = sd_journal_add_disjunction(j);
1204 if (r < 0)
1205 return r;
1206 count ++;
1207 }
1208 }
1209
1210 if (!strv_isempty(patterns)) {
1211 _cleanup_set_free_free_ Set *units = NULL;
1212 Iterator it;
1213 char *u;
1214
1215 r = get_possible_units(j, USER_UNITS, patterns, &units);
1216 if (r < 0)
1217 return r;
1218
1219 SET_FOREACH(u, units, it) {
1220 r = add_matches_for_user_unit(j, u, getuid());
1221 if (r < 0)
1222 return r;
1223 r = sd_journal_add_disjunction(j);
1224 if (r < 0)
1225 return r;
1226 count ++;
1227 }
1228 }
1229
1230 /* Complain if the user request matches but nothing whatsoever was
1231 * found, since otherwise everything would be matched. */
1232 if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0)
1233 return -ENODATA;
1234
1235 r = sd_journal_add_conjunction(j);
1236 if (r < 0)
1237 return r;
1238
1239 return 0;
1240 }
1241
1242 static int add_priorities(sd_journal *j) {
1243 char match[] = "PRIORITY=0";
1244 int i, r;
1245 assert(j);
1246
1247 if (arg_priorities == 0xFF)
1248 return 0;
1249
1250 for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1251 if (arg_priorities & (1 << i)) {
1252 match[sizeof(match)-2] = '0' + i;
1253
1254 r = sd_journal_add_match(j, match, strlen(match));
1255 if (r < 0)
1256 return log_error_errno(r, "Failed to add match: %m");
1257 }
1258
1259 r = sd_journal_add_conjunction(j);
1260 if (r < 0)
1261 return r;
1262
1263 return 0;
1264 }
1265
1266
1267 static int add_syslog_identifier(sd_journal *j) {
1268 int r;
1269 char **i;
1270
1271 assert(j);
1272
1273 STRV_FOREACH(i, arg_syslog_identifier) {
1274 char *u;
1275
1276 u = strappenda("SYSLOG_IDENTIFIER=", *i);
1277 r = sd_journal_add_match(j, u, 0);
1278 if (r < 0)
1279 return r;
1280 r = sd_journal_add_disjunction(j);
1281 if (r < 0)
1282 return r;
1283 }
1284
1285 r = sd_journal_add_conjunction(j);
1286 if (r < 0)
1287 return r;
1288
1289 return 0;
1290 }
1291
1292 static int setup_keys(void) {
1293 #ifdef HAVE_GCRYPT
1294 size_t mpk_size, seed_size, state_size, i;
1295 uint8_t *mpk, *seed, *state;
1296 ssize_t l;
1297 int fd = -1, r, attr = 0;
1298 sd_id128_t machine, boot;
1299 char *p = NULL, *k = NULL;
1300 struct FSSHeader h;
1301 uint64_t n;
1302 struct stat st;
1303
1304 r = stat("/var/log/journal", &st);
1305 if (r < 0 && errno != ENOENT && errno != ENOTDIR)
1306 return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal");
1307
1308 if (r < 0 || !S_ISDIR(st.st_mode)) {
1309 log_error("%s is not a directory, must be using persistent logging for FSS.",
1310 "/var/log/journal");
1311 return r < 0 ? -errno : -ENOTDIR;
1312 }
1313
1314 r = sd_id128_get_machine(&machine);
1315 if (r < 0)
1316 return log_error_errno(r, "Failed to get machine ID: %m");
1317
1318 r = sd_id128_get_boot(&boot);
1319 if (r < 0)
1320 return log_error_errno(r, "Failed to get boot ID: %m");
1321
1322 if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1323 SD_ID128_FORMAT_VAL(machine)) < 0)
1324 return log_oom();
1325
1326 if (access(p, F_OK) >= 0) {
1327 if (arg_force) {
1328 r = unlink(p);
1329 if (r < 0) {
1330 log_error_errno(errno, "unlink(\"%s\") failed: %m", p);
1331 r = -errno;
1332 goto finish;
1333 }
1334 } else {
1335 log_error("Sealing key file %s exists already. (--force to recreate)", p);
1336 r = -EEXIST;
1337 goto finish;
1338 }
1339 }
1340
1341 if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1342 SD_ID128_FORMAT_VAL(machine)) < 0) {
1343 r = log_oom();
1344 goto finish;
1345 }
1346
1347 mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1348 mpk = alloca(mpk_size);
1349
1350 seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1351 seed = alloca(seed_size);
1352
1353 state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1354 state = alloca(state_size);
1355
1356 fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1357 if (fd < 0) {
1358 log_error_errno(errno, "Failed to open /dev/random: %m");
1359 r = -errno;
1360 goto finish;
1361 }
1362
1363 log_info("Generating seed...");
1364 l = loop_read(fd, seed, seed_size, true);
1365 if (l < 0 || (size_t) l != seed_size) {
1366 log_error_errno(EIO, "Failed to read random seed: %m");
1367 r = -EIO;
1368 goto finish;
1369 }
1370
1371 log_info("Generating key pair...");
1372 FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1373
1374 log_info("Generating sealing key...");
1375 FSPRG_GenState0(state, mpk, seed, seed_size);
1376
1377 assert(arg_interval > 0);
1378
1379 n = now(CLOCK_REALTIME);
1380 n /= arg_interval;
1381
1382 safe_close(fd);
1383 fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC);
1384 if (fd < 0) {
1385 log_error_errno(errno, "Failed to open %s: %m", k);
1386 r = -errno;
1387 goto finish;
1388 }
1389
1390 /* Enable secure remove, exclusion from dump, synchronous
1391 * writing and in-place updating */
1392 if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1393 log_warning_errno(errno, "FS_IOC_GETFLAGS failed: %m");
1394
1395 attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1396
1397 if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1398 log_warning_errno(errno, "FS_IOC_SETFLAGS failed: %m");
1399
1400 zero(h);
1401 memcpy(h.signature, "KSHHRHLP", 8);
1402 h.machine_id = machine;
1403 h.boot_id = boot;
1404 h.header_size = htole64(sizeof(h));
1405 h.start_usec = htole64(n * arg_interval);
1406 h.interval_usec = htole64(arg_interval);
1407 h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1408 h.fsprg_state_size = htole64(state_size);
1409
1410 r = loop_write(fd, &h, sizeof(h), false);
1411 if (r < 0) {
1412 log_error_errno(r, "Failed to write header: %m");
1413 goto finish;
1414 }
1415
1416 r = loop_write(fd, state, state_size, false);
1417 if (r < 0) {
1418 log_error_errno(r, "Failed to write state: %m");
1419 goto finish;
1420 }
1421
1422 if (link(k, p) < 0) {
1423 log_error_errno(errno, "Failed to link file: %m");
1424 r = -errno;
1425 goto finish;
1426 }
1427
1428 if (on_tty()) {
1429 fprintf(stderr,
1430 "\n"
1431 "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1432 "the following local file. This key file is automatically updated when the\n"
1433 "sealing key is advanced. It should not be used on multiple hosts.\n"
1434 "\n"
1435 "\t%s\n"
1436 "\n"
1437 "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1438 "at a safe location and should not be saved locally on disk.\n"
1439 "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1440 fflush(stderr);
1441 }
1442 for (i = 0; i < seed_size; i++) {
1443 if (i > 0 && i % 3 == 0)
1444 putchar('-');
1445 printf("%02x", ((uint8_t*) seed)[i]);
1446 }
1447
1448 printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1449
1450 if (on_tty()) {
1451 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1452
1453 fprintf(stderr,
1454 ANSI_HIGHLIGHT_OFF "\n"
1455 "The sealing key is automatically changed every %s.\n",
1456 format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1457
1458 hn = gethostname_malloc();
1459
1460 if (hn) {
1461 hostname_cleanup(hn, false);
1462 fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1463 } else
1464 fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1465
1466 #ifdef HAVE_QRENCODE
1467 /* If this is not an UTF-8 system don't print any QR codes */
1468 if (is_locale_utf8()) {
1469 fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1470 print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1471 }
1472 #endif
1473 free(hn);
1474 }
1475
1476 r = 0;
1477
1478 finish:
1479 safe_close(fd);
1480
1481 if (k) {
1482 unlink(k);
1483 free(k);
1484 }
1485
1486 free(p);
1487
1488 return r;
1489 #else
1490 log_error("Forward-secure sealing not available.");
1491 return -ENOTSUP;
1492 #endif
1493 }
1494
1495 static int verify(sd_journal *j) {
1496 int r = 0;
1497 Iterator i;
1498 JournalFile *f;
1499
1500 assert(j);
1501
1502 log_show_color(true);
1503
1504 ORDERED_HASHMAP_FOREACH(f, j->files, i) {
1505 int k;
1506 usec_t first, validated, last;
1507
1508 #ifdef HAVE_GCRYPT
1509 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1510 log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1511 #endif
1512
1513 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1514 if (k == -EINVAL) {
1515 /* If the key was invalid give up right-away. */
1516 return k;
1517 } else if (k < 0) {
1518 log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1519 r = k;
1520 } else {
1521 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1522 log_info("PASS: %s", f->path);
1523
1524 if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1525 if (validated > 0) {
1526 log_info("=> Validated from %s to %s, final %s entries not sealed.",
1527 format_timestamp_maybe_utc(a, sizeof(a), first),
1528 format_timestamp_maybe_utc(b, sizeof(b), validated),
1529 format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1530 } else if (last > 0)
1531 log_info("=> No sealing yet, %s of entries not sealed.",
1532 format_timespan(c, sizeof(c), last - first, 0));
1533 else
1534 log_info("=> No sealing yet, no entries in file.");
1535 }
1536 }
1537 }
1538
1539 return r;
1540 }
1541
1542 #ifdef HAVE_ACL
1543 static int access_check_var_log_journal(sd_journal *j) {
1544 _cleanup_strv_free_ char **g = NULL;
1545 bool have_access;
1546 int r;
1547
1548 assert(j);
1549
1550 have_access = in_group("systemd-journal") > 0;
1551
1552 if (!have_access) {
1553 /* Let's enumerate all groups from the default ACL of
1554 * the directory, which generally should allow access
1555 * to most journal files too */
1556 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1557 if (r < 0)
1558 return r;
1559 }
1560
1561 if (!have_access) {
1562
1563 if (strv_isempty(g))
1564 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1565 " Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1566 " turn off this notice.");
1567 else {
1568 _cleanup_free_ char *s = NULL;
1569
1570 r = strv_extend(&g, "systemd-journal");
1571 if (r < 0)
1572 return log_oom();
1573
1574 strv_sort(g);
1575 strv_uniq(g);
1576
1577 s = strv_join(g, "', '");
1578 if (!s)
1579 return log_oom();
1580
1581 log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1582 " Users in the groups '%s' can see all messages.\n"
1583 " Pass -q to turn off this notice.", s);
1584 }
1585 }
1586
1587 return 0;
1588 }
1589 #endif
1590
1591 static int access_check(sd_journal *j) {
1592 Iterator it;
1593 void *code;
1594 int r = 0;
1595
1596 assert(j);
1597
1598 if (set_isempty(j->errors)) {
1599 if (ordered_hashmap_isempty(j->files))
1600 log_notice("No journal files were found.");
1601 return 0;
1602 }
1603
1604 if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1605 #ifdef HAVE_ACL
1606 /* If /var/log/journal doesn't even exist,
1607 * unprivileged users have no access at all */
1608 if (access("/var/log/journal", F_OK) < 0 &&
1609 geteuid() != 0 &&
1610 in_group("systemd-journal") <= 0) {
1611 log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1612 "enabled. Users in the 'systemd-journal' group may always access messages.");
1613 return -EACCES;
1614 }
1615
1616 /* If /var/log/journal exists, try to pring a nice
1617 notice if the user lacks access to it */
1618 if (!arg_quiet && geteuid() != 0) {
1619 r = access_check_var_log_journal(j);
1620 if (r < 0)
1621 return r;
1622 }
1623 #else
1624 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1625 log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1626 "group may access messages.");
1627 return -EACCES;
1628 }
1629 #endif
1630
1631 if (ordered_hashmap_isempty(j->files)) {
1632 log_error("No journal files were opened due to insufficient permissions.");
1633 r = -EACCES;
1634 }
1635 }
1636
1637 SET_FOREACH(code, j->errors, it) {
1638 int err;
1639
1640 err = -PTR_TO_INT(code);
1641 assert(err > 0);
1642
1643 if (err != EACCES)
1644 log_warning_errno(err, "Error was encountered while opening journal files: %m");
1645 }
1646
1647 return r;
1648 }
1649
1650 static int flush_to_var(void) {
1651 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1652 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
1653 _cleanup_close_ int watch_fd = -1;
1654 int r;
1655
1656 /* Quick exit */
1657 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
1658 return 0;
1659
1660 /* OK, let's actually do the full logic, send SIGUSR1 to the
1661 * daemon and set up inotify to wait for the flushed file to appear */
1662 r = bus_open_system_systemd(&bus);
1663 if (r < 0)
1664 return log_error_errno(r, "Failed to get D-Bus connection: %m");
1665
1666 r = sd_bus_call_method(
1667 bus,
1668 "org.freedesktop.systemd1",
1669 "/org/freedesktop/systemd1",
1670 "org.freedesktop.systemd1.Manager",
1671 "KillUnit",
1672 &error,
1673 NULL,
1674 "ssi", "systemd-journald.service", "main", SIGUSR1);
1675 if (r < 0) {
1676 log_error("Failed to kill journal service: %s", bus_error_message(&error, r));
1677 return r;
1678 }
1679
1680 mkdir_p("/run/systemd/journal", 0755);
1681
1682 watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
1683 if (watch_fd < 0)
1684 return log_error_errno(errno, "Failed to create inotify watch: %m");
1685
1686 r = inotify_add_watch(watch_fd, "/run/systemd/journal", IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR);
1687 if (r < 0)
1688 return log_error_errno(errno, "Failed to watch journal directory: %m");
1689
1690 for (;;) {
1691 if (access("/run/systemd/journal/flushed", F_OK) >= 0)
1692 break;
1693
1694 if (errno != ENOENT)
1695 return log_error_errno(errno, "Failed to check for existence of /run/systemd/journal/flushed: %m");
1696
1697 r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
1698 if (r < 0)
1699 return log_error_errno(r, "Failed to wait for event: %m");
1700
1701 r = flush_fd(watch_fd);
1702 if (r < 0)
1703 return log_error_errno(r, "Failed to flush inotify events: %m");
1704 }
1705
1706 return 0;
1707 }
1708
1709 int main(int argc, char *argv[]) {
1710 int r;
1711 _cleanup_journal_close_ sd_journal *j = NULL;
1712 bool need_seek = false;
1713 sd_id128_t previous_boot_id;
1714 bool previous_boot_id_valid = false, first_line = true;
1715 int n_shown = 0;
1716 bool ellipsized = false;
1717
1718 setlocale(LC_ALL, "");
1719 log_parse_environment();
1720 log_open();
1721
1722 r = parse_argv(argc, argv);
1723 if (r <= 0)
1724 goto finish;
1725
1726 signal(SIGWINCH, columns_lines_cache_reset);
1727 sigbus_install();
1728
1729 if (arg_action == ACTION_NEW_ID128) {
1730 r = generate_new_id128();
1731 goto finish;
1732 }
1733
1734 if (arg_action == ACTION_FLUSH) {
1735 r = flush_to_var();
1736 goto finish;
1737 }
1738
1739 if (arg_action == ACTION_SETUP_KEYS) {
1740 r = setup_keys();
1741 goto finish;
1742 }
1743
1744 if (arg_action == ACTION_UPDATE_CATALOG ||
1745 arg_action == ACTION_LIST_CATALOG ||
1746 arg_action == ACTION_DUMP_CATALOG) {
1747
1748 _cleanup_free_ char *database;
1749
1750 database = path_join(arg_root, CATALOG_DATABASE, NULL);
1751 if (!database) {
1752 r = log_oom();
1753 goto finish;
1754 }
1755
1756 if (arg_action == ACTION_UPDATE_CATALOG) {
1757 r = catalog_update(database, arg_root, catalog_file_dirs);
1758 if (r < 0)
1759 log_error_errno(r, "Failed to list catalog: %m");
1760 } else {
1761 bool oneline = arg_action == ACTION_LIST_CATALOG;
1762
1763 if (optind < argc)
1764 r = catalog_list_items(stdout, database,
1765 oneline, argv + optind);
1766 else
1767 r = catalog_list(stdout, database, oneline);
1768 if (r < 0)
1769 log_error_errno(r, "Failed to list catalog: %m");
1770 }
1771
1772 goto finish;
1773 }
1774
1775 if (arg_directory)
1776 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1777 else if (arg_file)
1778 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1779 else if (arg_machine)
1780 r = sd_journal_open_container(&j, arg_machine, 0);
1781 else
1782 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1783 if (r < 0) {
1784 log_error_errno(r, "Failed to open %s: %m",
1785 arg_directory ? arg_directory : arg_file ? "files" : "journal");
1786 return EXIT_FAILURE;
1787 }
1788
1789 r = access_check(j);
1790 if (r < 0)
1791 return EXIT_FAILURE;
1792
1793 if (arg_action == ACTION_VERIFY) {
1794 r = verify(j);
1795 goto finish;
1796 }
1797
1798 if (arg_action == ACTION_PRINT_HEADER) {
1799 journal_print_header(j);
1800 return EXIT_SUCCESS;
1801 }
1802
1803 if (arg_action == ACTION_DISK_USAGE) {
1804 uint64_t bytes = 0;
1805 char sbytes[FORMAT_BYTES_MAX];
1806
1807 r = sd_journal_get_usage(j, &bytes);
1808 if (r < 0)
1809 return EXIT_FAILURE;
1810
1811 printf("Archived and active journals take up %s on disk.\n",
1812 format_bytes(sbytes, sizeof(sbytes), bytes));
1813 return EXIT_SUCCESS;
1814 }
1815
1816 if (arg_action == ACTION_VACUUM) {
1817 Directory *d;
1818 Iterator i;
1819
1820 HASHMAP_FOREACH(d, j->directories_by_path, i) {
1821 int q;
1822
1823 if (d->is_root)
1824 continue;
1825
1826 q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_time, NULL, true);
1827 if (q < 0) {
1828 log_error_errno(q, "Failed to vacuum: %m");
1829 r = q;
1830 }
1831 }
1832
1833 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1834 }
1835
1836 if (arg_action == ACTION_LIST_BOOTS) {
1837 r = list_boots(j);
1838 goto finish;
1839 }
1840
1841 /* add_boot() must be called first!
1842 * It may need to seek the journal to find parent boot IDs. */
1843 r = add_boot(j);
1844 if (r < 0)
1845 return EXIT_FAILURE;
1846
1847 r = add_dmesg(j);
1848 if (r < 0)
1849 return EXIT_FAILURE;
1850
1851 r = add_units(j);
1852 strv_free(arg_system_units);
1853 strv_free(arg_user_units);
1854
1855 if (r < 0) {
1856 log_error_errno(r, "Failed to add filter for units: %m");
1857 return EXIT_FAILURE;
1858 }
1859
1860 r = add_syslog_identifier(j);
1861 if (r < 0) {
1862 log_error_errno(r, "Failed to add filter for syslog identifiers: %m");
1863 return EXIT_FAILURE;
1864 }
1865
1866 r = add_priorities(j);
1867 if (r < 0) {
1868 log_error_errno(r, "Failed to add filter for priorities: %m");
1869 return EXIT_FAILURE;
1870 }
1871
1872 r = add_matches(j, argv + optind);
1873 if (r < 0) {
1874 log_error_errno(r, "Failed to add filters: %m");
1875 return EXIT_FAILURE;
1876 }
1877
1878 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1879 _cleanup_free_ char *filter;
1880
1881 filter = journal_make_match_string(j);
1882 log_debug("Journal filter: %s", filter);
1883 }
1884
1885 if (arg_field) {
1886 const void *data;
1887 size_t size;
1888
1889 r = sd_journal_set_data_threshold(j, 0);
1890 if (r < 0) {
1891 log_error("Failed to unset data size threshold");
1892 return EXIT_FAILURE;
1893 }
1894
1895 r = sd_journal_query_unique(j, arg_field);
1896 if (r < 0) {
1897 log_error_errno(r, "Failed to query unique data objects: %m");
1898 return EXIT_FAILURE;
1899 }
1900
1901 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1902 const void *eq;
1903
1904 if (arg_lines >= 0 && n_shown >= arg_lines)
1905 break;
1906
1907 eq = memchr(data, '=', size);
1908 if (eq)
1909 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1910 else
1911 printf("%.*s\n", (int) size, (const char*) data);
1912
1913 n_shown ++;
1914 }
1915
1916 return EXIT_SUCCESS;
1917 }
1918
1919 /* Opening the fd now means the first sd_journal_wait() will actually wait */
1920 if (arg_follow) {
1921 r = sd_journal_get_fd(j);
1922 if (r < 0)
1923 return EXIT_FAILURE;
1924 }
1925
1926 if (arg_cursor || arg_after_cursor) {
1927 r = sd_journal_seek_cursor(j, arg_cursor ?: arg_after_cursor);
1928 if (r < 0) {
1929 log_error_errno(r, "Failed to seek to cursor: %m");
1930 return EXIT_FAILURE;
1931 }
1932 if (!arg_reverse)
1933 r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1934 else
1935 r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1936
1937 if (arg_after_cursor && r < 2) {
1938 /* We couldn't find the next entry after the cursor. */
1939 if (arg_follow)
1940 need_seek = true;
1941 else
1942 arg_lines = 0;
1943 }
1944
1945 } else if (arg_since_set && !arg_reverse) {
1946 r = sd_journal_seek_realtime_usec(j, arg_since);
1947 if (r < 0) {
1948 log_error_errno(r, "Failed to seek to date: %m");
1949 return EXIT_FAILURE;
1950 }
1951 r = sd_journal_next(j);
1952
1953 } else if (arg_until_set && arg_reverse) {
1954 r = sd_journal_seek_realtime_usec(j, arg_until);
1955 if (r < 0) {
1956 log_error_errno(r, "Failed to seek to date: %m");
1957 return EXIT_FAILURE;
1958 }
1959 r = sd_journal_previous(j);
1960
1961 } else if (arg_lines >= 0) {
1962 r = sd_journal_seek_tail(j);
1963 if (r < 0) {
1964 log_error_errno(r, "Failed to seek to tail: %m");
1965 return EXIT_FAILURE;
1966 }
1967
1968 r = sd_journal_previous_skip(j, arg_lines);
1969
1970 } else if (arg_reverse) {
1971 r = sd_journal_seek_tail(j);
1972 if (r < 0) {
1973 log_error_errno(r, "Failed to seek to tail: %m");
1974 return EXIT_FAILURE;
1975 }
1976
1977 r = sd_journal_previous(j);
1978
1979 } else {
1980 r = sd_journal_seek_head(j);
1981 if (r < 0) {
1982 log_error_errno(r, "Failed to seek to head: %m");
1983 return EXIT_FAILURE;
1984 }
1985
1986 r = sd_journal_next(j);
1987 }
1988
1989 if (r < 0) {
1990 log_error_errno(r, "Failed to iterate through journal: %m");
1991 return EXIT_FAILURE;
1992 }
1993
1994 if (!arg_follow)
1995 pager_open_if_enabled();
1996
1997 if (!arg_quiet) {
1998 usec_t start, end;
1999 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
2000
2001 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
2002 if (r < 0) {
2003 log_error_errno(r, "Failed to get cutoff: %m");
2004 goto finish;
2005 }
2006
2007 if (r > 0) {
2008 if (arg_follow)
2009 printf("-- Logs begin at %s. --\n",
2010 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start));
2011 else
2012 printf("-- Logs begin at %s, end at %s. --\n",
2013 format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start),
2014 format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end));
2015 }
2016 }
2017
2018 for (;;) {
2019 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
2020 int flags;
2021
2022 if (need_seek) {
2023 if (!arg_reverse)
2024 r = sd_journal_next(j);
2025 else
2026 r = sd_journal_previous(j);
2027 if (r < 0) {
2028 log_error_errno(r, "Failed to iterate through journal: %m");
2029 goto finish;
2030 }
2031 if (r == 0)
2032 break;
2033 }
2034
2035 if (arg_until_set && !arg_reverse) {
2036 usec_t usec;
2037
2038 r = sd_journal_get_realtime_usec(j, &usec);
2039 if (r < 0) {
2040 log_error_errno(r, "Failed to determine timestamp: %m");
2041 goto finish;
2042 }
2043 if (usec > arg_until)
2044 goto finish;
2045 }
2046
2047 if (arg_since_set && arg_reverse) {
2048 usec_t usec;
2049
2050 r = sd_journal_get_realtime_usec(j, &usec);
2051 if (r < 0) {
2052 log_error_errno(r, "Failed to determine timestamp: %m");
2053 goto finish;
2054 }
2055 if (usec < arg_since)
2056 goto finish;
2057 }
2058
2059 if (!arg_merge && !arg_quiet) {
2060 sd_id128_t boot_id;
2061
2062 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
2063 if (r >= 0) {
2064 if (previous_boot_id_valid &&
2065 !sd_id128_equal(boot_id, previous_boot_id))
2066 printf("%s-- Reboot --%s\n",
2067 ansi_highlight(), ansi_highlight_off());
2068
2069 previous_boot_id = boot_id;
2070 previous_boot_id_valid = true;
2071 }
2072 }
2073
2074 flags =
2075 arg_all * OUTPUT_SHOW_ALL |
2076 arg_full * OUTPUT_FULL_WIDTH |
2077 on_tty() * OUTPUT_COLOR |
2078 arg_catalog * OUTPUT_CATALOG |
2079 arg_utc * OUTPUT_UTC;
2080
2081 r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
2082 need_seek = true;
2083 if (r == -EADDRNOTAVAIL)
2084 break;
2085 else if (r < 0 || ferror(stdout))
2086 goto finish;
2087
2088 n_shown++;
2089 }
2090
2091 if (!arg_follow) {
2092 if (arg_show_cursor) {
2093 _cleanup_free_ char *cursor = NULL;
2094
2095 r = sd_journal_get_cursor(j, &cursor);
2096 if (r < 0 && r != -EADDRNOTAVAIL)
2097 log_error_errno(r, "Failed to get cursor: %m");
2098 else if (r >= 0)
2099 printf("-- cursor: %s\n", cursor);
2100 }
2101
2102 break;
2103 }
2104
2105 r = sd_journal_wait(j, (uint64_t) -1);
2106 if (r < 0) {
2107 log_error_errno(r, "Couldn't wait for journal event: %m");
2108 goto finish;
2109 }
2110
2111 first_line = false;
2112 }
2113
2114 finish:
2115 pager_close();
2116
2117 strv_free(arg_file);
2118
2119 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
2120 }