Bug Summary

File:build-scan/../src/journal/journal-send.c
Warning:line 502, column 16
Potential leak of memory pointed to by 'iov'

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-send.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/libjournal-client.a.p -I src/journal -I ../src/journal -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal-remote -I ../src/journal-remote -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 .. -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 default -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/journal-send.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <fcntl.h>
5#include <printf.h>
6#include <stddef.h>
7#include <sys/socket.h>
8#include <sys/un.h>
9#include <unistd.h>
10
11#define SD_JOURNAL_SUPPRESS_LOCATION
12
13#include "sd-journal.h"
14
15#include "alloc-util.h"
16#include "fd-util.h"
17#include "fileio.h"
18#include "io-util.h"
19#include "memfd-util.h"
20#include "socket-util.h"
21#include "stdio-util.h"
22#include "string-util.h"
23#include "util.h"
24
25#define SNDBUF_SIZE(8*1024*1024) (8*1024*1024)
26
27#define ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = &
(f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10
); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl
); } while (0)
\
28 do { \
29 size_t _fl; \
30 const char *_func = (func); \
31 char **_f = &(f); \
32 _fl = strlen(_func) + 1; \
33 *_f = alloca(_fl + 10)__builtin_alloca (_fl + 10); \
34 memcpy(*_f, "CODE_FUNC=", 10); \
35 memcpy(*_f + 10, _func, _fl); \
36 } while (false0)
37
38/* We open a single fd, and we'll share it with the current process,
39 * all its threads, and all its subprocesses. This means we need to
40 * initialize it atomically, and need to operate on it atomically
41 * never assuming we are the only user */
42
43static int journal_fd(void) {
44 int fd;
45 static int fd_plus_one = 0;
46
47retry:
48 if (fd_plus_one > 0)
49 return fd_plus_one - 1;
50
51 fd = socket(AF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC, 0);
52 if (fd < 0)
53 return -errno(*__errno_location ());
54
55 fd_inc_sndbuf(fd, SNDBUF_SIZE(8*1024*1024));
56
57 if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
58 safe_close(fd);
59 goto retry;
60 }
61
62 return fd;
63}
64
65_public___attribute__ ((visibility("default"))) int sd_journal_print(int priority, const char *format, ...) {
66 int r;
67 va_list ap;
68
69 va_start(ap, format)__builtin_va_start(ap, format);
70 r = sd_journal_printv(priority, format, ap);
71 va_end(ap)__builtin_va_end(ap);
72
73 return r;
74}
75
76_public___attribute__ ((visibility("default"))) int sd_journal_printv(int priority, const char *format, va_list ap) {
77
78 /* FIXME: Instead of limiting things to LINE_MAX we could do a
79 C99 variable-length array on the stack here in a loop. */
80
81 char buffer[8 + LINE_MAX2048], p[STRLEN("PRIORITY=")(sizeof("""PRIORITY=""") - 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];
82 struct iovec iov[2];
83
84 assert_return(priority >= 0, -EINVAL)do { if (!(((__builtin_expect(!!(priority >= 0),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority >= 0"
), "../src/journal/journal-send.c", 84, __PRETTY_FUNCTION__),
0))) return (-22); } while (0)
;
85 assert_return(priority <= 7, -EINVAL)do { if (!(((__builtin_expect(!!(priority <= 7),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority <= 7"
), "../src/journal/journal-send.c", 85, __PRETTY_FUNCTION__),
0))) return (-22); } while (0)
;
86 assert_return(format, -EINVAL)do { if (!(((__builtin_expect(!!(format),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("format"), "../src/journal/journal-send.c"
, 86, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
87
88 xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK)do { if ((__builtin_expect(!!(!(((size_t) snprintf(p, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(p), typeof(&*(p))), sizeof(p)/sizeof((p)[0]), ((void)0))
), "PRIORITY=%i", priority & 0x07) < (__extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(p), typeof(&*(p)))
, sizeof(p)/sizeof((p)[0]), ((void)0))))))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("xsprintf: " "p" "[] must be big enough"
), "../src/journal/journal-send.c", 88, __PRETTY_FUNCTION__);
} while (0)
;
89
90 memcpy(buffer, "MESSAGE=", 8);
91 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
92
93 /* Strip trailing whitespace, keep prefix whitespace. */
94 (void) strstrip(buffer);
95
96 /* Suppress empty lines */
97 if (isempty(buffer+8))
98 return 0;
99
100 iov[0] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen
(buffer)) }
;
101 iov[1] = IOVEC_MAKE_STRING(p)(struct iovec) { .iov_base = ((char*) p), .iov_len = (strlen(
p)) }
;
102
103 return sd_journal_sendv(iov, 2);
104}
105
106_printf_(1, 0)__attribute__ ((format (printf, 1, 0))) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
107 PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused
)) int _saved_errno_ = (*__errno_location ())
;
108 int r, n = 0, i = 0, j;
109 struct iovec *iov = NULL((void*)0);
110
111 assert(_iov)do { if ((__builtin_expect(!!(!(_iov)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_iov"), "../src/journal/journal-send.c"
, 111, __PRETTY_FUNCTION__); } while (0)
;
2
Taking false branch
3
Loop condition is false. Exiting loop
112
113 if (extra
3.1
'extra' is > 0
> 0) {
4
Taking true branch
114 n = MAX(extra * 2, extra + 4)__extension__ ({ const typeof((extra * 2)) __unique_prefix_A7
= ((extra * 2)); const typeof((extra + 4)) __unique_prefix_B8
= ((extra + 4)); __unique_prefix_A7 > __unique_prefix_B8 ?
__unique_prefix_A7 : __unique_prefix_B8; })
;
5
'?' condition is false
115 iov = malloc0(n * sizeof(struct iovec))(calloc(1, (n * sizeof(struct iovec))));
6
Memory is allocated
116 if (!iov) {
7
Assuming 'iov' is non-null
8
Taking false branch
117 r = -ENOMEM12;
118 goto fail;
119 }
120
121 i = extra;
122 }
123
124 while (format) {
9
Loop condition is false. Execution continues on line 157
125 struct iovec *c;
126 char *buffer;
127 va_list aq;
128
129 if (i >= n) {
130 n = MAX(i*2, 4)__extension__ ({ const typeof((i*2)) __unique_prefix_A9 = ((i
*2)); const typeof((4)) __unique_prefix_B10 = ((4)); __unique_prefix_A9
> __unique_prefix_B10 ? __unique_prefix_A9 : __unique_prefix_B10
; })
;
131 c = realloc(iov, n * sizeof(struct iovec));
132 if (!c) {
133 r = -ENOMEM12;
134 goto fail;
135 }
136
137 iov = c;
138 }
139
140 va_copy(aq, ap)__builtin_va_copy(aq, ap);
141 if (vasprintf(&buffer, format, aq) < 0) {
142 va_end(aq)__builtin_va_end(aq);
143 r = -ENOMEM12;
144 goto fail;
145 }
146 va_end(aq)__builtin_va_end(aq);
147
148 VA_FORMAT_ADVANCE(format, ap)do { int _argtypes[128]; size_t _i, _k; _k = parse_printf_format
((format), __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_argtypes), typeof(&*(_argtypes))), sizeof(_argtypes
)/sizeof((_argtypes)[0]), ((void)0))), _argtypes); do { if ((
__builtin_expect(!!(!(_k < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_argtypes), typeof(&
*(_argtypes))), sizeof(_argtypes)/sizeof((_argtypes)[0]), ((void
)0))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_k < ELEMENTSOF(_argtypes)"
), "../src/journal/journal-send.c", 148, __PRETTY_FUNCTION__)
; } while (0); for (_i = 0; _i < _k; _i++) { if (_argtypes
[_i] & (1 << 11)) { (void) __builtin_va_arg(ap, void
*); continue; } switch (_argtypes[_i]) { case PA_INT: case PA_INT
|(1 << 10): case PA_CHAR: (void) __builtin_va_arg(ap, int
); break; case PA_INT|(1 << 9): (void) __builtin_va_arg
(ap, long int); break; case PA_INT|(1 << 8): (void) __builtin_va_arg
(ap, long long int); break; case PA_WCHAR: (void) __builtin_va_arg
(ap, wchar_t); break; case PA_WSTRING: case PA_STRING: case PA_POINTER
: (void) __builtin_va_arg(ap, void*); break; case PA_FLOAT: case
PA_DOUBLE: (void) __builtin_va_arg(ap, double); break; case PA_DOUBLE
|(1 << 8): (void) __builtin_va_arg(ap, long double); break
; default: do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD
, ("Unknown format string argument."), "../src/journal/journal-send.c"
, 148, __PRETTY_FUNCTION__); } while (0); } } } while (0)
;
149
150 (void) strstrip(buffer); /* strip trailing whitespace, keep prefixing whitespace */
151
152 iov[i++] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen
(buffer)) }
;
153
154 format = va_arg(ap, char *)__builtin_va_arg(ap, char *);
155 }
156
157 *_iov = iov;
158
159 return i;
160
161fail:
162 for (j = 0; j < i; j++)
163 free(iov[j].iov_base);
164
165 free(iov);
166
167 return r;
168}
169
170_public___attribute__ ((visibility("default"))) int sd_journal_send(const char *format, ...) {
171 int r, i, j;
172 va_list ap;
173 struct iovec *iov = NULL((void*)0);
174
175 va_start(ap, format)__builtin_va_start(ap, format);
176 i = fill_iovec_sprintf(format, ap, 0, &iov);
177 va_end(ap)__builtin_va_end(ap);
178
179 if (_unlikely_(i < 0)(__builtin_expect(!!(i < 0),0))) {
180 r = i;
181 goto finish;
182 }
183
184 r = sd_journal_sendv(iov, i);
185
186finish:
187 for (j = 0; j < i; j++)
188 free(iov[j].iov_base);
189
190 free(iov);
191
192 return r;
193}
194
195_public___attribute__ ((visibility("default"))) int sd_journal_sendv(const struct iovec *iov, int n) {
196 PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused
)) int _saved_errno_ = (*__errno_location ())
;
197 int fd, r;
198 _cleanup_close___attribute__((cleanup(closep))) int buffer_fd = -1;
199 struct iovec *w;
200 uint64_t *l;
201 int i, j = 0;
202 static const union sockaddr_union sa = {
203 .un.sun_family = AF_UNIX1,
204 .un.sun_path = "/run/systemd/journal/socket",
205 };
206 struct msghdr mh = {
207 .msg_name = (struct sockaddr*) &sa.sa,
208 .msg_namelen = SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect
(!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm(
LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journal-send.c"
, 208, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof(
struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1
+ strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen
(_sa->sun_path, sizeof(_sa->sun_path))); })
,
209 };
210 ssize_t k;
211 bool_Bool have_syslog_identifier = false0;
212 bool_Bool seal = true1;
213
214 assert_return(iov, -EINVAL)do { if (!(((__builtin_expect(!!(iov),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("iov"), "../src/journal/journal-send.c",
214, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
215 assert_return(n > 0, -EINVAL)do { if (!(((__builtin_expect(!!(n > 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("n > 0"), "../src/journal/journal-send.c"
, 215, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
216
217 w = newa(struct iovec, n * 5 + 3)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(struct iovec), n * 5 + 3))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(struct iovec), n * 5 + 3)"
), "../src/journal/journal-send.c", 217, __PRETTY_FUNCTION__)
; } while (0); (struct iovec*) __builtin_alloca (sizeof(struct
iovec)*(n * 5 + 3)); })
;
218 l = newa(uint64_t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(uint64_t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(uint64_t), n)"), "../src/journal/journal-send.c"
, 218, __PRETTY_FUNCTION__); } while (0); (uint64_t*) __builtin_alloca
(sizeof(uint64_t)*(n)); })
;
219
220 for (i = 0; i < n; i++) {
221 char *c, *nl;
222
223 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)(__builtin_expect(!!(!iov[i].iov_base || iov[i].iov_len <=
1),0))
)
224 return -EINVAL22;
225
226 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
227 if (_unlikely_(!c || c == iov[i].iov_base)(__builtin_expect(!!(!c || c == iov[i].iov_base),0)))
228 return -EINVAL22;
229
230 have_syslog_identifier = have_syslog_identifier ||
231 (c == (char *) iov[i].iov_base + 17 &&
232 startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
233
234 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
235 if (nl) {
236 if (_unlikely_(nl < c)(__builtin_expect(!!(nl < c),0)))
237 return -EINVAL22;
238
239 /* Already includes a newline? Bummer, then
240 * let's write the variable name, then a
241 * newline, then the size (64bit LE), followed
242 * by the data and a final newline */
243
244 w[j++] = IOVEC_MAKE(iov[i].iov_base, c - (char*) iov[i].iov_base)(struct iovec) { .iov_base = (iov[i].iov_base), .iov_len = (c
- (char*) iov[i].iov_base) }
;
245 w[j++] = IOVEC_MAKE_STRING("\n")(struct iovec) { .iov_base = ((char*) "\n"), .iov_len = (strlen
("\n")) }
;
246
247 l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1)__uint64_identity (iov[i].iov_len - (c - (char*) iov[i].iov_base
) - 1)
;
248 w[j++] = IOVEC_MAKE(&l[i], sizeof(uint64_t))(struct iovec) { .iov_base = (&l[i]), .iov_len = (sizeof(
uint64_t)) }
;
249
250 w[j++] = IOVEC_MAKE(c + 1, iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1)(struct iovec) { .iov_base = (c + 1), .iov_len = (iov[i].iov_len
- (c - (char*) iov[i].iov_base) - 1) }
;
251 } else
252 /* Nothing special? Then just add the line and
253 * append a newline */
254 w[j++] = iov[i];
255
256 w[j++] = IOVEC_MAKE_STRING("\n")(struct iovec) { .iov_base = ((char*) "\n"), .iov_len = (strlen
("\n")) }
;
257 }
258
259 if (!have_syslog_identifier &&
260 string_is_safe(program_invocation_short_name)) {
261
262 /* Implicitly add program_invocation_short_name, if it
263 * is not set explicitly. We only do this for
264 * program_invocation_short_name, and nothing else
265 * since everything else is much nicer to retrieve
266 * from the outside. */
267
268 w[j++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=")(struct iovec) { .iov_base = ((char*) "SYSLOG_IDENTIFIER="), .
iov_len = (strlen("SYSLOG_IDENTIFIER=")) }
;
269 w[j++] = IOVEC_MAKE_STRING(program_invocation_short_name)(struct iovec) { .iov_base = ((char*) program_invocation_short_name
), .iov_len = (strlen(program_invocation_short_name)) }
;
270 w[j++] = IOVEC_MAKE_STRING("\n")(struct iovec) { .iov_base = ((char*) "\n"), .iov_len = (strlen
("\n")) }
;
271 }
272
273 fd = journal_fd();
274 if (_unlikely_(fd < 0)(__builtin_expect(!!(fd < 0),0)))
275 return fd;
276
277 mh.msg_iov = w;
278 mh.msg_iovlen = j;
279
280 k = sendmsg(fd, &mh, MSG_NOSIGNALMSG_NOSIGNAL);
281 if (k >= 0)
282 return 0;
283
284 /* Fail silently if the journal is not available */
285 if (errno(*__errno_location ()) == ENOENT2)
286 return 0;
287
288 if (!IN_SET(errno, EMSGSIZE, ENOBUFS)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){90, 105})/sizeof(int)]; switch((*__errno_location
())) { case 90: case 105: _found = 1; break; default: break;
} _found; })
)
289 return -errno(*__errno_location ());
290
291 /* Message doesn't fit... Let's dump the data in a memfd or
292 * temporary file and just pass a file descriptor of it to the
293 * other side.
294 *
295 * For the temporary files we use /dev/shm instead of /tmp
296 * here, since we want this to be a tmpfs, and one that is
297 * available from early boot on and where unprivileged users
298 * can create files. */
299 buffer_fd = memfd_new(NULL((void*)0));
300 if (buffer_fd < 0) {
301 if (buffer_fd == -ENOSYS38) {
302 buffer_fd = open_tmpfile_unlinkable("/dev/shm", O_RDWR02 | O_CLOEXEC02000000);
303 if (buffer_fd < 0)
304 return buffer_fd;
305
306 seal = false0;
307 } else
308 return buffer_fd;
309 }
310
311 n = writev(buffer_fd, w, j);
312 if (n < 0)
313 return -errno(*__errno_location ());
314
315 if (seal) {
316 r = memfd_set_sealed(buffer_fd);
317 if (r < 0)
318 return r;
319 }
320
321 r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0);
322 if (r == -ENOENT2)
323 /* Fail silently if the journal is not available */
324 return 0;
325 return r;
326}
327
328static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
329 PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused
)) int _saved_errno_ = (*__errno_location ())
;
330 size_t n, k;
331
332 k = isempty(message) ? 0 : strlen(message) + 2;
333 n = 8 + k + 256 + 1;
334
335 for (;;) {
336 char buffer[n];
337 char* j;
338
339 errno(*__errno_location ()) = 0;
340 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
341 if (errno(*__errno_location ()) == 0) {
342 char error[STRLEN("ERRNO=")(sizeof("""ERRNO=""") - 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];
343
344 if (j != buffer + 8 + k)
345 memmove(buffer + 8 + k, j, strlen(j)+1);
346
347 memcpy(buffer, "MESSAGE=", 8);
348
349 if (k > 0) {
350 memcpy(buffer + 8, message, k - 2);
351 memcpy(buffer + 8 + k - 2, ": ", 2);
352 }
353
354 xsprintf(error, "ERRNO=%i", _saved_errno_)do { if ((__builtin_expect(!!(!(((size_t) snprintf(error, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(error), typeof(&*(error))), sizeof(error)/sizeof((error)
[0]), ((void)0))), "ERRNO=%i", _saved_errno_) < (__extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(error), typeof(&*(error))), sizeof(error)/sizeof((error)
[0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("xsprintf: " "error" "[] must be big enough"), "../src/journal/journal-send.c"
, 354, __PRETTY_FUNCTION__); } while (0)
;
355
356 assert_cc(3 == LOG_ERR)GCC diagnostic push ; GCC diagnostic ignored "-Wdeclaration-after-statement"
; struct _assert_struct_11 { char x[(3 == 3) ? 0 : -1]; }; GCC
diagnostic pop
;
357 iov[skip+0] = IOVEC_MAKE_STRING("PRIORITY=3")(struct iovec) { .iov_base = ((char*) "PRIORITY=3"), .iov_len
= (strlen("PRIORITY=3")) }
;
358 iov[skip+1] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen
(buffer)) }
;
359 iov[skip+2] = IOVEC_MAKE_STRING(error)(struct iovec) { .iov_base = ((char*) error), .iov_len = (strlen
(error)) }
;
360
361 return sd_journal_sendv(iov, skip + 3);
362 }
363
364 if (errno(*__errno_location ()) != ERANGE34)
365 return -errno(*__errno_location ());
366
367 n *= 2;
368 }
369}
370
371_public___attribute__ ((visibility("default"))) int sd_journal_perror(const char *message) {
372 struct iovec iovec[3];
373
374 return fill_iovec_perror_and_send(message, 0, iovec);
375}
376
377_public___attribute__ ((visibility("default"))) int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
378 static const union sockaddr_union sa = {
379 .un.sun_family = AF_UNIX1,
380 .un.sun_path = "/run/systemd/journal/stdout",
381 };
382 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
383 char *header;
384 size_t l;
385 int r;
386
387 assert_return(priority >= 0, -EINVAL)do { if (!(((__builtin_expect(!!(priority >= 0),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority >= 0"
), "../src/journal/journal-send.c", 387, __PRETTY_FUNCTION__)
, 0))) return (-22); } while (0)
;
388 assert_return(priority <= 7, -EINVAL)do { if (!(((__builtin_expect(!!(priority <= 7),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority <= 7"
), "../src/journal/journal-send.c", 388, __PRETTY_FUNCTION__)
, 0))) return (-22); } while (0)
;
389
390 fd = socket(AF_UNIX1, SOCK_STREAMSOCK_STREAM|SOCK_CLOEXECSOCK_CLOEXEC, 0);
391 if (fd < 0)
392 return -errno(*__errno_location ());
393
394 r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect
(!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm(
LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journal-send.c"
, 394, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof(
struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1
+ strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen
(_sa->sun_path, sizeof(_sa->sun_path))); })
);
395 if (r < 0)
396 return -errno(*__errno_location ());
397
398 if (shutdown(fd, SHUT_RDSHUT_RD) < 0)
399 return -errno(*__errno_location ());
400
401 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE(8*1024*1024));
402
403 identifier = strempty(identifier);
404
405 l = strlen(identifier);
406 header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2)__builtin_alloca (l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
407
408 memcpy(header, identifier, l);
409 header[l++] = '\n';
410 header[l++] = '\n'; /* unit id */
411 header[l++] = '0' + priority;
412 header[l++] = '\n';
413 header[l++] = '0' + !!level_prefix;
414 header[l++] = '\n';
415 header[l++] = '0';
416 header[l++] = '\n';
417 header[l++] = '0';
418 header[l++] = '\n';
419 header[l++] = '0';
420 header[l++] = '\n';
421
422 r = loop_write(fd, header, l, false0);
423 if (r < 0)
424 return r;
425
426 return TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; });
427}
428
429_public___attribute__ ((visibility("default"))) int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
430 int r;
431 va_list ap;
432
433 va_start(ap, format)__builtin_va_start(ap, format);
434 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
435 va_end(ap)__builtin_va_end(ap);
436
437 return r;
438}
439
440_public___attribute__ ((visibility("default"))) int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
441 char buffer[8 + LINE_MAX2048], p[STRLEN("PRIORITY=")(sizeof("""PRIORITY=""") - 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];
442 struct iovec iov[5];
443 char *f;
444
445 assert_return(priority >= 0, -EINVAL)do { if (!(((__builtin_expect(!!(priority >= 0),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority >= 0"
), "../src/journal/journal-send.c", 445, __PRETTY_FUNCTION__)
, 0))) return (-22); } while (0)
;
446 assert_return(priority <= 7, -EINVAL)do { if (!(((__builtin_expect(!!(priority <= 7),1))) ? (1)
: (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority <= 7"
), "../src/journal/journal-send.c", 446, __PRETTY_FUNCTION__)
, 0))) return (-22); } while (0)
;
447 assert_return(format, -EINVAL)do { if (!(((__builtin_expect(!!(format),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("format"), "../src/journal/journal-send.c"
, 447, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
448
449 xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK)do { if ((__builtin_expect(!!(!(((size_t) snprintf(p, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(p), typeof(&*(p))), sizeof(p)/sizeof((p)[0]), ((void)0))
), "PRIORITY=%i", priority & 0x07) < (__extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(p), typeof(&*(p)))
, sizeof(p)/sizeof((p)[0]), ((void)0))))))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("xsprintf: " "p" "[] must be big enough"
), "../src/journal/journal-send.c", 449, __PRETTY_FUNCTION__)
; } while (0)
;
450
451 memcpy(buffer, "MESSAGE=", 8);
452 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
453
454 /* Strip trailing whitespace, keep prefixing whitespace */
455 (void) strstrip(buffer);
456
457 /* Suppress empty lines */
458 if (isempty(buffer+8))
459 return 0;
460
461 /* func is initialized from __func__ which is not a macro, but
462 * a static const char[], hence cannot easily be prefixed with
463 * CODE_FUNC=, hence let's do it manually here. */
464 ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = &
(f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10
); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl
); } while (0)
;
465
466 iov[0] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen
(buffer)) }
;
467 iov[1] = IOVEC_MAKE_STRING(p)(struct iovec) { .iov_base = ((char*) p), .iov_len = (strlen(
p)) }
;
468 iov[2] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen
(file)) }
;
469 iov[3] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen
(line)) }
;
470 iov[4] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen(
f)) }
;
471
472 return sd_journal_sendv(iov, ELEMENTSOF(iov)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(iov), typeof(&*(iov))), sizeof(iov)/sizeof((iov)[
0]), ((void)0)))
);
473}
474
475_public___attribute__ ((visibility("default"))) int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
476 _cleanup_free___attribute__((cleanup(freep))) struct iovec *iov = NULL((void*)0);
477 int r, i, j;
478 va_list ap;
479 char *f;
480
481 va_start(ap, format)__builtin_va_start(ap, format);
482 i = fill_iovec_sprintf(format, ap, 3, &iov);
1
Calling 'fill_iovec_sprintf'
10
Returned allocated memory via 4th parameter
483 va_end(ap)__builtin_va_end(ap);
484
485 if (_unlikely_(i < 0)(__builtin_expect(!!(i < 0),0))) {
11
Taking false branch
486 r = i;
487 goto finish;
488 }
489
490 ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = &
(f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10
); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl
); } while (0)
;
12
Loop condition is false. Exiting loop
491
492 iov[0] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen
(file)) }
;
493 iov[1] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen
(line)) }
;
494 iov[2] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen(
f)) }
;
495
496 r = sd_journal_sendv(iov, i);
497
498finish:
499 for (j = 3; j < i; j++)
13
Loop condition is false. Execution continues on line 502
500 free(iov[j].iov_base);
501
502 return r;
14
Potential leak of memory pointed to by 'iov'
503}
504
505_public___attribute__ ((visibility("default"))) int sd_journal_sendv_with_location(
506 const char *file, const char *line,
507 const char *func,
508 const struct iovec *iov, int n) {
509
510 struct iovec *niov;
511 char *f;
512
513 assert_return(iov, -EINVAL)do { if (!(((__builtin_expect(!!(iov),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("iov"), "../src/journal/journal-send.c",
513, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
514 assert_return(n > 0, -EINVAL)do { if (!(((__builtin_expect(!!(n > 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("n > 0"), "../src/journal/journal-send.c"
, 514, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
515
516 niov = newa(struct iovec, n + 3)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(struct iovec), n + 3))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("!size_multiply_overflow(sizeof(struct iovec), n + 3)"), "../src/journal/journal-send.c"
, 516, __PRETTY_FUNCTION__); } while (0); (struct iovec*) __builtin_alloca
(sizeof(struct iovec)*(n + 3)); })
;
517 memcpy(niov, iov, sizeof(struct iovec) * n);
518
519 ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = &
(f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10
); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl
); } while (0)
;
520
521 niov[n++] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen
(file)) }
;
522 niov[n++] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen
(line)) }
;
523 niov[n++] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen(
f)) }
;
524
525 return sd_journal_sendv(niov, n);
526}
527
528_public___attribute__ ((visibility("default"))) int sd_journal_perror_with_location(
529 const char *file, const char *line,
530 const char *func,
531 const char *message) {
532
533 struct iovec iov[6];
534 char *f;
535
536 ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = &
(f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10
); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl
); } while (0)
;
537
538 iov[0] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen
(file)) }
;
539 iov[1] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen
(line)) }
;
540 iov[2] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen(
f)) }
;
541
542 return fill_iovec_perror_and_send(message, 3, iov);
543}