LCOV - code coverage report
Current view: top level - journal - journald-stream.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 447 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 15 0.0 %

          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