]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/journal/journal-send.c
Merge pull request #3589 from brauner/cgroup_namespace
[thirdparty/systemd.git] / src / journal / journal-send.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2011 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <printf.h>
23 #include <stddef.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <unistd.h>
27
28 #define SD_JOURNAL_SUPPRESS_LOCATION
29
30 #include "sd-journal.h"
31
32 #include "alloc-util.h"
33 #include "fd-util.h"
34 #include "fileio.h"
35 #include "io-util.h"
36 #include "memfd-util.h"
37 #include "socket-util.h"
38 #include "stdio-util.h"
39 #include "string-util.h"
40 #include "util.h"
41
42 #define SNDBUF_SIZE (8*1024*1024)
43
44 #define ALLOCA_CODE_FUNC(f, func) \
45 do { \
46 size_t _fl; \
47 const char *_func = (func); \
48 char **_f = &(f); \
49 _fl = strlen(_func) + 1; \
50 *_f = alloca(_fl + 10); \
51 memcpy(*_f, "CODE_FUNC=", 10); \
52 memcpy(*_f + 10, _func, _fl); \
53 } while (false)
54
55 /* We open a single fd, and we'll share it with the current process,
56 * all its threads, and all its subprocesses. This means we need to
57 * initialize it atomically, and need to operate on it atomically
58 * never assuming we are the only user */
59
60 static int journal_fd(void) {
61 int fd;
62 static int fd_plus_one = 0;
63
64 retry:
65 if (fd_plus_one > 0)
66 return fd_plus_one - 1;
67
68 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
69 if (fd < 0)
70 return -errno;
71
72 fd_inc_sndbuf(fd, SNDBUF_SIZE);
73
74 if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
75 safe_close(fd);
76 goto retry;
77 }
78
79 return fd;
80 }
81
82 _public_ int sd_journal_print(int priority, const char *format, ...) {
83 int r;
84 va_list ap;
85
86 va_start(ap, format);
87 r = sd_journal_printv(priority, format, ap);
88 va_end(ap);
89
90 return r;
91 }
92
93 _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
94
95 /* FIXME: Instead of limiting things to LINE_MAX we could do a
96 C99 variable-length array on the stack here in a loop. */
97
98 char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1];
99 struct iovec iov[2];
100
101 assert_return(priority >= 0, -EINVAL);
102 assert_return(priority <= 7, -EINVAL);
103 assert_return(format, -EINVAL);
104
105 xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
106
107 memcpy(buffer, "MESSAGE=", 8);
108 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
109
110 /* Strip trailing whitespace, keep prefix whitespace. */
111 (void) strstrip(buffer);
112
113 /* Suppress empty lines */
114 if (isempty(buffer+8))
115 return 0;
116
117 zero(iov);
118 IOVEC_SET_STRING(iov[0], buffer);
119 IOVEC_SET_STRING(iov[1], p);
120
121 return sd_journal_sendv(iov, 2);
122 }
123
124 _printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
125 PROTECT_ERRNO;
126 int r, n = 0, i = 0, j;
127 struct iovec *iov = NULL;
128
129 assert(_iov);
130
131 if (extra > 0) {
132 n = MAX(extra * 2, extra + 4);
133 iov = malloc0(n * sizeof(struct iovec));
134 if (!iov) {
135 r = -ENOMEM;
136 goto fail;
137 }
138
139 i = extra;
140 }
141
142 while (format) {
143 struct iovec *c;
144 char *buffer;
145 va_list aq;
146
147 if (i >= n) {
148 n = MAX(i*2, 4);
149 c = realloc(iov, n * sizeof(struct iovec));
150 if (!c) {
151 r = -ENOMEM;
152 goto fail;
153 }
154
155 iov = c;
156 }
157
158 va_copy(aq, ap);
159 if (vasprintf(&buffer, format, aq) < 0) {
160 va_end(aq);
161 r = -ENOMEM;
162 goto fail;
163 }
164 va_end(aq);
165
166 VA_FORMAT_ADVANCE(format, ap);
167
168 (void) strstrip(buffer); /* strip trailing whitespace, keep prefixing whitespace */
169
170 IOVEC_SET_STRING(iov[i++], buffer);
171
172 format = va_arg(ap, char *);
173 }
174
175 *_iov = iov;
176
177 return i;
178
179 fail:
180 for (j = 0; j < i; j++)
181 free(iov[j].iov_base);
182
183 free(iov);
184
185 return r;
186 }
187
188 _public_ int sd_journal_send(const char *format, ...) {
189 int r, i, j;
190 va_list ap;
191 struct iovec *iov = NULL;
192
193 va_start(ap, format);
194 i = fill_iovec_sprintf(format, ap, 0, &iov);
195 va_end(ap);
196
197 if (_unlikely_(i < 0)) {
198 r = i;
199 goto finish;
200 }
201
202 r = sd_journal_sendv(iov, i);
203
204 finish:
205 for (j = 0; j < i; j++)
206 free(iov[j].iov_base);
207
208 free(iov);
209
210 return r;
211 }
212
213 _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
214 PROTECT_ERRNO;
215 int fd, r;
216 _cleanup_close_ int buffer_fd = -1;
217 struct iovec *w;
218 uint64_t *l;
219 int i, j = 0;
220 static const union sockaddr_union sa = {
221 .un.sun_family = AF_UNIX,
222 .un.sun_path = "/run/systemd/journal/socket",
223 };
224 struct msghdr mh = {
225 .msg_name = (struct sockaddr*) &sa.sa,
226 .msg_namelen = SOCKADDR_UN_LEN(sa.un),
227 };
228 ssize_t k;
229 bool have_syslog_identifier = false;
230 bool seal = true;
231
232 assert_return(iov, -EINVAL);
233 assert_return(n > 0, -EINVAL);
234
235 w = newa(struct iovec, n * 5 + 3);
236 l = newa(uint64_t, n);
237
238 for (i = 0; i < n; i++) {
239 char *c, *nl;
240
241 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
242 return -EINVAL;
243
244 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
245 if (_unlikely_(!c || c == iov[i].iov_base))
246 return -EINVAL;
247
248 have_syslog_identifier = have_syslog_identifier ||
249 (c == (char *) iov[i].iov_base + 17 &&
250 startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
251
252 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
253 if (nl) {
254 if (_unlikely_(nl < c))
255 return -EINVAL;
256
257 /* Already includes a newline? Bummer, then
258 * let's write the variable name, then a
259 * newline, then the size (64bit LE), followed
260 * by the data and a final newline */
261
262 w[j].iov_base = iov[i].iov_base;
263 w[j].iov_len = c - (char*) iov[i].iov_base;
264 j++;
265
266 IOVEC_SET_STRING(w[j++], "\n");
267
268 l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
269 w[j].iov_base = &l[i];
270 w[j].iov_len = sizeof(uint64_t);
271 j++;
272
273 w[j].iov_base = c + 1;
274 w[j].iov_len = iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1;
275 j++;
276
277 } else
278 /* Nothing special? Then just add the line and
279 * append a newline */
280 w[j++] = iov[i];
281
282 IOVEC_SET_STRING(w[j++], "\n");
283 }
284
285 if (!have_syslog_identifier &&
286 string_is_safe(program_invocation_short_name)) {
287
288 /* Implicitly add program_invocation_short_name, if it
289 * is not set explicitly. We only do this for
290 * program_invocation_short_name, and nothing else
291 * since everything else is much nicer to retrieve
292 * from the outside. */
293
294 IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
295 IOVEC_SET_STRING(w[j++], program_invocation_short_name);
296 IOVEC_SET_STRING(w[j++], "\n");
297 }
298
299 fd = journal_fd();
300 if (_unlikely_(fd < 0))
301 return fd;
302
303 mh.msg_iov = w;
304 mh.msg_iovlen = j;
305
306 k = sendmsg(fd, &mh, MSG_NOSIGNAL);
307 if (k >= 0)
308 return 0;
309
310 /* Fail silently if the journal is not available */
311 if (errno == ENOENT)
312 return 0;
313
314 if (errno != EMSGSIZE && errno != ENOBUFS)
315 return -errno;
316
317 /* Message doesn't fit... Let's dump the data in a memfd or
318 * temporary file and just pass a file descriptor of it to the
319 * other side.
320 *
321 * For the temporary files we use /dev/shm instead of /tmp
322 * here, since we want this to be a tmpfs, and one that is
323 * available from early boot on and where unprivileged users
324 * can create files. */
325 buffer_fd = memfd_new(NULL);
326 if (buffer_fd < 0) {
327 if (buffer_fd == -ENOSYS) {
328 buffer_fd = open_tmpfile_unlinkable("/dev/shm", O_RDWR | O_CLOEXEC);
329 if (buffer_fd < 0)
330 return buffer_fd;
331
332 seal = false;
333 } else
334 return buffer_fd;
335 }
336
337 n = writev(buffer_fd, w, j);
338 if (n < 0)
339 return -errno;
340
341 if (seal) {
342 r = memfd_set_sealed(buffer_fd);
343 if (r < 0)
344 return r;
345 }
346
347 r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0);
348 if (r == -ENOENT)
349 /* Fail silently if the journal is not available */
350 return 0;
351 return r;
352 }
353
354 static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
355 PROTECT_ERRNO;
356 size_t n, k;
357
358 k = isempty(message) ? 0 : strlen(message) + 2;
359 n = 8 + k + 256 + 1;
360
361 for (;;) {
362 char buffer[n];
363 char* j;
364
365 errno = 0;
366 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
367 if (errno == 0) {
368 char error[sizeof("ERRNO=")-1 + DECIMAL_STR_MAX(int) + 1];
369
370 if (j != buffer + 8 + k)
371 memmove(buffer + 8 + k, j, strlen(j)+1);
372
373 memcpy(buffer, "MESSAGE=", 8);
374
375 if (k > 0) {
376 memcpy(buffer + 8, message, k - 2);
377 memcpy(buffer + 8 + k - 2, ": ", 2);
378 }
379
380 xsprintf(error, "ERRNO=%i", _saved_errno_);
381
382 assert_cc(3 == LOG_ERR);
383 IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
384 IOVEC_SET_STRING(iov[skip+1], buffer);
385 IOVEC_SET_STRING(iov[skip+2], error);
386
387 return sd_journal_sendv(iov, skip + 3);
388 }
389
390 if (errno != ERANGE)
391 return -errno;
392
393 n *= 2;
394 }
395 }
396
397 _public_ int sd_journal_perror(const char *message) {
398 struct iovec iovec[3];
399
400 return fill_iovec_perror_and_send(message, 0, iovec);
401 }
402
403 _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
404 static const union sockaddr_union sa = {
405 .un.sun_family = AF_UNIX,
406 .un.sun_path = "/run/systemd/journal/stdout",
407 };
408 _cleanup_close_ int fd = -1;
409 char *header;
410 size_t l;
411 int r;
412
413 assert_return(priority >= 0, -EINVAL);
414 assert_return(priority <= 7, -EINVAL);
415
416 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
417 if (fd < 0)
418 return -errno;
419
420 r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
421 if (r < 0)
422 return -errno;
423
424 if (shutdown(fd, SHUT_RD) < 0)
425 return -errno;
426
427 fd_inc_sndbuf(fd, SNDBUF_SIZE);
428
429 if (!identifier)
430 identifier = "";
431
432 l = strlen(identifier);
433 header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
434
435 memcpy(header, identifier, l);
436 header[l++] = '\n';
437 header[l++] = '\n'; /* unit id */
438 header[l++] = '0' + priority;
439 header[l++] = '\n';
440 header[l++] = '0' + !!level_prefix;
441 header[l++] = '\n';
442 header[l++] = '0';
443 header[l++] = '\n';
444 header[l++] = '0';
445 header[l++] = '\n';
446 header[l++] = '0';
447 header[l++] = '\n';
448
449 r = loop_write(fd, header, l, false);
450 if (r < 0)
451 return r;
452
453 r = fd;
454 fd = -1;
455 return r;
456 }
457
458 _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
459 int r;
460 va_list ap;
461
462 va_start(ap, format);
463 r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
464 va_end(ap);
465
466 return r;
467 }
468
469 _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
470 char buffer[8 + LINE_MAX], p[sizeof("PRIORITY=")-1 + DECIMAL_STR_MAX(int) + 1];
471 struct iovec iov[5];
472 char *f;
473
474 assert_return(priority >= 0, -EINVAL);
475 assert_return(priority <= 7, -EINVAL);
476 assert_return(format, -EINVAL);
477
478 xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
479
480 memcpy(buffer, "MESSAGE=", 8);
481 vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
482
483 /* Strip trailing whitespace, keep prefixing whitespace */
484 (void) strstrip(buffer);
485
486 /* Suppress empty lines */
487 if (isempty(buffer+8))
488 return 0;
489
490 /* func is initialized from __func__ which is not a macro, but
491 * a static const char[], hence cannot easily be prefixed with
492 * CODE_FUNC=, hence let's do it manually here. */
493 ALLOCA_CODE_FUNC(f, func);
494
495 zero(iov);
496 IOVEC_SET_STRING(iov[0], buffer);
497 IOVEC_SET_STRING(iov[1], p);
498 IOVEC_SET_STRING(iov[2], file);
499 IOVEC_SET_STRING(iov[3], line);
500 IOVEC_SET_STRING(iov[4], f);
501
502 return sd_journal_sendv(iov, ELEMENTSOF(iov));
503 }
504
505 _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
506 int r, i, j;
507 va_list ap;
508 struct iovec *iov = NULL;
509 char *f;
510
511 va_start(ap, format);
512 i = fill_iovec_sprintf(format, ap, 3, &iov);
513 va_end(ap);
514
515 if (_unlikely_(i < 0)) {
516 r = i;
517 goto finish;
518 }
519
520 ALLOCA_CODE_FUNC(f, func);
521
522 IOVEC_SET_STRING(iov[0], file);
523 IOVEC_SET_STRING(iov[1], line);
524 IOVEC_SET_STRING(iov[2], f);
525
526 r = sd_journal_sendv(iov, i);
527
528 finish:
529 for (j = 3; j < i; j++)
530 free(iov[j].iov_base);
531
532 free(iov);
533
534 return r;
535 }
536
537 _public_ int sd_journal_sendv_with_location(
538 const char *file, const char *line,
539 const char *func,
540 const struct iovec *iov, int n) {
541
542 struct iovec *niov;
543 char *f;
544
545 assert_return(iov, -EINVAL);
546 assert_return(n > 0, -EINVAL);
547
548 niov = alloca(sizeof(struct iovec) * (n + 3));
549 memcpy(niov, iov, sizeof(struct iovec) * n);
550
551 ALLOCA_CODE_FUNC(f, func);
552
553 IOVEC_SET_STRING(niov[n++], file);
554 IOVEC_SET_STRING(niov[n++], line);
555 IOVEC_SET_STRING(niov[n++], f);
556
557 return sd_journal_sendv(niov, n);
558 }
559
560 _public_ int sd_journal_perror_with_location(
561 const char *file, const char *line,
562 const char *func,
563 const char *message) {
564
565 struct iovec iov[6];
566 char *f;
567
568 ALLOCA_CODE_FUNC(f, func);
569
570 IOVEC_SET_STRING(iov[0], file);
571 IOVEC_SET_STRING(iov[1], line);
572 IOVEC_SET_STRING(iov[2], f);
573
574 return fill_iovec_perror_and_send(message, 3, iov);
575 }