LCOV - code coverage report
Current view: top level - journal - journald-stream.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 447 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 15 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 429 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <stddef.h>
       4                 :            : #include <unistd.h>
       5                 :            : 
       6                 :            : #if HAVE_SELINUX
       7                 :            : #include <selinux/selinux.h>
       8                 :            : #endif
       9                 :            : 
      10                 :            : #include "sd-daemon.h"
      11                 :            : #include "sd-event.h"
      12                 :            : 
      13                 :            : #include "alloc-util.h"
      14                 :            : #include "dirent-util.h"
      15                 :            : #include "env-file.h"
      16                 :            : #include "errno-util.h"
      17                 :            : #include "escape.h"
      18                 :            : #include "fd-util.h"
      19                 :            : #include "fileio.h"
      20                 :            : #include "io-util.h"
      21                 :            : #include "journald-console.h"
      22                 :            : #include "journald-context.h"
      23                 :            : #include "journald-kmsg.h"
      24                 :            : #include "journald-server.h"
      25                 :            : #include "journald-stream.h"
      26                 :            : #include "journald-syslog.h"
      27                 :            : #include "journald-wall.h"
      28                 :            : #include "mkdir.h"
      29                 :            : #include "parse-util.h"
      30                 :            : #include "process-util.h"
      31                 :            : #include "selinux-util.h"
      32                 :            : #include "socket-util.h"
      33                 :            : #include "stdio-util.h"
      34                 :            : #include "string-util.h"
      35                 :            : #include "syslog-util.h"
      36                 :            : #include "tmpfile-util.h"
      37                 :            : #include "unit-name.h"
      38                 :            : 
      39                 :            : #define STDOUT_STREAMS_MAX 4096
      40                 :            : 
      41                 :            : typedef enum StdoutStreamState {
      42                 :            :         STDOUT_STREAM_IDENTIFIER,
      43                 :            :         STDOUT_STREAM_UNIT_ID,
      44                 :            :         STDOUT_STREAM_PRIORITY,
      45                 :            :         STDOUT_STREAM_LEVEL_PREFIX,
      46                 :            :         STDOUT_STREAM_FORWARD_TO_SYSLOG,
      47                 :            :         STDOUT_STREAM_FORWARD_TO_KMSG,
      48                 :            :         STDOUT_STREAM_FORWARD_TO_CONSOLE,
      49                 :            :         STDOUT_STREAM_RUNNING
      50                 :            : } StdoutStreamState;
      51                 :            : 
      52                 :            : /* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length
      53                 :            :  * was reached, or the end of the stream was reached */
      54                 :            : 
      55                 :            : typedef enum LineBreak {
      56                 :            :         LINE_BREAK_NEWLINE,
      57                 :            :         LINE_BREAK_NUL,
      58                 :            :         LINE_BREAK_LINE_MAX,
      59                 :            :         LINE_BREAK_EOF,
      60                 :            : } LineBreak;
      61                 :            : 
      62                 :            : struct StdoutStream {
      63                 :            :         Server *server;
      64                 :            :         StdoutStreamState state;
      65                 :            : 
      66                 :            :         int fd;
      67                 :            : 
      68                 :            :         struct ucred ucred;
      69                 :            :         char *label;
      70                 :            :         char *identifier;
      71                 :            :         char *unit_id;
      72                 :            :         int priority;
      73                 :            :         bool level_prefix:1;
      74                 :            :         bool forward_to_syslog:1;
      75                 :            :         bool forward_to_kmsg:1;
      76                 :            :         bool forward_to_console:1;
      77                 :            : 
      78                 :            :         bool fdstore:1;
      79                 :            :         bool in_notify_queue:1;
      80                 :            : 
      81                 :            :         char *buffer;
      82                 :            :         size_t length;
      83                 :            :         size_t allocated;
      84                 :            : 
      85                 :            :         sd_event_source *event_source;
      86                 :            : 
      87                 :            :         char *state_file;
      88                 :            : 
      89                 :            :         ClientContext *context;
      90                 :            : 
      91                 :            :         LIST_FIELDS(StdoutStream, stdout_stream);
      92                 :            :         LIST_FIELDS(StdoutStream, stdout_stream_notify_queue);
      93                 :            : 
      94                 :            :         char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX];
      95                 :            : };
      96                 :            : 
      97                 :          0 : void stdout_stream_free(StdoutStream *s) {
      98         [ #  # ]:          0 :         if (!s)
      99                 :          0 :                 return;
     100                 :            : 
     101         [ #  # ]:          0 :         if (s->server) {
     102                 :            : 
     103         [ #  # ]:          0 :                 if (s->context)
     104                 :          0 :                         client_context_release(s->server, s->context);
     105                 :            : 
     106         [ #  # ]:          0 :                 assert(s->server->n_stdout_streams > 0);
     107                 :          0 :                 s->server->n_stdout_streams--;
     108   [ #  #  #  #  :          0 :                 LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
             #  #  #  # ]
     109                 :            : 
     110         [ #  # ]:          0 :                 if (s->in_notify_queue)
     111   [ #  #  #  #  :          0 :                         LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
             #  #  #  # ]
     112                 :            :         }
     113                 :            : 
     114         [ #  # ]:          0 :         if (s->event_source) {
     115                 :          0 :                 sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
     116                 :          0 :                 s->event_source = sd_event_source_unref(s->event_source);
     117                 :            :         }
     118                 :            : 
     119                 :          0 :         safe_close(s->fd);
     120                 :          0 :         free(s->label);
     121                 :          0 :         free(s->identifier);
     122                 :          0 :         free(s->unit_id);
     123                 :          0 :         free(s->state_file);
     124                 :          0 :         free(s->buffer);
     125                 :            : 
     126                 :          0 :         free(s);
     127                 :            : }
     128                 :            : 
     129         [ #  # ]:          0 : DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
     130                 :            : 
     131                 :          0 : void stdout_stream_destroy(StdoutStream *s) {
     132         [ #  # ]:          0 :         if (!s)
     133                 :          0 :                 return;
     134                 :            : 
     135         [ #  # ]:          0 :         if (s->state_file)
     136                 :          0 :                 (void) unlink(s->state_file);
     137                 :            : 
     138                 :          0 :         stdout_stream_free(s);
     139                 :            : }
     140                 :            : 
     141                 :          0 : static int stdout_stream_save(StdoutStream *s) {
     142                 :          0 :         _cleanup_free_ char *temp_path = NULL;
     143                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
     144                 :            :         int r;
     145                 :            : 
     146         [ #  # ]:          0 :         assert(s);
     147                 :            : 
     148         [ #  # ]:          0 :         if (s->state != STDOUT_STREAM_RUNNING)
     149                 :          0 :                 return 0;
     150                 :            : 
     151         [ #  # ]:          0 :         if (!s->state_file) {
     152                 :            :                 struct stat st;
     153                 :            : 
     154                 :          0 :                 r = fstat(s->fd, &st);
     155         [ #  # ]:          0 :                 if (r < 0)
     156         [ #  # ]:          0 :                         return log_warning_errno(errno, "Failed to stat connected stream: %m");
     157                 :            : 
     158                 :            :                 /* We use device and inode numbers as identifier for the stream */
     159         [ #  # ]:          0 :                 if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0)
     160                 :          0 :                         return log_oom();
     161                 :            :         }
     162                 :            : 
     163                 :          0 :         (void) mkdir_p("/run/systemd/journal/streams", 0755);
     164                 :            : 
     165                 :          0 :         r = fopen_temporary(s->state_file, &f, &temp_path);
     166         [ #  # ]:          0 :         if (r < 0)
     167                 :          0 :                 goto fail;
     168                 :            : 
     169                 :          0 :         fprintf(f,
     170                 :            :                 "# This is private data. Do not parse\n"
     171                 :            :                 "PRIORITY=%i\n"
     172                 :            :                 "LEVEL_PREFIX=%i\n"
     173                 :            :                 "FORWARD_TO_SYSLOG=%i\n"
     174                 :            :                 "FORWARD_TO_KMSG=%i\n"
     175                 :            :                 "FORWARD_TO_CONSOLE=%i\n"
     176                 :            :                 "STREAM_ID=%s\n",
     177                 :            :                 s->priority,
     178                 :          0 :                 s->level_prefix,
     179                 :          0 :                 s->forward_to_syslog,
     180                 :          0 :                 s->forward_to_kmsg,
     181                 :          0 :                 s->forward_to_console,
     182                 :          0 :                 s->id_field + STRLEN("_STREAM_ID="));
     183                 :            : 
     184         [ #  # ]:          0 :         if (!isempty(s->identifier)) {
     185         [ #  # ]:          0 :                 _cleanup_free_ char *escaped;
     186                 :            : 
     187                 :          0 :                 escaped = cescape(s->identifier);
     188         [ #  # ]:          0 :                 if (!escaped) {
     189                 :          0 :                         r = -ENOMEM;
     190                 :          0 :                         goto fail;
     191                 :            :                 }
     192                 :            : 
     193                 :          0 :                 fprintf(f, "IDENTIFIER=%s\n", escaped);
     194                 :            :         }
     195                 :            : 
     196         [ #  # ]:          0 :         if (!isempty(s->unit_id)) {
     197         [ #  # ]:          0 :                 _cleanup_free_ char *escaped;
     198                 :            : 
     199                 :          0 :                 escaped = cescape(s->unit_id);
     200         [ #  # ]:          0 :                 if (!escaped) {
     201                 :          0 :                         r = -ENOMEM;
     202                 :          0 :                         goto fail;
     203                 :            :                 }
     204                 :            : 
     205                 :          0 :                 fprintf(f, "UNIT=%s\n", escaped);
     206                 :            :         }
     207                 :            : 
     208                 :          0 :         r = fflush_and_check(f);
     209         [ #  # ]:          0 :         if (r < 0)
     210                 :          0 :                 goto fail;
     211                 :            : 
     212         [ #  # ]:          0 :         if (rename(temp_path, s->state_file) < 0) {
     213                 :          0 :                 r = -errno;
     214                 :          0 :                 goto fail;
     215                 :            :         }
     216                 :            : 
     217   [ #  #  #  # ]:          0 :         if (!s->fdstore && !s->in_notify_queue) {
     218   [ #  #  #  # ]:          0 :                 LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
     219                 :          0 :                 s->in_notify_queue = true;
     220                 :            : 
     221         [ #  # ]:          0 :                 if (s->server->notify_event_source) {
     222                 :          0 :                         r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON);
     223         [ #  # ]:          0 :                         if (r < 0)
     224         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to enable notify event source: %m");
     225                 :            :                 }
     226                 :            :         }
     227                 :            : 
     228                 :          0 :         return 0;
     229                 :            : 
     230                 :          0 : fail:
     231                 :          0 :         (void) unlink(s->state_file);
     232                 :            : 
     233         [ #  # ]:          0 :         if (temp_path)
     234                 :          0 :                 (void) unlink(temp_path);
     235                 :            : 
     236         [ #  # ]:          0 :         return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file);
     237                 :            : }
     238                 :            : 
     239                 :          0 : static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) {
     240                 :            :         struct iovec *iovec;
     241                 :            :         int priority;
     242                 :          0 :         char syslog_priority[] = "PRIORITY=\0";
     243                 :            :         char syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int) + 1];
     244                 :          0 :         _cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
     245                 :          0 :         size_t n = 0, m;
     246                 :            :         int r;
     247                 :            : 
     248         [ #  # ]:          0 :         assert(s);
     249         [ #  # ]:          0 :         assert(p);
     250                 :            : 
     251         [ #  # ]:          0 :         if (s->context)
     252                 :          0 :                 (void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY);
     253         [ #  # ]:          0 :         else if (pid_is_valid(s->ucred.pid)) {
     254                 :          0 :                 r = client_context_acquire(s->server, s->ucred.pid, &s->ucred, s->label, strlen_ptr(s->label), s->unit_id, &s->context);
     255         [ #  # ]:          0 :                 if (r < 0)
     256         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to acquire client context, ignoring: %m");
     257                 :            :         }
     258                 :            : 
     259                 :          0 :         priority = s->priority;
     260                 :            : 
     261         [ #  # ]:          0 :         if (s->level_prefix)
     262                 :          0 :                 syslog_parse_priority(&p, &priority, false);
     263                 :            : 
     264         [ #  # ]:          0 :         if (!client_context_test_priority(s->context, priority))
     265                 :          0 :                 return 0;
     266                 :            : 
     267         [ #  # ]:          0 :         if (isempty(p))
     268                 :          0 :                 return 0;
     269                 :            : 
     270   [ #  #  #  # ]:          0 :         if (s->forward_to_syslog || s->server->forward_to_syslog)
     271                 :          0 :                 server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
     272                 :            : 
     273   [ #  #  #  # ]:          0 :         if (s->forward_to_kmsg || s->server->forward_to_kmsg)
     274                 :          0 :                 server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
     275                 :            : 
     276   [ #  #  #  # ]:          0 :         if (s->forward_to_console || s->server->forward_to_console)
     277                 :          0 :                 server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
     278                 :            : 
     279         [ #  # ]:          0 :         if (s->server->forward_to_wall)
     280                 :          0 :                 server_forward_wall(s->server, priority, s->identifier, p, &s->ucred);
     281                 :            : 
     282                 :          0 :         m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(s->context);
     283   [ #  #  #  # ]:          0 :         iovec = newa(struct iovec, m);
     284                 :            : 
     285                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=stdout");
     286                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(s->id_field);
     287                 :            : 
     288                 :          0 :         syslog_priority[STRLEN("PRIORITY=")] = '0' + LOG_PRI(priority);
     289                 :          0 :         iovec[n++] = IOVEC_MAKE_STRING(syslog_priority);
     290                 :            : 
     291         [ #  # ]:          0 :         if (priority & LOG_FACMASK) {
     292         [ #  # ]:          0 :                 xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
     293                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(syslog_facility);
     294                 :            :         }
     295                 :            : 
     296         [ #  # ]:          0 :         if (s->identifier) {
     297                 :          0 :                 syslog_identifier = strjoin("SYSLOG_IDENTIFIER=", s->identifier);
     298         [ #  # ]:          0 :                 if (syslog_identifier)
     299                 :          0 :                         iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier);
     300                 :            :         }
     301                 :            : 
     302         [ #  # ]:          0 :         if (line_break != LINE_BREAK_NEWLINE) {
     303                 :            :                 const char *c;
     304                 :            : 
     305                 :            :                 /* If this log message was generated due to an uncommon line break then mention this in the log
     306                 :            :                  * entry */
     307                 :            : 
     308         [ #  # ]:          0 :                 c =     line_break == LINE_BREAK_NUL ?      "_LINE_BREAK=nul" :
     309         [ #  # ]:          0 :                         line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" :
     310                 :            :                                                             "_LINE_BREAK=eof";
     311                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(c);
     312                 :            :         }
     313                 :            : 
     314                 :          0 :         message = strjoin("MESSAGE=", p);
     315         [ #  # ]:          0 :         if (message)
     316                 :          0 :                 iovec[n++] = IOVEC_MAKE_STRING(message);
     317                 :            : 
     318                 :          0 :         server_dispatch_message(s->server, iovec, n, m, s->context, NULL, priority, 0);
     319                 :          0 :         return 0;
     320                 :            : }
     321                 :            : 
     322                 :          0 : static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) {
     323                 :            :         int r;
     324                 :            :         char *orig;
     325                 :            : 
     326         [ #  # ]:          0 :         assert(s);
     327         [ #  # ]:          0 :         assert(p);
     328                 :            : 
     329                 :          0 :         orig = p;
     330                 :          0 :         p = strstrip(p);
     331                 :            : 
     332                 :            :         /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */
     333   [ #  #  #  # ]:          0 :         if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) {
     334         [ #  # ]:          0 :                 log_warning("Control protocol line not properly terminated.");
     335                 :          0 :                 return -EINVAL;
     336                 :            :         }
     337                 :            : 
     338   [ #  #  #  #  :          0 :         switch (s->state) {
             #  #  #  #  
                      # ]
     339                 :            : 
     340                 :          0 :         case STDOUT_STREAM_IDENTIFIER:
     341         [ #  # ]:          0 :                 if (!isempty(p)) {
     342                 :          0 :                         s->identifier = strdup(p);
     343         [ #  # ]:          0 :                         if (!s->identifier)
     344                 :          0 :                                 return log_oom();
     345                 :            :                 }
     346                 :            : 
     347                 :          0 :                 s->state = STDOUT_STREAM_UNIT_ID;
     348                 :          0 :                 return 0;
     349                 :            : 
     350                 :          0 :         case STDOUT_STREAM_UNIT_ID:
     351         [ #  # ]:          0 :                 if (s->ucred.uid == 0 &&
     352         [ #  # ]:          0 :                     unit_name_is_valid(p, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
     353                 :            : 
     354                 :          0 :                         s->unit_id = strdup(p);
     355         [ #  # ]:          0 :                         if (!s->unit_id)
     356                 :          0 :                                 return log_oom();
     357                 :            :                 }
     358                 :            : 
     359                 :          0 :                 s->state = STDOUT_STREAM_PRIORITY;
     360                 :          0 :                 return 0;
     361                 :            : 
     362                 :          0 :         case STDOUT_STREAM_PRIORITY:
     363                 :          0 :                 r = safe_atoi(p, &s->priority);
     364   [ #  #  #  #  :          0 :                 if (r < 0 || s->priority < 0 || s->priority > 999) {
                   #  # ]
     365         [ #  # ]:          0 :                         log_warning("Failed to parse log priority line.");
     366                 :          0 :                         return -EINVAL;
     367                 :            :                 }
     368                 :            : 
     369                 :          0 :                 s->state = STDOUT_STREAM_LEVEL_PREFIX;
     370                 :          0 :                 return 0;
     371                 :            : 
     372                 :          0 :         case STDOUT_STREAM_LEVEL_PREFIX:
     373                 :          0 :                 r = parse_boolean(p);
     374         [ #  # ]:          0 :                 if (r < 0) {
     375         [ #  # ]:          0 :                         log_warning("Failed to parse level prefix line.");
     376                 :          0 :                         return -EINVAL;
     377                 :            :                 }
     378                 :            : 
     379                 :          0 :                 s->level_prefix = r;
     380                 :          0 :                 s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
     381                 :          0 :                 return 0;
     382                 :            : 
     383                 :          0 :         case STDOUT_STREAM_FORWARD_TO_SYSLOG:
     384                 :          0 :                 r = parse_boolean(p);
     385         [ #  # ]:          0 :                 if (r < 0) {
     386         [ #  # ]:          0 :                         log_warning("Failed to parse forward to syslog line.");
     387                 :          0 :                         return -EINVAL;
     388                 :            :                 }
     389                 :            : 
     390                 :          0 :                 s->forward_to_syslog = r;
     391                 :          0 :                 s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
     392                 :          0 :                 return 0;
     393                 :            : 
     394                 :          0 :         case STDOUT_STREAM_FORWARD_TO_KMSG:
     395                 :          0 :                 r = parse_boolean(p);
     396         [ #  # ]:          0 :                 if (r < 0) {
     397         [ #  # ]:          0 :                         log_warning("Failed to parse copy to kmsg line.");
     398                 :          0 :                         return -EINVAL;
     399                 :            :                 }
     400                 :            : 
     401                 :          0 :                 s->forward_to_kmsg = r;
     402                 :          0 :                 s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
     403                 :          0 :                 return 0;
     404                 :            : 
     405                 :          0 :         case STDOUT_STREAM_FORWARD_TO_CONSOLE:
     406                 :          0 :                 r = parse_boolean(p);
     407         [ #  # ]:          0 :                 if (r < 0) {
     408         [ #  # ]:          0 :                         log_warning("Failed to parse copy to console line.");
     409                 :          0 :                         return -EINVAL;
     410                 :            :                 }
     411                 :            : 
     412                 :          0 :                 s->forward_to_console = r;
     413                 :          0 :                 s->state = STDOUT_STREAM_RUNNING;
     414                 :            : 
     415                 :            :                 /* Try to save the stream, so that journald can be restarted and we can recover */
     416                 :          0 :                 (void) stdout_stream_save(s);
     417                 :          0 :                 return 0;
     418                 :            : 
     419                 :          0 :         case STDOUT_STREAM_RUNNING:
     420                 :          0 :                 return stdout_stream_log(s, orig, line_break);
     421                 :            :         }
     422                 :            : 
     423                 :          0 :         assert_not_reached("Unknown stream state");
     424                 :            : }
     425                 :            : 
     426                 :          0 : static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
     427                 :            :         char *p;
     428                 :            :         size_t remaining;
     429                 :            :         int r;
     430                 :            : 
     431         [ #  # ]:          0 :         assert(s);
     432                 :            : 
     433                 :          0 :         p = s->buffer;
     434                 :          0 :         remaining = s->length;
     435                 :            : 
     436                 :            :         /* XXX: This function does nothing if (s->length == 0) */
     437                 :            : 
     438                 :          0 :         for (;;) {
     439                 :            :                 LineBreak line_break;
     440                 :            :                 size_t skip;
     441                 :            :                 char *end1, *end2;
     442                 :            : 
     443                 :          0 :                 end1 = memchr(p, '\n', remaining);
     444         [ #  # ]:          0 :                 end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining);
     445                 :            : 
     446         [ #  # ]:          0 :                 if (end2) {
     447                 :            :                         /* We found a NUL terminator */
     448                 :          0 :                         skip = end2 - p + 1;
     449                 :          0 :                         line_break = LINE_BREAK_NUL;
     450         [ #  # ]:          0 :                 } else if (end1) {
     451                 :            :                         /* We found a \n terminator */
     452                 :          0 :                         *end1 = 0;
     453                 :          0 :                         skip = end1 - p + 1;
     454                 :          0 :                         line_break = LINE_BREAK_NEWLINE;
     455         [ #  # ]:          0 :                 } else if (remaining >= s->server->line_max) {
     456                 :            :                         /* Force a line break after the maximum line length */
     457                 :          0 :                         *(p + s->server->line_max) = 0;
     458                 :          0 :                         skip = remaining;
     459                 :          0 :                         line_break = LINE_BREAK_LINE_MAX;
     460                 :            :                 } else
     461                 :          0 :                         break;
     462                 :            : 
     463                 :          0 :                 r = stdout_stream_line(s, p, line_break);
     464         [ #  # ]:          0 :                 if (r < 0)
     465                 :          0 :                         return r;
     466                 :            : 
     467                 :          0 :                 remaining -= skip;
     468                 :          0 :                 p += skip;
     469                 :            :         }
     470                 :            : 
     471   [ #  #  #  # ]:          0 :         if (force_flush && remaining > 0) {
     472                 :          0 :                 p[remaining] = 0;
     473                 :          0 :                 r = stdout_stream_line(s, p, LINE_BREAK_EOF);
     474         [ #  # ]:          0 :                 if (r < 0)
     475                 :          0 :                         return r;
     476                 :            : 
     477                 :          0 :                 p += remaining;
     478                 :          0 :                 remaining = 0;
     479                 :            :         }
     480                 :            : 
     481         [ #  # ]:          0 :         if (p > s->buffer) {
     482                 :          0 :                 memmove(s->buffer, p, remaining);
     483                 :          0 :                 s->length = remaining;
     484                 :            :         }
     485                 :            : 
     486                 :          0 :         return 0;
     487                 :            : }
     488                 :            : 
     489                 :          0 : static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
     490                 :          0 :         StdoutStream *s = userdata;
     491                 :            :         size_t limit;
     492                 :            :         ssize_t l;
     493                 :            :         int r;
     494                 :            : 
     495         [ #  # ]:          0 :         assert(s);
     496                 :            : 
     497         [ #  # ]:          0 :         if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
     498         [ #  # ]:          0 :                 log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents);
     499                 :          0 :                 goto terminate;
     500                 :            :         }
     501                 :            : 
     502                 :            :         /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
     503         [ #  # ]:          0 :         if (s->length + 1 >= s->allocated) {
     504         [ #  # ]:          0 :                 if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) {
     505                 :          0 :                         log_oom();
     506                 :          0 :                         goto terminate;
     507                 :            :                 }
     508                 :            :         }
     509                 :            : 
     510                 :            :         /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also,
     511                 :            :          * always leave room for a terminating NUL we might need to add. */
     512                 :          0 :         limit = MIN(s->allocated - 1, s->server->line_max);
     513                 :            : 
     514                 :          0 :         l = read(s->fd, s->buffer + s->length, limit - s->length);
     515         [ #  # ]:          0 :         if (l < 0) {
     516         [ #  # ]:          0 :                 if (errno == EAGAIN)
     517                 :          0 :                         return 0;
     518                 :            : 
     519         [ #  # ]:          0 :                 log_warning_errno(errno, "Failed to read from stream: %m");
     520                 :          0 :                 goto terminate;
     521                 :            :         }
     522                 :            : 
     523         [ #  # ]:          0 :         if (l == 0) {
     524                 :          0 :                 stdout_stream_scan(s, true);
     525                 :          0 :                 goto terminate;
     526                 :            :         }
     527                 :            : 
     528                 :          0 :         s->length += l;
     529                 :          0 :         r = stdout_stream_scan(s, false);
     530         [ #  # ]:          0 :         if (r < 0)
     531                 :          0 :                 goto terminate;
     532                 :            : 
     533                 :          0 :         return 1;
     534                 :            : 
     535                 :          0 : terminate:
     536                 :          0 :         stdout_stream_destroy(s);
     537                 :          0 :         return 0;
     538                 :            : }
     539                 :            : 
     540                 :          0 : int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
     541                 :          0 :         _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
     542                 :            :         sd_id128_t id;
     543                 :            :         int r;
     544                 :            : 
     545         [ #  # ]:          0 :         assert(s);
     546         [ #  # ]:          0 :         assert(fd >= 0);
     547                 :            : 
     548                 :          0 :         r = sd_id128_randomize(&id);
     549         [ #  # ]:          0 :         if (r < 0)
     550         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate stream ID: %m");
     551                 :            : 
     552                 :          0 :         stream = new0(StdoutStream, 1);
     553         [ #  # ]:          0 :         if (!stream)
     554                 :          0 :                 return log_oom();
     555                 :            : 
     556                 :          0 :         stream->fd = -1;
     557                 :          0 :         stream->priority = LOG_INFO;
     558                 :            : 
     559         [ #  # ]:          0 :         xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
     560                 :            : 
     561                 :          0 :         r = getpeercred(fd, &stream->ucred);
     562         [ #  # ]:          0 :         if (r < 0)
     563         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to determine peer credentials: %m");
     564                 :            : 
     565         [ #  # ]:          0 :         if (mac_selinux_use()) {
     566                 :          0 :                 r = getpeersec(fd, &stream->label);
     567   [ #  #  #  # ]:          0 :                 if (r < 0 && r != -EOPNOTSUPP)
     568         [ #  # ]:          0 :                         (void) log_warning_errno(r, "Failed to determine peer security context: %m");
     569                 :            :         }
     570                 :            : 
     571                 :          0 :         (void) shutdown(fd, SHUT_WR);
     572                 :            : 
     573                 :          0 :         r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream);
     574         [ #  # ]:          0 :         if (r < 0)
     575         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add stream to event loop: %m");
     576                 :            : 
     577                 :          0 :         r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
     578         [ #  # ]:          0 :         if (r < 0)
     579         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to adjust stdout event source priority: %m");
     580                 :            : 
     581                 :          0 :         stream->fd = fd;
     582                 :            : 
     583                 :          0 :         stream->server = s;
     584   [ #  #  #  # ]:          0 :         LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
     585                 :          0 :         s->n_stdout_streams++;
     586                 :            : 
     587         [ #  # ]:          0 :         if (ret)
     588                 :          0 :                 *ret = stream;
     589                 :            : 
     590                 :          0 :         stream = NULL;
     591                 :            : 
     592                 :          0 :         return 0;
     593                 :            : }
     594                 :            : 
     595                 :          0 : static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) {
     596                 :          0 :         _cleanup_close_ int fd = -1;
     597                 :          0 :         Server *s = userdata;
     598                 :            :         int r;
     599                 :            : 
     600         [ #  # ]:          0 :         assert(s);
     601                 :            : 
     602         [ #  # ]:          0 :         if (revents != EPOLLIN)
     603         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EIO),
     604                 :            :                                        "Got invalid event from epoll for stdout server fd: %" PRIx32,
     605                 :            :                                        revents);
     606                 :            : 
     607                 :          0 :         fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
     608         [ #  # ]:          0 :         if (fd < 0) {
     609         [ #  # ]:          0 :                 if (ERRNO_IS_ACCEPT_AGAIN(errno))
     610                 :          0 :                         return 0;
     611                 :            : 
     612         [ #  # ]:          0 :                 return log_error_errno(errno, "Failed to accept stdout connection: %m");
     613                 :            :         }
     614                 :            : 
     615         [ #  # ]:          0 :         if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
     616                 :            :                 struct ucred u;
     617                 :            : 
     618                 :          0 :                 r = getpeercred(fd, &u);
     619                 :            : 
     620                 :            :                 /* By closing fd here we make sure that the client won't wait too long for journald to
     621                 :            :                  * gather all the data it adds to the error message to find out that the connection has
     622                 :            :                  * just been refused.
     623                 :            :                  */
     624                 :          0 :                 fd = safe_close(fd);
     625                 :            : 
     626         [ #  # ]:          0 :                 server_driver_message(s, r < 0 ? 0 : u.pid, NULL, LOG_MESSAGE("Too many stdout streams, refusing connection."), NULL);
     627                 :          0 :                 return 0;
     628                 :            :         }
     629                 :            : 
     630                 :          0 :         r = stdout_stream_install(s, fd, NULL);
     631         [ #  # ]:          0 :         if (r < 0)
     632                 :          0 :                 return r;
     633                 :            : 
     634                 :          0 :         fd = -1;
     635                 :          0 :         return 0;
     636                 :            : }
     637                 :            : 
     638                 :          0 : static int stdout_stream_load(StdoutStream *stream, const char *fname) {
     639                 :            :         _cleanup_free_ char
     640                 :          0 :                 *priority = NULL,
     641                 :          0 :                 *level_prefix = NULL,
     642                 :          0 :                 *forward_to_syslog = NULL,
     643                 :          0 :                 *forward_to_kmsg = NULL,
     644                 :          0 :                 *forward_to_console = NULL,
     645                 :          0 :                 *stream_id = NULL;
     646                 :            :         int r;
     647                 :            : 
     648         [ #  # ]:          0 :         assert(stream);
     649         [ #  # ]:          0 :         assert(fname);
     650                 :            : 
     651         [ #  # ]:          0 :         if (!stream->state_file) {
     652                 :          0 :                 stream->state_file = path_join("/run/systemd/journal/streams", fname);
     653         [ #  # ]:          0 :                 if (!stream->state_file)
     654                 :          0 :                         return log_oom();
     655                 :            :         }
     656                 :            : 
     657                 :          0 :         r = parse_env_file(NULL, stream->state_file,
     658                 :            :                            "PRIORITY", &priority,
     659                 :            :                            "LEVEL_PREFIX", &level_prefix,
     660                 :            :                            "FORWARD_TO_SYSLOG", &forward_to_syslog,
     661                 :            :                            "FORWARD_TO_KMSG", &forward_to_kmsg,
     662                 :            :                            "FORWARD_TO_CONSOLE", &forward_to_console,
     663                 :            :                            "IDENTIFIER", &stream->identifier,
     664                 :            :                            "UNIT", &stream->unit_id,
     665                 :            :                            "STREAM_ID", &stream_id);
     666         [ #  # ]:          0 :         if (r < 0)
     667         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to read: %s", stream->state_file);
     668                 :            : 
     669         [ #  # ]:          0 :         if (priority) {
     670                 :            :                 int p;
     671                 :            : 
     672                 :          0 :                 p = log_level_from_string(priority);
     673         [ #  # ]:          0 :                 if (p >= 0)
     674                 :          0 :                         stream->priority = p;
     675                 :            :         }
     676                 :            : 
     677         [ #  # ]:          0 :         if (level_prefix) {
     678                 :          0 :                 r = parse_boolean(level_prefix);
     679         [ #  # ]:          0 :                 if (r >= 0)
     680                 :          0 :                         stream->level_prefix = r;
     681                 :            :         }
     682                 :            : 
     683         [ #  # ]:          0 :         if (forward_to_syslog) {
     684                 :          0 :                 r = parse_boolean(forward_to_syslog);
     685         [ #  # ]:          0 :                 if (r >= 0)
     686                 :          0 :                         stream->forward_to_syslog = r;
     687                 :            :         }
     688                 :            : 
     689         [ #  # ]:          0 :         if (forward_to_kmsg) {
     690                 :          0 :                 r = parse_boolean(forward_to_kmsg);
     691         [ #  # ]:          0 :                 if (r >= 0)
     692                 :          0 :                         stream->forward_to_kmsg = r;
     693                 :            :         }
     694                 :            : 
     695         [ #  # ]:          0 :         if (forward_to_console) {
     696                 :          0 :                 r = parse_boolean(forward_to_console);
     697         [ #  # ]:          0 :                 if (r >= 0)
     698                 :          0 :                         stream->forward_to_console = r;
     699                 :            :         }
     700                 :            : 
     701         [ #  # ]:          0 :         if (stream_id) {
     702                 :            :                 sd_id128_t id;
     703                 :            : 
     704                 :          0 :                 r = sd_id128_from_string(stream_id, &id);
     705         [ #  # ]:          0 :                 if (r >= 0)
     706         [ #  # ]:          0 :                         xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id));
     707                 :            :         }
     708                 :            : 
     709                 :          0 :         return 0;
     710                 :            : }
     711                 :            : 
     712                 :          0 : static int stdout_stream_restore(Server *s, const char *fname, int fd) {
     713                 :            :         StdoutStream *stream;
     714                 :            :         int r;
     715                 :            : 
     716         [ #  # ]:          0 :         assert(s);
     717         [ #  # ]:          0 :         assert(fname);
     718         [ #  # ]:          0 :         assert(fd >= 0);
     719                 :            : 
     720         [ #  # ]:          0 :         if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
     721         [ #  # ]:          0 :                 log_warning("Too many stdout streams, refusing restoring of stream.");
     722                 :          0 :                 return -ENOBUFS;
     723                 :            :         }
     724                 :            : 
     725                 :          0 :         r = stdout_stream_install(s, fd, &stream);
     726         [ #  # ]:          0 :         if (r < 0)
     727                 :          0 :                 return r;
     728                 :            : 
     729                 :          0 :         stream->state = STDOUT_STREAM_RUNNING;
     730                 :          0 :         stream->fdstore = true;
     731                 :            : 
     732                 :            :         /* Ignore all parsing errors */
     733                 :          0 :         (void) stdout_stream_load(stream, fname);
     734                 :            : 
     735                 :          0 :         return 0;
     736                 :            : }
     737                 :            : 
     738                 :          0 : int server_restore_streams(Server *s, FDSet *fds) {
     739                 :          0 :         _cleanup_closedir_ DIR *d = NULL;
     740                 :            :         struct dirent *de;
     741                 :            :         int r;
     742                 :            : 
     743                 :          0 :         d = opendir("/run/systemd/journal/streams");
     744         [ #  # ]:          0 :         if (!d) {
     745         [ #  # ]:          0 :                 if (errno == ENOENT)
     746                 :          0 :                         return 0;
     747                 :            : 
     748         [ #  # ]:          0 :                 return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m");
     749                 :            :         }
     750                 :            : 
     751   [ #  #  #  #  :          0 :         FOREACH_DIRENT(de, d, goto fail) {
                   #  # ]
     752                 :            :                 unsigned long st_dev, st_ino;
     753                 :          0 :                 bool found = false;
     754                 :            :                 Iterator i;
     755                 :            :                 int fd;
     756                 :            : 
     757         [ #  # ]:          0 :                 if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2)
     758                 :          0 :                         continue;
     759                 :            : 
     760         [ #  # ]:          0 :                 FDSET_FOREACH(fd, fds, i) {
     761                 :            :                         struct stat st;
     762                 :            : 
     763         [ #  # ]:          0 :                         if (fstat(fd, &st) < 0)
     764         [ #  # ]:          0 :                                 return log_error_errno(errno, "Failed to stat %s: %m", de->d_name);
     765                 :            : 
     766   [ #  #  #  #  :          0 :                         if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) {
                   #  # ]
     767                 :          0 :                                 found = true;
     768                 :          0 :                                 break;
     769                 :            :                         }
     770                 :            :                 }
     771                 :            : 
     772         [ #  # ]:          0 :                 if (!found) {
     773                 :            :                         /* No file descriptor? Then let's delete the state file */
     774         [ #  # ]:          0 :                         log_debug("Cannot restore stream file %s", de->d_name);
     775         [ #  # ]:          0 :                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
     776         [ #  # ]:          0 :                                 log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m",
     777                 :            :                                                   de->d_name);
     778                 :          0 :                         continue;
     779                 :            :                 }
     780                 :            : 
     781                 :          0 :                 fdset_remove(fds, fd);
     782                 :            : 
     783                 :          0 :                 r = stdout_stream_restore(s, de->d_name, fd);
     784         [ #  # ]:          0 :                 if (r < 0)
     785                 :          0 :                         safe_close(fd);
     786                 :            :         }
     787                 :            : 
     788                 :          0 :         return 0;
     789                 :            : 
     790                 :          0 : fail:
     791         [ #  # ]:          0 :         return log_error_errno(errno, "Failed to read streams directory: %m");
     792                 :            : }
     793                 :            : 
     794                 :          0 : int server_open_stdout_socket(Server *s) {
     795                 :            :         static const union sockaddr_union sa = {
     796                 :            :                 .un.sun_family = AF_UNIX,
     797                 :            :                 .un.sun_path = "/run/systemd/journal/stdout",
     798                 :            :         };
     799                 :            :         int r;
     800                 :            : 
     801         [ #  # ]:          0 :         assert(s);
     802                 :            : 
     803         [ #  # ]:          0 :         if (s->stdout_fd < 0) {
     804                 :          0 :                 s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     805         [ #  # ]:          0 :                 if (s->stdout_fd < 0)
     806         [ #  # ]:          0 :                         return log_error_errno(errno, "socket() failed: %m");
     807                 :            : 
     808                 :          0 :                 (void) sockaddr_un_unlink(&sa.un);
     809                 :            : 
     810   [ #  #  #  # ]:          0 :                 r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
     811         [ #  # ]:          0 :                 if (r < 0)
     812         [ #  # ]:          0 :                         return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
     813                 :            : 
     814                 :          0 :                 (void) chmod(sa.un.sun_path, 0666);
     815                 :            : 
     816         [ #  # ]:          0 :                 if (listen(s->stdout_fd, SOMAXCONN) < 0)
     817         [ #  # ]:          0 :                         return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path);
     818                 :            :         } else
     819                 :          0 :                 (void) fd_nonblock(s->stdout_fd, true);
     820                 :            : 
     821                 :          0 :         r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s);
     822         [ #  # ]:          0 :         if (r < 0)
     823         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
     824                 :            : 
     825                 :          0 :         r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5);
     826         [ #  # ]:          0 :         if (r < 0)
     827         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
     828                 :            : 
     829                 :          0 :         return 0;
     830                 :            : }
     831                 :            : 
     832                 :          0 : void stdout_stream_send_notify(StdoutStream *s) {
     833                 :          0 :         struct iovec iovec = {
     834                 :            :                 .iov_base = (char*) "FDSTORE=1",
     835                 :            :                 .iov_len = STRLEN("FDSTORE=1"),
     836                 :            :         };
     837                 :          0 :         struct msghdr msghdr = {
     838                 :            :                 .msg_iov = &iovec,
     839                 :            :                 .msg_iovlen = 1,
     840                 :            :         };
     841                 :            :         struct cmsghdr *cmsg;
     842                 :            :         ssize_t l;
     843                 :            : 
     844         [ #  # ]:          0 :         assert(s);
     845         [ #  # ]:          0 :         assert(!s->fdstore);
     846         [ #  # ]:          0 :         assert(s->in_notify_queue);
     847         [ #  # ]:          0 :         assert(s->server);
     848         [ #  # ]:          0 :         assert(s->server->notify_fd >= 0);
     849                 :            : 
     850                 :            :         /* Store the connection fd in PID 1, so that we get it passed
     851                 :            :          * in again on next start */
     852                 :            : 
     853                 :          0 :         msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
     854         [ #  # ]:          0 :         msghdr.msg_control = alloca0(msghdr.msg_controllen);
     855                 :            : 
     856         [ #  # ]:          0 :         cmsg = CMSG_FIRSTHDR(&msghdr);
     857                 :          0 :         cmsg->cmsg_level = SOL_SOCKET;
     858                 :          0 :         cmsg->cmsg_type = SCM_RIGHTS;
     859                 :          0 :         cmsg->cmsg_len = CMSG_LEN(sizeof(int));
     860                 :            : 
     861                 :          0 :         memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int));
     862                 :            : 
     863                 :          0 :         l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL);
     864         [ #  # ]:          0 :         if (l < 0) {
     865         [ #  # ]:          0 :                 if (errno == EAGAIN)
     866                 :          0 :                         return;
     867                 :            : 
     868         [ #  # ]:          0 :                 log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m");
     869                 :            :         } else {
     870         [ #  # ]:          0 :                 log_debug("Successfully sent stream file descriptor to service manager.");
     871                 :          0 :                 s->fdstore = 1;
     872                 :            :         }
     873                 :            : 
     874   [ #  #  #  #  :          0 :         LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
             #  #  #  # ]
     875                 :          0 :         s->in_notify_queue = false;
     876                 :            : 
     877                 :            : }

Generated by: LCOV version 1.14