LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-socket.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 501 699 71.7 %
Date: 2019-08-23 13:36:53 Functions: 28 30 93.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 311 581 53.5 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <endian.h>
       4                 :            : #include <poll.h>
       5                 :            : #include <stdlib.h>
       6                 :            : #include <unistd.h>
       7                 :            : 
       8                 :            : #include "sd-bus.h"
       9                 :            : #include "sd-daemon.h"
      10                 :            : 
      11                 :            : #include "alloc-util.h"
      12                 :            : #include "bus-internal.h"
      13                 :            : #include "bus-message.h"
      14                 :            : #include "bus-socket.h"
      15                 :            : #include "fd-util.h"
      16                 :            : #include "format-util.h"
      17                 :            : #include "fs-util.h"
      18                 :            : #include "hexdecoct.h"
      19                 :            : #include "io-util.h"
      20                 :            : #include "macro.h"
      21                 :            : #include "memory-util.h"
      22                 :            : #include "missing.h"
      23                 :            : #include "path-util.h"
      24                 :            : #include "process-util.h"
      25                 :            : #include "rlimit-util.h"
      26                 :            : #include "selinux-util.h"
      27                 :            : #include "signal-util.h"
      28                 :            : #include "stdio-util.h"
      29                 :            : #include "string-util.h"
      30                 :            : #include "user-util.h"
      31                 :            : #include "utf8.h"
      32                 :            : 
      33                 :            : #define SNDBUF_SIZE (8*1024*1024)
      34                 :            : 
      35                 :        740 : static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
      36                 :            : 
      37         [ +  + ]:       1256 :         while (size > 0) {
      38                 :        516 :                 struct iovec *i = iov + *idx;
      39                 :            : 
      40         [ -  + ]:        516 :                 if (i->iov_len > size) {
      41                 :          0 :                         i->iov_base = (uint8_t*) i->iov_base + size;
      42                 :          0 :                         i->iov_len -= size;
      43                 :          0 :                         return;
      44                 :            :                 }
      45                 :            : 
      46                 :        516 :                 size -= i->iov_len;
      47                 :            : 
      48                 :        516 :                 *i = IOVEC_MAKE(NULL, 0);
      49                 :            : 
      50                 :        516 :                 (*idx)++;
      51                 :            :         }
      52                 :            : }
      53                 :            : 
      54                 :        760 : static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
      55         [ -  + ]:        760 :         assert(m);
      56         [ -  + ]:        760 :         assert(p);
      57         [ -  + ]:        760 :         assert(sz > 0);
      58                 :            : 
      59                 :        760 :         m->iovec[m->n_iovec++] = IOVEC_MAKE((void*) p, sz);
      60                 :            : 
      61                 :        760 :         return 0;
      62                 :            : }
      63                 :            : 
      64                 :        536 : static int bus_message_setup_iovec(sd_bus_message *m) {
      65                 :            :         struct bus_body_part *part;
      66                 :            :         unsigned n, i;
      67                 :            :         int r;
      68                 :            : 
      69         [ -  + ]:        536 :         assert(m);
      70         [ -  + ]:        536 :         assert(m->sealed);
      71                 :            : 
      72         [ -  + ]:        536 :         if (m->n_iovec > 0)
      73                 :          0 :                 return 0;
      74                 :            : 
      75         [ -  + ]:        536 :         assert(!m->iovec);
      76                 :            : 
      77                 :        536 :         n = 1 + m->n_body_parts;
      78         [ +  + ]:        536 :         if (n < ELEMENTSOF(m->iovec_fixed))
      79                 :        312 :                 m->iovec = m->iovec_fixed;
      80                 :            :         else {
      81                 :        224 :                 m->iovec = new(struct iovec, n);
      82         [ -  + ]:        224 :                 if (!m->iovec) {
      83                 :          0 :                         r = -ENOMEM;
      84                 :          0 :                         goto fail;
      85                 :            :                 }
      86                 :            :         }
      87                 :            : 
      88                 :        536 :         r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m));
      89         [ -  + ]:        536 :         if (r < 0)
      90                 :          0 :                 goto fail;
      91                 :            : 
      92         [ +  + ]:        760 :         MESSAGE_FOREACH_PART(part, i, m)  {
      93                 :        224 :                 r = bus_body_part_map(part);
      94         [ -  + ]:        224 :                 if (r < 0)
      95                 :          0 :                         goto fail;
      96                 :            : 
      97                 :        224 :                 r = append_iovec(m, part->data, part->size);
      98         [ -  + ]:        224 :                 if (r < 0)
      99                 :          0 :                         goto fail;
     100                 :            :         }
     101                 :            : 
     102         [ -  + ]:        536 :         assert(n == m->n_iovec);
     103                 :            : 
     104                 :        536 :         return 0;
     105                 :            : 
     106                 :          0 : fail:
     107                 :          0 :         m->poisoned = true;
     108                 :          0 :         return r;
     109                 :            : }
     110                 :            : 
     111                 :        700 : bool bus_socket_auth_needs_write(sd_bus *b) {
     112                 :            : 
     113                 :            :         unsigned i;
     114                 :            : 
     115         [ +  + ]:        700 :         if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
     116                 :        303 :                 return false;
     117                 :            : 
     118         [ +  + ]:        670 :         for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) {
     119                 :        529 :                 struct iovec *j = b->auth_iovec + i;
     120                 :            : 
     121         [ +  + ]:        529 :                 if (j->iov_len > 0)
     122                 :        256 :                         return true;
     123                 :            :         }
     124                 :            : 
     125                 :        141 :         return false;
     126                 :            : }
     127                 :            : 
     128                 :        463 : static int bus_socket_write_auth(sd_bus *b) {
     129                 :            :         ssize_t k;
     130                 :            : 
     131         [ -  + ]:        463 :         assert(b);
     132         [ -  + ]:        463 :         assert(b->state == BUS_AUTHENTICATING);
     133                 :            : 
     134         [ +  + ]:        463 :         if (!bus_socket_auth_needs_write(b))
     135                 :        259 :                 return 0;
     136                 :            : 
     137         [ -  + ]:        204 :         if (b->prefer_writev)
     138                 :          0 :                 k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
     139                 :            :         else {
     140                 :            :                 struct msghdr mh;
     141         [ +  - ]:        204 :                 zero(mh);
     142                 :            : 
     143                 :        204 :                 mh.msg_iov = b->auth_iovec + b->auth_index;
     144                 :        204 :                 mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
     145                 :            : 
     146                 :        204 :                 k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
     147   [ -  +  #  # ]:        204 :                 if (k < 0 && errno == ENOTSOCK) {
     148                 :          0 :                         b->prefer_writev = true;
     149                 :          0 :                         k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
     150                 :            :                 }
     151                 :            :         }
     152                 :            : 
     153         [ -  + ]:        204 :         if (k < 0)
     154         [ #  # ]:          0 :                 return errno == EAGAIN ? 0 : -errno;
     155                 :            : 
     156                 :        204 :         iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
     157                 :        204 :         return 1;
     158                 :            : }
     159                 :            : 
     160                 :        342 : static int bus_socket_auth_verify_client(sd_bus *b) {
     161                 :            :         char *d, *e, *f, *start;
     162                 :            :         sd_id128_t peer;
     163                 :            :         int r;
     164                 :            : 
     165         [ -  + ]:        342 :         assert(b);
     166                 :            : 
     167                 :            :         /*
     168                 :            :          * We expect three response lines:
     169                 :            :          *   "DATA\r\n"
     170                 :            :          *   "OK <server-id>\r\n"
     171                 :            :          *   "AGREE_UNIX_FD\r\n"        (optional)
     172                 :            :          */
     173                 :            : 
     174                 :        342 :         d = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
     175         [ +  + ]:        342 :         if (!d)
     176                 :        202 :                 return 0;
     177                 :            : 
     178                 :        140 :         e = memmem(d + 2, b->rbuffer_size - (d - (char*) b->rbuffer) - 2, "\r\n", 2);
     179         [ -  + ]:        140 :         if (!e)
     180                 :          0 :                 return 0;
     181                 :            : 
     182         [ +  + ]:        140 :         if (b->accept_fd) {
     183                 :        132 :                 f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
     184         [ -  + ]:        132 :                 if (!f)
     185                 :          0 :                         return 0;
     186                 :            : 
     187                 :        132 :                 start = f + 2;
     188                 :            :         } else {
     189                 :          8 :                 f = NULL;
     190                 :          8 :                 start = e + 2;
     191                 :            :         }
     192                 :            : 
     193                 :            :         /* Nice! We got all the lines we need. First check the DATA line. */
     194                 :            : 
     195         [ +  + ]:        140 :         if (d - (char*) b->rbuffer == 4) {
     196         [ -  + ]:        136 :                 if (memcmp(b->rbuffer, "DATA", 4))
     197                 :          0 :                         return -EPERM;
     198         [ -  + ]:          4 :         } else if (d - (char*) b->rbuffer == 3 + 32) {
     199                 :            :                 /*
     200                 :            :                  * Old versions of the server-side implementation of `sd-bus` replied with "OK <id>" to
     201                 :            :                  * "AUTH" requests from a client, even if the "AUTH" line did not contain inlined
     202                 :            :                  * arguments. Therefore, we also accept "OK <id>" here, even though it is technically the
     203                 :            :                  * wrong reply. We ignore the "<id>" parameter, though, since it has no real value.
     204                 :            :                  */
     205         [ #  # ]:          0 :                 if (memcmp(b->rbuffer, "OK ", 3))
     206                 :          0 :                         return -EPERM;
     207                 :            :         } else
     208                 :          4 :                 return -EPERM;
     209                 :            : 
     210                 :            :         /* Now check the OK line. */
     211                 :            : 
     212         [ -  + ]:        136 :         if (e - d != 2 + 3 + 32)
     213                 :          0 :                 return -EPERM;
     214                 :            : 
     215         [ -  + ]:        136 :         if (memcmp(d + 2, "OK ", 3))
     216                 :          0 :                 return -EPERM;
     217                 :            : 
     218         [ +  + ]:        136 :         b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
     219                 :            : 
     220         [ +  + ]:       2312 :         for (unsigned i = 0; i < 32; i += 2) {
     221                 :            :                 int x, y;
     222                 :            : 
     223                 :       2176 :                 x = unhexchar(d[2 + 3 + i]);
     224                 :       2176 :                 y = unhexchar(d[2 + 3 + i + 1]);
     225                 :            : 
     226   [ +  -  -  + ]:       2176 :                 if (x < 0 || y < 0)
     227                 :          0 :                         return -EINVAL;
     228                 :            : 
     229                 :       2176 :                 peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
     230                 :            :         }
     231                 :            : 
     232         [ -  + ]:        136 :         if (!sd_id128_is_null(b->server_id) &&
     233         [ #  # ]:          0 :             !sd_id128_equal(b->server_id, peer))
     234                 :          0 :                 return -EPERM;
     235                 :            : 
     236                 :        136 :         b->server_id = peer;
     237                 :            : 
     238                 :            :         /* And possibly check the third line, too */
     239                 :            : 
     240         [ +  + ]:        136 :         if (f)
     241                 :        128 :                 b->can_fds =
     242         [ +  + ]:        252 :                         (f - e == STRLEN("\r\nAGREE_UNIX_FD")) &&
     243         [ +  - ]:        124 :                         memcmp(e + 2, "AGREE_UNIX_FD",
     244                 :            :                                STRLEN("AGREE_UNIX_FD")) == 0;
     245                 :            : 
     246                 :        136 :         b->rbuffer_size -= (start - (char*) b->rbuffer);
     247                 :        136 :         memmove(b->rbuffer, start, b->rbuffer_size);
     248                 :            : 
     249                 :        136 :         r = bus_start_running(b);
     250         [ -  + ]:        136 :         if (r < 0)
     251                 :          0 :                 return r;
     252                 :            : 
     253                 :        136 :         return 1;
     254                 :            : }
     255                 :            : 
     256                 :        364 : static bool line_equals(const char *s, size_t m, const char *line) {
     257                 :            :         size_t l;
     258                 :            : 
     259                 :        364 :         l = strlen(line);
     260         [ +  + ]:        364 :         if (l != m)
     261                 :        244 :                 return false;
     262                 :            : 
     263                 :        120 :         return memcmp(s, line, l) == 0;
     264                 :            : }
     265                 :            : 
     266                 :        816 : static bool line_begins(const char *s, size_t m, const char *word) {
     267                 :            :         const char *p;
     268                 :            : 
     269                 :        816 :         p = memory_startswith(s, m, word);
     270   [ +  +  +  +  :        816 :         return p && (p == (s + m) || *p == ' ');
                   +  - ]
     271                 :            : }
     272                 :            : 
     273                 :         12 : static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
     274                 :         12 :         _cleanup_free_ char *token = NULL;
     275                 :            :         size_t len;
     276                 :            :         int r;
     277                 :            : 
     278         [ +  + ]:         12 :         if (!b->anonymous_auth)
     279                 :          4 :                 return 0;
     280                 :            : 
     281         [ +  + ]:          8 :         if (l <= 0)
     282                 :          4 :                 return 1;
     283                 :            : 
     284         [ -  + ]:          4 :         assert(p[0] == ' ');
     285                 :          4 :         p++; l--;
     286                 :            : 
     287         [ -  + ]:          4 :         if (l % 2 != 0)
     288                 :          0 :                 return 0;
     289                 :            : 
     290                 :          4 :         r = unhexmem(p, l, (void **) &token, &len);
     291         [ -  + ]:          4 :         if (r < 0)
     292                 :          0 :                 return 0;
     293                 :            : 
     294         [ -  + ]:          4 :         if (memchr(token, 0, len))
     295                 :          0 :                 return 0;
     296                 :            : 
     297                 :          4 :         return !!utf8_is_valid(token);
     298                 :            : }
     299                 :            : 
     300                 :         72 : static int verify_external_token(sd_bus *b, const char *p, size_t l) {
     301                 :         72 :         _cleanup_free_ char *token = NULL;
     302                 :            :         size_t len;
     303                 :            :         uid_t u;
     304                 :            :         int r;
     305                 :            : 
     306                 :            :         /* We don't do any real authentication here. Instead, we if
     307                 :            :          * the owner of this bus wanted authentication he should have
     308                 :            :          * checked SO_PEERCRED before even creating the bus object. */
     309                 :            : 
     310   [ +  +  -  + ]:         72 :         if (!b->anonymous_auth && !b->ucred_valid)
     311                 :          0 :                 return 0;
     312                 :            : 
     313         [ +  - ]:         72 :         if (l <= 0)
     314                 :         72 :                 return 1;
     315                 :            : 
     316         [ #  # ]:          0 :         assert(p[0] == ' ');
     317                 :          0 :         p++; l--;
     318                 :            : 
     319         [ #  # ]:          0 :         if (l % 2 != 0)
     320                 :          0 :                 return 0;
     321                 :            : 
     322                 :          0 :         r = unhexmem(p, l, (void**) &token, &len);
     323         [ #  # ]:          0 :         if (r < 0)
     324                 :          0 :                 return 0;
     325                 :            : 
     326         [ #  # ]:          0 :         if (memchr(token, 0, len))
     327                 :          0 :                 return 0;
     328                 :            : 
     329                 :          0 :         r = parse_uid(token, &u);
     330         [ #  # ]:          0 :         if (r < 0)
     331                 :          0 :                 return 0;
     332                 :            : 
     333                 :            :         /* We ignore the passed value if anonymous authentication is
     334                 :            :          * on anyway. */
     335   [ #  #  #  # ]:          0 :         if (!b->anonymous_auth && u != b->ucred.uid)
     336                 :          0 :                 return 0;
     337                 :            : 
     338                 :          0 :         return 1;
     339                 :            : }
     340                 :            : 
     341                 :        128 : static int bus_socket_auth_write(sd_bus *b, const char *t) {
     342                 :            :         char *p;
     343                 :            :         size_t l;
     344                 :            : 
     345         [ -  + ]:        128 :         assert(b);
     346         [ -  + ]:        128 :         assert(t);
     347                 :            : 
     348                 :            :         /* We only make use of the first iovec */
     349   [ +  -  -  + ]:        128 :         assert(IN_SET(b->auth_index, 0, 1));
     350                 :            : 
     351                 :        128 :         l = strlen(t);
     352                 :        128 :         p = malloc(b->auth_iovec[0].iov_len + l);
     353         [ -  + ]:        128 :         if (!p)
     354                 :          0 :                 return -ENOMEM;
     355                 :            : 
     356                 :        128 :         memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
     357                 :        128 :         memcpy(p + b->auth_iovec[0].iov_len, t, l);
     358                 :            : 
     359                 :        128 :         b->auth_iovec[0].iov_base = p;
     360                 :        128 :         b->auth_iovec[0].iov_len += l;
     361                 :            : 
     362                 :        128 :         free(b->auth_buffer);
     363                 :        128 :         b->auth_buffer = p;
     364                 :        128 :         b->auth_index = 0;
     365                 :        128 :         return 0;
     366                 :            : }
     367                 :            : 
     368                 :         40 : static int bus_socket_auth_write_ok(sd_bus *b) {
     369                 :            :         char t[3 + 32 + 2 + 1];
     370                 :            : 
     371         [ -  + ]:         40 :         assert(b);
     372                 :            : 
     373         [ -  + ]:         40 :         xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
     374                 :            : 
     375                 :         40 :         return bus_socket_auth_write(b, t);
     376                 :            : }
     377                 :            : 
     378                 :        145 : static int bus_socket_auth_verify_server(sd_bus *b) {
     379                 :            :         char *e;
     380                 :            :         const char *line;
     381                 :            :         size_t l;
     382                 :        145 :         bool processed = false;
     383                 :            :         int r;
     384                 :            : 
     385         [ -  + ]:        145 :         assert(b);
     386                 :            : 
     387         [ +  + ]:        145 :         if (b->rbuffer_size < 1)
     388                 :         54 :                 return 0;
     389                 :            : 
     390                 :            :         /* First char must be a NUL byte */
     391         [ -  + ]:         91 :         if (*(char*) b->rbuffer != 0)
     392                 :          0 :                 return -EIO;
     393                 :            : 
     394         [ -  + ]:         91 :         if (b->rbuffer_size < 3)
     395                 :          0 :                 return 0;
     396                 :            : 
     397                 :            :         /* Begin with the first line */
     398         [ +  + ]:         91 :         if (b->auth_rbegin <= 0)
     399                 :         44 :                 b->auth_rbegin = 1;
     400                 :            : 
     401                 :            :         for (;;) {
     402                 :            :                 /* Check if line is complete */
     403                 :        347 :                 line = (char*) b->rbuffer + b->auth_rbegin;
     404                 :        219 :                 e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
     405         [ +  + ]:        219 :                 if (!e)
     406                 :         11 :                         return processed;
     407                 :            : 
     408                 :        208 :                 l = e - line;
     409                 :            : 
     410         [ +  + ]:        208 :                 if (line_begins(line, l, "AUTH ANONYMOUS")) {
     411                 :            : 
     412                 :          8 :                         r = verify_anonymous_token(b,
     413                 :            :                                                    line + strlen("AUTH ANONYMOUS"),
     414                 :            :                                                    l - strlen("AUTH ANONYMOUS"));
     415         [ -  + ]:          8 :                         if (r < 0)
     416                 :          0 :                                 return r;
     417         [ +  + ]:          8 :                         if (r == 0)
     418                 :          4 :                                 r = bus_socket_auth_write(b, "REJECTED\r\n");
     419                 :            :                         else {
     420                 :          4 :                                 b->auth = BUS_AUTH_ANONYMOUS;
     421         [ +  - ]:          4 :                                 if (l <= strlen("AUTH ANONYMOUS"))
     422                 :          4 :                                         r = bus_socket_auth_write(b, "DATA\r\n");
     423                 :            :                                 else
     424                 :          0 :                                         r = bus_socket_auth_write_ok(b);
     425                 :            :                         }
     426                 :            : 
     427         [ +  + ]:        200 :                 } else if (line_begins(line, l, "AUTH EXTERNAL")) {
     428                 :            : 
     429                 :         36 :                         r = verify_external_token(b,
     430                 :            :                                                   line + strlen("AUTH EXTERNAL"),
     431                 :            :                                                   l - strlen("AUTH EXTERNAL"));
     432         [ -  + ]:         36 :                         if (r < 0)
     433                 :          0 :                                 return r;
     434         [ -  + ]:         36 :                         if (r == 0)
     435                 :          0 :                                 r = bus_socket_auth_write(b, "REJECTED\r\n");
     436                 :            :                         else {
     437                 :         36 :                                 b->auth = BUS_AUTH_EXTERNAL;
     438         [ +  - ]:         36 :                                 if (l <= strlen("AUTH EXTERNAL"))
     439                 :         36 :                                         r = bus_socket_auth_write(b, "DATA\r\n");
     440                 :            :                                 else
     441                 :          0 :                                         r = bus_socket_auth_write_ok(b);
     442                 :            :                         }
     443                 :            : 
     444         [ -  + ]:        164 :                 } else if (line_begins(line, l, "AUTH"))
     445                 :          0 :                         r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
     446   [ +  -  -  + ]:        328 :                 else if (line_equals(line, l, "CANCEL") ||
     447                 :        164 :                          line_begins(line, l, "ERROR")) {
     448                 :            : 
     449                 :          0 :                         b->auth = _BUS_AUTH_INVALID;
     450                 :          0 :                         r = bus_socket_auth_write(b, "REJECTED\r\n");
     451                 :            : 
     452         [ +  + ]:        164 :                 } else if (line_equals(line, l, "BEGIN")) {
     453                 :            : 
     454         [ +  + ]:         84 :                         if (b->auth == _BUS_AUTH_INVALID)
     455                 :          4 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     456                 :            :                         else {
     457                 :            :                                 /* We can't leave from the auth phase
     458                 :            :                                  * before we haven't written
     459                 :            :                                  * everything queued, so let's check
     460                 :            :                                  * that */
     461                 :            : 
     462         [ +  + ]:         80 :                                 if (bus_socket_auth_needs_write(b))
     463                 :         40 :                                         return 1;
     464                 :            : 
     465                 :         40 :                                 b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
     466                 :         40 :                                 memmove(b->rbuffer, e + 2, b->rbuffer_size);
     467                 :         40 :                                 return bus_start_running(b);
     468                 :            :                         }
     469                 :            : 
     470         [ +  + ]:         80 :                 } else if (line_begins(line, l, "DATA")) {
     471                 :            : 
     472         [ +  + ]:         44 :                         if (b->auth == _BUS_AUTH_INVALID)
     473                 :          4 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     474                 :            :                         else {
     475         [ +  + ]:         40 :                                 if (b->auth == BUS_AUTH_ANONYMOUS)
     476                 :          4 :                                         r = verify_anonymous_token(b, line + 4, l - 4);
     477                 :            :                                 else
     478                 :         36 :                                         r = verify_external_token(b, line + 4, l - 4);
     479                 :            : 
     480         [ -  + ]:         40 :                                 if (r < 0)
     481                 :          0 :                                         return r;
     482         [ -  + ]:         40 :                                 if (r == 0) {
     483                 :          0 :                                         b->auth = _BUS_AUTH_INVALID;
     484                 :          0 :                                         r = bus_socket_auth_write(b, "REJECTED\r\n");
     485                 :            :                                 } else
     486                 :         40 :                                         r = bus_socket_auth_write_ok(b);
     487                 :            :                         }
     488         [ +  - ]:         36 :                 } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
     489   [ +  +  +  + ]:         36 :                         if (b->auth == _BUS_AUTH_INVALID || !b->accept_fd)
     490                 :          8 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     491                 :            :                         else {
     492                 :         28 :                                 b->can_fds = true;
     493                 :         28 :                                 r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n");
     494                 :            :                         }
     495                 :            :                 } else
     496                 :          0 :                         r = bus_socket_auth_write(b, "ERROR\r\n");
     497                 :            : 
     498         [ -  + ]:        128 :                 if (r < 0)
     499                 :          0 :                         return r;
     500                 :            : 
     501                 :        128 :                 b->auth_rbegin = e + 2 - (char*) b->rbuffer;
     502                 :            : 
     503                 :        128 :                 processed = true;
     504                 :            :         }
     505                 :            : }
     506                 :            : 
     507                 :        487 : static int bus_socket_auth_verify(sd_bus *b) {
     508         [ -  + ]:        487 :         assert(b);
     509                 :            : 
     510         [ +  + ]:        487 :         if (b->is_server)
     511                 :        145 :                 return bus_socket_auth_verify_server(b);
     512                 :            :         else
     513                 :        342 :                 return bus_socket_auth_verify_client(b);
     514                 :            : }
     515                 :            : 
     516                 :        303 : static int bus_socket_read_auth(sd_bus *b) {
     517                 :            :         struct msghdr mh;
     518                 :        303 :         struct iovec iov = {};
     519                 :            :         size_t n;
     520                 :            :         ssize_t k;
     521                 :            :         int r;
     522                 :            :         void *p;
     523                 :            :         union {
     524                 :            :                 struct cmsghdr cmsghdr;
     525                 :            :                 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
     526                 :            :         } control;
     527                 :        303 :         bool handle_cmsg = false;
     528                 :            : 
     529         [ -  + ]:        303 :         assert(b);
     530         [ -  + ]:        303 :         assert(b->state == BUS_AUTHENTICATING);
     531                 :            : 
     532                 :        303 :         r = bus_socket_auth_verify(b);
     533         [ +  + ]:        303 :         if (r != 0)
     534                 :         40 :                 return r;
     535                 :            : 
     536                 :        263 :         n = MAX(256u, b->rbuffer_size * 2);
     537                 :            : 
     538         [ -  + ]:        263 :         if (n > BUS_AUTH_SIZE_MAX)
     539                 :          0 :                 n = BUS_AUTH_SIZE_MAX;
     540                 :            : 
     541         [ -  + ]:        263 :         if (b->rbuffer_size >= n)
     542                 :          0 :                 return -ENOBUFS;
     543                 :            : 
     544                 :        263 :         p = realloc(b->rbuffer, n);
     545         [ -  + ]:        263 :         if (!p)
     546                 :          0 :                 return -ENOMEM;
     547                 :            : 
     548                 :        263 :         b->rbuffer = p;
     549                 :            : 
     550                 :        263 :         iov = IOVEC_MAKE((uint8_t *)b->rbuffer + b->rbuffer_size, n - b->rbuffer_size);
     551                 :            : 
     552         [ -  + ]:        263 :         if (b->prefer_readv)
     553                 :          0 :                 k = readv(b->input_fd, &iov, 1);
     554                 :            :         else {
     555         [ +  - ]:        263 :                 zero(mh);
     556                 :        263 :                 mh.msg_iov = &iov;
     557                 :        263 :                 mh.msg_iovlen = 1;
     558                 :        263 :                 mh.msg_control = &control;
     559                 :        263 :                 mh.msg_controllen = sizeof(control);
     560                 :            : 
     561                 :        263 :                 k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
     562   [ +  +  -  + ]:        263 :                 if (k < 0 && errno == ENOTSOCK) {
     563                 :          0 :                         b->prefer_readv = true;
     564                 :          0 :                         k = readv(b->input_fd, &iov, 1);
     565                 :            :                 } else
     566                 :        263 :                         handle_cmsg = true;
     567                 :            :         }
     568         [ +  + ]:        263 :         if (k < 0)
     569         [ -  + ]:         75 :                 return errno == EAGAIN ? 0 : -errno;
     570         [ +  + ]:        188 :         if (k == 0)
     571                 :          4 :                 return -ECONNRESET;
     572                 :            : 
     573                 :        184 :         b->rbuffer_size += k;
     574                 :            : 
     575         [ +  - ]:        184 :         if (handle_cmsg) {
     576                 :            :                 struct cmsghdr *cmsg;
     577                 :            : 
     578   [ -  +  -  + ]:        184 :                 CMSG_FOREACH(cmsg, &mh)
     579         [ #  # ]:          0 :                         if (cmsg->cmsg_level == SOL_SOCKET &&
     580         [ #  # ]:          0 :                             cmsg->cmsg_type == SCM_RIGHTS) {
     581                 :            :                                 int j;
     582                 :            : 
     583                 :            :                                 /* Whut? We received fds during the auth
     584                 :            :                                  * protocol? Somebody is playing games with
     585                 :            :                                  * us. Close them all, and fail */
     586                 :          0 :                                 j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
     587                 :          0 :                                 close_many((int*) CMSG_DATA(cmsg), j);
     588                 :          0 :                                 return -EIO;
     589                 :            :                         } else
     590         [ #  # ]:          0 :                                 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
     591                 :            :                                           cmsg->cmsg_level, cmsg->cmsg_type);
     592                 :            :         }
     593                 :            : 
     594                 :        184 :         r = bus_socket_auth_verify(b);
     595         [ +  - ]:        184 :         if (r != 0)
     596                 :        184 :                 return r;
     597                 :            : 
     598                 :          0 :         return 1;
     599                 :            : }
     600                 :            : 
     601                 :        316 : void bus_socket_setup(sd_bus *b) {
     602         [ -  + ]:        316 :         assert(b);
     603                 :            : 
     604                 :            :         /* Increase the buffers to 8 MB */
     605                 :        316 :         (void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
     606                 :        316 :         (void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
     607                 :            : 
     608                 :        316 :         b->message_version = 1;
     609                 :        316 :         b->message_endian = 0;
     610                 :        316 : }
     611                 :            : 
     612                 :        204 : static void bus_get_peercred(sd_bus *b) {
     613                 :            :         int r;
     614                 :            : 
     615         [ -  + ]:        204 :         assert(b);
     616         [ -  + ]:        204 :         assert(!b->ucred_valid);
     617         [ -  + ]:        204 :         assert(!b->label);
     618         [ -  + ]:        204 :         assert(b->n_groups == (size_t) -1);
     619                 :            : 
     620                 :            :         /* Get the peer for socketpair() sockets */
     621                 :        204 :         b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
     622                 :            : 
     623                 :            :         /* Get the SELinux context of the peer */
     624                 :        204 :         r = getpeersec(b->input_fd, &b->label);
     625   [ -  +  #  #  :        204 :         if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
                   #  # ]
     626         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to determine peer security context: %m");
     627                 :            : 
     628                 :            :         /* Get the list of auxiliary groups of the peer */
     629                 :        204 :         r = getpeergroups(b->input_fd, &b->groups);
     630         [ +  - ]:        204 :         if (r >= 0)
     631                 :        204 :                 b->n_groups = (size_t) r;
     632   [ #  #  #  # ]:          0 :         else if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
     633         [ #  # ]:          0 :                 log_debug_errno(r, "Failed to determine peer's group list: %m");
     634                 :        204 : }
     635                 :            : 
     636                 :        160 : static int bus_socket_start_auth_client(sd_bus *b) {
     637                 :            :         static const char sasl_auth_anonymous[] = {
     638                 :            :                 /*
     639                 :            :                  * We use an arbitrary trace-string for the ANONYMOUS authentication. It can be used by the
     640                 :            :                  * message broker to aid debugging of clients. We fully anonymize the connection and use a
     641                 :            :                  * static default.
     642                 :            :                  */
     643                 :            :                 "\0AUTH ANONYMOUS\r\n"
     644                 :            :                 /* HEX a n o n y m o u s */
     645                 :            :                 "DATA 616e6f6e796d6f7573\r\n"
     646                 :            :         };
     647                 :            :         static const char sasl_auth_external[] = {
     648                 :            :                 "\0AUTH EXTERNAL\r\n"
     649                 :            :                 "DATA\r\n"
     650                 :            :         };
     651                 :            :         static const char sasl_negotiate_unix_fd[] = {
     652                 :            :                 "NEGOTIATE_UNIX_FD\r\n"
     653                 :            :         };
     654                 :            :         static const char sasl_begin[] = {
     655                 :            :                 "BEGIN\r\n"
     656                 :            :         };
     657                 :        160 :         size_t i = 0;
     658                 :            : 
     659         [ -  + ]:        160 :         assert(b);
     660                 :            : 
     661         [ +  + ]:        160 :         if (b->anonymous_auth)
     662                 :          8 :                 b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_anonymous, sizeof(sasl_auth_anonymous) - 1);
     663                 :            :         else
     664                 :        152 :                 b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_external, sizeof(sasl_auth_external) - 1);
     665                 :            : 
     666         [ +  + ]:        160 :         if (b->accept_fd)
     667                 :        152 :                 b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_negotiate_unix_fd);
     668                 :            : 
     669                 :        160 :         b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_begin);
     670                 :            : 
     671                 :        160 :         return bus_socket_write_auth(b);
     672                 :            : }
     673                 :            : 
     674                 :        204 : int bus_socket_start_auth(sd_bus *b) {
     675         [ -  + ]:        204 :         assert(b);
     676                 :            : 
     677                 :        204 :         bus_get_peercred(b);
     678                 :            : 
     679                 :        204 :         bus_set_state(b, BUS_AUTHENTICATING);
     680                 :        204 :         b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT;
     681                 :            : 
     682         [ -  + ]:        204 :         if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
     683                 :          0 :                 b->accept_fd = false;
     684                 :            : 
     685         [ -  + ]:        204 :         if (b->output_fd != b->input_fd)
     686         [ #  # ]:          0 :                 if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
     687                 :          0 :                         b->accept_fd = false;
     688                 :            : 
     689         [ +  + ]:        204 :         if (b->is_server)
     690                 :         44 :                 return bus_socket_read_auth(b);
     691                 :            :         else
     692                 :        160 :                 return bus_socket_start_auth_client(b);
     693                 :            : }
     694                 :            : 
     695                 :         56 : static int bus_socket_inotify_setup(sd_bus *b) {
     696                 :         56 :         _cleanup_free_ int *new_watches = NULL;
     697                 :         56 :         _cleanup_free_ char *absolute = NULL;
     698                 :         56 :         size_t n_allocated = 0, n = 0, done = 0, i;
     699                 :         56 :         unsigned max_follow = 32;
     700                 :            :         const char *p;
     701                 :            :         int wd, r;
     702                 :            : 
     703         [ -  + ]:         56 :         assert(b);
     704         [ -  + ]:         56 :         assert(b->watch_bind);
     705         [ -  + ]:         56 :         assert(b->sockaddr.sa.sa_family == AF_UNIX);
     706         [ -  + ]:         56 :         assert(b->sockaddr.un.sun_path[0] != 0);
     707                 :            : 
     708                 :            :         /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket
     709                 :            :          * appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes
     710                 :            :          * to all prefix components of the path, and every time we get an event for that we try to reconnect again,
     711                 :            :          * without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe
     712                 :            :          * to all relevant changes of anything in the path, so that our watches include any possibly newly created path
     713                 :            :          * components. */
     714                 :            : 
     715         [ +  + ]:         56 :         if (b->inotify_fd < 0) {
     716                 :          8 :                 b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
     717         [ -  + ]:          8 :                 if (b->inotify_fd < 0)
     718                 :          0 :                         return -errno;
     719                 :            : 
     720                 :          8 :                 b->inotify_fd = fd_move_above_stdio(b->inotify_fd);
     721                 :            :         }
     722                 :            : 
     723                 :            :         /* Make sure the path is NUL terminated */
     724                 :         56 :         p = strndupa(b->sockaddr.un.sun_path, sizeof(b->sockaddr.un.sun_path));
     725                 :            : 
     726                 :            :         /* Make sure the path is absolute */
     727                 :         56 :         r = path_make_absolute_cwd(p, &absolute);
     728         [ -  + ]:         56 :         if (r < 0)
     729                 :          0 :                 goto fail;
     730                 :            : 
     731                 :            :         /* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory
     732                 :            :          * that exists we want to know when files are created or moved into it. For all parents of it we just care if
     733                 :            :          * they are removed or renamed. */
     734                 :            : 
     735         [ -  + ]:         56 :         if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
     736                 :          0 :                 r = -ENOMEM;
     737                 :          0 :                 goto fail;
     738                 :            :         }
     739                 :            : 
     740                 :            :         /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and
     741                 :            :          * always exists */
     742                 :         56 :         wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
     743         [ -  + ]:         56 :         if (wd < 0) {
     744         [ #  # ]:          0 :                 r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
     745                 :          0 :                 goto fail;
     746                 :            :         } else
     747                 :         56 :                 new_watches[n++] = wd;
     748                 :            : 
     749                 :        456 :         for (;;) {
     750   [ +  +  -  +  :       1456 :                 _cleanup_free_ char *component = NULL, *prefix = NULL, *destination = NULL;
          -  +  +  -  +  
          -  +  +  -  +  
                      - ]
     751                 :            :                 size_t n_slashes, n_component;
     752                 :        512 :                 char *c = NULL;
     753                 :            : 
     754                 :        512 :                 n_slashes = strspn(absolute + done, "/");
     755                 :        512 :                 n_component = n_slashes + strcspn(absolute + done + n_slashes, "/");
     756                 :            : 
     757         [ +  + ]:        512 :                 if (n_component == 0) /* The end */
     758                 :          8 :                         break;
     759                 :            : 
     760                 :        504 :                 component = strndup(absolute + done, n_component);
     761         [ -  + ]:        504 :                 if (!component) {
     762                 :          0 :                         r = -ENOMEM;
     763                 :          0 :                         goto fail;
     764                 :            :                 }
     765                 :            : 
     766                 :            :                 /* A trailing slash? That's a directory, and not a socket then */
     767         [ -  + ]:        504 :                 if (path_equal(component, "/")) {
     768                 :          0 :                         r = -EISDIR;
     769                 :          0 :                         goto fail;
     770                 :            :                 }
     771                 :            : 
     772                 :            :                 /* A single dot? Let's eat this up */
     773         [ -  + ]:        504 :                 if (path_equal(component, "/.")) {
     774                 :          0 :                         done += n_component;
     775                 :          0 :                         continue;
     776                 :            :                 }
     777                 :            : 
     778                 :        504 :                 prefix = strndup(absolute, done + n_component);
     779         [ -  + ]:        504 :                 if (!prefix) {
     780                 :          0 :                         r = -ENOMEM;
     781                 :          0 :                         goto fail;
     782                 :            :                 }
     783                 :            : 
     784         [ -  + ]:        504 :                 if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
     785                 :          0 :                         r = -ENOMEM;
     786                 :          0 :                         goto fail;
     787                 :            :                 }
     788                 :            : 
     789                 :        504 :                 wd = inotify_add_watch(b->inotify_fd, prefix, IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO|IN_DONT_FOLLOW);
     790         [ +  - ]:        504 :                 log_debug("Added inotify watch for %s on bus %s: %i", prefix, strna(b->description), wd);
     791                 :            : 
     792         [ +  + ]:        504 :                 if (wd < 0) {
     793   [ +  -  +  - ]:         48 :                         if (IN_SET(errno, ENOENT, ELOOP))
     794                 :         48 :                                 break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */
     795                 :            : 
     796         [ #  # ]:          0 :                         r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", empty_to_root(prefix));
     797                 :          0 :                         goto fail;
     798                 :            :                 } else
     799                 :        456 :                         new_watches[n++] = wd;
     800                 :            : 
     801                 :            :                 /* Check if this is possibly a symlink. If so, let's follow it and watch it too. */
     802                 :        456 :                 r = readlink_malloc(prefix, &destination);
     803         [ +  + ]:        456 :                 if (r == -EINVAL) { /* not a symlink */
     804                 :        416 :                         done += n_component;
     805                 :        416 :                         continue;
     806                 :            :                 }
     807         [ -  + ]:         40 :                 if (r < 0)
     808                 :          0 :                         goto fail;
     809                 :            : 
     810         [ -  + ]:         40 :                 if (isempty(destination)) { /* Empty symlink target? Yuck! */
     811                 :          0 :                         r = -EINVAL;
     812                 :          0 :                         goto fail;
     813                 :            :                 }
     814                 :            : 
     815         [ -  + ]:         40 :                 if (max_follow <= 0) { /* Let's make sure we don't follow symlinks forever */
     816                 :          0 :                         r = -ELOOP;
     817                 :          0 :                         goto fail;
     818                 :            :                 }
     819                 :            : 
     820         [ +  + ]:         40 :                 if (path_is_absolute(destination)) {
     821                 :            :                         /* For absolute symlinks we build the new path and start anew */
     822                 :         24 :                         c = strjoin(destination, absolute + done + n_component);
     823                 :         24 :                         done = 0;
     824                 :            :                 } else {
     825         [ +  - ]:         16 :                         _cleanup_free_ char *t = NULL;
     826                 :            : 
     827                 :            :                         /* For relative symlinks we replace the last component, and try again */
     828                 :         16 :                         t = strndup(absolute, done);
     829         [ -  + ]:         16 :                         if (!t)
     830                 :          0 :                                 return -ENOMEM;
     831                 :            : 
     832                 :         16 :                         c = strjoin(t, "/", destination, absolute + done + n_component);
     833                 :            :                 }
     834         [ -  + ]:         40 :                 if (!c) {
     835                 :          0 :                         r = -ENOMEM;
     836                 :          0 :                         goto fail;
     837                 :            :                 }
     838                 :            : 
     839                 :         40 :                 free(absolute);
     840                 :         40 :                 absolute = c;
     841                 :            : 
     842                 :         40 :                 max_follow--;
     843                 :            :         }
     844                 :            : 
     845                 :            :         /* And now, let's remove all watches from the previous iteration we don't need anymore */
     846         [ +  + ]:        448 :         for (i = 0; i < b->n_inotify_watches; i++) {
     847                 :        392 :                 bool found = false;
     848                 :            :                 size_t j;
     849                 :            : 
     850         [ +  + ]:       1624 :                 for (j = 0; j < n; j++)
     851         [ +  + ]:       1616 :                         if (new_watches[j] == b->inotify_watches[i]) {
     852                 :        384 :                                 found = true;
     853                 :        384 :                                 break;
     854                 :            :                         }
     855                 :            : 
     856         [ +  + ]:        392 :                 if (found)
     857                 :        384 :                         continue;
     858                 :            : 
     859                 :          8 :                 (void) inotify_rm_watch(b->inotify_fd, b->inotify_watches[i]);
     860                 :            :         }
     861                 :            : 
     862                 :         56 :         free_and_replace(b->inotify_watches, new_watches);
     863                 :         56 :         b->n_inotify_watches = n;
     864                 :            : 
     865                 :         56 :         return 0;
     866                 :            : 
     867                 :          0 : fail:
     868                 :          0 :         bus_close_inotify_fd(b);
     869                 :          0 :         return r;
     870                 :            : }
     871                 :            : 
     872                 :        184 : int bus_socket_connect(sd_bus *b) {
     873                 :        184 :         bool inotify_done = false;
     874                 :            :         int r;
     875                 :            : 
     876         [ -  + ]:        184 :         assert(b);
     877                 :            : 
     878                 :            :         for (;;) {
     879         [ -  + ]:        240 :                 assert(b->input_fd < 0);
     880         [ -  + ]:        240 :                 assert(b->output_fd < 0);
     881         [ -  + ]:        240 :                 assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
     882                 :            : 
     883                 :        240 :                 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     884         [ -  + ]:        240 :                 if (b->input_fd < 0)
     885                 :          0 :                         return -errno;
     886                 :            : 
     887                 :        240 :                 b->input_fd = fd_move_above_stdio(b->input_fd);
     888                 :            : 
     889                 :        240 :                 b->output_fd = b->input_fd;
     890                 :        240 :                 bus_socket_setup(b);
     891                 :            : 
     892         [ +  + ]:        240 :                 if (connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size) < 0) {
     893         [ -  + ]:        112 :                         if (errno == EINPROGRESS) {
     894                 :            : 
     895                 :            :                                 /* If we have any inotify watches open, close them now, we don't need them anymore, as
     896                 :            :                                  * we have successfully initiated a connection */
     897                 :          0 :                                 bus_close_inotify_fd(b);
     898                 :            : 
     899                 :            :                                 /* Note that very likely we are already in BUS_OPENING state here, as we enter it when
     900                 :            :                                  * we start parsing the address string. The only reason we set the state explicitly
     901                 :            :                                  * here, is to undo BUS_WATCH_BIND, in case we did the inotify magic. */
     902                 :          0 :                                 bus_set_state(b, BUS_OPENING);
     903                 :          0 :                                 return 1;
     904                 :            :                         }
     905                 :            : 
     906   [ +  -  +  -  :        112 :                         if (IN_SET(errno, ENOENT, ECONNREFUSED) &&  /* ENOENT → unix socket doesn't exist at all; ECONNREFUSED → unix socket stale */
                   +  - ]
     907                 :        112 :                             b->watch_bind &&
     908         [ +  - ]:        112 :                             b->sockaddr.sa.sa_family == AF_UNIX &&
     909         [ +  - ]:        112 :                             b->sockaddr.un.sun_path[0] != 0) {
     910                 :            : 
     911                 :            :                                 /* This connection attempt failed, let's release the socket for now, and start with a
     912                 :            :                                  * fresh one when reconnecting. */
     913                 :        112 :                                 bus_close_io_fds(b);
     914                 :            : 
     915         [ +  + ]:        112 :                                 if (inotify_done) {
     916                 :            :                                         /* inotify set up already, don't do it again, just return now, and remember
     917                 :            :                                          * that we are waiting for inotify events now. */
     918                 :         56 :                                         bus_set_state(b, BUS_WATCH_BIND);
     919                 :         56 :                                         return 1;
     920                 :            :                                 }
     921                 :            : 
     922                 :            :                                 /* This is a file system socket, and the inotify logic is enabled. Let's create the necessary inotify fd. */
     923                 :         56 :                                 r = bus_socket_inotify_setup(b);
     924         [ -  + ]:         56 :                                 if (r < 0)
     925                 :          0 :                                         return r;
     926                 :            : 
     927                 :            :                                 /* Let's now try to connect a second time, because in theory there's otherwise a race
     928                 :            :                                  * here: the socket might have been created in the time between our first connect() and
     929                 :            :                                  * the time we set up the inotify logic. But let's remember that we set up inotify now,
     930                 :            :                                  * so that we don't do the connect() more than twice. */
     931                 :         56 :                                 inotify_done = true;
     932                 :            : 
     933                 :            :                         } else
     934                 :          0 :                                 return -errno;
     935                 :            :                 } else
     936                 :        128 :                         break;
     937                 :            :         }
     938                 :            : 
     939                 :            :         /* Yay, established, we don't need no inotify anymore! */
     940                 :        128 :         bus_close_inotify_fd(b);
     941                 :            : 
     942                 :        128 :         return bus_socket_start_auth(b);
     943                 :            : }
     944                 :            : 
     945                 :          0 : int bus_socket_exec(sd_bus *b) {
     946                 :            :         int s[2], r;
     947                 :            : 
     948         [ #  # ]:          0 :         assert(b);
     949         [ #  # ]:          0 :         assert(b->input_fd < 0);
     950         [ #  # ]:          0 :         assert(b->output_fd < 0);
     951         [ #  # ]:          0 :         assert(b->exec_path);
     952         [ #  # ]:          0 :         assert(b->busexec_pid == 0);
     953                 :            : 
     954                 :          0 :         r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
     955         [ #  # ]:          0 :         if (r < 0)
     956                 :          0 :                 return -errno;
     957                 :            : 
     958                 :          0 :         r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &b->busexec_pid);
     959         [ #  # ]:          0 :         if (r < 0) {
     960                 :          0 :                 safe_close_pair(s);
     961                 :          0 :                 return r;
     962                 :            :         }
     963         [ #  # ]:          0 :         if (r == 0) {
     964                 :            :                 /* Child */
     965                 :            : 
     966         [ #  # ]:          0 :                 if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0)
     967                 :          0 :                         _exit(EXIT_FAILURE);
     968                 :            : 
     969                 :          0 :                 (void) rlimit_nofile_safe();
     970                 :            : 
     971         [ #  # ]:          0 :                 if (b->exec_argv)
     972                 :          0 :                         execvp(b->exec_path, b->exec_argv);
     973                 :            :                 else {
     974                 :          0 :                         const char *argv[] = { b->exec_path, NULL };
     975                 :          0 :                         execvp(b->exec_path, (char**) argv);
     976                 :            :                 }
     977                 :            : 
     978                 :          0 :                 _exit(EXIT_FAILURE);
     979                 :            :         }
     980                 :            : 
     981                 :          0 :         safe_close(s[1]);
     982                 :          0 :         b->output_fd = b->input_fd = fd_move_above_stdio(s[0]);
     983                 :            : 
     984                 :          0 :         bus_socket_setup(b);
     985                 :            : 
     986                 :          0 :         return bus_socket_start_auth(b);
     987                 :            : }
     988                 :            : 
     989                 :         76 : int bus_socket_take_fd(sd_bus *b) {
     990         [ -  + ]:         76 :         assert(b);
     991                 :            : 
     992                 :         76 :         bus_socket_setup(b);
     993                 :            : 
     994                 :         76 :         return bus_socket_start_auth(b);
     995                 :            : }
     996                 :            : 
     997                 :        536 : int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
     998                 :            :         struct iovec *iov;
     999                 :            :         ssize_t k;
    1000                 :            :         size_t n;
    1001                 :            :         unsigned j;
    1002                 :            :         int r;
    1003                 :            : 
    1004         [ -  + ]:        536 :         assert(bus);
    1005         [ -  + ]:        536 :         assert(m);
    1006         [ -  + ]:        536 :         assert(idx);
    1007   [ +  -  -  + ]:        536 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1008                 :            : 
    1009         [ -  + ]:        536 :         if (*idx >= BUS_MESSAGE_SIZE(m))
    1010                 :          0 :                 return 0;
    1011                 :            : 
    1012                 :        536 :         r = bus_message_setup_iovec(m);
    1013         [ -  + ]:        536 :         if (r < 0)
    1014                 :          0 :                 return r;
    1015                 :            : 
    1016                 :        536 :         n = m->n_iovec * sizeof(struct iovec);
    1017   [ -  +  -  + ]:        536 :         iov = newa(struct iovec, n);
    1018                 :        536 :         memcpy_safe(iov, m->iovec, n);
    1019                 :            : 
    1020                 :        536 :         j = 0;
    1021                 :        536 :         iovec_advance(iov, &j, *idx);
    1022                 :            : 
    1023         [ -  + ]:        536 :         if (bus->prefer_writev)
    1024                 :          0 :                 k = writev(bus->output_fd, iov, m->n_iovec);
    1025                 :            :         else {
    1026                 :       1072 :                 struct msghdr mh = {
    1027                 :            :                         .msg_iov = iov,
    1028                 :        536 :                         .msg_iovlen = m->n_iovec,
    1029                 :            :                 };
    1030                 :            : 
    1031   [ +  +  +  - ]:        536 :                 if (m->n_fds > 0 && *idx == 0) {
    1032                 :            :                         struct cmsghdr *control;
    1033                 :            : 
    1034                 :          4 :                         mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
    1035                 :          4 :                         mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
    1036                 :          4 :                         control->cmsg_level = SOL_SOCKET;
    1037                 :          4 :                         control->cmsg_type = SCM_RIGHTS;
    1038                 :          4 :                         memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
    1039                 :            :                 }
    1040                 :            : 
    1041                 :        536 :                 k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
    1042   [ -  +  #  # ]:        536 :                 if (k < 0 && errno == ENOTSOCK) {
    1043                 :          0 :                         bus->prefer_writev = true;
    1044                 :          0 :                         k = writev(bus->output_fd, iov, m->n_iovec);
    1045                 :            :                 }
    1046                 :            :         }
    1047                 :            : 
    1048         [ -  + ]:        536 :         if (k < 0)
    1049         [ #  # ]:          0 :                 return errno == EAGAIN ? 0 : -errno;
    1050                 :            : 
    1051                 :        536 :         *idx += (size_t) k;
    1052                 :        536 :         return 1;
    1053                 :            : }
    1054                 :            : 
    1055                 :       2313 : static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
    1056                 :            :         uint32_t a, b;
    1057                 :            :         uint8_t e;
    1058                 :            :         uint64_t sum;
    1059                 :            : 
    1060         [ -  + ]:       2313 :         assert(bus);
    1061         [ -  + ]:       2313 :         assert(need);
    1062   [ +  -  -  + ]:       2313 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1063                 :            : 
    1064         [ +  + ]:       2313 :         if (bus->rbuffer_size < sizeof(struct bus_header)) {
    1065                 :        895 :                 *need = sizeof(struct bus_header) + 8;
    1066                 :            : 
    1067                 :            :                 /* Minimum message size:
    1068                 :            :                  *
    1069                 :            :                  * Header +
    1070                 :            :                  *
    1071                 :            :                  *  Method Call: +2 string headers
    1072                 :            :                  *       Signal: +3 string headers
    1073                 :            :                  * Method Error: +1 string headers
    1074                 :            :                  *               +1 uint32 headers
    1075                 :            :                  * Method Reply: +1 uint32 headers
    1076                 :            :                  *
    1077                 :            :                  * A string header is at least 9 bytes
    1078                 :            :                  * A uint32 header is at least 8 bytes
    1079                 :            :                  *
    1080                 :            :                  * Hence the minimum message size of a valid message
    1081                 :            :                  * is header + 8 bytes */
    1082                 :            : 
    1083                 :        895 :                 return 0;
    1084                 :            :         }
    1085                 :            : 
    1086                 :       1418 :         a = ((const uint32_t*) bus->rbuffer)[1];
    1087                 :       1418 :         b = ((const uint32_t*) bus->rbuffer)[3];
    1088                 :            : 
    1089                 :       1418 :         e = ((const uint8_t*) bus->rbuffer)[0];
    1090         [ +  - ]:       1418 :         if (e == BUS_LITTLE_ENDIAN) {
    1091                 :       1418 :                 a = le32toh(a);
    1092                 :       1418 :                 b = le32toh(b);
    1093         [ #  # ]:          0 :         } else if (e == BUS_BIG_ENDIAN) {
    1094                 :          0 :                 a = be32toh(a);
    1095                 :          0 :                 b = be32toh(b);
    1096                 :            :         } else
    1097                 :          0 :                 return -EBADMSG;
    1098                 :            : 
    1099                 :       1418 :         sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
    1100         [ -  + ]:       1418 :         if (sum >= BUS_MESSAGE_SIZE_MAX)
    1101                 :          0 :                 return -ENOBUFS;
    1102                 :            : 
    1103                 :       1418 :         *need = (size_t) sum;
    1104                 :       1418 :         return 0;
    1105                 :            : }
    1106                 :            : 
    1107                 :        526 : static int bus_socket_make_message(sd_bus *bus, size_t size) {
    1108                 :        526 :         sd_bus_message *t = NULL;
    1109                 :            :         void *b;
    1110                 :            :         int r;
    1111                 :            : 
    1112         [ -  + ]:        526 :         assert(bus);
    1113         [ -  + ]:        526 :         assert(bus->rbuffer_size >= size);
    1114   [ +  -  -  + ]:        526 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1115                 :            : 
    1116                 :        526 :         r = bus_rqueue_make_room(bus);
    1117         [ -  + ]:        526 :         if (r < 0)
    1118                 :          0 :                 return r;
    1119                 :            : 
    1120         [ -  + ]:        526 :         if (bus->rbuffer_size > size) {
    1121                 :          0 :                 b = memdup((const uint8_t*) bus->rbuffer + size,
    1122                 :          0 :                            bus->rbuffer_size - size);
    1123         [ #  # ]:          0 :                 if (!b)
    1124                 :          0 :                         return -ENOMEM;
    1125                 :            :         } else
    1126                 :        526 :                 b = NULL;
    1127                 :            : 
    1128                 :        526 :         r = bus_message_from_malloc(bus,
    1129                 :            :                                     bus->rbuffer, size,
    1130                 :            :                                     bus->fds, bus->n_fds,
    1131                 :            :                                     NULL,
    1132                 :            :                                     &t);
    1133         [ -  + ]:        526 :         if (r == -EBADMSG) {
    1134         [ #  # ]:          0 :                 log_debug_errno(r, "Received invalid message from connection %s, dropping.", strna(bus->description));
    1135                 :          0 :                 free(bus->rbuffer); /* We want to drop current rbuffer and proceed with whatever remains in b */
    1136         [ -  + ]:        526 :         } else if (r < 0) {
    1137                 :          0 :                 free(b);
    1138                 :          0 :                 return r;
    1139                 :            :         }
    1140                 :            : 
    1141                 :            :         /* rbuffer ownership was either transferred to t, or we got EBADMSG and dropped it. */
    1142                 :        526 :         bus->rbuffer = b;
    1143                 :        526 :         bus->rbuffer_size -= size;
    1144                 :            : 
    1145                 :        526 :         bus->fds = NULL;
    1146                 :        526 :         bus->n_fds = 0;
    1147                 :            : 
    1148         [ +  - ]:        526 :         if (t) {
    1149                 :        526 :                 t->read_counter = ++bus->read_counter;
    1150                 :        526 :                 bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus);
    1151                 :        526 :                 sd_bus_message_unref(t);
    1152                 :            :         }
    1153                 :            : 
    1154                 :        526 :         return 1;
    1155                 :            : }
    1156                 :            : 
    1157                 :       1341 : int bus_socket_read_message(sd_bus *bus) {
    1158                 :            :         struct msghdr mh;
    1159                 :       1341 :         struct iovec iov = {};
    1160                 :            :         ssize_t k;
    1161                 :            :         size_t need;
    1162                 :            :         int r;
    1163                 :            :         void *b;
    1164                 :            :         union {
    1165                 :            :                 struct cmsghdr cmsghdr;
    1166                 :            :                 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
    1167                 :            :         } control;
    1168                 :       1341 :         bool handle_cmsg = false;
    1169                 :            : 
    1170         [ -  + ]:       1341 :         assert(bus);
    1171   [ +  -  -  + ]:       1341 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1172                 :            : 
    1173                 :       1341 :         r = bus_socket_read_message_need(bus, &need);
    1174         [ -  + ]:       1341 :         if (r < 0)
    1175                 :          0 :                 return r;
    1176                 :            : 
    1177         [ -  + ]:       1341 :         if (bus->rbuffer_size >= need)
    1178                 :          0 :                 return bus_socket_make_message(bus, need);
    1179                 :            : 
    1180                 :       1341 :         b = realloc(bus->rbuffer, need);
    1181         [ -  + ]:       1341 :         if (!b)
    1182                 :          0 :                 return -ENOMEM;
    1183                 :            : 
    1184                 :       1341 :         bus->rbuffer = b;
    1185                 :            : 
    1186                 :       1341 :         iov = IOVEC_MAKE((uint8_t *)bus->rbuffer + bus->rbuffer_size, need - bus->rbuffer_size);
    1187                 :            : 
    1188         [ -  + ]:       1341 :         if (bus->prefer_readv)
    1189                 :          0 :                 k = readv(bus->input_fd, &iov, 1);
    1190                 :            :         else {
    1191         [ +  - ]:       1341 :                 zero(mh);
    1192                 :       1341 :                 mh.msg_iov = &iov;
    1193                 :       1341 :                 mh.msg_iovlen = 1;
    1194                 :       1341 :                 mh.msg_control = &control;
    1195                 :       1341 :                 mh.msg_controllen = sizeof(control);
    1196                 :            : 
    1197                 :       1341 :                 k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
    1198   [ +  +  -  + ]:       1341 :                 if (k < 0 && errno == ENOTSOCK) {
    1199                 :          0 :                         bus->prefer_readv = true;
    1200                 :          0 :                         k = readv(bus->input_fd, &iov, 1);
    1201                 :            :                 } else
    1202                 :       1341 :                         handle_cmsg = true;
    1203                 :            :         }
    1204         [ +  + ]:       1341 :         if (k < 0)
    1205         [ -  + ]:        365 :                 return errno == EAGAIN ? 0 : -errno;
    1206         [ +  + ]:        976 :         if (k == 0)
    1207                 :          4 :                 return -ECONNRESET;
    1208                 :            : 
    1209                 :        972 :         bus->rbuffer_size += k;
    1210                 :            : 
    1211         [ +  - ]:        972 :         if (handle_cmsg) {
    1212                 :            :                 struct cmsghdr *cmsg;
    1213                 :            : 
    1214   [ +  +  +  + ]:        976 :                 CMSG_FOREACH(cmsg, &mh)
    1215         [ +  - ]:          4 :                         if (cmsg->cmsg_level == SOL_SOCKET &&
    1216         [ +  - ]:          4 :                             cmsg->cmsg_type == SCM_RIGHTS) {
    1217                 :            :                                 int n, *f, i;
    1218                 :            : 
    1219                 :          4 :                                 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
    1220                 :            : 
    1221         [ -  + ]:          4 :                                 if (!bus->can_fds) {
    1222                 :            :                                         /* Whut? We received fds but this
    1223                 :            :                                          * isn't actually enabled? Close them,
    1224                 :            :                                          * and fail */
    1225                 :            : 
    1226                 :          0 :                                         close_many((int*) CMSG_DATA(cmsg), n);
    1227                 :          0 :                                         return -EIO;
    1228                 :            :                                 }
    1229                 :            : 
    1230                 :          4 :                                 f = reallocarray(bus->fds, bus->n_fds + n, sizeof(int));
    1231         [ -  + ]:          4 :                                 if (!f) {
    1232                 :          0 :                                         close_many((int*) CMSG_DATA(cmsg), n);
    1233                 :          0 :                                         return -ENOMEM;
    1234                 :            :                                 }
    1235                 :            : 
    1236         [ +  + ]:          8 :                                 for (i = 0; i < n; i++)
    1237                 :          4 :                                         f[bus->n_fds++] = fd_move_above_stdio(((int*) CMSG_DATA(cmsg))[i]);
    1238                 :          4 :                                 bus->fds = f;
    1239                 :            :                         } else
    1240         [ #  # ]:          0 :                                 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
    1241                 :            :                                           cmsg->cmsg_level, cmsg->cmsg_type);
    1242                 :            :         }
    1243                 :            : 
    1244                 :        972 :         r = bus_socket_read_message_need(bus, &need);
    1245         [ -  + ]:        972 :         if (r < 0)
    1246                 :          0 :                 return r;
    1247                 :            : 
    1248         [ +  + ]:        972 :         if (bus->rbuffer_size >= need)
    1249                 :        526 :                 return bus_socket_make_message(bus, need);
    1250                 :            : 
    1251                 :        446 :         return 1;
    1252                 :            : }
    1253                 :            : 
    1254                 :          0 : int bus_socket_process_opening(sd_bus *b) {
    1255                 :          0 :         int error = 0;
    1256                 :          0 :         socklen_t slen = sizeof(error);
    1257                 :          0 :         struct pollfd p = {
    1258                 :          0 :                 .fd = b->output_fd,
    1259                 :            :                 .events = POLLOUT,
    1260                 :            :         };
    1261                 :            :         int r;
    1262                 :            : 
    1263         [ #  # ]:          0 :         assert(b->state == BUS_OPENING);
    1264                 :            : 
    1265                 :          0 :         r = poll(&p, 1, 0);
    1266         [ #  # ]:          0 :         if (r < 0)
    1267                 :          0 :                 return -errno;
    1268                 :            : 
    1269         [ #  # ]:          0 :         if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
    1270                 :          0 :                 return 0;
    1271                 :            : 
    1272                 :          0 :         r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
    1273         [ #  # ]:          0 :         if (r < 0)
    1274                 :          0 :                 b->last_connect_error = errno;
    1275         [ #  # ]:          0 :         else if (error != 0)
    1276                 :          0 :                 b->last_connect_error = error;
    1277         [ #  # ]:          0 :         else if (p.revents & (POLLERR|POLLHUP))
    1278                 :          0 :                 b->last_connect_error = ECONNREFUSED;
    1279                 :            :         else
    1280                 :          0 :                 return bus_socket_start_auth(b);
    1281                 :            : 
    1282                 :          0 :         return bus_next_address(b);
    1283                 :            : }
    1284                 :            : 
    1285                 :        303 : int bus_socket_process_authenticating(sd_bus *b) {
    1286                 :            :         int r;
    1287                 :            : 
    1288         [ -  + ]:        303 :         assert(b);
    1289         [ -  + ]:        303 :         assert(b->state == BUS_AUTHENTICATING);
    1290                 :            : 
    1291         [ -  + ]:        303 :         if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
    1292                 :          0 :                 return -ETIMEDOUT;
    1293                 :            : 
    1294                 :        303 :         r = bus_socket_write_auth(b);
    1295         [ +  + ]:        303 :         if (r != 0)
    1296                 :         44 :                 return r;
    1297                 :            : 
    1298                 :        259 :         return bus_socket_read_auth(b);
    1299                 :            : }
    1300                 :            : 
    1301                 :         84 : int bus_socket_process_watch_bind(sd_bus *b) {
    1302                 :            :         int r, q;
    1303                 :            : 
    1304         [ -  + ]:         84 :         assert(b);
    1305         [ -  + ]:         84 :         assert(b->state == BUS_WATCH_BIND);
    1306         [ -  + ]:         84 :         assert(b->inotify_fd >= 0);
    1307                 :            : 
    1308                 :         84 :         r = flush_fd(b->inotify_fd);
    1309         [ +  + ]:         84 :         if (r <= 0)
    1310                 :         28 :                 return r;
    1311                 :            : 
    1312         [ +  - ]:         56 :         log_debug("Got inotify event on bus %s.", strna(b->description));
    1313                 :            : 
    1314                 :            :         /* We flushed events out of the inotify fd. In that case, maybe the socket is valid now? Let's try to connect
    1315                 :            :          * to it again */
    1316                 :            : 
    1317                 :         56 :         r = bus_socket_connect(b);
    1318         [ -  + ]:         56 :         if (r < 0)
    1319                 :          0 :                 return r;
    1320                 :            : 
    1321                 :         56 :         q = bus_attach_io_events(b);
    1322         [ -  + ]:         56 :         if (q < 0)
    1323                 :          0 :                 return q;
    1324                 :            : 
    1325                 :         56 :         q = bus_attach_inotify_event(b);
    1326         [ -  + ]:         56 :         if (q < 0)
    1327                 :          0 :                 return q;
    1328                 :            : 
    1329                 :         56 :         return r;
    1330                 :            : }

Generated by: LCOV version 1.14