]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
4f37cbd9 ZJS |
2 | |
3 | #include "acl-util.h" | |
2ec1fb31 YW |
4 | #include "bus-error.h" |
5 | #include "bus-locator.h" | |
6 | #include "bus-util.h" | |
7 | #include "fd-util.h" | |
4f37cbd9 ZJS |
8 | #include "fs-util.h" |
9 | #include "hashmap.h" | |
10 | #include "journal-internal.h" | |
11 | #include "journal-util.h" | |
12 | #include "log.h" | |
13 | #include "strv.h" | |
14 | #include "user-util.h" | |
15 | ||
e79d0b59 | 16 | static int access_check_var_log_journal(sd_journal *j, bool want_other_users) { |
4f37cbd9 ZJS |
17 | int r; |
18 | ||
19 | assert(j); | |
20 | ||
21 | /* If we are root, we should have access, don't warn. */ | |
22 | if (getuid() == 0) | |
23 | return 0; | |
24 | ||
25 | /* If we are in the 'systemd-journal' group, we should have | |
26 | * access too. */ | |
27 | r = in_group("systemd-journal"); | |
28 | if (r < 0) | |
29 | return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m"); | |
30 | if (r > 0) | |
31 | return 0; | |
32 | ||
349cc4a5 | 33 | #if HAVE_ACL |
d5a99b7c JJ |
34 | _cleanup_strv_free_ char **g = NULL; |
35 | const char* dir; | |
36 | ||
4f37cbd9 ZJS |
37 | if (laccess("/run/log/journal", F_OK) >= 0) |
38 | dir = "/run/log/journal"; | |
39 | else | |
40 | dir = "/var/log/journal"; | |
41 | ||
42 | /* If we are in any of the groups listed in the journal ACLs, | |
43 | * then all is good, too. Let's enumerate all groups from the | |
44 | * default ACL of the directory, which generally should allow | |
45 | * access to most journal files too. */ | |
46 | r = acl_search_groups(dir, &g); | |
47 | if (r < 0) | |
48 | return log_error_errno(r, "Failed to search journal ACL: %m"); | |
49 | if (r > 0) | |
50 | return 0; | |
51 | ||
52 | /* Print a pretty list, if there were ACLs set. */ | |
53 | if (!strv_isempty(g)) { | |
54 | _cleanup_free_ char *s = NULL; | |
55 | ||
5238e957 | 56 | /* There are groups in the ACL, let's list them */ |
4f37cbd9 ZJS |
57 | r = strv_extend(&g, "systemd-journal"); |
58 | if (r < 0) | |
59 | return log_oom(); | |
60 | ||
61 | strv_sort(g); | |
62 | strv_uniq(g); | |
63 | ||
64 | s = strv_join(g, "', '"); | |
65 | if (!s) | |
66 | return log_oom(); | |
67 | ||
e79d0b59 | 68 | log_notice("Hint: You are currently not seeing messages from %s.\n" |
4f37cbd9 | 69 | " Users in groups '%s' can see all messages.\n" |
e79d0b59 ZJS |
70 | " Pass -q to turn off this notice.", |
71 | want_other_users ? "other users and the system" : "the system", | |
72 | s); | |
4f37cbd9 ZJS |
73 | return 1; |
74 | } | |
75 | #endif | |
76 | ||
77 | /* If no ACLs were found, print a short version of the message. */ | |
e79d0b59 | 78 | log_notice("Hint: You are currently not seeing messages from %s.\n" |
4f37cbd9 | 79 | " Users in the 'systemd-journal' group can see all messages. Pass -q to\n" |
e79d0b59 ZJS |
80 | " turn off this notice.", |
81 | want_other_users ? "other users and the system" : "the system"); | |
4f37cbd9 ZJS |
82 | |
83 | return 1; | |
84 | } | |
85 | ||
1a8f0ce6 ZJS |
86 | int journal_access_blocked(sd_journal *j) { |
87 | return hashmap_contains(j->errors, INT_TO_PTR(-EACCES)); | |
88 | } | |
89 | ||
e79d0b59 | 90 | int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users) { |
4f37cbd9 ZJS |
91 | void *code; |
92 | char *path; | |
93 | int r = 0; | |
94 | ||
95 | assert(j); | |
96 | ||
97 | if (hashmap_isempty(j->errors)) { | |
98 | if (ordered_hashmap_isempty(j->files) && !quiet) | |
99 | log_notice("No journal files were found."); | |
100 | ||
101 | return 0; | |
102 | } | |
103 | ||
1a8f0ce6 | 104 | if (journal_access_blocked(j)) { |
4f37cbd9 | 105 | if (!quiet) |
e79d0b59 | 106 | (void) access_check_var_log_journal(j, want_other_users); |
4f37cbd9 ZJS |
107 | |
108 | if (ordered_hashmap_isempty(j->files)) | |
109 | r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions."); | |
110 | } | |
111 | ||
90e74a66 | 112 | HASHMAP_FOREACH_KEY(path, code, j->errors) { |
4f37cbd9 ZJS |
113 | int err; |
114 | ||
115 | err = abs(PTR_TO_INT(code)); | |
116 | ||
117 | switch (err) { | |
118 | case EACCES: | |
119 | continue; | |
120 | ||
121 | case ENODATA: | |
122 | log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path); | |
123 | break; | |
124 | ||
125 | case EPROTONOSUPPORT: | |
126 | log_warning_errno(err, "Journal file %1$s uses an unsupported feature, ignoring file.\n" | |
127 | "Use SYSTEMD_LOG_LEVEL=debug journalctl --file=%1$s to see the details.", | |
128 | path); | |
129 | break; | |
130 | ||
131 | case EBADMSG: | |
132 | log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path); | |
133 | break; | |
134 | ||
763c46de LP |
135 | case ETOOMANYREFS: |
136 | log_warning_errno(err, "Too many journal files (limit is at %u) in scope, ignoring file '%s'.", JOURNAL_FILES_MAX, path); | |
137 | break; | |
138 | ||
4f37cbd9 ZJS |
139 | default: |
140 | log_warning_errno(err, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path); | |
141 | break; | |
142 | } | |
143 | } | |
144 | ||
145 | return r; | |
146 | } | |
2ec1fb31 YW |
147 | |
148 | int journal_open_machine(sd_journal **ret, const char *machine) { | |
149 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; | |
150 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; | |
151 | _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; | |
152 | _cleanup_(sd_journal_closep) sd_journal *j = NULL; | |
153 | _cleanup_close_ int machine_fd = -EBADF; | |
154 | int fd, r; | |
155 | ||
156 | assert(ret); | |
157 | assert(machine); | |
158 | ||
159 | if (geteuid() != 0) | |
160 | /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of | |
161 | * the container, thus we need root privileges to override them. */ | |
162 | return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Using the --machine= switch requires root privileges."); | |
163 | ||
164 | r = sd_bus_open_system(&bus); | |
165 | if (r < 0) | |
166 | return log_error_errno(r, "Failed to open system bus: %m"); | |
167 | ||
168 | r = bus_call_method(bus, bus_machine_mgr, "OpenMachineRootDirectory", &error, &reply, "s", machine); | |
169 | if (r < 0) | |
170 | return log_error_errno(r, "Failed to open root directory of machine '%s': %s", | |
171 | machine, bus_error_message(&error, r)); | |
172 | ||
173 | r = sd_bus_message_read(reply, "h", &fd); | |
174 | if (r < 0) | |
175 | return bus_log_parse_error(r); | |
176 | ||
177 | machine_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); | |
178 | if (machine_fd < 0) | |
179 | return log_error_errno(errno, "Failed to duplicate file descriptor: %m"); | |
180 | ||
181 | r = sd_journal_open_directory_fd(&j, machine_fd, SD_JOURNAL_OS_ROOT | SD_JOURNAL_TAKE_DIRECTORY_FD); | |
182 | if (r < 0) | |
183 | return log_error_errno(r, "Failed to open journal in machine '%s': %m", machine); | |
184 | ||
185 | TAKE_FD(machine_fd); | |
186 | *ret = TAKE_PTR(j); | |
187 | return 0; | |
188 | } |