LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-socket.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 501 699 71.7 %
Date: 2019-08-22 15:41:25 Functions: 28 30 93.3 %

          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         185 : static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
      36             : 
      37         314 :         while (size > 0) {
      38         129 :                 struct iovec *i = iov + *idx;
      39             : 
      40         129 :                 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         129 :                 size -= i->iov_len;
      47             : 
      48         129 :                 *i = IOVEC_MAKE(NULL, 0);
      49             : 
      50         129 :                 (*idx)++;
      51             :         }
      52             : }
      53             : 
      54         190 : static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
      55         190 :         assert(m);
      56         190 :         assert(p);
      57         190 :         assert(sz > 0);
      58             : 
      59         190 :         m->iovec[m->n_iovec++] = IOVEC_MAKE((void*) p, sz);
      60             : 
      61         190 :         return 0;
      62             : }
      63             : 
      64         134 : 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         134 :         assert(m);
      70         134 :         assert(m->sealed);
      71             : 
      72         134 :         if (m->n_iovec > 0)
      73           0 :                 return 0;
      74             : 
      75         134 :         assert(!m->iovec);
      76             : 
      77         134 :         n = 1 + m->n_body_parts;
      78         134 :         if (n < ELEMENTSOF(m->iovec_fixed))
      79          78 :                 m->iovec = m->iovec_fixed;
      80             :         else {
      81          56 :                 m->iovec = new(struct iovec, n);
      82          56 :                 if (!m->iovec) {
      83           0 :                         r = -ENOMEM;
      84           0 :                         goto fail;
      85             :                 }
      86             :         }
      87             : 
      88         134 :         r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m));
      89         134 :         if (r < 0)
      90           0 :                 goto fail;
      91             : 
      92         190 :         MESSAGE_FOREACH_PART(part, i, m)  {
      93          56 :                 r = bus_body_part_map(part);
      94          56 :                 if (r < 0)
      95           0 :                         goto fail;
      96             : 
      97          56 :                 r = append_iovec(m, part->data, part->size);
      98          56 :                 if (r < 0)
      99           0 :                         goto fail;
     100             :         }
     101             : 
     102         134 :         assert(n == m->n_iovec);
     103             : 
     104         134 :         return 0;
     105             : 
     106           0 : fail:
     107           0 :         m->poisoned = true;
     108           0 :         return r;
     109             : }
     110             : 
     111         175 : bool bus_socket_auth_needs_write(sd_bus *b) {
     112             : 
     113             :         unsigned i;
     114             : 
     115         175 :         if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
     116          76 :                 return false;
     117             : 
     118         166 :         for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) {
     119         131 :                 struct iovec *j = b->auth_iovec + i;
     120             : 
     121         131 :                 if (j->iov_len > 0)
     122          64 :                         return true;
     123             :         }
     124             : 
     125          35 :         return false;
     126             : }
     127             : 
     128         117 : static int bus_socket_write_auth(sd_bus *b) {
     129             :         ssize_t k;
     130             : 
     131         117 :         assert(b);
     132         117 :         assert(b->state == BUS_AUTHENTICATING);
     133             : 
     134         117 :         if (!bus_socket_auth_needs_write(b))
     135          66 :                 return 0;
     136             : 
     137          51 :         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          51 :                 zero(mh);
     142             : 
     143          51 :                 mh.msg_iov = b->auth_iovec + b->auth_index;
     144          51 :                 mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
     145             : 
     146          51 :                 k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
     147          51 :                 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          51 :         if (k < 0)
     154           0 :                 return errno == EAGAIN ? 0 : -errno;
     155             : 
     156          51 :         iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
     157          51 :         return 1;
     158             : }
     159             : 
     160          87 : 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          87 :         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          87 :         d = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
     175          87 :         if (!d)
     176          52 :                 return 0;
     177             : 
     178          35 :         e = memmem(d + 2, b->rbuffer_size - (d - (char*) b->rbuffer) - 2, "\r\n", 2);
     179          35 :         if (!e)
     180           0 :                 return 0;
     181             : 
     182          35 :         if (b->accept_fd) {
     183          33 :                 f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
     184          33 :                 if (!f)
     185           0 :                         return 0;
     186             : 
     187          33 :                 start = f + 2;
     188             :         } else {
     189           2 :                 f = NULL;
     190           2 :                 start = e + 2;
     191             :         }
     192             : 
     193             :         /* Nice! We got all the lines we need. First check the DATA line. */
     194             : 
     195          35 :         if (d - (char*) b->rbuffer == 4) {
     196          34 :                 if (memcmp(b->rbuffer, "DATA", 4))
     197           0 :                         return -EPERM;
     198           1 :         } 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           1 :                 return -EPERM;
     209             : 
     210             :         /* Now check the OK line. */
     211             : 
     212          34 :         if (e - d != 2 + 3 + 32)
     213           0 :                 return -EPERM;
     214             : 
     215          34 :         if (memcmp(d + 2, "OK ", 3))
     216           0 :                 return -EPERM;
     217             : 
     218          34 :         b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
     219             : 
     220         578 :         for (unsigned i = 0; i < 32; i += 2) {
     221             :                 int x, y;
     222             : 
     223         544 :                 x = unhexchar(d[2 + 3 + i]);
     224         544 :                 y = unhexchar(d[2 + 3 + i + 1]);
     225             : 
     226         544 :                 if (x < 0 || y < 0)
     227           0 :                         return -EINVAL;
     228             : 
     229         544 :                 peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
     230             :         }
     231             : 
     232          34 :         if (!sd_id128_is_null(b->server_id) &&
     233           0 :             !sd_id128_equal(b->server_id, peer))
     234           0 :                 return -EPERM;
     235             : 
     236          34 :         b->server_id = peer;
     237             : 
     238             :         /* And possibly check the third line, too */
     239             : 
     240          34 :         if (f)
     241          32 :                 b->can_fds =
     242          63 :                         (f - e == STRLEN("\r\nAGREE_UNIX_FD")) &&
     243          31 :                         memcmp(e + 2, "AGREE_UNIX_FD",
     244             :                                STRLEN("AGREE_UNIX_FD")) == 0;
     245             : 
     246          34 :         b->rbuffer_size -= (start - (char*) b->rbuffer);
     247          34 :         memmove(b->rbuffer, start, b->rbuffer_size);
     248             : 
     249          34 :         r = bus_start_running(b);
     250          34 :         if (r < 0)
     251           0 :                 return r;
     252             : 
     253          34 :         return 1;
     254             : }
     255             : 
     256          91 : static bool line_equals(const char *s, size_t m, const char *line) {
     257             :         size_t l;
     258             : 
     259          91 :         l = strlen(line);
     260          91 :         if (l != m)
     261          61 :                 return false;
     262             : 
     263          30 :         return memcmp(s, line, l) == 0;
     264             : }
     265             : 
     266         204 : static bool line_begins(const char *s, size_t m, const char *word) {
     267             :         const char *p;
     268             : 
     269         204 :         p = memory_startswith(s, m, word);
     270         204 :         return p && (p == (s + m) || *p == ' ');
     271             : }
     272             : 
     273           3 : static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
     274           3 :         _cleanup_free_ char *token = NULL;
     275             :         size_t len;
     276             :         int r;
     277             : 
     278           3 :         if (!b->anonymous_auth)
     279           1 :                 return 0;
     280             : 
     281           2 :         if (l <= 0)
     282           1 :                 return 1;
     283             : 
     284           1 :         assert(p[0] == ' ');
     285           1 :         p++; l--;
     286             : 
     287           1 :         if (l % 2 != 0)
     288           0 :                 return 0;
     289             : 
     290           1 :         r = unhexmem(p, l, (void **) &token, &len);
     291           1 :         if (r < 0)
     292           0 :                 return 0;
     293             : 
     294           1 :         if (memchr(token, 0, len))
     295           0 :                 return 0;
     296             : 
     297           1 :         return !!utf8_is_valid(token);
     298             : }
     299             : 
     300          18 : static int verify_external_token(sd_bus *b, const char *p, size_t l) {
     301          18 :         _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          18 :         if (!b->anonymous_auth && !b->ucred_valid)
     311           0 :                 return 0;
     312             : 
     313          18 :         if (l <= 0)
     314          18 :                 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          32 : static int bus_socket_auth_write(sd_bus *b, const char *t) {
     342             :         char *p;
     343             :         size_t l;
     344             : 
     345          32 :         assert(b);
     346          32 :         assert(t);
     347             : 
     348             :         /* We only make use of the first iovec */
     349          32 :         assert(IN_SET(b->auth_index, 0, 1));
     350             : 
     351          32 :         l = strlen(t);
     352          32 :         p = malloc(b->auth_iovec[0].iov_len + l);
     353          32 :         if (!p)
     354           0 :                 return -ENOMEM;
     355             : 
     356          32 :         memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
     357          32 :         memcpy(p + b->auth_iovec[0].iov_len, t, l);
     358             : 
     359          32 :         b->auth_iovec[0].iov_base = p;
     360          32 :         b->auth_iovec[0].iov_len += l;
     361             : 
     362          32 :         free(b->auth_buffer);
     363          32 :         b->auth_buffer = p;
     364          32 :         b->auth_index = 0;
     365          32 :         return 0;
     366             : }
     367             : 
     368          10 : static int bus_socket_auth_write_ok(sd_bus *b) {
     369             :         char t[3 + 32 + 2 + 1];
     370             : 
     371          10 :         assert(b);
     372             : 
     373          10 :         xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
     374             : 
     375          10 :         return bus_socket_auth_write(b, t);
     376             : }
     377             : 
     378          36 : static int bus_socket_auth_verify_server(sd_bus *b) {
     379             :         char *e;
     380             :         const char *line;
     381             :         size_t l;
     382          36 :         bool processed = false;
     383             :         int r;
     384             : 
     385          36 :         assert(b);
     386             : 
     387          36 :         if (b->rbuffer_size < 1)
     388          13 :                 return 0;
     389             : 
     390             :         /* First char must be a NUL byte */
     391          23 :         if (*(char*) b->rbuffer != 0)
     392           0 :                 return -EIO;
     393             : 
     394          23 :         if (b->rbuffer_size < 3)
     395           0 :                 return 0;
     396             : 
     397             :         /* Begin with the first line */
     398          23 :         if (b->auth_rbegin <= 0)
     399          11 :                 b->auth_rbegin = 1;
     400             : 
     401             :         for (;;) {
     402             :                 /* Check if line is complete */
     403          87 :                 line = (char*) b->rbuffer + b->auth_rbegin;
     404          55 :                 e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
     405          55 :                 if (!e)
     406           3 :                         return processed;
     407             : 
     408          52 :                 l = e - line;
     409             : 
     410          52 :                 if (line_begins(line, l, "AUTH ANONYMOUS")) {
     411             : 
     412           2 :                         r = verify_anonymous_token(b,
     413             :                                                    line + strlen("AUTH ANONYMOUS"),
     414             :                                                    l - strlen("AUTH ANONYMOUS"));
     415           2 :                         if (r < 0)
     416           0 :                                 return r;
     417           2 :                         if (r == 0)
     418           1 :                                 r = bus_socket_auth_write(b, "REJECTED\r\n");
     419             :                         else {
     420           1 :                                 b->auth = BUS_AUTH_ANONYMOUS;
     421           1 :                                 if (l <= strlen("AUTH ANONYMOUS"))
     422           1 :                                         r = bus_socket_auth_write(b, "DATA\r\n");
     423             :                                 else
     424           0 :                                         r = bus_socket_auth_write_ok(b);
     425             :                         }
     426             : 
     427          50 :                 } else if (line_begins(line, l, "AUTH EXTERNAL")) {
     428             : 
     429           9 :                         r = verify_external_token(b,
     430             :                                                   line + strlen("AUTH EXTERNAL"),
     431             :                                                   l - strlen("AUTH EXTERNAL"));
     432           9 :                         if (r < 0)
     433           0 :                                 return r;
     434           9 :                         if (r == 0)
     435           0 :                                 r = bus_socket_auth_write(b, "REJECTED\r\n");
     436             :                         else {
     437           9 :                                 b->auth = BUS_AUTH_EXTERNAL;
     438           9 :                                 if (l <= strlen("AUTH EXTERNAL"))
     439           9 :                                         r = bus_socket_auth_write(b, "DATA\r\n");
     440             :                                 else
     441           0 :                                         r = bus_socket_auth_write_ok(b);
     442             :                         }
     443             : 
     444          41 :                 } else if (line_begins(line, l, "AUTH"))
     445           0 :                         r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
     446          82 :                 else if (line_equals(line, l, "CANCEL") ||
     447          41 :                          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          41 :                 } else if (line_equals(line, l, "BEGIN")) {
     453             : 
     454          21 :                         if (b->auth == _BUS_AUTH_INVALID)
     455           1 :                                 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          20 :                                 if (bus_socket_auth_needs_write(b))
     463          10 :                                         return 1;
     464             : 
     465          10 :                                 b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
     466          10 :                                 memmove(b->rbuffer, e + 2, b->rbuffer_size);
     467          10 :                                 return bus_start_running(b);
     468             :                         }
     469             : 
     470          20 :                 } else if (line_begins(line, l, "DATA")) {
     471             : 
     472          11 :                         if (b->auth == _BUS_AUTH_INVALID)
     473           1 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     474             :                         else {
     475          10 :                                 if (b->auth == BUS_AUTH_ANONYMOUS)
     476           1 :                                         r = verify_anonymous_token(b, line + 4, l - 4);
     477             :                                 else
     478           9 :                                         r = verify_external_token(b, line + 4, l - 4);
     479             : 
     480          10 :                                 if (r < 0)
     481           0 :                                         return r;
     482          10 :                                 if (r == 0) {
     483           0 :                                         b->auth = _BUS_AUTH_INVALID;
     484           0 :                                         r = bus_socket_auth_write(b, "REJECTED\r\n");
     485             :                                 } else
     486          10 :                                         r = bus_socket_auth_write_ok(b);
     487             :                         }
     488           9 :                 } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
     489           9 :                         if (b->auth == _BUS_AUTH_INVALID || !b->accept_fd)
     490           2 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     491             :                         else {
     492           7 :                                 b->can_fds = true;
     493           7 :                                 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          32 :                 if (r < 0)
     499           0 :                         return r;
     500             : 
     501          32 :                 b->auth_rbegin = e + 2 - (char*) b->rbuffer;
     502             : 
     503          32 :                 processed = true;
     504             :         }
     505             : }
     506             : 
     507         123 : static int bus_socket_auth_verify(sd_bus *b) {
     508         123 :         assert(b);
     509             : 
     510         123 :         if (b->is_server)
     511          36 :                 return bus_socket_auth_verify_server(b);
     512             :         else
     513          87 :                 return bus_socket_auth_verify_client(b);
     514             : }
     515             : 
     516          77 : static int bus_socket_read_auth(sd_bus *b) {
     517             :         struct msghdr mh;
     518          77 :         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          77 :         bool handle_cmsg = false;
     528             : 
     529          77 :         assert(b);
     530          77 :         assert(b->state == BUS_AUTHENTICATING);
     531             : 
     532          77 :         r = bus_socket_auth_verify(b);
     533          77 :         if (r != 0)
     534          10 :                 return r;
     535             : 
     536          67 :         n = MAX(256u, b->rbuffer_size * 2);
     537             : 
     538          67 :         if (n > BUS_AUTH_SIZE_MAX)
     539           0 :                 n = BUS_AUTH_SIZE_MAX;
     540             : 
     541          67 :         if (b->rbuffer_size >= n)
     542           0 :                 return -ENOBUFS;
     543             : 
     544          67 :         p = realloc(b->rbuffer, n);
     545          67 :         if (!p)
     546           0 :                 return -ENOMEM;
     547             : 
     548          67 :         b->rbuffer = p;
     549             : 
     550          67 :         iov = IOVEC_MAKE((uint8_t *)b->rbuffer + b->rbuffer_size, n - b->rbuffer_size);
     551             : 
     552          67 :         if (b->prefer_readv)
     553           0 :                 k = readv(b->input_fd, &iov, 1);
     554             :         else {
     555          67 :                 zero(mh);
     556          67 :                 mh.msg_iov = &iov;
     557          67 :                 mh.msg_iovlen = 1;
     558          67 :                 mh.msg_control = &control;
     559          67 :                 mh.msg_controllen = sizeof(control);
     560             : 
     561          67 :                 k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
     562          67 :                 if (k < 0 && errno == ENOTSOCK) {
     563           0 :                         b->prefer_readv = true;
     564           0 :                         k = readv(b->input_fd, &iov, 1);
     565             :                 } else
     566          67 :                         handle_cmsg = true;
     567             :         }
     568          67 :         if (k < 0)
     569          20 :                 return errno == EAGAIN ? 0 : -errno;
     570          47 :         if (k == 0)
     571           1 :                 return -ECONNRESET;
     572             : 
     573          46 :         b->rbuffer_size += k;
     574             : 
     575          46 :         if (handle_cmsg) {
     576             :                 struct cmsghdr *cmsg;
     577             : 
     578          46 :                 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          46 :         r = bus_socket_auth_verify(b);
     595          46 :         if (r != 0)
     596          46 :                 return r;
     597             : 
     598           0 :         return 1;
     599             : }
     600             : 
     601          79 : void bus_socket_setup(sd_bus *b) {
     602          79 :         assert(b);
     603             : 
     604             :         /* Increase the buffers to 8 MB */
     605          79 :         (void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
     606          79 :         (void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
     607             : 
     608          79 :         b->message_version = 1;
     609          79 :         b->message_endian = 0;
     610          79 : }
     611             : 
     612          51 : static void bus_get_peercred(sd_bus *b) {
     613             :         int r;
     614             : 
     615          51 :         assert(b);
     616          51 :         assert(!b->ucred_valid);
     617          51 :         assert(!b->label);
     618          51 :         assert(b->n_groups == (size_t) -1);
     619             : 
     620             :         /* Get the peer for socketpair() sockets */
     621          51 :         b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
     622             : 
     623             :         /* Get the SELinux context of the peer */
     624          51 :         r = getpeersec(b->input_fd, &b->label);
     625          51 :         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          51 :         r = getpeergroups(b->input_fd, &b->groups);
     630          51 :         if (r >= 0)
     631          51 :                 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          51 : }
     635             : 
     636          40 : 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          40 :         size_t i = 0;
     658             : 
     659          40 :         assert(b);
     660             : 
     661          40 :         if (b->anonymous_auth)
     662           2 :                 b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_anonymous, sizeof(sasl_auth_anonymous) - 1);
     663             :         else
     664          38 :                 b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_external, sizeof(sasl_auth_external) - 1);
     665             : 
     666          40 :         if (b->accept_fd)
     667          38 :                 b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_negotiate_unix_fd);
     668             : 
     669          40 :         b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_begin);
     670             : 
     671          40 :         return bus_socket_write_auth(b);
     672             : }
     673             : 
     674          51 : int bus_socket_start_auth(sd_bus *b) {
     675          51 :         assert(b);
     676             : 
     677          51 :         bus_get_peercred(b);
     678             : 
     679          51 :         bus_set_state(b, BUS_AUTHENTICATING);
     680          51 :         b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT;
     681             : 
     682          51 :         if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
     683           0 :                 b->accept_fd = false;
     684             : 
     685          51 :         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          51 :         if (b->is_server)
     690          11 :                 return bus_socket_read_auth(b);
     691             :         else
     692          40 :                 return bus_socket_start_auth_client(b);
     693             : }
     694             : 
     695          14 : static int bus_socket_inotify_setup(sd_bus *b) {
     696          14 :         _cleanup_free_ int *new_watches = NULL;
     697          14 :         _cleanup_free_ char *absolute = NULL;
     698          14 :         size_t n_allocated = 0, n = 0, done = 0, i;
     699          14 :         unsigned max_follow = 32;
     700             :         const char *p;
     701             :         int wd, r;
     702             : 
     703          14 :         assert(b);
     704          14 :         assert(b->watch_bind);
     705          14 :         assert(b->sockaddr.sa.sa_family == AF_UNIX);
     706          14 :         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          14 :         if (b->inotify_fd < 0) {
     716           2 :                 b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
     717           2 :                 if (b->inotify_fd < 0)
     718           0 :                         return -errno;
     719             : 
     720           2 :                 b->inotify_fd = fd_move_above_stdio(b->inotify_fd);
     721             :         }
     722             : 
     723             :         /* Make sure the path is NUL terminated */
     724          14 :         p = strndupa(b->sockaddr.un.sun_path, sizeof(b->sockaddr.un.sun_path));
     725             : 
     726             :         /* Make sure the path is absolute */
     727          14 :         r = path_make_absolute_cwd(p, &absolute);
     728          14 :         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          14 :         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          14 :         wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
     743          14 :         if (wd < 0) {
     744           0 :                 r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
     745           0 :                 goto fail;
     746             :         } else
     747          14 :                 new_watches[n++] = wd;
     748             : 
     749         114 :         for (;;) {
     750         364 :                 _cleanup_free_ char *component = NULL, *prefix = NULL, *destination = NULL;
     751             :                 size_t n_slashes, n_component;
     752         128 :                 char *c = NULL;
     753             : 
     754         128 :                 n_slashes = strspn(absolute + done, "/");
     755         128 :                 n_component = n_slashes + strcspn(absolute + done + n_slashes, "/");
     756             : 
     757         128 :                 if (n_component == 0) /* The end */
     758           2 :                         break;
     759             : 
     760         126 :                 component = strndup(absolute + done, n_component);
     761         126 :                 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         126 :                 if (path_equal(component, "/")) {
     768           0 :                         r = -EISDIR;
     769           0 :                         goto fail;
     770             :                 }
     771             : 
     772             :                 /* A single dot? Let's eat this up */
     773         126 :                 if (path_equal(component, "/.")) {
     774           0 :                         done += n_component;
     775           0 :                         continue;
     776             :                 }
     777             : 
     778         126 :                 prefix = strndup(absolute, done + n_component);
     779         126 :                 if (!prefix) {
     780           0 :                         r = -ENOMEM;
     781           0 :                         goto fail;
     782             :                 }
     783             : 
     784         126 :                 if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
     785           0 :                         r = -ENOMEM;
     786           0 :                         goto fail;
     787             :                 }
     788             : 
     789         126 :                 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         126 :                 log_debug("Added inotify watch for %s on bus %s: %i", prefix, strna(b->description), wd);
     791             : 
     792         126 :                 if (wd < 0) {
     793          12 :                         if (IN_SET(errno, ENOENT, ELOOP))
     794          12 :                                 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         114 :                         new_watches[n++] = wd;
     800             : 
     801             :                 /* Check if this is possibly a symlink. If so, let's follow it and watch it too. */
     802         114 :                 r = readlink_malloc(prefix, &destination);
     803         114 :                 if (r == -EINVAL) { /* not a symlink */
     804         104 :                         done += n_component;
     805         104 :                         continue;
     806             :                 }
     807          10 :                 if (r < 0)
     808           0 :                         goto fail;
     809             : 
     810          10 :                 if (isempty(destination)) { /* Empty symlink target? Yuck! */
     811           0 :                         r = -EINVAL;
     812           0 :                         goto fail;
     813             :                 }
     814             : 
     815          10 :                 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          10 :                 if (path_is_absolute(destination)) {
     821             :                         /* For absolute symlinks we build the new path and start anew */
     822           6 :                         c = strjoin(destination, absolute + done + n_component);
     823           6 :                         done = 0;
     824             :                 } else {
     825           4 :                         _cleanup_free_ char *t = NULL;
     826             : 
     827             :                         /* For relative symlinks we replace the last component, and try again */
     828           4 :                         t = strndup(absolute, done);
     829           4 :                         if (!t)
     830           0 :                                 return -ENOMEM;
     831             : 
     832           4 :                         c = strjoin(t, "/", destination, absolute + done + n_component);
     833             :                 }
     834          10 :                 if (!c) {
     835           0 :                         r = -ENOMEM;
     836           0 :                         goto fail;
     837             :                 }
     838             : 
     839          10 :                 free(absolute);
     840          10 :                 absolute = c;
     841             : 
     842          10 :                 max_follow--;
     843             :         }
     844             : 
     845             :         /* And now, let's remove all watches from the previous iteration we don't need anymore */
     846         112 :         for (i = 0; i < b->n_inotify_watches; i++) {
     847          98 :                 bool found = false;
     848             :                 size_t j;
     849             : 
     850         406 :                 for (j = 0; j < n; j++)
     851         404 :                         if (new_watches[j] == b->inotify_watches[i]) {
     852          96 :                                 found = true;
     853          96 :                                 break;
     854             :                         }
     855             : 
     856          98 :                 if (found)
     857          96 :                         continue;
     858             : 
     859           2 :                 (void) inotify_rm_watch(b->inotify_fd, b->inotify_watches[i]);
     860             :         }
     861             : 
     862          14 :         free_and_replace(b->inotify_watches, new_watches);
     863          14 :         b->n_inotify_watches = n;
     864             : 
     865          14 :         return 0;
     866             : 
     867           0 : fail:
     868           0 :         bus_close_inotify_fd(b);
     869           0 :         return r;
     870             : }
     871             : 
     872          46 : int bus_socket_connect(sd_bus *b) {
     873          46 :         bool inotify_done = false;
     874             :         int r;
     875             : 
     876          46 :         assert(b);
     877             : 
     878             :         for (;;) {
     879          60 :                 assert(b->input_fd < 0);
     880          60 :                 assert(b->output_fd < 0);
     881          60 :                 assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
     882             : 
     883          60 :                 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     884          60 :                 if (b->input_fd < 0)
     885           0 :                         return -errno;
     886             : 
     887          60 :                 b->input_fd = fd_move_above_stdio(b->input_fd);
     888             : 
     889          60 :                 b->output_fd = b->input_fd;
     890          60 :                 bus_socket_setup(b);
     891             : 
     892          60 :                 if (connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size) < 0) {
     893          28 :                         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          28 :                         if (IN_SET(errno, ENOENT, ECONNREFUSED) &&  /* ENOENT → unix socket doesn't exist at all; ECONNREFUSED → unix socket stale */
     907          28 :                             b->watch_bind &&
     908          28 :                             b->sockaddr.sa.sa_family == AF_UNIX &&
     909          28 :                             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          28 :                                 bus_close_io_fds(b);
     914             : 
     915          28 :                                 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          14 :                                         bus_set_state(b, BUS_WATCH_BIND);
     919          14 :                                         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          14 :                                 r = bus_socket_inotify_setup(b);
     924          14 :                                 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          14 :                                 inotify_done = true;
     932             : 
     933             :                         } else
     934           0 :                                 return -errno;
     935             :                 } else
     936          32 :                         break;
     937             :         }
     938             : 
     939             :         /* Yay, established, we don't need no inotify anymore! */
     940          32 :         bus_close_inotify_fd(b);
     941             : 
     942          32 :         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          19 : int bus_socket_take_fd(sd_bus *b) {
     990          19 :         assert(b);
     991             : 
     992          19 :         bus_socket_setup(b);
     993             : 
     994          19 :         return bus_socket_start_auth(b);
     995             : }
     996             : 
     997         134 : 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         134 :         assert(bus);
    1005         134 :         assert(m);
    1006         134 :         assert(idx);
    1007         134 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1008             : 
    1009         134 :         if (*idx >= BUS_MESSAGE_SIZE(m))
    1010           0 :                 return 0;
    1011             : 
    1012         134 :         r = bus_message_setup_iovec(m);
    1013         134 :         if (r < 0)
    1014           0 :                 return r;
    1015             : 
    1016         134 :         n = m->n_iovec * sizeof(struct iovec);
    1017         134 :         iov = newa(struct iovec, n);
    1018         134 :         memcpy_safe(iov, m->iovec, n);
    1019             : 
    1020         134 :         j = 0;
    1021         134 :         iovec_advance(iov, &j, *idx);
    1022             : 
    1023         134 :         if (bus->prefer_writev)
    1024           0 :                 k = writev(bus->output_fd, iov, m->n_iovec);
    1025             :         else {
    1026         268 :                 struct msghdr mh = {
    1027             :                         .msg_iov = iov,
    1028         134 :                         .msg_iovlen = m->n_iovec,
    1029             :                 };
    1030             : 
    1031         134 :                 if (m->n_fds > 0 && *idx == 0) {
    1032             :                         struct cmsghdr *control;
    1033             : 
    1034           1 :                         mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
    1035           1 :                         mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
    1036           1 :                         control->cmsg_level = SOL_SOCKET;
    1037           1 :                         control->cmsg_type = SCM_RIGHTS;
    1038           1 :                         memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
    1039             :                 }
    1040             : 
    1041         134 :                 k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
    1042         134 :                 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         134 :         if (k < 0)
    1049           0 :                 return errno == EAGAIN ? 0 : -errno;
    1050             : 
    1051         134 :         *idx += (size_t) k;
    1052         134 :         return 1;
    1053             : }
    1054             : 
    1055         625 : 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         625 :         assert(bus);
    1061         625 :         assert(need);
    1062         625 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1063             : 
    1064         625 :         if (bus->rbuffer_size < sizeof(struct bus_header)) {
    1065         239 :                 *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         239 :                 return 0;
    1084             :         }
    1085             : 
    1086         386 :         a = ((const uint32_t*) bus->rbuffer)[1];
    1087         386 :         b = ((const uint32_t*) bus->rbuffer)[3];
    1088             : 
    1089         386 :         e = ((const uint8_t*) bus->rbuffer)[0];
    1090         386 :         if (e == BUS_LITTLE_ENDIAN) {
    1091         386 :                 a = le32toh(a);
    1092         386 :                 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         386 :         sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
    1100         386 :         if (sum >= BUS_MESSAGE_SIZE_MAX)
    1101           0 :                 return -ENOBUFS;
    1102             : 
    1103         386 :         *need = (size_t) sum;
    1104         386 :         return 0;
    1105             : }
    1106             : 
    1107         142 : static int bus_socket_make_message(sd_bus *bus, size_t size) {
    1108         142 :         sd_bus_message *t = NULL;
    1109             :         void *b;
    1110             :         int r;
    1111             : 
    1112         142 :         assert(bus);
    1113         142 :         assert(bus->rbuffer_size >= size);
    1114         142 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1115             : 
    1116         142 :         r = bus_rqueue_make_room(bus);
    1117         142 :         if (r < 0)
    1118           0 :                 return r;
    1119             : 
    1120         142 :         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         142 :                 b = NULL;
    1127             : 
    1128         142 :         r = bus_message_from_malloc(bus,
    1129             :                                     bus->rbuffer, size,
    1130             :                                     bus->fds, bus->n_fds,
    1131             :                                     NULL,
    1132             :                                     &t);
    1133         142 :         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         142 :         } 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         142 :         bus->rbuffer = b;
    1143         142 :         bus->rbuffer_size -= size;
    1144             : 
    1145         142 :         bus->fds = NULL;
    1146         142 :         bus->n_fds = 0;
    1147             : 
    1148         142 :         if (t) {
    1149         142 :                 t->read_counter = ++bus->read_counter;
    1150         142 :                 bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus);
    1151         142 :                 sd_bus_message_unref(t);
    1152             :         }
    1153             : 
    1154         142 :         return 1;
    1155             : }
    1156             : 
    1157         361 : int bus_socket_read_message(sd_bus *bus) {
    1158             :         struct msghdr mh;
    1159         361 :         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         361 :         bool handle_cmsg = false;
    1169             : 
    1170         361 :         assert(bus);
    1171         361 :         assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
    1172             : 
    1173         361 :         r = bus_socket_read_message_need(bus, &need);
    1174         361 :         if (r < 0)
    1175           0 :                 return r;
    1176             : 
    1177         361 :         if (bus->rbuffer_size >= need)
    1178           0 :                 return bus_socket_make_message(bus, need);
    1179             : 
    1180         361 :         b = realloc(bus->rbuffer, need);
    1181         361 :         if (!b)
    1182           0 :                 return -ENOMEM;
    1183             : 
    1184         361 :         bus->rbuffer = b;
    1185             : 
    1186         361 :         iov = IOVEC_MAKE((uint8_t *)bus->rbuffer + bus->rbuffer_size, need - bus->rbuffer_size);
    1187             : 
    1188         361 :         if (bus->prefer_readv)
    1189           0 :                 k = readv(bus->input_fd, &iov, 1);
    1190             :         else {
    1191         361 :                 zero(mh);
    1192         361 :                 mh.msg_iov = &iov;
    1193         361 :                 mh.msg_iovlen = 1;
    1194         361 :                 mh.msg_control = &control;
    1195         361 :                 mh.msg_controllen = sizeof(control);
    1196             : 
    1197         361 :                 k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
    1198         361 :                 if (k < 0 && errno == ENOTSOCK) {
    1199           0 :                         bus->prefer_readv = true;
    1200           0 :                         k = readv(bus->input_fd, &iov, 1);
    1201             :                 } else
    1202         361 :                         handle_cmsg = true;
    1203             :         }
    1204         361 :         if (k < 0)
    1205          96 :                 return errno == EAGAIN ? 0 : -errno;
    1206         265 :         if (k == 0)
    1207           1 :                 return -ECONNRESET;
    1208             : 
    1209         264 :         bus->rbuffer_size += k;
    1210             : 
    1211         264 :         if (handle_cmsg) {
    1212             :                 struct cmsghdr *cmsg;
    1213             : 
    1214         265 :                 CMSG_FOREACH(cmsg, &mh)
    1215           1 :                         if (cmsg->cmsg_level == SOL_SOCKET &&
    1216           1 :                             cmsg->cmsg_type == SCM_RIGHTS) {
    1217             :                                 int n, *f, i;
    1218             : 
    1219           1 :                                 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
    1220             : 
    1221           1 :                                 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           1 :                                 f = reallocarray(bus->fds, bus->n_fds + n, sizeof(int));
    1231           1 :                                 if (!f) {
    1232           0 :                                         close_many((int*) CMSG_DATA(cmsg), n);
    1233           0 :                                         return -ENOMEM;
    1234             :                                 }
    1235             : 
    1236           2 :                                 for (i = 0; i < n; i++)
    1237           1 :                                         f[bus->n_fds++] = fd_move_above_stdio(((int*) CMSG_DATA(cmsg))[i]);
    1238           1 :                                 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         264 :         r = bus_socket_read_message_need(bus, &need);
    1245         264 :         if (r < 0)
    1246           0 :                 return r;
    1247             : 
    1248         264 :         if (bus->rbuffer_size >= need)
    1249         142 :                 return bus_socket_make_message(bus, need);
    1250             : 
    1251         122 :         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          77 : int bus_socket_process_authenticating(sd_bus *b) {
    1286             :         int r;
    1287             : 
    1288          77 :         assert(b);
    1289          77 :         assert(b->state == BUS_AUTHENTICATING);
    1290             : 
    1291          77 :         if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
    1292           0 :                 return -ETIMEDOUT;
    1293             : 
    1294          77 :         r = bus_socket_write_auth(b);
    1295          77 :         if (r != 0)
    1296          11 :                 return r;
    1297             : 
    1298          66 :         return bus_socket_read_auth(b);
    1299             : }
    1300             : 
    1301          21 : int bus_socket_process_watch_bind(sd_bus *b) {
    1302             :         int r, q;
    1303             : 
    1304          21 :         assert(b);
    1305          21 :         assert(b->state == BUS_WATCH_BIND);
    1306          21 :         assert(b->inotify_fd >= 0);
    1307             : 
    1308          21 :         r = flush_fd(b->inotify_fd);
    1309          21 :         if (r <= 0)
    1310           7 :                 return r;
    1311             : 
    1312          14 :         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          14 :         r = bus_socket_connect(b);
    1318          14 :         if (r < 0)
    1319           0 :                 return r;
    1320             : 
    1321          14 :         q = bus_attach_io_events(b);
    1322          14 :         if (q < 0)
    1323           0 :                 return q;
    1324             : 
    1325          14 :         q = bus_attach_inotify_event(b);
    1326          14 :         if (q < 0)
    1327           0 :                 return q;
    1328             : 
    1329          14 :         return r;
    1330             : }

Generated by: LCOV version 1.14