1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <selinux/selinux.h>
28 #include "sd-daemon.h"
31 #include "alloc-util.h"
32 #include "dirent-util.h"
37 #include "journald-console.h"
38 #include "journald-context.h"
39 #include "journald-kmsg.h"
40 #include "journald-server.h"
41 #include "journald-stream.h"
42 #include "journald-syslog.h"
43 #include "journald-wall.h"
45 #include "parse-util.h"
46 #include "process-util.h"
47 #include "selinux-util.h"
48 #include "socket-util.h"
49 #include "stdio-util.h"
50 #include "string-util.h"
51 #include "syslog-util.h"
52 #include "unit-name.h"
54 #define STDOUT_STREAMS_MAX 4096
56 typedef enum StdoutStreamState
{
57 STDOUT_STREAM_IDENTIFIER
,
58 STDOUT_STREAM_UNIT_ID
,
59 STDOUT_STREAM_PRIORITY
,
60 STDOUT_STREAM_LEVEL_PREFIX
,
61 STDOUT_STREAM_FORWARD_TO_SYSLOG
,
62 STDOUT_STREAM_FORWARD_TO_KMSG
,
63 STDOUT_STREAM_FORWARD_TO_CONSOLE
,
67 /* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length
68 * was reached, or the end of the stream was reached */
70 typedef enum LineBreak
{
79 StdoutStreamState state
;
89 bool forward_to_syslog
:1;
90 bool forward_to_kmsg
:1;
91 bool forward_to_console
:1;
94 bool in_notify_queue
:1;
100 sd_event_source
*event_source
;
104 ClientContext
*context
;
106 LIST_FIELDS(StdoutStream
, stdout_stream
);
107 LIST_FIELDS(StdoutStream
, stdout_stream_notify_queue
);
109 char id_field
[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX
];
112 void stdout_stream_free(StdoutStream
*s
) {
119 client_context_release(s
->server
, s
->context
);
121 assert(s
->server
->n_stdout_streams
> 0);
122 s
->server
->n_stdout_streams
--;
123 LIST_REMOVE(stdout_stream
, s
->server
->stdout_streams
, s
);
125 if (s
->in_notify_queue
)
126 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
129 if (s
->event_source
) {
130 sd_event_source_set_enabled(s
->event_source
, SD_EVENT_OFF
);
131 s
->event_source
= sd_event_source_unref(s
->event_source
);
144 DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream
*, stdout_stream_free
);
146 static void stdout_stream_destroy(StdoutStream
*s
) {
151 (void) unlink(s
->state_file
);
153 stdout_stream_free(s
);
156 static int stdout_stream_save(StdoutStream
*s
) {
157 _cleanup_free_
char *temp_path
= NULL
;
158 _cleanup_fclose_
FILE *f
= NULL
;
163 if (s
->state
!= STDOUT_STREAM_RUNNING
)
166 if (!s
->state_file
) {
169 r
= fstat(s
->fd
, &st
);
171 return log_warning_errno(errno
, "Failed to stat connected stream: %m");
173 /* We use device and inode numbers as identifier for the stream */
174 if (asprintf(&s
->state_file
, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st
.st_dev
, (unsigned long) st
.st_ino
) < 0)
178 mkdir_p("/run/systemd/journal/streams", 0755);
180 r
= fopen_temporary(s
->state_file
, &f
, &temp_path
);
185 "# This is private data. Do not parse\n"
188 "FORWARD_TO_SYSLOG=%i\n"
189 "FORWARD_TO_KMSG=%i\n"
190 "FORWARD_TO_CONSOLE=%i\n"
194 s
->forward_to_syslog
,
196 s
->forward_to_console
,
197 s
->id_field
+ STRLEN("_STREAM_ID="));
199 if (!isempty(s
->identifier
)) {
200 _cleanup_free_
char *escaped
;
202 escaped
= cescape(s
->identifier
);
208 fprintf(f
, "IDENTIFIER=%s\n", escaped
);
211 if (!isempty(s
->unit_id
)) {
212 _cleanup_free_
char *escaped
;
214 escaped
= cescape(s
->unit_id
);
220 fprintf(f
, "UNIT=%s\n", escaped
);
223 r
= fflush_and_check(f
);
227 if (rename(temp_path
, s
->state_file
) < 0) {
232 if (!s
->fdstore
&& !s
->in_notify_queue
) {
233 LIST_PREPEND(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
234 s
->in_notify_queue
= true;
236 if (s
->server
->notify_event_source
) {
237 r
= sd_event_source_set_enabled(s
->server
->notify_event_source
, SD_EVENT_ON
);
239 log_warning_errno(r
, "Failed to enable notify event source: %m");
246 (void) unlink(s
->state_file
);
249 (void) unlink(temp_path
);
251 return log_error_errno(r
, "Failed to save stream data %s: %m", s
->state_file
);
254 static int stdout_stream_log(StdoutStream
*s
, const char *p
, LineBreak line_break
) {
257 char syslog_priority
[] = "PRIORITY=\0";
258 char syslog_facility
[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int) + 1];
259 _cleanup_free_
char *message
= NULL
, *syslog_identifier
= NULL
;
267 (void) client_context_maybe_refresh(s
->server
, s
->context
, NULL
, NULL
, 0, NULL
, USEC_INFINITY
);
268 else if (pid_is_valid(s
->ucred
.pid
)) {
269 r
= client_context_acquire(s
->server
, s
->ucred
.pid
, &s
->ucred
, s
->label
, strlen_ptr(s
->label
), s
->unit_id
, &s
->context
);
271 log_warning_errno(r
, "Failed to acquire client context, ignoring: %m");
274 priority
= s
->priority
;
277 syslog_parse_priority(&p
, &priority
, false);
279 if (!client_context_test_priority(s
->context
, priority
))
285 if (s
->forward_to_syslog
|| s
->server
->forward_to_syslog
)
286 server_forward_syslog(s
->server
, syslog_fixup_facility(priority
), s
->identifier
, p
, &s
->ucred
, NULL
);
288 if (s
->forward_to_kmsg
|| s
->server
->forward_to_kmsg
)
289 server_forward_kmsg(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
291 if (s
->forward_to_console
|| s
->server
->forward_to_console
)
292 server_forward_console(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
294 if (s
->server
->forward_to_wall
)
295 server_forward_wall(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
297 m
= N_IOVEC_META_FIELDS
+ 7 + client_context_extra_fields_n_iovec(s
->context
);
298 iovec
= newa(struct iovec
, m
);
300 iovec
[n
++] = IOVEC_MAKE_STRING("_TRANSPORT=stdout");
301 iovec
[n
++] = IOVEC_MAKE_STRING(s
->id_field
);
303 syslog_priority
[STRLEN("PRIORITY=")] = '0' + LOG_PRI(priority
);
304 iovec
[n
++] = IOVEC_MAKE_STRING(syslog_priority
);
306 if (priority
& LOG_FACMASK
) {
307 xsprintf(syslog_facility
, "SYSLOG_FACILITY=%i", LOG_FAC(priority
));
308 iovec
[n
++] = IOVEC_MAKE_STRING(syslog_facility
);
312 syslog_identifier
= strappend("SYSLOG_IDENTIFIER=", s
->identifier
);
313 if (syslog_identifier
)
314 iovec
[n
++] = IOVEC_MAKE_STRING(syslog_identifier
);
317 if (line_break
!= LINE_BREAK_NEWLINE
) {
320 /* If this log message was generated due to an uncommon line break then mention this in the log
323 c
= line_break
== LINE_BREAK_NUL
? "_LINE_BREAK=nul" :
324 line_break
== LINE_BREAK_LINE_MAX
? "_LINE_BREAK=line-max" :
326 iovec
[n
++] = IOVEC_MAKE_STRING(c
);
329 message
= strappend("MESSAGE=", p
);
331 iovec
[n
++] = IOVEC_MAKE_STRING(message
);
333 server_dispatch_message(s
->server
, iovec
, n
, m
, s
->context
, NULL
, priority
, 0);
337 static int stdout_stream_line(StdoutStream
*s
, char *p
, LineBreak line_break
) {
347 /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */
348 if (line_break
!= LINE_BREAK_NEWLINE
&& s
->state
!= STDOUT_STREAM_RUNNING
) {
349 log_warning("Control protocol line not properly terminated.");
355 case STDOUT_STREAM_IDENTIFIER
:
357 s
->identifier
= strdup(p
);
362 s
->state
= STDOUT_STREAM_UNIT_ID
;
365 case STDOUT_STREAM_UNIT_ID
:
366 if (s
->ucred
.uid
== 0 &&
367 unit_name_is_valid(p
, UNIT_NAME_PLAIN
|UNIT_NAME_INSTANCE
)) {
369 s
->unit_id
= strdup(p
);
374 s
->state
= STDOUT_STREAM_PRIORITY
;
377 case STDOUT_STREAM_PRIORITY
:
378 r
= safe_atoi(p
, &s
->priority
);
379 if (r
< 0 || s
->priority
< 0 || s
->priority
> 999) {
380 log_warning("Failed to parse log priority line.");
384 s
->state
= STDOUT_STREAM_LEVEL_PREFIX
;
387 case STDOUT_STREAM_LEVEL_PREFIX
:
388 r
= parse_boolean(p
);
390 log_warning("Failed to parse level prefix line.");
394 s
->level_prefix
= !!r
;
395 s
->state
= STDOUT_STREAM_FORWARD_TO_SYSLOG
;
398 case STDOUT_STREAM_FORWARD_TO_SYSLOG
:
399 r
= parse_boolean(p
);
401 log_warning("Failed to parse forward to syslog line.");
405 s
->forward_to_syslog
= !!r
;
406 s
->state
= STDOUT_STREAM_FORWARD_TO_KMSG
;
409 case STDOUT_STREAM_FORWARD_TO_KMSG
:
410 r
= parse_boolean(p
);
412 log_warning("Failed to parse copy to kmsg line.");
416 s
->forward_to_kmsg
= !!r
;
417 s
->state
= STDOUT_STREAM_FORWARD_TO_CONSOLE
;
420 case STDOUT_STREAM_FORWARD_TO_CONSOLE
:
421 r
= parse_boolean(p
);
423 log_warning("Failed to parse copy to console line.");
427 s
->forward_to_console
= !!r
;
428 s
->state
= STDOUT_STREAM_RUNNING
;
430 /* Try to save the stream, so that journald can be restarted and we can recover */
431 (void) stdout_stream_save(s
);
434 case STDOUT_STREAM_RUNNING
:
435 return stdout_stream_log(s
, orig
, line_break
);
438 assert_not_reached("Unknown stream state");
441 static int stdout_stream_scan(StdoutStream
*s
, bool force_flush
) {
449 remaining
= s
->length
;
451 /* XXX: This function does nothing if (s->length == 0) */
454 LineBreak line_break
;
458 end1
= memchr(p
, '\n', remaining
);
459 end2
= memchr(p
, 0, end1
? (size_t) (end1
- p
) : remaining
);
462 /* We found a NUL terminator */
464 line_break
= LINE_BREAK_NUL
;
466 /* We found a \n terminator */
469 line_break
= LINE_BREAK_NEWLINE
;
470 } else if (remaining
>= s
->server
->line_max
) {
471 /* Force a line break after the maximum line length */
472 *(p
+ s
->server
->line_max
) = 0;
474 line_break
= LINE_BREAK_LINE_MAX
;
478 r
= stdout_stream_line(s
, p
, line_break
);
486 if (force_flush
&& remaining
> 0) {
488 r
= stdout_stream_line(s
, p
, LINE_BREAK_EOF
);
497 memmove(s
->buffer
, p
, remaining
);
498 s
->length
= remaining
;
504 static int stdout_stream_process(sd_event_source
*es
, int fd
, uint32_t revents
, void *userdata
) {
505 StdoutStream
*s
= userdata
;
512 if ((revents
|EPOLLIN
|EPOLLHUP
) != (EPOLLIN
|EPOLLHUP
)) {
513 log_error("Got invalid event from epoll for stdout stream: %"PRIx32
, revents
);
517 /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
518 if (s
->length
+ 1 >= s
->allocated
) {
519 if (!GREEDY_REALLOC(s
->buffer
, s
->allocated
, s
->length
+ 1 + 1024)) {
525 /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also,
526 * always leave room for a terminating NUL we might need to add. */
527 limit
= MIN(s
->allocated
- 1, s
->server
->line_max
);
529 l
= read(s
->fd
, s
->buffer
+ s
->length
, limit
- s
->length
);
534 log_warning_errno(errno
, "Failed to read from stream: %m");
539 stdout_stream_scan(s
, true);
544 r
= stdout_stream_scan(s
, false);
551 stdout_stream_destroy(s
);
555 static int stdout_stream_install(Server
*s
, int fd
, StdoutStream
**ret
) {
556 _cleanup_(stdout_stream_freep
) StdoutStream
*stream
= NULL
;
563 r
= sd_id128_randomize(&id
);
565 return log_error_errno(r
, "Failed to generate stream ID: %m");
567 stream
= new0(StdoutStream
, 1);
572 stream
->priority
= LOG_INFO
;
574 xsprintf(stream
->id_field
, "_STREAM_ID=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(id
));
576 r
= getpeercred(fd
, &stream
->ucred
);
578 return log_error_errno(r
, "Failed to determine peer credentials: %m");
580 if (mac_selinux_use()) {
581 r
= getpeersec(fd
, &stream
->label
);
582 if (r
< 0 && r
!= -EOPNOTSUPP
)
583 (void) log_warning_errno(r
, "Failed to determine peer security context: %m");
586 (void) shutdown(fd
, SHUT_WR
);
588 r
= sd_event_add_io(s
->event
, &stream
->event_source
, fd
, EPOLLIN
, stdout_stream_process
, stream
);
590 return log_error_errno(r
, "Failed to add stream to event loop: %m");
592 r
= sd_event_source_set_priority(stream
->event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
594 return log_error_errno(r
, "Failed to adjust stdout event source priority: %m");
599 LIST_PREPEND(stdout_stream
, s
->stdout_streams
, stream
);
600 s
->n_stdout_streams
++;
610 static int stdout_stream_new(sd_event_source
*es
, int listen_fd
, uint32_t revents
, void *userdata
) {
611 _cleanup_close_
int fd
= -1;
612 Server
*s
= userdata
;
617 if (revents
!= EPOLLIN
) {
618 log_error("Got invalid event from epoll for stdout server fd: %"PRIx32
, revents
);
622 fd
= accept4(s
->stdout_fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
627 return log_error_errno(errno
, "Failed to accept stdout connection: %m");
630 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
631 log_warning("Too many stdout streams, refusing connection.");
635 r
= stdout_stream_install(s
, fd
, NULL
);
643 static int stdout_stream_load(StdoutStream
*stream
, const char *fname
) {
646 *level_prefix
= NULL
,
647 *forward_to_syslog
= NULL
,
648 *forward_to_kmsg
= NULL
,
649 *forward_to_console
= NULL
,
656 if (!stream
->state_file
) {
657 stream
->state_file
= strappend("/run/systemd/journal/streams/", fname
);
658 if (!stream
->state_file
)
662 r
= parse_env_file(stream
->state_file
, NEWLINE
,
663 "PRIORITY", &priority
,
664 "LEVEL_PREFIX", &level_prefix
,
665 "FORWARD_TO_SYSLOG", &forward_to_syslog
,
666 "FORWARD_TO_KMSG", &forward_to_kmsg
,
667 "FORWARD_TO_CONSOLE", &forward_to_console
,
668 "IDENTIFIER", &stream
->identifier
,
669 "UNIT", &stream
->unit_id
,
670 "STREAM_ID", &stream_id
,
673 return log_error_errno(r
, "Failed to read: %s", stream
->state_file
);
678 p
= log_level_from_string(priority
);
680 stream
->priority
= p
;
684 r
= parse_boolean(level_prefix
);
686 stream
->level_prefix
= r
;
689 if (forward_to_syslog
) {
690 r
= parse_boolean(forward_to_syslog
);
692 stream
->forward_to_syslog
= r
;
695 if (forward_to_kmsg
) {
696 r
= parse_boolean(forward_to_kmsg
);
698 stream
->forward_to_kmsg
= r
;
701 if (forward_to_console
) {
702 r
= parse_boolean(forward_to_console
);
704 stream
->forward_to_console
= r
;
710 r
= sd_id128_from_string(stream_id
, &id
);
712 xsprintf(stream
->id_field
, "_STREAM_ID=" SD_ID128_FORMAT_STR
, SD_ID128_FORMAT_VAL(id
));
718 static int stdout_stream_restore(Server
*s
, const char *fname
, int fd
) {
719 StdoutStream
*stream
;
726 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
727 log_warning("Too many stdout streams, refusing restoring of stream.");
731 r
= stdout_stream_install(s
, fd
, &stream
);
735 stream
->state
= STDOUT_STREAM_RUNNING
;
736 stream
->fdstore
= true;
738 /* Ignore all parsing errors */
739 (void) stdout_stream_load(stream
, fname
);
744 int server_restore_streams(Server
*s
, FDSet
*fds
) {
745 _cleanup_closedir_
DIR *d
= NULL
;
749 d
= opendir("/run/systemd/journal/streams");
754 return log_warning_errno(errno
, "Failed to enumerate /run/systemd/journal/streams: %m");
757 FOREACH_DIRENT(de
, d
, goto fail
) {
758 unsigned long st_dev
, st_ino
;
763 if (sscanf(de
->d_name
, "%lu:%lu", &st_dev
, &st_ino
) != 2)
766 FDSET_FOREACH(fd
, fds
, i
) {
769 if (fstat(fd
, &st
) < 0)
770 return log_error_errno(errno
, "Failed to stat %s: %m", de
->d_name
);
772 if (S_ISSOCK(st
.st_mode
) && st
.st_dev
== st_dev
&& st
.st_ino
== st_ino
) {
779 /* No file descriptor? Then let's delete the state file */
780 log_debug("Cannot restore stream file %s", de
->d_name
);
781 unlinkat(dirfd(d
), de
->d_name
, 0);
785 fdset_remove(fds
, fd
);
787 r
= stdout_stream_restore(s
, de
->d_name
, fd
);
795 return log_error_errno(errno
, "Failed to read streams directory: %m");
798 int server_open_stdout_socket(Server
*s
) {
799 static const union sockaddr_union sa
= {
800 .un
.sun_family
= AF_UNIX
,
801 .un
.sun_path
= "/run/systemd/journal/stdout",
807 if (s
->stdout_fd
< 0) {
808 s
->stdout_fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
809 if (s
->stdout_fd
< 0)
810 return log_error_errno(errno
, "socket() failed: %m");
812 (void) unlink(sa
.un
.sun_path
);
814 r
= bind(s
->stdout_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
));
816 return log_error_errno(errno
, "bind(%s) failed: %m", sa
.un
.sun_path
);
818 (void) chmod(sa
.un
.sun_path
, 0666);
820 if (listen(s
->stdout_fd
, SOMAXCONN
) < 0)
821 return log_error_errno(errno
, "listen(%s) failed: %m", sa
.un
.sun_path
);
823 fd_nonblock(s
->stdout_fd
, 1);
825 r
= sd_event_add_io(s
->event
, &s
->stdout_event_source
, s
->stdout_fd
, EPOLLIN
, stdout_stream_new
, s
);
827 return log_error_errno(r
, "Failed to add stdout server fd to event source: %m");
829 r
= sd_event_source_set_priority(s
->stdout_event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
831 return log_error_errno(r
, "Failed to adjust priority of stdout server event source: %m");
836 void stdout_stream_send_notify(StdoutStream
*s
) {
837 struct iovec iovec
= {
838 .iov_base
= (char*) "FDSTORE=1",
839 .iov_len
= STRLEN("FDSTORE=1"),
841 struct msghdr msghdr
= {
845 struct cmsghdr
*cmsg
;
850 assert(s
->in_notify_queue
);
852 assert(s
->server
->notify_fd
>= 0);
854 /* Store the connection fd in PID 1, so that we get it passed
855 * in again on next start */
857 msghdr
.msg_controllen
= CMSG_SPACE(sizeof(int));
858 msghdr
.msg_control
= alloca0(msghdr
.msg_controllen
);
860 cmsg
= CMSG_FIRSTHDR(&msghdr
);
861 cmsg
->cmsg_level
= SOL_SOCKET
;
862 cmsg
->cmsg_type
= SCM_RIGHTS
;
863 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
865 memcpy(CMSG_DATA(cmsg
), &s
->fd
, sizeof(int));
867 l
= sendmsg(s
->server
->notify_fd
, &msghdr
, MSG_DONTWAIT
|MSG_NOSIGNAL
);
872 log_error_errno(errno
, "Failed to send stream file descriptor to service manager: %m");
874 log_debug("Successfully sent stream file descriptor to service manager.");
878 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
879 s
->in_notify_queue
= false;