Bug Summary

File:build-scan/../src/journal-remote/journal-remote.c
Warning:line 253, column 53
Access to field 'event' results in a dereference of a null pointer (loaded from variable 'source')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name journal-remote.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/journal-remote/libsystemd-journal-remote.a.p -I src/journal-remote -I ../src/journal-remote -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/p11-kit-1 -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/journal-remote/journal-remote.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <fcntl.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/prctl.h>
9#include <sys/socket.h>
10#include <stdint.h>
11
12#include "sd-daemon.h"
13
14#include "alloc-util.h"
15#include "def.h"
16#include "escape.h"
17#include "fd-util.h"
18#include "journal-file.h"
19#include "journal-remote-write.h"
20#include "journal-remote.h"
21#include "journald-native.h"
22#include "macro.h"
23#include "parse-util.h"
24#include "process-util.h"
25#include "socket-util.h"
26#include "stdio-util.h"
27#include "string-util.h"
28#include "strv.h"
29
30#define REMOTE_JOURNAL_PATH"/var/log/journal/remote" "/var/log/journal/remote"
31
32#define filename_escape(s)xescape((s), "/ ") xescape((s), "/ ")
33
34static int open_output(RemoteServer *s, Writer *w, const char* host) {
35 _cleanup_free___attribute__((cleanup(freep))) char *_filename = NULL((void*)0);
36 const char *filename;
37 int r;
38
39 switch (s->split_mode) {
40 case JOURNAL_WRITE_SPLIT_NONE:
41 filename = s->output;
42 break;
43
44 case JOURNAL_WRITE_SPLIT_HOST: {
45 _cleanup_free___attribute__((cleanup(freep))) char *name;
46
47 assert(host)do { if ((__builtin_expect(!!(!(host)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("host"), "../src/journal-remote/journal-remote.c"
, 47, __PRETTY_FUNCTION__); } while (0)
;
48
49 name = filename_escape(host)xescape((host), "/ ");
50 if (!name)
51 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 51, __func__)
;
52
53 r = asprintf(&_filename, "%s/remote-%s.journal", s->output, name);
54 if (r < 0)
55 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 55, __func__)
;
56
57 filename = _filename;
58 break;
59 }
60
61 default:
62 assert_not_reached("what?")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"what?"), "../src/journal-remote/journal-remote.c", 62, __PRETTY_FUNCTION__
); } while (0)
;
63 }
64
65 r = journal_file_open_reliably(filename,
66 O_RDWR02|O_CREAT0100, 0640,
67 s->compress, (uint64_t) -1, s->seal,
68 &w->metrics,
69 w->mmap, NULL((void*)0),
70 NULL((void*)0), &w->journal);
71 if (r < 0)
72 return log_error_errno(r, "Failed to open output journal %s: %m", filename)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 72, __func__, "Failed to open output journal %s: %m"
, filename) : -abs(_e); })
;
73
74 log_debug("Opened output file %s", w->journal->path)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 74, __func__, "Opened output file %s"
, w->journal->path) : -abs(_e); })
;
75 return 0;
76}
77
78/**********************************************************************
79 **********************************************************************
80 **********************************************************************/
81
82static int init_writer_hashmap(RemoteServer *s) {
83 static const struct hash_ops* const hash_ops[] = {
84 [JOURNAL_WRITE_SPLIT_NONE] = NULL((void*)0),
85 [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops,
86 };
87
88 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/journal-remote/journal-remote.c"
, 88, __PRETTY_FUNCTION__); } while (0)
;
89 assert(s->split_mode >= 0 && s->split_mode < (int) ELEMENTSOF(hash_ops))do { if ((__builtin_expect(!!(!(s->split_mode >= 0 &&
s->split_mode < (int) __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(hash_ops), typeof(&
*(hash_ops))), sizeof(hash_ops)/sizeof((hash_ops)[0]), ((void
)0))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->split_mode >= 0 && s->split_mode < (int) ELEMENTSOF(hash_ops)"
), "../src/journal-remote/journal-remote.c", 89, __PRETTY_FUNCTION__
); } while (0)
;
90
91 s->writers = hashmap_new(hash_ops[s->split_mode])internal_hashmap_new(hash_ops[s->split_mode] );
92 if (!s->writers)
93 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 93, __func__)
;
94
95 return 0;
96}
97
98int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer) {
99 _cleanup_(writer_unrefp)__attribute__((cleanup(writer_unrefp))) Writer *w = NULL((void*)0);
100 const void *key;
101 int r;
102
103 switch(s->split_mode) {
104 case JOURNAL_WRITE_SPLIT_NONE:
105 key = "one and only";
106 break;
107
108 case JOURNAL_WRITE_SPLIT_HOST:
109 assert(host)do { if ((__builtin_expect(!!(!(host)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("host"), "../src/journal-remote/journal-remote.c"
, 109, __PRETTY_FUNCTION__); } while (0)
;
110 key = host;
111 break;
112
113 default:
114 assert_not_reached("what split mode?")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"what split mode?"), "../src/journal-remote/journal-remote.c"
, 114, __PRETTY_FUNCTION__); } while (0)
;
115 }
116
117 w = hashmap_get(s->writers, key);
118 if (w)
119 writer_ref(w);
120 else {
121 w = writer_new(s);
122 if (!w)
123 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 123, __func__)
;
124
125 if (s->split_mode == JOURNAL_WRITE_SPLIT_HOST) {
126 w->hashmap_key = strdup(key);
127 if (!w->hashmap_key)
128 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 128, __func__)
;
129 }
130
131 r = open_output(s, w, host);
132 if (r < 0)
133 return r;
134
135 r = hashmap_put(s->writers, w->hashmap_key ?: key, w);
136 if (r < 0)
137 return r;
138 }
139
140 *writer = TAKE_PTR(w)({ typeof(w) _ptr_ = (w); (w) = ((void*)0); _ptr_; });
141
142 return 0;
143}
144
145/**********************************************************************
146 **********************************************************************
147 **********************************************************************/
148
149/* This should go away as soon as µhttpd allows state to be passed around. */
150RemoteServer *journal_remote_server_global;
151
152static int dispatch_raw_source_event(sd_event_source *event,
153 int fd,
154 uint32_t revents,
155 void *userdata);
156static int dispatch_raw_source_until_block(sd_event_source *event,
157 void *userdata);
158static int dispatch_blocking_source_event(sd_event_source *event,
159 void *userdata);
160static int dispatch_raw_connection_event(sd_event_source *event,
161 int fd,
162 uint32_t revents,
163 void *userdata);
164
165static int get_source_for_fd(RemoteServer *s,
166 int fd, char *name, RemoteSource **source) {
167 Writer *writer;
168 int r;
169
170 /* This takes ownership of name, but only on success. */
171
172 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal-remote/journal-remote.c"
, 172, __PRETTY_FUNCTION__); } while (0)
;
14
Taking false branch
15
Loop condition is false. Exiting loop
173 assert(source)do { if ((__builtin_expect(!!(!(source)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("source"), "../src/journal-remote/journal-remote.c"
, 173, __PRETTY_FUNCTION__); } while (0)
;
16
Taking false branch
17
Loop condition is false. Exiting loop
174
175 if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1)greedy_realloc0((void**) &(s->sources), &(s->sources_size
), (fd + 1), sizeof((s->sources)[0]))
)
18
Assuming the condition is true
19
Taking true branch
176 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 176, __func__)
;
20
Returning without writing to '*source'
177
178 r = journal_remote_get_writer(s, name, &writer);
179 if (r < 0)
180 return log_warning_errno(r, "Failed to get writer for source %s: %m",({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 181, __func__, "Failed to get writer for source %s: %m"
, name) : -abs(_e); })
181 name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 181, __func__, "Failed to get writer for source %s: %m"
, name) : -abs(_e); })
;
182
183 if (s->sources[fd] == NULL((void*)0)) {
184 s->sources[fd] = source_new(fd, false0, name, writer);
185 if (!s->sources[fd]) {
186 writer_unref(writer);
187 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 187, __func__)
;
188 }
189
190 s->active++;
191 }
192
193 *source = s->sources[fd];
194 return 0;
195}
196
197static int remove_source(RemoteServer *s, int fd) {
198 RemoteSource *source;
199
200 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/journal-remote/journal-remote.c"
, 200, __PRETTY_FUNCTION__); } while (0)
;
201 assert(fd >= 0 && fd < (ssize_t) s->sources_size)do { if ((__builtin_expect(!!(!(fd >= 0 && fd <
(ssize_t) s->sources_size)),0))) log_assert_failed_realm(
LOG_REALM_SYSTEMD, ("fd >= 0 && fd < (ssize_t) s->sources_size"
), "../src/journal-remote/journal-remote.c", 201, __PRETTY_FUNCTION__
); } while (0)
;
202
203 source = s->sources[fd];
204 if (source) {
205 /* this closes fd too */
206 source_free(source);
207 s->sources[fd] = NULL((void*)0);
208 s->active--;
209 }
210
211 return 0;
212}
213
214int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool_Bool own_name) {
215 RemoteSource *source = NULL((void*)0);
3
'source' initialized to a null pointer value
216 int r;
217
218 /* This takes ownership of name, even on failure, if own_name is true. */
219
220 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/journal-remote/journal-remote.c"
, 220, __PRETTY_FUNCTION__); } while (0)
;
4
Assuming 's' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
221 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal-remote/journal-remote.c"
, 221, __PRETTY_FUNCTION__); } while (0)
;
7
Taking false branch
8
Loop condition is false. Exiting loop
222 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/journal-remote/journal-remote.c"
, 222, __PRETTY_FUNCTION__); } while (0)
;
9
Assuming 'name' is non-null
10
Taking false branch
11
Loop condition is false. Exiting loop
223
224 if (!own_name
11.1
'own_name' is true
) {
12
Taking false branch
225 name = strdup(name);
226 if (!name)
227 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal-remote/journal-remote.c"
, 227, __func__)
;
228 }
229
230 r = get_source_for_fd(s, fd, name, &source);
13
Calling 'get_source_for_fd'
21
Returning from 'get_source_for_fd'
231 if (r < 0) {
22
Assuming 'r' is >= 0
23
Taking false branch
232 log_error_errno(r, "Failed to create source for fd:%d (%s): %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 233, __func__, "Failed to create source for fd:%d (%s): %m"
, fd, name) : -abs(_e); })
233 fd, name)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 233, __func__, "Failed to create source for fd:%d (%s): %m"
, fd, name) : -abs(_e); })
;
234 free(name);
235 return r;
236 }
237
238 r = sd_event_add_io(s->events, &source->event,
239 fd, EPOLLINEPOLLIN|EPOLLRDHUPEPOLLRDHUP|EPOLLPRIEPOLLPRI,
240 dispatch_raw_source_event, source);
241 if (r == 0) {
24
Assuming 'r' is not equal to 0
25
Taking false branch
242 /* Add additional source for buffer processing. It will be
243 * enabled later. */
244 r = sd_event_add_defer(s->events, &source->buffer_event,
245 dispatch_raw_source_until_block, source);
246 if (r == 0)
247 sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF);
248 } else if (r == -EPERM1) {
26
Assuming the condition is true
27
Taking true branch
249 log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 249, __func__, "Falling back to sd_event_add_defer for fd:%d (%s)"
, fd, name) : -abs(_e); })
;
28
Assuming the condition is false
29
'?' condition is false
250 r = sd_event_add_defer(s->events, &source->event,
251 dispatch_blocking_source_event, source);
252 if (r == 0)
30
Assuming 'r' is equal to 0
31
Taking true branch
253 sd_event_source_set_enabled(source->event, SD_EVENT_ON);
32
Access to field 'event' results in a dereference of a null pointer (loaded from variable 'source')
254 }
255 if (r < 0) {
256 log_error_errno(r, "Failed to register event source for fd:%d: %m",({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 257, __func__, "Failed to register event source for fd:%d: %m"
, fd) : -abs(_e); })
257 fd)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 257, __func__, "Failed to register event source for fd:%d: %m"
, fd) : -abs(_e); })
;
258 goto error;
259 }
260
261 r = sd_event_source_set_description(source->event, name);
262 if (r < 0) {
263 log_error_errno(r, "Failed to set source name for fd:%d: %m", fd)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 263, __func__, "Failed to set source name for fd:%d: %m"
, fd) : -abs(_e); })
;
264 goto error;
265 }
266
267 return 1; /* work to do */
268
269 error:
270 remove_source(s, fd);
271 return r;
272}
273
274int journal_remote_add_raw_socket(RemoteServer *s, int fd) {
275 int r;
276 _cleanup_close___attribute__((cleanup(closep))) int fd_ = fd;
277 char name[STRLEN("raw-socket-")(sizeof("""raw-socket-""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof
(int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2
*(sizeof(int) > 8)])))
+ 1];
278
279 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal-remote/journal-remote.c"
, 279, __PRETTY_FUNCTION__); } while (0)
;
280
281 r = sd_event_add_io(s->events, &s->listen_event,
282 fd, EPOLLINEPOLLIN,
283 dispatch_raw_connection_event, s);
284 if (r < 0)
285 return r;
286
287 xsprintf(name, "raw-socket-%d", fd)do { if ((__builtin_expect(!!(!(((size_t) snprintf(name, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(name), typeof(&*(name))), sizeof(name)/sizeof((name)[0])
, ((void)0))), "raw-socket-%d", fd) < (__extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(name), typeof(&*(name
))), sizeof(name)/sizeof((name)[0]), ((void)0))))))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("xsprintf: " "name" "[] must be big enough"
), "../src/journal-remote/journal-remote.c", 287, __PRETTY_FUNCTION__
); } while (0)
;
288
289 r = sd_event_source_set_description(s->listen_event, name);
290 if (r < 0)
291 return r;
292
293 fd_ = -1;
294 s->active++;
295 return 0;
296}
297
298/**********************************************************************
299 **********************************************************************
300 **********************************************************************/
301
302int journal_remote_server_init(
303 RemoteServer *s,
304 const char *output,
305 JournalWriteSplitMode split_mode,
306 bool_Bool compress,
307 bool_Bool seal) {
308
309 int r;
310
311 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/journal-remote/journal-remote.c"
, 311, __PRETTY_FUNCTION__); } while (0)
;
312
313 assert(journal_remote_server_global == NULL)do { if ((__builtin_expect(!!(!(journal_remote_server_global ==
((void*)0))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("journal_remote_server_global == NULL"), "../src/journal-remote/journal-remote.c"
, 313, __PRETTY_FUNCTION__); } while (0)
;
314 journal_remote_server_global = s;
315
316 s->split_mode = split_mode;
317 s->compress = compress;
318 s->seal = seal;
319
320 if (output)
321 s->output = output;
322 else if (split_mode == JOURNAL_WRITE_SPLIT_NONE)
323 s->output = REMOTE_JOURNAL_PATH"/var/log/journal/remote" "/remote.journal";
324 else if (split_mode == JOURNAL_WRITE_SPLIT_HOST)
325 s->output = REMOTE_JOURNAL_PATH"/var/log/journal/remote";
326 else
327 assert_not_reached("bad split mode")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, (
"bad split mode"), "../src/journal-remote/journal-remote.c", 327
, __PRETTY_FUNCTION__); } while (0)
;
328
329 r = sd_event_default(&s->events);
330 if (r < 0)
331 return log_error_errno(r, "Failed to allocate event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 331, __func__, "Failed to allocate event loop: %m"
) : -abs(_e); })
;
332
333 r = init_writer_hashmap(s);
334 if (r < 0)
335 return r;
336
337 return 0;
338}
339
340#if HAVE_MICROHTTPD1
341static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) {
342 MHD_stop_daemon(d->daemon);
343 sd_event_source_unref(d->io_event);
344 sd_event_source_unref(d->timer_event);
345 free(d);
346}
347#endif
348
349RemoteServer* journal_remote_server_destroy(RemoteServer *s) {
350 size_t i;
351
352#if HAVE_MICROHTTPD1
353 hashmap_free_with_destructor(s->daemons, MHDDaemonWrapper_free)({ ({ void *_item; while ((_item = hashmap_steal_first(s->
daemons))) MHDDaemonWrapper_free(_item); }); hashmap_free(s->
daemons); })
;
354#endif
355
356 assert(s->sources_size == 0 || s->sources)do { if ((__builtin_expect(!!(!(s->sources_size == 0 || s->
sources)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->sources_size == 0 || s->sources"
), "../src/journal-remote/journal-remote.c", 356, __PRETTY_FUNCTION__
); } while (0)
;
357 for (i = 0; i < s->sources_size; i++)
358 remove_source(s, i);
359 free(s->sources);
360
361 writer_unref(s->_single_writer);
362 hashmap_free(s->writers);
363
364 sd_event_source_unref(s->sigterm_event);
365 sd_event_source_unref(s->sigint_event);
366 sd_event_source_unref(s->listen_event);
367 sd_event_unref(s->events);
368
369 if (s == journal_remote_server_global)
370 journal_remote_server_global = NULL((void*)0);
371
372 /* fds that we're listening on remain open... */
373 return NULL((void*)0);
374}
375
376/**********************************************************************
377 **********************************************************************
378 **********************************************************************/
379
380int journal_remote_handle_raw_source(
381 sd_event_source *event,
382 int fd,
383 uint32_t revents,
384 RemoteServer *s) {
385
386 RemoteSource *source;
387 int r;
388
389 /* Returns 1 if there might be more data pending,
390 * 0 if data is currently exhausted, negative on error.
391 */
392
393 assert(fd >= 0 && fd < (ssize_t) s->sources_size)do { if ((__builtin_expect(!!(!(fd >= 0 && fd <
(ssize_t) s->sources_size)),0))) log_assert_failed_realm(
LOG_REALM_SYSTEMD, ("fd >= 0 && fd < (ssize_t) s->sources_size"
), "../src/journal-remote/journal-remote.c", 393, __PRETTY_FUNCTION__
); } while (0)
;
394 source = s->sources[fd];
395 assert(source->importer.fd == fd)do { if ((__builtin_expect(!!(!(source->importer.fd == fd)
),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("source->importer.fd == fd"
), "../src/journal-remote/journal-remote.c", 395, __PRETTY_FUNCTION__
); } while (0)
;
396
397 r = process_source(source, s->compress, s->seal);
398 if (journal_importer_eof(&source->importer)) {
399 size_t remaining;
400
401 log_debug("EOF reached with source %s (fd=%d)",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 402, __func__, "EOF reached with source %s (fd=%d)"
, source->importer.name, source->importer.fd) : -abs(_e
); })
402 source->importer.name, source->importer.fd)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 402, __func__, "EOF reached with source %s (fd=%d)"
, source->importer.name, source->importer.fd) : -abs(_e
); })
;
403
404 remaining = journal_importer_bytes_remaining(&source->importer);
405 if (remaining > 0)
406 log_notice("Premature EOF. %zu bytes lost.", remaining)({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 406, __func__, "Premature EOF. %zu bytes lost."
, remaining) : -abs(_e); })
;
407 remove_source(s, source->importer.fd);
408 log_debug("%zu active sources remaining", s->active)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 408, __func__, "%zu active sources remaining"
, s->active) : -abs(_e); })
;
409 return 0;
410 } else if (r == -E2BIG7) {
411 log_notice("Entry with too many fields, skipped")({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 411, __func__, "Entry with too many fields, skipped"
) : -abs(_e); })
;
412 return 1;
413 } else if (r == -ENOBUFS105) {
414 log_notice("Entry too big, skipped")({ int _level = (((5))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 414, __func__, "Entry too big, skipped"
) : -abs(_e); })
;
415 return 1;
416 } else if (r == -EAGAIN11) {
417 return 0;
418 } else if (r < 0) {
419 log_debug_errno(r, "Closing connection: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 419, __func__, "Closing connection: %m"
) : -abs(_e); })
;
420 remove_source(s, fd);
421 return 0;
422 } else
423 return 1;
424}
425
426static int dispatch_raw_source_until_block(sd_event_source *event,
427 void *userdata) {
428 RemoteSource *source = userdata;
429 int r;
430
431 /* Make sure event stays around even if source is destroyed */
432 sd_event_source_ref(event);
433
434 r = journal_remote_handle_raw_source(event, source->importer.fd, EPOLLINEPOLLIN, journal_remote_server_global);
435 if (r != 1)
436 /* No more data for now */
437 sd_event_source_set_enabled(event, SD_EVENT_OFF);
438
439 sd_event_source_unref(event);
440
441 return r;
442}
443
444static int dispatch_raw_source_event(sd_event_source *event,
445 int fd,
446 uint32_t revents,
447 void *userdata) {
448 RemoteSource *source = userdata;
449 int r;
450
451 assert(source->event)do { if ((__builtin_expect(!!(!(source->event)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("source->event"), "../src/journal-remote/journal-remote.c"
, 451, __PRETTY_FUNCTION__); } while (0)
;
452 assert(source->buffer_event)do { if ((__builtin_expect(!!(!(source->buffer_event)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("source->buffer_event"
), "../src/journal-remote/journal-remote.c", 452, __PRETTY_FUNCTION__
); } while (0)
;
453
454 r = journal_remote_handle_raw_source(event, fd, EPOLLINEPOLLIN, journal_remote_server_global);
455 if (r == 1)
456 /* Might have more data. We need to rerun the handler
457 * until we are sure the buffer is exhausted. */
458 sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON);
459
460 return r;
461}
462
463static int dispatch_blocking_source_event(sd_event_source *event,
464 void *userdata) {
465 RemoteSource *source = userdata;
466
467 return journal_remote_handle_raw_source(event, source->importer.fd, EPOLLINEPOLLIN, journal_remote_server_global);
468}
469
470static int accept_connection(const char* type, int fd,
471 SocketAddress *addr, char **hostname) {
472 int fd2, r;
473
474 log_debug("Accepting new %s connection on fd:%d", type, fd)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 474, __func__, "Accepting new %s connection on fd:%d"
, type, fd) : -abs(_e); })
;
475 fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCKSOCK_NONBLOCK|SOCK_CLOEXECSOCK_CLOEXEC);
476 if (fd2 < 0)
477 return log_error_errno(errno, "accept() on fd:%d failed: %m", fd)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/journal-remote/journal-remote.c"
, 477, __func__, "accept() on fd:%d failed: %m", fd) : -abs(_e
); })
;
478
479 switch(socket_address_family(addr)((addr)->sockaddr.sa.sa_family)) {
480 case AF_INET2:
481 case AF_INET610: {
482 _cleanup_free___attribute__((cleanup(freep))) char *a = NULL((void*)0);
483 char *b;
484
485 r = socket_address_print(addr, &a);
486 if (r < 0) {
487 log_error_errno(r, "socket_address_print(): %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 487, __func__, "socket_address_print(): %m"
) : -abs(_e); })
;
488 close(fd2);
489 return r;
490 }
491
492 r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b);
493 if (r < 0) {
494 log_error_errno(r, "Resolving hostname failed: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 494, __func__, "Resolving hostname failed: %m"
) : -abs(_e); })
;
495 close(fd2);
496 return r;
497 }
498
499 log_debug("Accepted %s %s connection from %s",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 502, __func__, "Accepted %s %s connection from %s"
, type, ((addr)->sockaddr.sa.sa_family) == 2 ? "IP" : "IPv6"
, a) : -abs(_e); })
500 type,({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 502, __func__, "Accepted %s %s connection from %s"
, type, ((addr)->sockaddr.sa.sa_family) == 2 ? "IP" : "IPv6"
, a) : -abs(_e); })
501 socket_address_family(addr) == AF_INET ? "IP" : "IPv6",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 502, __func__, "Accepted %s %s connection from %s"
, type, ((addr)->sockaddr.sa.sa_family) == 2 ? "IP" : "IPv6"
, a) : -abs(_e); })
502 a)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 502, __func__, "Accepted %s %s connection from %s"
, type, ((addr)->sockaddr.sa.sa_family) == 2 ? "IP" : "IPv6"
, a) : -abs(_e); })
;
503
504 *hostname = b;
505
506 return fd2;
507 };
508 default:
509 log_error("Rejected %s connection with unsupported family %d",({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 510, __func__, "Rejected %s connection with unsupported family %d"
, type, ((addr)->sockaddr.sa.sa_family)) : -abs(_e); })
510 type, socket_address_family(addr))({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/journal-remote/journal-remote.c", 510, __func__, "Rejected %s connection with unsupported family %d"
, type, ((addr)->sockaddr.sa.sa_family)) : -abs(_e); })
;
511 close(fd2);
512
513 return -EINVAL22;
514 }
515}
516
517static int dispatch_raw_connection_event(sd_event_source *event,
518 int fd,
519 uint32_t revents,
520 void *userdata) {
521 RemoteServer *s = userdata;
522 int fd2;
523 SocketAddress addr = {
524 .size = sizeof(union sockaddr_union),
525 .type = SOCK_STREAMSOCK_STREAM,
526 };
527 char *hostname = NULL((void*)0);
528
529 fd2 = accept_connection("raw", fd, &addr, &hostname);
530 if (fd2
0.1
'fd2' is >= 0
< 0)
1
Taking false branch
531 return fd2;
532
533 return journal_remote_add_source(s, fd2, hostname, true1);
2
Calling 'journal_remote_add_source'
534}