LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-socket.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 391 565 69.2 %
Date: 2015-07-29 18:47:03 Functions: 26 28 92.9 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <endian.h>
      23             : #include <stdlib.h>
      24             : #include <unistd.h>
      25             : #include <poll.h>
      26             : 
      27             : #include "sd-daemon.h"
      28             : #include "util.h"
      29             : #include "macro.h"
      30             : #include "missing.h"
      31             : #include "utf8.h"
      32             : #include "formats-util.h"
      33             : #include "signal-util.h"
      34             : 
      35             : #include "sd-bus.h"
      36             : #include "bus-socket.h"
      37             : #include "bus-internal.h"
      38             : #include "bus-message.h"
      39             : 
      40             : #define SNDBUF_SIZE (8*1024*1024)
      41             : 
      42          88 : static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
      43             : 
      44         211 :         while (size > 0) {
      45          35 :                 struct iovec *i = iov + *idx;
      46             : 
      47          35 :                 if (i->iov_len > size) {
      48           0 :                         i->iov_base = (uint8_t*) i->iov_base + size;
      49           0 :                         i->iov_len -= size;
      50           0 :                         return;
      51             :                 }
      52             : 
      53          35 :                 size -= i->iov_len;
      54             : 
      55          35 :                 i->iov_base = NULL;
      56          35 :                 i->iov_len = 0;
      57             : 
      58          35 :                 (*idx) ++;
      59             :         }
      60             : }
      61             : 
      62         102 : static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
      63         102 :         assert(m);
      64         102 :         assert(p);
      65         102 :         assert(sz > 0);
      66             : 
      67         102 :         m->iovec[m->n_iovec].iov_base = (void*) p;
      68         102 :         m->iovec[m->n_iovec].iov_len = sz;
      69         102 :         m->n_iovec++;
      70             : 
      71         102 :         return 0;
      72             : }
      73             : 
      74          71 : static int bus_message_setup_iovec(sd_bus_message *m) {
      75             :         struct bus_body_part *part;
      76             :         unsigned n, i;
      77             :         int r;
      78             : 
      79          71 :         assert(m);
      80          71 :         assert(m->sealed);
      81             : 
      82          71 :         if (m->n_iovec > 0)
      83           0 :                 return 0;
      84             : 
      85          71 :         assert(!m->iovec);
      86             : 
      87          71 :         n = 1 + m->n_body_parts;
      88          71 :         if (n < ELEMENTSOF(m->iovec_fixed))
      89          40 :                 m->iovec = m->iovec_fixed;
      90             :         else {
      91          31 :                 m->iovec = new(struct iovec, n);
      92          31 :                 if (!m->iovec) {
      93           0 :                         r = -ENOMEM;
      94           0 :                         goto fail;
      95             :                 }
      96             :         }
      97             : 
      98          71 :         r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m));
      99          71 :         if (r < 0)
     100           0 :                 goto fail;
     101             : 
     102         102 :         MESSAGE_FOREACH_PART(part, i, m)  {
     103          31 :                 r = bus_body_part_map(part);
     104          31 :                 if (r < 0)
     105           0 :                         goto fail;
     106             : 
     107          31 :                 r = append_iovec(m, part->data, part->size);
     108          31 :                 if (r < 0)
     109           0 :                         goto fail;
     110             :         }
     111             : 
     112          71 :         assert(n == m->n_iovec);
     113             : 
     114          71 :         return 0;
     115             : 
     116             : fail:
     117           0 :         m->poisoned = true;
     118           0 :         return r;
     119             : }
     120             : 
     121          71 : bool bus_socket_auth_needs_write(sd_bus *b) {
     122             : 
     123             :         unsigned i;
     124             : 
     125          71 :         if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
     126          27 :                 return false;
     127             : 
     128          87 :         for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) {
     129          67 :                 struct iovec *j = b->auth_iovec + i;
     130             : 
     131          67 :                 if (j->iov_len > 0)
     132          24 :                         return true;
     133             :         }
     134             : 
     135          20 :         return false;
     136             : }
     137             : 
     138          46 : static int bus_socket_write_auth(sd_bus *b) {
     139             :         ssize_t k;
     140             : 
     141          46 :         assert(b);
     142          46 :         assert(b->state == BUS_AUTHENTICATING);
     143             : 
     144          46 :         if (!bus_socket_auth_needs_write(b))
     145          29 :                 return 0;
     146             : 
     147          17 :         if (b->prefer_writev)
     148           0 :                 k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
     149             :         else {
     150             :                 struct msghdr mh;
     151          17 :                 zero(mh);
     152             : 
     153          17 :                 mh.msg_iov = b->auth_iovec + b->auth_index;
     154          17 :                 mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
     155             : 
     156          17 :                 k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
     157          17 :                 if (k < 0 && errno == ENOTSOCK) {
     158           0 :                         b->prefer_writev = true;
     159           0 :                         k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
     160             :                 }
     161             :         }
     162             : 
     163          17 :         if (k < 0)
     164           0 :                 return errno == EAGAIN ? 0 : -errno;
     165             : 
     166          17 :         iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
     167          17 :         return 1;
     168             : }
     169             : 
     170          27 : static int bus_socket_auth_verify_client(sd_bus *b) {
     171             :         char *e, *f, *start;
     172             :         sd_id128_t peer;
     173             :         unsigned i;
     174             :         int r;
     175             : 
     176          27 :         assert(b);
     177             : 
     178             :         /* We expect two response lines: "OK" and possibly
     179             :          * "AGREE_UNIX_FD" */
     180             : 
     181          27 :         e = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
     182          27 :         if (!e)
     183          18 :                 return 0;
     184             : 
     185           9 :         if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) {
     186           7 :                 f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
     187           7 :                 if (!f)
     188           0 :                         return 0;
     189             : 
     190           7 :                 start = f + 2;
     191             :         } else {
     192           2 :                 f = NULL;
     193           2 :                 start = e + 2;
     194             :         }
     195             : 
     196             :         /* Nice! We got all the lines we need. First check the OK
     197             :          * line */
     198             : 
     199           9 :         if (e - (char*) b->rbuffer != 3 + 32)
     200           1 :                 return -EPERM;
     201             : 
     202           8 :         if (memcmp(b->rbuffer, "OK ", 3))
     203           0 :                 return -EPERM;
     204             : 
     205           8 :         b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
     206             : 
     207         136 :         for (i = 0; i < 32; i += 2) {
     208             :                 int x, y;
     209             : 
     210         128 :                 x = unhexchar(((char*) b->rbuffer)[3 + i]);
     211         128 :                 y = unhexchar(((char*) b->rbuffer)[3 + i + 1]);
     212             : 
     213         128 :                 if (x < 0 || y < 0)
     214           0 :                         return -EINVAL;
     215             : 
     216         128 :                 peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
     217             :         }
     218             : 
     219           8 :         if (!sd_id128_equal(b->server_id, SD_ID128_NULL) &&
     220           0 :             !sd_id128_equal(b->server_id, peer))
     221           0 :                 return -EPERM;
     222             : 
     223           8 :         b->server_id = peer;
     224             : 
     225             :         /* And possibly check the second line, too */
     226             : 
     227           8 :         if (f)
     228           6 :                 b->can_fds =
     229          11 :                         (f - e == strlen("\r\nAGREE_UNIX_FD")) &&
     230           5 :                         memcmp(e + 2, "AGREE_UNIX_FD", strlen("AGREE_UNIX_FD")) == 0;
     231             : 
     232           8 :         b->rbuffer_size -= (start - (char*) b->rbuffer);
     233           8 :         memmove(b->rbuffer, start, b->rbuffer_size);
     234             : 
     235           8 :         r = bus_start_running(b);
     236           8 :         if (r < 0)
     237           0 :                 return r;
     238             : 
     239           8 :         return 1;
     240             : }
     241             : 
     242          48 : static bool line_equals(const char *s, size_t m, const char *line) {
     243             :         size_t l;
     244             : 
     245          48 :         l = strlen(line);
     246          48 :         if (l != m)
     247          27 :                 return false;
     248             : 
     249          21 :         return memcmp(s, line, l) == 0;
     250             : }
     251             : 
     252         104 : static bool line_begins(const char *s, size_t m, const char *word) {
     253             :         size_t l;
     254             : 
     255         104 :         l = strlen(word);
     256         104 :         if (m < l)
     257          30 :                 return false;
     258             : 
     259          74 :         if (memcmp(s, word, l) != 0)
     260          66 :                 return false;
     261             : 
     262           8 :         return m == l || (m > l && s[l] == ' ');
     263             : }
     264             : 
     265           2 : static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
     266           4 :         _cleanup_free_ char *token = NULL;
     267             :         size_t len;
     268             :         int r;
     269             : 
     270           2 :         if (!b->anonymous_auth)
     271           1 :                 return 0;
     272             : 
     273           1 :         if (l <= 0)
     274           0 :                 return 1;
     275             : 
     276           1 :         assert(p[0] == ' ');
     277           1 :         p++; l--;
     278             : 
     279           1 :         if (l % 2 != 0)
     280           0 :                 return 0;
     281             : 
     282           1 :         r = unhexmem(p, l, (void **) &token, &len);
     283           1 :         if (r < 0)
     284           0 :                 return 0;
     285             : 
     286           1 :         if (memchr(token, 0, len))
     287           0 :                 return 0;
     288             : 
     289           1 :         return !!utf8_is_valid(token);
     290             : }
     291             : 
     292           6 : static int verify_external_token(sd_bus *b, const char *p, size_t l) {
     293          12 :         _cleanup_free_ char *token = NULL;
     294             :         size_t len;
     295             :         uid_t u;
     296             :         int r;
     297             : 
     298             :         /* We don't do any real authentication here. Instead, we if
     299             :          * the owner of this bus wanted authentication he should have
     300             :          * checked SO_PEERCRED before even creating the bus object. */
     301             : 
     302           6 :         if (!b->anonymous_auth && !b->ucred_valid)
     303           0 :                 return 0;
     304             : 
     305           6 :         if (l <= 0)
     306           0 :                 return 1;
     307             : 
     308           6 :         assert(p[0] == ' ');
     309           6 :         p++; l--;
     310             : 
     311           6 :         if (l % 2 != 0)
     312           0 :                 return 0;
     313             : 
     314           6 :         r = unhexmem(p, l, (void**) &token, &len);
     315           6 :         if (r < 0)
     316           0 :                 return 0;
     317             : 
     318           6 :         if (memchr(token, 0, len))
     319           0 :                 return 0;
     320             : 
     321           6 :         r = parse_uid(token, &u);
     322           6 :         if (r < 0)
     323           0 :                 return 0;
     324             : 
     325             :         /* We ignore the passed value if anonymous authentication is
     326             :          * on anyway. */
     327           6 :         if (!b->anonymous_auth && u != b->ucred.uid)
     328           0 :                 return 0;
     329             : 
     330           6 :         return 1;
     331             : }
     332             : 
     333          15 : static int bus_socket_auth_write(sd_bus *b, const char *t) {
     334             :         char *p;
     335             :         size_t l;
     336             : 
     337          15 :         assert(b);
     338          15 :         assert(t);
     339             : 
     340             :         /* We only make use of the first iovec */
     341          15 :         assert(b->auth_index == 0 || b->auth_index == 1);
     342             : 
     343          15 :         l = strlen(t);
     344          15 :         p = malloc(b->auth_iovec[0].iov_len + l);
     345          15 :         if (!p)
     346           0 :                 return -ENOMEM;
     347             : 
     348          15 :         memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
     349          15 :         memcpy(p + b->auth_iovec[0].iov_len, t, l);
     350             : 
     351          15 :         b->auth_iovec[0].iov_base = p;
     352          15 :         b->auth_iovec[0].iov_len += l;
     353             : 
     354          15 :         free(b->auth_buffer);
     355          15 :         b->auth_buffer = p;
     356          15 :         b->auth_index = 0;
     357          15 :         return 0;
     358             : }
     359             : 
     360           7 : static int bus_socket_auth_write_ok(sd_bus *b) {
     361             :         char t[3 + 32 + 2 + 1];
     362             : 
     363           7 :         assert(b);
     364             : 
     365           7 :         xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
     366             : 
     367           7 :         return bus_socket_auth_write(b, t);
     368             : }
     369             : 
     370          27 : static int bus_socket_auth_verify_server(sd_bus *b) {
     371             :         char *e;
     372             :         const char *line;
     373             :         size_t l;
     374          27 :         bool processed = false;
     375             :         int r;
     376             : 
     377          27 :         assert(b);
     378             : 
     379          27 :         if (b->rbuffer_size < 1)
     380          10 :                 return 0;
     381             : 
     382             :         /* First char must be a NUL byte */
     383          17 :         if (*(char*) b->rbuffer != 0)
     384           0 :                 return -EIO;
     385             : 
     386          17 :         if (b->rbuffer_size < 3)
     387           0 :                 return 0;
     388             : 
     389             :         /* Begin with the first line */
     390          17 :         if (b->auth_rbegin <= 0)
     391           8 :                 b->auth_rbegin = 1;
     392             : 
     393             :         for (;;) {
     394             :                 /* Check if line is complete */
     395          32 :                 line = (char*) b->rbuffer + b->auth_rbegin;
     396          32 :                 e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
     397          32 :                 if (!e)
     398           3 :                         return processed;
     399             : 
     400          29 :                 l = e - line;
     401             : 
     402          29 :                 if (line_begins(line, l, "AUTH ANONYMOUS")) {
     403             : 
     404           2 :                         r = verify_anonymous_token(b, line + 14, l - 14);
     405           2 :                         if (r < 0)
     406           0 :                                 return r;
     407           2 :                         if (r == 0)
     408           1 :                                 r = bus_socket_auth_write(b, "REJECTED\r\n");
     409             :                         else {
     410           1 :                                 b->auth = BUS_AUTH_ANONYMOUS;
     411           1 :                                 r = bus_socket_auth_write_ok(b);
     412             :                         }
     413             : 
     414          27 :                 } else if (line_begins(line, l, "AUTH EXTERNAL")) {
     415             : 
     416           6 :                         r = verify_external_token(b, line + 13, l - 13);
     417           6 :                         if (r < 0)
     418           0 :                                 return r;
     419           6 :                         if (r == 0)
     420           0 :                                 r = bus_socket_auth_write(b, "REJECTED\r\n");
     421             :                         else {
     422           6 :                                 b->auth = BUS_AUTH_EXTERNAL;
     423           6 :                                 r = bus_socket_auth_write_ok(b);
     424             :                         }
     425             : 
     426          21 :                 } else if (line_begins(line, l, "AUTH"))
     427           0 :                         r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
     428          42 :                 else if (line_equals(line, l, "CANCEL") ||
     429          21 :                          line_begins(line, l, "ERROR")) {
     430             : 
     431           0 :                         b->auth = _BUS_AUTH_INVALID;
     432           0 :                         r = bus_socket_auth_write(b, "REJECTED\r\n");
     433             : 
     434          21 :                 } else if (line_equals(line, l, "BEGIN")) {
     435             : 
     436          15 :                         if (b->auth == _BUS_AUTH_INVALID)
     437           1 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     438             :                         else {
     439             :                                 /* We can't leave from the auth phase
     440             :                                  * before we haven't written
     441             :                                  * everything queued, so let's check
     442             :                                  * that */
     443             : 
     444          14 :                                 if (bus_socket_auth_needs_write(b))
     445           7 :                                         return 1;
     446             : 
     447           7 :                                 b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
     448           7 :                                 memmove(b->rbuffer, e + 2, b->rbuffer_size);
     449           7 :                                 return bus_start_running(b);
     450             :                         }
     451             : 
     452           6 :                 } else if (line_begins(line, l, "DATA")) {
     453             : 
     454           0 :                         if (b->auth == _BUS_AUTH_INVALID)
     455           0 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     456             :                         else {
     457           0 :                                 if (b->auth == BUS_AUTH_ANONYMOUS)
     458           0 :                                         r = verify_anonymous_token(b, line + 4, l - 4);
     459             :                                 else
     460           0 :                                         r = verify_external_token(b, line + 4, l - 4);
     461             : 
     462           0 :                                 if (r < 0)
     463           0 :                                         return r;
     464           0 :                                 if (r == 0) {
     465           0 :                                         b->auth = _BUS_AUTH_INVALID;
     466           0 :                                         r = bus_socket_auth_write(b, "REJECTED\r\n");
     467             :                                 } else
     468           0 :                                         r = bus_socket_auth_write_ok(b);
     469             :                         }
     470           6 :                 } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
     471           6 :                         if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
     472           2 :                                 r = bus_socket_auth_write(b, "ERROR\r\n");
     473             :                         else {
     474           4 :                                 b->can_fds = true;
     475           4 :                                 r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n");
     476             :                         }
     477             :                 } else
     478           0 :                         r = bus_socket_auth_write(b, "ERROR\r\n");
     479             : 
     480          15 :                 if (r < 0)
     481           0 :                         return r;
     482             : 
     483          15 :                 b->auth_rbegin = e + 2 - (char*) b->rbuffer;
     484             : 
     485          15 :                 processed = true;
     486          15 :         }
     487             : }
     488             : 
     489          54 : static int bus_socket_auth_verify(sd_bus *b) {
     490          54 :         assert(b);
     491             : 
     492          54 :         if (b->is_server)
     493          27 :                 return bus_socket_auth_verify_server(b);
     494             :         else
     495          27 :                 return bus_socket_auth_verify_client(b);
     496             : }
     497             : 
     498          37 : static int bus_socket_read_auth(sd_bus *b) {
     499             :         struct msghdr mh;
     500          37 :         struct iovec iov = {};
     501             :         size_t n;
     502             :         ssize_t k;
     503             :         int r;
     504             :         void *p;
     505             :         union {
     506             :                 struct cmsghdr cmsghdr;
     507             :                 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
     508             :         } control;
     509          37 :         bool handle_cmsg = false;
     510             : 
     511          37 :         assert(b);
     512          37 :         assert(b->state == BUS_AUTHENTICATING);
     513             : 
     514          37 :         r = bus_socket_auth_verify(b);
     515          37 :         if (r != 0)
     516           7 :                 return r;
     517             : 
     518          30 :         n = MAX(256u, b->rbuffer_size * 2);
     519             : 
     520          30 :         if (n > BUS_AUTH_SIZE_MAX)
     521           0 :                 n = BUS_AUTH_SIZE_MAX;
     522             : 
     523          30 :         if (b->rbuffer_size >= n)
     524           0 :                 return -ENOBUFS;
     525             : 
     526          30 :         p = realloc(b->rbuffer, n);
     527          30 :         if (!p)
     528           0 :                 return -ENOMEM;
     529             : 
     530          30 :         b->rbuffer = p;
     531             : 
     532          30 :         iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size;
     533          30 :         iov.iov_len = n - b->rbuffer_size;
     534             : 
     535          30 :         if (b->prefer_readv)
     536           0 :                 k = readv(b->input_fd, &iov, 1);
     537             :         else {
     538          30 :                 zero(mh);
     539          30 :                 mh.msg_iov = &iov;
     540          30 :                 mh.msg_iovlen = 1;
     541          30 :                 mh.msg_control = &control;
     542          30 :                 mh.msg_controllen = sizeof(control);
     543             : 
     544          30 :                 k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
     545          30 :                 if (k < 0 && errno == ENOTSOCK) {
     546           0 :                         b->prefer_readv = true;
     547           0 :                         k = readv(b->input_fd, &iov, 1);
     548             :                 } else
     549          30 :                         handle_cmsg = true;
     550             :         }
     551          30 :         if (k < 0)
     552          12 :                 return errno == EAGAIN ? 0 : -errno;
     553          18 :         if (k == 0)
     554           1 :                 return -ECONNRESET;
     555             : 
     556          17 :         b->rbuffer_size += k;
     557             : 
     558          17 :         if (handle_cmsg) {
     559             :                 struct cmsghdr *cmsg;
     560             : 
     561          17 :                 CMSG_FOREACH(cmsg, &mh)
     562           0 :                         if (cmsg->cmsg_level == SOL_SOCKET &&
     563           0 :                             cmsg->cmsg_type == SCM_RIGHTS) {
     564             :                                 int j;
     565             : 
     566             :                                 /* Whut? We received fds during the auth
     567             :                                  * protocol? Somebody is playing games with
     568             :                                  * us. Close them all, and fail */
     569           0 :                                 j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
     570           0 :                                 close_many((int*) CMSG_DATA(cmsg), j);
     571           0 :                                 return -EIO;
     572             :                         } else
     573           0 :                                 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
     574             :                                           cmsg->cmsg_level, cmsg->cmsg_type);
     575             :         }
     576             : 
     577          17 :         r = bus_socket_auth_verify(b);
     578          17 :         if (r != 0)
     579          17 :                 return r;
     580             : 
     581           0 :         return 1;
     582             : }
     583             : 
     584          17 : void bus_socket_setup(sd_bus *b) {
     585          17 :         assert(b);
     586             : 
     587             :         /* Increase the buffers to 8 MB */
     588          17 :         fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
     589          17 :         fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
     590             : 
     591          17 :         b->is_kernel = false;
     592          17 :         b->message_version = 1;
     593          17 :         b->message_endian = 0;
     594          17 : }
     595             : 
     596          17 : static void bus_get_peercred(sd_bus *b) {
     597             :         int r;
     598             : 
     599          17 :         assert(b);
     600             : 
     601             :         /* Get the peer for socketpair() sockets */
     602          17 :         b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
     603             : 
     604             :         /* Get the SELinux context of the peer */
     605          17 :         r = getpeersec(b->input_fd, &b->label);
     606          17 :         if (r < 0 && r != -EOPNOTSUPP)
     607          17 :                 log_debug_errno(r, "Failed to determine peer security context: %m");
     608          17 : }
     609             : 
     610           9 : static int bus_socket_start_auth_client(sd_bus *b) {
     611             :         size_t l;
     612             :         const char *auth_suffix, *auth_prefix;
     613             : 
     614           9 :         assert(b);
     615             : 
     616           9 :         if (b->anonymous_auth) {
     617           2 :                 auth_prefix = "\0AUTH ANONYMOUS ";
     618             : 
     619             :                 /* For ANONYMOUS auth we send some arbitrary "trace" string */
     620           2 :                 l = 9;
     621           2 :                 b->auth_buffer = hexmem("anonymous", l);
     622             :         } else {
     623             :                 char text[DECIMAL_STR_MAX(uid_t) + 1];
     624             : 
     625           7 :                 auth_prefix = "\0AUTH EXTERNAL ";
     626             : 
     627           7 :                 xsprintf(text, UID_FMT, geteuid());
     628             : 
     629           7 :                 l = strlen(text);
     630           7 :                 b->auth_buffer = hexmem(text, l);
     631             :         }
     632             : 
     633           9 :         if (!b->auth_buffer)
     634           0 :                 return -ENOMEM;
     635             : 
     636           9 :         if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
     637           7 :                 auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
     638             :         else
     639           2 :                 auth_suffix = "\r\nBEGIN\r\n";
     640             : 
     641           9 :         b->auth_iovec[0].iov_base = (void*) auth_prefix;
     642           9 :         b->auth_iovec[0].iov_len = 1 + strlen(auth_prefix + 1);
     643           9 :         b->auth_iovec[1].iov_base = (void*) b->auth_buffer;
     644           9 :         b->auth_iovec[1].iov_len = l * 2;
     645           9 :         b->auth_iovec[2].iov_base = (void*) auth_suffix;
     646           9 :         b->auth_iovec[2].iov_len = strlen(auth_suffix);
     647             : 
     648           9 :         return bus_socket_write_auth(b);
     649             : }
     650             : 
     651          17 : int bus_socket_start_auth(sd_bus *b) {
     652          17 :         assert(b);
     653             : 
     654          17 :         bus_get_peercred(b);
     655             : 
     656          17 :         b->state = BUS_AUTHENTICATING;
     657          17 :         b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
     658             : 
     659          17 :         if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
     660           0 :                 b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
     661             : 
     662          17 :         if (b->output_fd != b->input_fd)
     663           0 :                 if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
     664           0 :                         b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
     665             : 
     666          17 :         if (b->is_server)
     667           8 :                 return bus_socket_read_auth(b);
     668             :         else
     669           9 :                 return bus_socket_start_auth_client(b);
     670             : }
     671             : 
     672           1 : int bus_socket_connect(sd_bus *b) {
     673             :         int r;
     674             : 
     675           1 :         assert(b);
     676           1 :         assert(b->input_fd < 0);
     677           1 :         assert(b->output_fd < 0);
     678           1 :         assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
     679             : 
     680           1 :         b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
     681           1 :         if (b->input_fd < 0)
     682           0 :                 return -errno;
     683             : 
     684           1 :         b->output_fd = b->input_fd;
     685             : 
     686           1 :         bus_socket_setup(b);
     687             : 
     688           1 :         r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
     689           1 :         if (r < 0) {
     690           0 :                 if (errno == EINPROGRESS)
     691           0 :                         return 1;
     692             : 
     693           0 :                 return -errno;
     694             :         }
     695             : 
     696           1 :         return bus_socket_start_auth(b);
     697             : }
     698             : 
     699           0 : int bus_socket_exec(sd_bus *b) {
     700             :         int s[2], r;
     701             :         pid_t pid;
     702             : 
     703           0 :         assert(b);
     704           0 :         assert(b->input_fd < 0);
     705           0 :         assert(b->output_fd < 0);
     706           0 :         assert(b->exec_path);
     707             : 
     708           0 :         r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
     709           0 :         if (r < 0)
     710           0 :                 return -errno;
     711             : 
     712           0 :         pid = fork();
     713           0 :         if (pid < 0) {
     714           0 :                 safe_close_pair(s);
     715           0 :                 return -errno;
     716             :         }
     717           0 :         if (pid == 0) {
     718             :                 /* Child */
     719             : 
     720           0 :                 (void) reset_all_signal_handlers();
     721           0 :                 (void) reset_signal_mask();
     722             : 
     723           0 :                 close_all_fds(s+1, 1);
     724             : 
     725           0 :                 assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
     726           0 :                 assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
     727             : 
     728           0 :                 if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
     729           0 :                         safe_close(s[1]);
     730             : 
     731           0 :                 fd_cloexec(STDIN_FILENO, false);
     732           0 :                 fd_cloexec(STDOUT_FILENO, false);
     733           0 :                 fd_nonblock(STDIN_FILENO, false);
     734           0 :                 fd_nonblock(STDOUT_FILENO, false);
     735             : 
     736           0 :                 if (b->exec_argv)
     737           0 :                         execvp(b->exec_path, b->exec_argv);
     738             :                 else {
     739           0 :                         const char *argv[] = { b->exec_path, NULL };
     740           0 :                         execvp(b->exec_path, (char**) argv);
     741             :                 }
     742             : 
     743           0 :                 _exit(EXIT_FAILURE);
     744             :         }
     745             : 
     746           0 :         safe_close(s[1]);
     747           0 :         b->output_fd = b->input_fd = s[0];
     748             : 
     749           0 :         bus_socket_setup(b);
     750             : 
     751           0 :         return bus_socket_start_auth(b);
     752             : }
     753             : 
     754          16 : int bus_socket_take_fd(sd_bus *b) {
     755          16 :         assert(b);
     756             : 
     757          16 :         bus_socket_setup(b);
     758             : 
     759          16 :         return bus_socket_start_auth(b);
     760             : }
     761             : 
     762          71 : int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
     763             :         struct iovec *iov;
     764             :         ssize_t k;
     765             :         size_t n;
     766             :         unsigned j;
     767             :         int r;
     768             : 
     769          71 :         assert(bus);
     770          71 :         assert(m);
     771          71 :         assert(idx);
     772          71 :         assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
     773             : 
     774          71 :         if (*idx >= BUS_MESSAGE_SIZE(m))
     775           0 :                 return 0;
     776             : 
     777          71 :         r = bus_message_setup_iovec(m);
     778          71 :         if (r < 0)
     779           0 :                 return r;
     780             : 
     781          71 :         n = m->n_iovec * sizeof(struct iovec);
     782          71 :         iov = alloca(n);
     783          71 :         memcpy(iov, m->iovec, n);
     784             : 
     785          71 :         j = 0;
     786          71 :         iovec_advance(iov, &j, *idx);
     787             : 
     788          71 :         if (bus->prefer_writev)
     789           0 :                 k = writev(bus->output_fd, iov, m->n_iovec);
     790             :         else {
     791         142 :                 struct msghdr mh = {
     792             :                         .msg_iov = iov,
     793          71 :                         .msg_iovlen = m->n_iovec,
     794             :                 };
     795             : 
     796          71 :                 if (m->n_fds > 0) {
     797             :                         struct cmsghdr *control;
     798             : 
     799           0 :                         mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
     800           0 :                         mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
     801           0 :                         control->cmsg_level = SOL_SOCKET;
     802           0 :                         control->cmsg_type = SCM_RIGHTS;
     803           0 :                         memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
     804             :                 }
     805             : 
     806          71 :                 k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
     807          71 :                 if (k < 0 && errno == ENOTSOCK) {
     808           0 :                         bus->prefer_writev = true;
     809           0 :                         k = writev(bus->output_fd, iov, m->n_iovec);
     810             :                 }
     811             :         }
     812             : 
     813          71 :         if (k < 0)
     814           0 :                 return errno == EAGAIN ? 0 : -errno;
     815             : 
     816          71 :         *idx += (size_t) k;
     817          71 :         return 1;
     818             : }
     819             : 
     820         320 : static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
     821             :         uint32_t a, b;
     822             :         uint8_t e;
     823             :         uint64_t sum;
     824             : 
     825         320 :         assert(bus);
     826         320 :         assert(need);
     827         320 :         assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
     828             : 
     829         320 :         if (bus->rbuffer_size < sizeof(struct bus_header)) {
     830         138 :                 *need = sizeof(struct bus_header) + 8;
     831             : 
     832             :                 /* Minimum message size:
     833             :                  *
     834             :                  * Header +
     835             :                  *
     836             :                  *  Method Call: +2 string headers
     837             :                  *       Signal: +3 string headers
     838             :                  * Method Error: +1 string headers
     839             :                  *               +1 uint32 headers
     840             :                  * Method Reply: +1 uint32 headers
     841             :                  *
     842             :                  * A string header is at least 9 bytes
     843             :                  * A uint32 header is at least 8 bytes
     844             :                  *
     845             :                  * Hence the minimum message size of a valid message
     846             :                  * is header + 8 bytes */
     847             : 
     848         138 :                 return 0;
     849             :         }
     850             : 
     851         182 :         a = ((const uint32_t*) bus->rbuffer)[1];
     852         182 :         b = ((const uint32_t*) bus->rbuffer)[3];
     853             : 
     854         182 :         e = ((const uint8_t*) bus->rbuffer)[0];
     855         182 :         if (e == BUS_LITTLE_ENDIAN) {
     856         182 :                 a = le32toh(a);
     857         182 :                 b = le32toh(b);
     858           0 :         } else if (e == BUS_BIG_ENDIAN) {
     859           0 :                 a = be32toh(a);
     860           0 :                 b = be32toh(b);
     861             :         } else
     862           0 :                 return -EBADMSG;
     863             : 
     864         182 :         sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
     865         182 :         if (sum >= BUS_MESSAGE_SIZE_MAX)
     866           0 :                 return -ENOBUFS;
     867             : 
     868         182 :         *need = (size_t) sum;
     869         182 :         return 0;
     870             : }
     871             : 
     872          72 : static int bus_socket_make_message(sd_bus *bus, size_t size) {
     873             :         sd_bus_message *t;
     874             :         void *b;
     875             :         int r;
     876             : 
     877          72 :         assert(bus);
     878          72 :         assert(bus->rbuffer_size >= size);
     879          72 :         assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
     880             : 
     881          72 :         r = bus_rqueue_make_room(bus);
     882          72 :         if (r < 0)
     883           0 :                 return r;
     884             : 
     885          72 :         if (bus->rbuffer_size > size) {
     886           0 :                 b = memdup((const uint8_t*) bus->rbuffer + size,
     887           0 :                            bus->rbuffer_size - size);
     888           0 :                 if (!b)
     889           0 :                         return -ENOMEM;
     890             :         } else
     891          72 :                 b = NULL;
     892             : 
     893          72 :         r = bus_message_from_malloc(bus,
     894             :                                     bus->rbuffer, size,
     895             :                                     bus->fds, bus->n_fds,
     896             :                                     NULL,
     897             :                                     &t);
     898          72 :         if (r < 0) {
     899           0 :                 free(b);
     900           0 :                 return r;
     901             :         }
     902             : 
     903          72 :         bus->rbuffer = b;
     904          72 :         bus->rbuffer_size -= size;
     905             : 
     906          72 :         bus->fds = NULL;
     907          72 :         bus->n_fds = 0;
     908             : 
     909          72 :         bus->rqueue[bus->rqueue_size++] = t;
     910             : 
     911          72 :         return 1;
     912             : }
     913             : 
     914         193 : int bus_socket_read_message(sd_bus *bus) {
     915             :         struct msghdr mh;
     916         193 :         struct iovec iov = {};
     917             :         ssize_t k;
     918             :         size_t need;
     919             :         int r;
     920             :         void *b;
     921             :         union {
     922             :                 struct cmsghdr cmsghdr;
     923             :                 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
     924             :         } control;
     925         193 :         bool handle_cmsg = false;
     926             : 
     927         193 :         assert(bus);
     928         193 :         assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
     929             : 
     930         193 :         r = bus_socket_read_message_need(bus, &need);
     931         193 :         if (r < 0)
     932           0 :                 return r;
     933             : 
     934         193 :         if (bus->rbuffer_size >= need)
     935           0 :                 return bus_socket_make_message(bus, need);
     936             : 
     937         193 :         b = realloc(bus->rbuffer, need);
     938         193 :         if (!b)
     939           0 :                 return -ENOMEM;
     940             : 
     941         193 :         bus->rbuffer = b;
     942             : 
     943         193 :         iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
     944         193 :         iov.iov_len = need - bus->rbuffer_size;
     945             : 
     946         193 :         if (bus->prefer_readv)
     947           0 :                 k = readv(bus->input_fd, &iov, 1);
     948             :         else {
     949         193 :                 zero(mh);
     950         193 :                 mh.msg_iov = &iov;
     951         193 :                 mh.msg_iovlen = 1;
     952         193 :                 mh.msg_control = &control;
     953         193 :                 mh.msg_controllen = sizeof(control);
     954             : 
     955         193 :                 k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
     956         193 :                 if (k < 0 && errno == ENOTSOCK) {
     957           0 :                         bus->prefer_readv = true;
     958           0 :                         k = readv(bus->input_fd, &iov, 1);
     959             :                 } else
     960         193 :                         handle_cmsg = true;
     961             :         }
     962         193 :         if (k < 0)
     963          66 :                 return errno == EAGAIN ? 0 : -errno;
     964         127 :         if (k == 0)
     965           0 :                 return -ECONNRESET;
     966             : 
     967         127 :         bus->rbuffer_size += k;
     968             : 
     969         127 :         if (handle_cmsg) {
     970             :                 struct cmsghdr *cmsg;
     971             : 
     972         127 :                 CMSG_FOREACH(cmsg, &mh)
     973           0 :                         if (cmsg->cmsg_level == SOL_SOCKET &&
     974           0 :                             cmsg->cmsg_type == SCM_RIGHTS) {
     975             :                                 int n, *f;
     976             : 
     977           0 :                                 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
     978             : 
     979           0 :                                 if (!bus->can_fds) {
     980             :                                         /* Whut? We received fds but this
     981             :                                          * isn't actually enabled? Close them,
     982             :                                          * and fail */
     983             : 
     984           0 :                                         close_many((int*) CMSG_DATA(cmsg), n);
     985           0 :                                         return -EIO;
     986             :                                 }
     987             : 
     988           0 :                                 f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
     989           0 :                                 if (!f) {
     990           0 :                                         close_many((int*) CMSG_DATA(cmsg), n);
     991           0 :                                         return -ENOMEM;
     992             :                                 }
     993             : 
     994           0 :                                 memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
     995           0 :                                 bus->fds = f;
     996           0 :                                 bus->n_fds += n;
     997             :                         } else
     998           0 :                                 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
     999             :                                           cmsg->cmsg_level, cmsg->cmsg_type);
    1000             :         }
    1001             : 
    1002         127 :         r = bus_socket_read_message_need(bus, &need);
    1003         127 :         if (r < 0)
    1004           0 :                 return r;
    1005             : 
    1006         127 :         if (bus->rbuffer_size >= need)
    1007          72 :                 return bus_socket_make_message(bus, need);
    1008             : 
    1009          55 :         return 1;
    1010             : }
    1011             : 
    1012           0 : int bus_socket_process_opening(sd_bus *b) {
    1013           0 :         int error = 0;
    1014           0 :         socklen_t slen = sizeof(error);
    1015           0 :         struct pollfd p = {
    1016           0 :                 .fd = b->output_fd,
    1017             :                 .events = POLLOUT,
    1018             :         };
    1019             :         int r;
    1020             : 
    1021           0 :         assert(b->state == BUS_OPENING);
    1022             : 
    1023           0 :         r = poll(&p, 1, 0);
    1024           0 :         if (r < 0)
    1025           0 :                 return -errno;
    1026             : 
    1027           0 :         if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
    1028           0 :                 return 0;
    1029             : 
    1030           0 :         r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
    1031           0 :         if (r < 0)
    1032           0 :                 b->last_connect_error = errno;
    1033           0 :         else if (error != 0)
    1034           0 :                 b->last_connect_error = error;
    1035           0 :         else if (p.revents & (POLLERR|POLLHUP))
    1036           0 :                 b->last_connect_error = ECONNREFUSED;
    1037             :         else
    1038           0 :                 return bus_socket_start_auth(b);
    1039             : 
    1040           0 :         return bus_next_address(b);
    1041             : }
    1042             : 
    1043          37 : int bus_socket_process_authenticating(sd_bus *b) {
    1044             :         int r;
    1045             : 
    1046          37 :         assert(b);
    1047          37 :         assert(b->state == BUS_AUTHENTICATING);
    1048             : 
    1049          37 :         if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
    1050           0 :                 return -ETIMEDOUT;
    1051             : 
    1052          37 :         r = bus_socket_write_auth(b);
    1053          37 :         if (r != 0)
    1054           8 :                 return r;
    1055             : 
    1056          29 :         return bus_socket_read_auth(b);
    1057             : }

Generated by: LCOV version 1.11