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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <stddef.h>
       4                 :            : #include <sys/epoll.h>
       5                 :            : #include <sys/mman.h>
       6                 :            : #include <sys/statvfs.h>
       7                 :            : #include <unistd.h>
       8                 :            : 
       9                 :            : #include "alloc-util.h"
      10                 :            : #include "fd-util.h"
      11                 :            : #include "fs-util.h"
      12                 :            : #include "io-util.h"
      13                 :            : #include "journal-importer.h"
      14                 :            : #include "journal-util.h"
      15                 :            : #include "journald-console.h"
      16                 :            : #include "journald-kmsg.h"
      17                 :            : #include "journald-native.h"
      18                 :            : #include "journald-server.h"
      19                 :            : #include "journald-syslog.h"
      20                 :            : #include "journald-wall.h"
      21                 :            : #include "memfd-util.h"
      22                 :            : #include "memory-util.h"
      23                 :            : #include "parse-util.h"
      24                 :            : #include "path-util.h"
      25                 :            : #include "process-util.h"
      26                 :            : #include "selinux-util.h"
      27                 :            : #include "socket-util.h"
      28                 :            : #include "string-util.h"
      29                 :            : #include "strv.h"
      30                 :            : #include "unaligned.h"
      31                 :            : 
      32                 :          0 : static bool allow_object_pid(const struct ucred *ucred) {
      33   [ #  #  #  # ]:          0 :         return ucred && ucred->uid == 0;
      34                 :            : }
      35                 :            : 
      36                 :          0 : static void server_process_entry_meta(
      37                 :            :                 const char *p, size_t l,
      38                 :            :                 const struct ucred *ucred,
      39                 :            :                 int *priority,
      40                 :            :                 char **identifier,
      41                 :            :                 char **message,
      42                 :            :                 pid_t *object_pid) {
      43                 :            : 
      44                 :            :         /* We need to determine the priority of this entry for the rate limiting logic */
      45                 :            : 
      46   [ #  #  #  # ]:          0 :         if (l == 10 &&
      47                 :          0 :             startswith(p, "PRIORITY=") &&
      48   [ #  #  #  # ]:          0 :             p[9] >= '0' && p[9] <= '9')
      49                 :          0 :                 *priority = (*priority & LOG_FACMASK) | (p[9] - '0');
      50                 :            : 
      51   [ #  #  #  # ]:          0 :         else if (l == 17 &&
      52                 :          0 :                  startswith(p, "SYSLOG_FACILITY=") &&
      53   [ #  #  #  # ]:          0 :                  p[16] >= '0' && p[16] <= '9')
      54                 :          0 :                 *priority = (*priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
      55                 :            : 
      56   [ #  #  #  # ]:          0 :         else if (l == 18 &&
      57                 :          0 :                  startswith(p, "SYSLOG_FACILITY=") &&
      58   [ #  #  #  # ]:          0 :                  p[16] >= '0' && p[16] <= '9' &&
      59   [ #  #  #  # ]:          0 :                  p[17] >= '0' && p[17] <= '9')
      60                 :          0 :                 *priority = (*priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
      61                 :            : 
      62   [ #  #  #  # ]:          0 :         else if (l >= 19 &&
      63                 :          0 :                  startswith(p, "SYSLOG_IDENTIFIER=")) {
      64                 :            :                 char *t;
      65                 :            : 
      66                 :          0 :                 t = memdup_suffix0(p + 18, l - 18);
      67         [ #  # ]:          0 :                 if (t) {
      68                 :          0 :                         free(*identifier);
      69                 :          0 :                         *identifier = t;
      70                 :            :                 }
      71                 :            : 
      72   [ #  #  #  # ]:          0 :         } else if (l >= 8 &&
      73                 :          0 :                    startswith(p, "MESSAGE=")) {
      74                 :            :                 char *t;
      75                 :            : 
      76                 :          0 :                 t = memdup_suffix0(p + 8, l - 8);
      77         [ #  # ]:          0 :                 if (t) {
      78                 :          0 :                         free(*message);
      79                 :          0 :                         *message = t;
      80                 :            :                 }
      81                 :            : 
      82   [ #  #  #  # ]:          0 :         } else if (l > STRLEN("OBJECT_PID=") &&
      83         [ #  # ]:          0 :                    l < STRLEN("OBJECT_PID=")  + DECIMAL_STR_MAX(pid_t) &&
      84         [ #  # ]:          0 :                    startswith(p, "OBJECT_PID=") &&
      85                 :          0 :                    allow_object_pid(ucred)) {
      86                 :            :                 char buf[DECIMAL_STR_MAX(pid_t)];
      87                 :          0 :                 memcpy(buf, p + STRLEN("OBJECT_PID="),
      88                 :            :                        l - STRLEN("OBJECT_PID="));
      89                 :          0 :                 buf[l-STRLEN("OBJECT_PID=")] = '\0';
      90                 :            : 
      91                 :          0 :                 (void) parse_pid(buf, object_pid);
      92                 :            :         }
      93                 :          0 : }
      94                 :            : 
      95                 :          0 : static int server_process_entry(
      96                 :            :                 Server *s,
      97                 :            :                 const void *buffer, size_t *remaining,
      98                 :            :                 ClientContext *context,
      99                 :            :                 const struct ucred *ucred,
     100                 :            :                 const struct timeval *tv,
     101                 :            :                 const char *label, size_t label_len) {
     102                 :            : 
     103                 :            :         /* Process a single entry from a native message. Returns 0 if nothing special happened and the message
     104                 :            :          * processing should continue, and a negative or positive value otherwise.
     105                 :            :          *
     106                 :            :          * Note that *remaining is altered on both success and failure. */
     107                 :            : 
     108                 :          0 :         size_t n = 0, j, tn = (size_t) -1, m = 0, entry_size = 0;
     109                 :          0 :         char *identifier = NULL, *message = NULL;
     110                 :          0 :         struct iovec *iovec = NULL;
     111                 :          0 :         int priority = LOG_INFO;
     112                 :          0 :         pid_t object_pid = 0;
     113                 :            :         const char *p;
     114                 :          0 :         int r = 1;
     115                 :            : 
     116                 :          0 :         p = buffer;
     117                 :            : 
     118         [ #  # ]:          0 :         while (*remaining > 0) {
     119                 :            :                 const char *e, *q;
     120                 :            : 
     121                 :          0 :                 e = memchr(p, '\n', *remaining);
     122                 :            : 
     123         [ #  # ]:          0 :                 if (!e) {
     124                 :            :                         /* Trailing noise, let's ignore it, and flush what we collected */
     125         [ #  # ]:          0 :                         log_debug("Received message with trailing noise, ignoring.");
     126                 :          0 :                         break; /* finish processing of the message */
     127                 :            :                 }
     128                 :            : 
     129         [ #  # ]:          0 :                 if (e == p) {
     130                 :            :                         /* Entry separator */
     131                 :          0 :                         *remaining -= 1;
     132                 :          0 :                         break;
     133                 :            :                 }
     134                 :            : 
     135   [ #  #  #  # ]:          0 :                 if (IN_SET(*p, '.', '#')) {
     136                 :            :                         /* Ignore control commands for now, and comments too. */
     137                 :          0 :                         *remaining -= (e - p) + 1;
     138                 :          0 :                         p = e + 1;
     139                 :          0 :                         continue;
     140                 :            :                 }
     141                 :            : 
     142                 :            :                 /* A property follows */
     143         [ #  # ]:          0 :                 if (n > ENTRY_FIELD_COUNT_MAX) {
     144         [ #  # ]:          0 :                         log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry.");
     145                 :          0 :                         goto finish;
     146                 :            :                 }
     147                 :            : 
     148                 :            :                 /* n existing properties, 1 new, +1 for _TRANSPORT */
     149         [ #  # ]:          0 :                 if (!GREEDY_REALLOC(iovec, m,
     150                 :            :                                     n + 2 +
     151                 :            :                                     N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS +
     152                 :            :                                     client_context_extra_fields_n_iovec(context))) {
     153                 :          0 :                         r = log_oom();
     154                 :          0 :                         goto finish;
     155                 :            :                 }
     156                 :            : 
     157                 :          0 :                 q = memchr(p, '=', e - p);
     158         [ #  # ]:          0 :                 if (q) {
     159         [ #  # ]:          0 :                         if (journal_field_valid(p, q - p, false)) {
     160                 :            :                                 size_t l;
     161                 :            : 
     162                 :          0 :                                 l = e - p;
     163         [ #  # ]:          0 :                                 if (l > DATA_SIZE_MAX) {
     164         [ #  # ]:          0 :                                         log_debug("Received text block of %zu bytes is too large, ignoring entry.", l);
     165                 :          0 :                                         goto finish;
     166                 :            :                                 }
     167                 :            : 
     168         [ #  # ]:          0 :                                 if (entry_size + l + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
     169         [ #  # ]:          0 :                                         log_debug("Entry is too big (%zu bytes after processing %zu entries), ignoring entry.",
     170                 :            :                                                   entry_size + l, n + 1);
     171                 :          0 :                                         goto finish;
     172                 :            :                                 }
     173                 :            : 
     174                 :            :                                 /* If the field name starts with an underscore, skip the variable, since that indicates
     175                 :            :                                  * a trusted field */
     176                 :          0 :                                 iovec[n++] = IOVEC_MAKE((char*) p, l);
     177                 :          0 :                                 entry_size += l;
     178                 :            : 
     179                 :          0 :                                 server_process_entry_meta(p, l, ucred,
     180                 :            :                                                           &priority,
     181                 :            :                                                           &identifier,
     182                 :            :                                                           &message,
     183                 :            :                                                           &object_pid);
     184                 :            :                         }
     185                 :            : 
     186                 :          0 :                         *remaining -= (e - p) + 1;
     187                 :          0 :                         p = e + 1;
     188                 :          0 :                         continue;
     189                 :            :                 } else {
     190                 :            :                         uint64_t l, total;
     191                 :            :                         char *k;
     192                 :            : 
     193         [ #  # ]:          0 :                         if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) {
     194         [ #  # ]:          0 :                                 log_debug("Failed to parse message, ignoring.");
     195                 :          0 :                                 break;
     196                 :            :                         }
     197                 :            : 
     198                 :          0 :                         l = unaligned_read_le64(e + 1);
     199         [ #  # ]:          0 :                         if (l > DATA_SIZE_MAX) {
     200         [ #  # ]:          0 :                                 log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", l);
     201                 :          0 :                                 goto finish;
     202                 :            :                         }
     203                 :            : 
     204                 :          0 :                         total = (e - p) + 1 + l;
     205         [ #  # ]:          0 :                         if (entry_size + total + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
     206         [ #  # ]:          0 :                                 log_debug("Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.",
     207                 :            :                                           entry_size + total, n + 1);
     208                 :          0 :                                 goto finish;
     209                 :            :                         }
     210                 :            : 
     211         [ #  # ]:          0 :                         if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
     212         [ #  # ]:          0 :                             e[1+sizeof(uint64_t)+l] != '\n') {
     213         [ #  # ]:          0 :                                 log_debug("Failed to parse message, ignoring.");
     214                 :          0 :                                 break;
     215                 :            :                         }
     216                 :            : 
     217                 :          0 :                         k = malloc(total);
     218         [ #  # ]:          0 :                         if (!k) {
     219                 :          0 :                                 log_oom();
     220                 :          0 :                                 break;
     221                 :            :                         }
     222                 :            : 
     223                 :          0 :                         memcpy(k, p, e - p);
     224                 :          0 :                         k[e - p] = '=';
     225                 :          0 :                         memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
     226                 :            : 
     227         [ #  # ]:          0 :                         if (journal_field_valid(p, e - p, false)) {
     228                 :          0 :                                 iovec[n] = IOVEC_MAKE(k, (e - p) + 1 + l);
     229                 :          0 :                                 entry_size += iovec[n].iov_len;
     230                 :          0 :                                 n++;
     231                 :            : 
     232                 :          0 :                                 server_process_entry_meta(k, (e - p) + 1 + l, ucred,
     233                 :            :                                                           &priority,
     234                 :            :                                                           &identifier,
     235                 :            :                                                           &message,
     236                 :            :                                                           &object_pid);
     237                 :            :                         } else
     238                 :          0 :                                 free(k);
     239                 :            : 
     240                 :          0 :                         *remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
     241                 :          0 :                         p = e + 1 + sizeof(uint64_t) + l + 1;
     242                 :            :                 }
     243                 :            :         }
     244                 :            : 
     245         [ #  # ]:          0 :         if (n <= 0)
     246                 :          0 :                 goto finish;
     247                 :            : 
     248                 :          0 :         tn = n++;
     249                 :          0 :         iovec[tn] = IOVEC_MAKE_STRING("_TRANSPORT=journal");
     250                 :          0 :         entry_size += STRLEN("_TRANSPORT=journal");
     251                 :            : 
     252         [ #  # ]:          0 :         if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
     253         [ #  # ]:          0 :                 log_debug("Entry is too big with %zu properties and %zu bytes, ignoring.", n, entry_size);
     254                 :          0 :                 goto finish;
     255                 :            :         }
     256                 :            : 
     257                 :          0 :         r = 0; /* Success, we read the message. */
     258                 :            : 
     259         [ #  # ]:          0 :         if (!client_context_test_priority(context, priority))
     260                 :          0 :                 goto finish;
     261                 :            : 
     262         [ #  # ]:          0 :         if (message) {
     263         [ #  # ]:          0 :                 if (s->forward_to_syslog)
     264                 :          0 :                         server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv);
     265                 :            : 
     266         [ #  # ]:          0 :                 if (s->forward_to_kmsg)
     267                 :          0 :                         server_forward_kmsg(s, priority, identifier, message, ucred);
     268                 :            : 
     269         [ #  # ]:          0 :                 if (s->forward_to_console)
     270                 :          0 :                         server_forward_console(s, priority, identifier, message, ucred);
     271                 :            : 
     272         [ #  # ]:          0 :                 if (s->forward_to_wall)
     273                 :          0 :                         server_forward_wall(s, priority, identifier, message, ucred);
     274                 :            :         }
     275                 :            : 
     276                 :          0 :         server_dispatch_message(s, iovec, n, m, context, tv, priority, object_pid);
     277                 :            : 
     278                 :          0 : finish:
     279         [ #  # ]:          0 :         for (j = 0; j < n; j++)  {
     280         [ #  # ]:          0 :                 if (j == tn)
     281                 :          0 :                         continue;
     282                 :            : 
     283         [ #  # ]:          0 :                 if (iovec[j].iov_base < buffer ||
     284         [ #  # ]:          0 :                     (const char*) iovec[j].iov_base >= p + *remaining)
     285                 :          0 :                         free(iovec[j].iov_base);
     286                 :            :         }
     287                 :            : 
     288                 :          0 :         free(iovec);
     289                 :          0 :         free(identifier);
     290                 :          0 :         free(message);
     291                 :            : 
     292                 :          0 :         return r;
     293                 :            : }
     294                 :            : 
     295                 :          0 : void server_process_native_message(
     296                 :            :                 Server *s,
     297                 :            :                 const char *buffer, size_t buffer_size,
     298                 :            :                 const struct ucred *ucred,
     299                 :            :                 const struct timeval *tv,
     300                 :            :                 const char *label, size_t label_len) {
     301                 :            : 
     302                 :          0 :         size_t remaining = buffer_size;
     303                 :          0 :         ClientContext *context = NULL;
     304                 :            :         int r;
     305                 :            : 
     306         [ #  # ]:          0 :         assert(s);
     307   [ #  #  #  # ]:          0 :         assert(buffer || buffer_size == 0);
     308                 :            : 
     309   [ #  #  #  # ]:          0 :         if (ucred && pid_is_valid(ucred->pid)) {
     310                 :          0 :                 r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context);
     311         [ #  # ]:          0 :                 if (r < 0)
     312         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid);
     313                 :            :         }
     314                 :            : 
     315                 :            :         do {
     316                 :          0 :                 r = server_process_entry(s,
     317                 :          0 :                                          (const uint8_t*) buffer + (buffer_size - remaining), &remaining,
     318                 :            :                                          context, ucred, tv, label, label_len);
     319         [ #  # ]:          0 :         } while (r == 0);
     320                 :          0 : }
     321                 :            : 
     322                 :          0 : void server_process_native_file(
     323                 :            :                 Server *s,
     324                 :            :                 int fd,
     325                 :            :                 const struct ucred *ucred,
     326                 :            :                 const struct timeval *tv,
     327                 :            :                 const char *label, size_t label_len) {
     328                 :            : 
     329                 :            :         struct stat st;
     330                 :            :         bool sealed;
     331                 :            :         int r;
     332                 :            : 
     333                 :            :         /* Data is in the passed fd, probably it didn't fit in a datagram. */
     334                 :            : 
     335         [ #  # ]:          0 :         assert(s);
     336         [ #  # ]:          0 :         assert(fd >= 0);
     337                 :            : 
     338                 :            :         /* If it's a memfd, check if it is sealed. If so, we can just
     339                 :            :          * mmap it and use it, and do not need to copy the data out. */
     340                 :          0 :         sealed = memfd_get_sealed(fd) > 0;
     341                 :            : 
     342   [ #  #  #  #  :          0 :         if (!sealed && (!ucred || ucred->uid != 0)) {
                   #  # ]
     343         [ #  # ]:          0 :                 _cleanup_free_ char *k = NULL;
     344                 :            :                 const char *e;
     345                 :            : 
     346                 :            :                 /* If this is not a sealed memfd, and the peer is unknown or
     347                 :            :                  * unprivileged, then verify the path. */
     348                 :            : 
     349                 :          0 :                 r = fd_get_path(fd, &k);
     350         [ #  # ]:          0 :                 if (r < 0) {
     351         [ #  # ]:          0 :                         log_error_errno(r, "readlink(/proc/self/fd/%i) failed: %m", fd);
     352                 :          0 :                         return;
     353                 :            :                 }
     354                 :            : 
     355                 :          0 :                 e = PATH_STARTSWITH_SET(k, "/dev/shm/", "/tmp/", "/var/tmp/");
     356         [ #  # ]:          0 :                 if (!e) {
     357         [ #  # ]:          0 :                         log_error("Received file outside of allowed directories. Refusing.");
     358                 :          0 :                         return;
     359                 :            :                 }
     360                 :            : 
     361         [ #  # ]:          0 :                 if (!filename_is_valid(e)) {
     362         [ #  # ]:          0 :                         log_error("Received file in subdirectory of allowed directories. Refusing.");
     363                 :          0 :                         return;
     364                 :            :                 }
     365                 :            :         }
     366                 :            : 
     367         [ #  # ]:          0 :         if (fstat(fd, &st) < 0) {
     368         [ #  # ]:          0 :                 log_error_errno(errno, "Failed to stat passed file, ignoring: %m");
     369                 :          0 :                 return;
     370                 :            :         }
     371                 :            : 
     372         [ #  # ]:          0 :         if (!S_ISREG(st.st_mode)) {
     373         [ #  # ]:          0 :                 log_error("File passed is not regular. Ignoring.");
     374                 :          0 :                 return;
     375                 :            :         }
     376                 :            : 
     377         [ #  # ]:          0 :         if (st.st_size <= 0)
     378                 :          0 :                 return;
     379                 :            : 
     380                 :            :         /* When !sealed, set a lower memory limit. We have to read the file,
     381                 :            :          * effectively doubling memory use. */
     382   [ #  #  #  # ]:          0 :         if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) {
     383         [ #  # ]:          0 :                 log_error("File passed too large (%"PRIu64" bytes). Ignoring.", (uint64_t) st.st_size);
     384                 :          0 :                 return;
     385                 :            :         }
     386                 :            : 
     387         [ #  # ]:          0 :         if (sealed) {
     388                 :            :                 void *p;
     389                 :            :                 size_t ps;
     390                 :            : 
     391                 :            :                 /* The file is sealed, we can just map it and use it. */
     392                 :            : 
     393                 :          0 :                 ps = PAGE_ALIGN(st.st_size);
     394                 :          0 :                 p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0);
     395         [ #  # ]:          0 :                 if (p == MAP_FAILED) {
     396         [ #  # ]:          0 :                         log_error_errno(errno, "Failed to map memfd, ignoring: %m");
     397                 :          0 :                         return;
     398                 :            :                 }
     399                 :            : 
     400                 :          0 :                 server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len);
     401         [ #  # ]:          0 :                 assert_se(munmap(p, ps) >= 0);
     402                 :            :         } else {
     403         [ #  # ]:          0 :                 _cleanup_free_ void *p = NULL;
     404                 :            :                 struct statvfs vfs;
     405                 :            :                 ssize_t n;
     406                 :            : 
     407         [ #  # ]:          0 :                 if (fstatvfs(fd, &vfs) < 0) {
     408         [ #  # ]:          0 :                         log_error_errno(errno, "Failed to stat file system of passed file, not processing it: %m");
     409                 :          0 :                         return;
     410                 :            :                 }
     411                 :            : 
     412                 :            :                 /* Refuse operating on file systems that have
     413                 :            :                  * mandatory locking enabled, see:
     414                 :            :                  *
     415                 :            :                  * https://github.com/systemd/systemd/issues/1822
     416                 :            :                  */
     417         [ #  # ]:          0 :                 if (vfs.f_flag & ST_MANDLOCK) {
     418         [ #  # ]:          0 :                         log_error("Received file descriptor from file system with mandatory locking enabled, not processing it.");
     419                 :          0 :                         return;
     420                 :            :                 }
     421                 :            : 
     422                 :            :                 /* Make the fd non-blocking. On regular files this has
     423                 :            :                  * the effect of bypassing mandatory locking. Of
     424                 :            :                  * course, this should normally not be necessary given
     425                 :            :                  * the check above, but let's better be safe than
     426                 :            :                  * sorry, after all NFS is pretty confusing regarding
     427                 :            :                  * file system flags, and we better don't trust it,
     428                 :            :                  * and so is SMB. */
     429                 :          0 :                 r = fd_nonblock(fd, true);
     430         [ #  # ]:          0 :                 if (r < 0) {
     431         [ #  # ]:          0 :                         log_error_errno(r, "Failed to make fd non-blocking, not processing it: %m");
     432                 :          0 :                         return;
     433                 :            :                 }
     434                 :            : 
     435                 :            :                 /* The file is not sealed, we can't map the file here, since
     436                 :            :                  * clients might then truncate it and trigger a SIGBUS for
     437                 :            :                  * us. So let's stupidly read it. */
     438                 :            : 
     439                 :          0 :                 p = malloc(st.st_size);
     440         [ #  # ]:          0 :                 if (!p) {
     441                 :          0 :                         log_oom();
     442                 :          0 :                         return;
     443                 :            :                 }
     444                 :            : 
     445                 :          0 :                 n = pread(fd, p, st.st_size, 0);
     446         [ #  # ]:          0 :                 if (n < 0)
     447         [ #  # ]:          0 :                         log_error_errno(errno, "Failed to read file, ignoring: %m");
     448         [ #  # ]:          0 :                 else if (n > 0)
     449                 :          0 :                         server_process_native_message(s, p, n, ucred, tv, label, label_len);
     450                 :            :         }
     451                 :            : }
     452                 :            : 
     453                 :          0 : int server_open_native_socket(Server *s) {
     454                 :            : 
     455                 :            :         static const union sockaddr_union sa = {
     456                 :            :                 .un.sun_family = AF_UNIX,
     457                 :            :                 .un.sun_path = "/run/systemd/journal/socket",
     458                 :            :         };
     459                 :            :         int r;
     460                 :            : 
     461         [ #  # ]:          0 :         assert(s);
     462                 :            : 
     463         [ #  # ]:          0 :         if (s->native_fd < 0) {
     464                 :          0 :                 s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     465         [ #  # ]:          0 :                 if (s->native_fd < 0)
     466         [ #  # ]:          0 :                         return log_error_errno(errno, "socket() failed: %m");
     467                 :            : 
     468                 :          0 :                 (void) sockaddr_un_unlink(&sa.un);
     469                 :            : 
     470   [ #  #  #  # ]:          0 :                 r = bind(s->native_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
     471         [ #  # ]:          0 :                 if (r < 0)
     472         [ #  # ]:          0 :                         return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
     473                 :            : 
     474                 :          0 :                 (void) chmod(sa.un.sun_path, 0666);
     475                 :            :         } else
     476                 :          0 :                 (void) fd_nonblock(s->native_fd, true);
     477                 :            : 
     478                 :          0 :         r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSCRED, true);
     479         [ #  # ]:          0 :         if (r < 0)
     480         [ #  # ]:          0 :                 return log_error_errno(r, "SO_PASSCRED failed: %m");
     481                 :            : 
     482                 :            : #if HAVE_SELINUX
     483         [ #  # ]:          0 :         if (mac_selinux_use()) {
     484                 :          0 :                 r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSSEC, true);
     485         [ #  # ]:          0 :                 if (r < 0)
     486         [ #  # ]:          0 :                         log_warning_errno(r, "SO_PASSSEC failed: %m");
     487                 :            :         }
     488                 :            : #endif
     489                 :            : 
     490                 :          0 :         r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, true);
     491         [ #  # ]:          0 :         if (r < 0)
     492         [ #  # ]:          0 :                 return log_error_errno(r, "SO_TIMESTAMP failed: %m");
     493                 :            : 
     494                 :          0 :         r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, server_process_datagram, s);
     495         [ #  # ]:          0 :         if (r < 0)
     496         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to add native server fd to event loop: %m");
     497                 :            : 
     498                 :          0 :         r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5);
     499         [ #  # ]:          0 :         if (r < 0)
     500         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to adjust native event source priority: %m");
     501                 :            : 
     502                 :          0 :         return 0;
     503                 :            : }

Generated by: LCOV version 1.14