LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-kernel.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 710 942 75.4 %
Date: 2015-07-29 18:47:03 Functions: 31 36 86.1 %

          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             : #ifdef HAVE_VALGRIND_MEMCHECK_H
      23             : #include <valgrind/memcheck.h>
      24             : #endif
      25             : 
      26             : #include <fcntl.h>
      27             : #include <malloc.h>
      28             : #include <sys/mman.h>
      29             : #include <sys/prctl.h>
      30             : 
      31             : /* When we include libgen.h because we need dirname() we immediately
      32             :  * undefine basename() since libgen.h defines it as a macro to the POSIX
      33             :  * version which is really broken. We prefer GNU basename(). */
      34             : #include <libgen.h>
      35             : #undef basename
      36             : 
      37             : #include "util.h"
      38             : #include "strv.h"
      39             : #include "memfd-util.h"
      40             : #include "capability.h"
      41             : #include "fileio.h"
      42             : #include "formats-util.h"
      43             : 
      44             : #include "bus-internal.h"
      45             : #include "bus-message.h"
      46             : #include "bus-kernel.h"
      47             : #include "bus-bloom.h"
      48             : #include "bus-util.h"
      49             : #include "bus-label.h"
      50             : 
      51             : #define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
      52             : 
      53       15502 : int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
      54             :         int r;
      55             : 
      56       15502 :         assert(s);
      57       15502 :         assert(id);
      58             : 
      59       15502 :         if (!startswith(s, ":1."))
      60          14 :                 return 0;
      61             : 
      62       15488 :         r = safe_atou64(s + 3, id);
      63       15488 :         if (r < 0)
      64           0 :                 return r;
      65             : 
      66       15488 :         return 1;
      67             : }
      68             : 
      69       31066 : static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
      70       31066 :         assert(d);
      71       31066 :         assert(sz > 0);
      72             : 
      73       31066 :         *d = ALIGN8_PTR(*d);
      74             : 
      75             :         /* Note that p can be NULL, which encodes a region full of
      76             :          * zeroes, which is useful to optimize certain padding
      77             :          * conditions */
      78             : 
      79       31066 :         (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
      80       31066 :         (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
      81       31066 :         (*d)->vec.address = PTR_TO_UINT64(p);
      82       31066 :         (*d)->vec.size = sz;
      83             : 
      84       31066 :         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
      85       31066 : }
      86             : 
      87           3 : static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) {
      88           3 :         assert(d);
      89           3 :         assert(memfd >= 0);
      90           3 :         assert(sz > 0);
      91             : 
      92           3 :         *d = ALIGN8_PTR(*d);
      93           3 :         (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
      94           3 :         (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
      95           3 :         (*d)->memfd.fd = memfd;
      96           3 :         (*d)->memfd.start = start;
      97           3 :         (*d)->memfd.size = sz;
      98             : 
      99           3 :         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
     100           3 : }
     101             : 
     102          10 : static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
     103          10 :         assert(d);
     104          10 :         assert(s);
     105             : 
     106          10 :         *d = ALIGN8_PTR(*d);
     107             : 
     108          10 :         (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
     109          10 :         (*d)->type = KDBUS_ITEM_DST_NAME;
     110          10 :         memcpy((*d)->str, s, length + 1);
     111             : 
     112          10 :         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
     113          10 : }
     114             : 
     115          33 : static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
     116             :         struct kdbus_item *i;
     117             : 
     118          33 :         assert(d);
     119             : 
     120          33 :         i = ALIGN8_PTR(*d);
     121             : 
     122          33 :         i->size = offsetof(struct kdbus_item, bloom_filter) +
     123          33 :                   offsetof(struct kdbus_bloom_filter, data) +
     124             :                   length;
     125          33 :         i->type = KDBUS_ITEM_BLOOM_FILTER;
     126             : 
     127          33 :         *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
     128             : 
     129          33 :         return &i->bloom_filter;
     130             : }
     131             : 
     132           2 : static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
     133           2 :         assert(d);
     134           2 :         assert(fds);
     135           2 :         assert(n_fds > 0);
     136             : 
     137           2 :         *d = ALIGN8_PTR(*d);
     138           2 :         (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
     139           2 :         (*d)->type = KDBUS_ITEM_FDS;
     140           2 :         memcpy((*d)->fds, fds, sizeof(int) * n_fds);
     141             : 
     142           2 :         *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
     143           2 : }
     144             : 
     145          32 : static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
     146             :         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
     147             :         char *e;
     148             : 
     149          32 :         assert(data);
     150          32 :         assert(size > 0);
     151          32 :         assert(i < 64);
     152          32 :         assert(t);
     153             : 
     154          32 :         e = stpcpy(buf, "arg");
     155          32 :         if (i < 10)
     156          32 :                 *(e++) = '0' + (char) i;
     157             :         else {
     158           0 :                 *(e++) = '0' + (char) (i / 10);
     159           0 :                 *(e++) = '0' + (char) (i % 10);
     160             :         }
     161             : 
     162          32 :         *e = 0;
     163          32 :         bloom_add_pair(data, size, n_hash, buf, t);
     164             : 
     165          32 :         strcpy(e, "-dot-prefix");
     166          32 :         bloom_add_prefixes(data, size, n_hash, buf, t, '.');
     167          32 :         strcpy(e, "-slash-prefix");
     168          32 :         bloom_add_prefixes(data, size, n_hash, buf, t, '/');
     169          32 : }
     170             : 
     171          33 : static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
     172             :         void *data;
     173             :         unsigned i;
     174             :         int r;
     175             : 
     176          33 :         assert(m);
     177          33 :         assert(bloom);
     178             : 
     179          33 :         data = bloom->data;
     180          33 :         memzero(data, m->bus->bloom_size);
     181          33 :         bloom->generation = 0;
     182             : 
     183          33 :         bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
     184             : 
     185          33 :         if (m->interface)
     186          33 :                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
     187          33 :         if (m->member)
     188          33 :                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
     189          33 :         if (m->path) {
     190          33 :                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
     191          33 :                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
     192          33 :                 bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
     193             :         }
     194             : 
     195          33 :         r = sd_bus_message_rewind(m, true);
     196          33 :         if (r < 0)
     197           0 :                 return r;
     198             : 
     199          70 :         for (i = 0; i < 64; i++) {
     200             :                 const char *t, *contents;
     201             :                 char type;
     202             : 
     203          35 :                 r = sd_bus_message_peek_type(m, &type, &contents);
     204          35 :                 if (r < 0)
     205           0 :                         return r;
     206             : 
     207          35 :                 if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
     208             : 
     209             :                         /* The bloom filter includes simple strings of any kind */
     210          30 :                         r = sd_bus_message_read_basic(m, type, &t);
     211          30 :                         if (r < 0)
     212           0 :                                 return r;
     213             : 
     214          30 :                         add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
     215          35 :                 } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
     216             : 
     217             :                         /* As well as array of simple strings of any kinds */
     218           2 :                         r = sd_bus_message_enter_container(m, type, contents);
     219           2 :                         if (r < 0)
     220           0 :                                 return r;
     221             : 
     222           6 :                         while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
     223           2 :                                 add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
     224           2 :                         if (r < 0)
     225           0 :                                 return r;
     226             : 
     227           2 :                         r = sd_bus_message_exit_container(m);
     228           2 :                         if (r < 0)
     229           0 :                                 return r;
     230             : 
     231             :                 } else
     232             :                         /* Stop adding to bloom filter as soon as we
     233             :                          * run into the first argument we cannot add
     234             :                          * to it. */
     235             :                         break;
     236             :         }
     237             : 
     238          33 :         return 0;
     239             : }
     240             : 
     241       15531 : static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
     242             :         struct bus_body_part *part;
     243             :         struct kdbus_item *d;
     244             :         const char *destination;
     245             :         bool well_known;
     246             :         uint64_t unique;
     247             :         size_t sz, dl;
     248             :         unsigned i;
     249             :         int r;
     250             : 
     251       15531 :         assert(b);
     252       15531 :         assert(m);
     253       15531 :         assert(m->sealed);
     254             : 
     255             :         /* We put this together only once, if this message is reused
     256             :          * we reuse the earlier-built version */
     257       15531 :         if (m->kdbus)
     258           0 :                 return 0;
     259             : 
     260       15531 :         destination = m->destination ?: m->destination_ptr;
     261             : 
     262       15531 :         if (destination) {
     263       15498 :                 r = bus_kernel_parse_unique_name(destination, &unique);
     264       15498 :                 if (r < 0)
     265           0 :                         return r;
     266             : 
     267       15498 :                 well_known = r == 0;
     268             :         } else
     269          33 :                 well_known = false;
     270             : 
     271       15531 :         sz = offsetof(struct kdbus_msg, items);
     272             : 
     273             :         /* Add in fixed header, fields header and payload */
     274       15531 :         sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) +
     275             :                                              MAX(sizeof(struct kdbus_vec),
     276             :                                                  sizeof(struct kdbus_memfd)));
     277             : 
     278             :         /* Add space for bloom filter */
     279       15531 :         sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
     280             :                      offsetof(struct kdbus_bloom_filter, data) +
     281             :                      m->bus->bloom_size);
     282             : 
     283             :         /* Add in well-known destination header */
     284       15531 :         if (well_known) {
     285          10 :                 dl = strlen(destination);
     286          10 :                 sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
     287             :         }
     288             : 
     289             :         /* Add space for unix fds */
     290       15531 :         if (m->n_fds > 0)
     291           2 :                 sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
     292             : 
     293       15531 :         m->kdbus = memalign(8, sz);
     294       15531 :         if (!m->kdbus) {
     295           0 :                 r = -ENOMEM;
     296           0 :                 goto fail;
     297             :         }
     298             : 
     299       15531 :         m->free_kdbus = true;
     300       15531 :         memzero(m->kdbus, sz);
     301             : 
     302       31062 :         m->kdbus->flags =
     303       31062 :                 ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
     304       31062 :                 ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
     305       15531 :                 ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
     306             : 
     307       15531 :         if (well_known)
     308             :                 /* verify_destination_id will usually be 0, which makes the kernel driver only look
     309             :                  * at the provided well-known name. Otherwise, the kernel will make sure the provided
     310             :                  * destination id matches the owner of the provided weel-known-name, and fail if they
     311             :                  * differ. Currently, this is only needed for bus-proxyd. */
     312          10 :                 m->kdbus->dst_id = m->verify_destination_id;
     313             :         else
     314       15521 :                 m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST;
     315             : 
     316       15531 :         m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
     317       15531 :         m->kdbus->cookie = m->header->dbus2.cookie;
     318       15531 :         m->kdbus->priority = m->priority;
     319             : 
     320       15531 :         if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     321       15524 :                 m->kdbus->cookie_reply = m->reply_cookie;
     322             :         else {
     323             :                 struct timespec now;
     324             : 
     325           7 :                 assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
     326          14 :                 m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
     327           7 :                                        m->timeout * NSEC_PER_USEC;
     328             :         }
     329             : 
     330       15531 :         d = m->kdbus->items;
     331             : 
     332       15531 :         if (well_known)
     333          10 :                 append_destination(&d, destination, dl);
     334             : 
     335       15531 :         append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
     336             : 
     337       31069 :         MESSAGE_FOREACH_PART(part, i, m) {
     338       15538 :                 if (part->is_zero) {
     339             :                         /* If this is padding then simply send a
     340             :                          * vector with a NULL data pointer which the
     341             :                          * kernel will just pass through. This is the
     342             :                          * most efficient way to encode zeroes */
     343             : 
     344           1 :                         append_payload_vec(&d, NULL, part->size);
     345           1 :                         continue;
     346             :                 }
     347             : 
     348       15537 :                 if (part->memfd >= 0 && part->sealed && destination) {
     349             :                         /* Try to send a memfd, if the part is
     350             :                          * sealed and this is not a broadcast. Since we can only  */
     351             : 
     352           3 :                         append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size);
     353           3 :                         continue;
     354             :                 }
     355             : 
     356             :                 /* Otherwise, let's send a vector to the actual data.
     357             :                  * For that, we need to map it first. */
     358       15534 :                 r = bus_body_part_map(part);
     359       15534 :                 if (r < 0)
     360           0 :                         goto fail;
     361             : 
     362       15534 :                 append_payload_vec(&d, part->data, part->size);
     363             :         }
     364             : 
     365       15531 :         if (m->header->type == SD_BUS_MESSAGE_SIGNAL) {
     366             :                 struct kdbus_bloom_filter *bloom;
     367             : 
     368          33 :                 bloom = append_bloom(&d, m->bus->bloom_size);
     369          33 :                 r = bus_message_setup_bloom(m, bloom);
     370          33 :                 if (r < 0)
     371           0 :                         goto fail;
     372             :         }
     373             : 
     374       15531 :         if (m->n_fds > 0)
     375           2 :                 append_fds(&d, m->fds, m->n_fds);
     376             : 
     377       15531 :         m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
     378       15531 :         assert(m->kdbus->size <= sz);
     379             : 
     380       15531 :         return 0;
     381             : 
     382             : fail:
     383           0 :         m->poisoned = true;
     384           0 :         return r;
     385             : }
     386             : 
     387           0 : static void unset_memfds(struct sd_bus_message *m) {
     388             :         struct bus_body_part *part;
     389             :         unsigned i;
     390             : 
     391           0 :         assert(m);
     392             : 
     393             :         /* Make sure the memfds are not freed twice */
     394           0 :         MESSAGE_FOREACH_PART(part, i, m)
     395           0 :                 if (part->memfd >= 0)
     396           0 :                         part->memfd = -1;
     397           0 : }
     398             : 
     399           6 : static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) {
     400           6 :         assert(bus);
     401           6 :         assert(m);
     402             : 
     403           6 :         if (!ts)
     404           0 :                 return;
     405             : 
     406           6 :         if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP))
     407           4 :                 return;
     408             : 
     409           2 :         m->realtime = ts->realtime_ns / NSEC_PER_USEC;
     410           2 :         m->monotonic = ts->monotonic_ns / NSEC_PER_USEC;
     411           2 :         m->seqnum = ts->seqnum;
     412             : }
     413             : 
     414       15516 : static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
     415       15516 :         sd_bus_message *m = NULL;
     416             :         struct kdbus_item *d;
     417       15516 :         unsigned n_fds = 0;
     418       31031 :         _cleanup_free_ int *fds = NULL;
     419       15516 :         struct bus_header *header = NULL;
     420       15516 :         void *footer = NULL;
     421       15516 :         size_t header_size = 0, footer_size = 0;
     422       15516 :         size_t n_bytes = 0, idx = 0;
     423       15516 :         const char *destination = NULL, *seclabel = NULL;
     424       15516 :         bool last_was_memfd = false;
     425             :         int r;
     426             : 
     427       15516 :         assert(bus);
     428       15516 :         assert(k);
     429       15516 :         assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
     430             : 
     431       61245 :         KDBUS_ITEM_FOREACH(d, k, items) {
     432             :                 size_t l;
     433             : 
     434       45729 :                 l = d->size - offsetof(struct kdbus_item, data);
     435             : 
     436       45729 :                 switch (d->type) {
     437             : 
     438             :                 case KDBUS_ITEM_PAYLOAD_OFF:
     439       38326 :                         if (!header) {
     440       15516 :                                 header = (struct bus_header*)((uint8_t*) k + d->vec.offset);
     441       15516 :                                 header_size = d->vec.size;
     442             :                         }
     443             : 
     444       38326 :                         footer = (uint8_t*) k + d->vec.offset;
     445       38326 :                         footer_size = d->vec.size;
     446             : 
     447       38326 :                         n_bytes += d->vec.size;
     448       38326 :                         last_was_memfd = false;
     449       38326 :                         break;
     450             : 
     451             :                 case KDBUS_ITEM_PAYLOAD_MEMFD:
     452        7347 :                         if (!header) /* memfd cannot be first part */
     453           0 :                                 return -EBADMSG;
     454             : 
     455        7347 :                         n_bytes += d->memfd.size;
     456        7347 :                         last_was_memfd = true;
     457        7347 :                         break;
     458             : 
     459             :                 case KDBUS_ITEM_FDS: {
     460             :                         int *f;
     461             :                         unsigned j;
     462             : 
     463           2 :                         j = l / sizeof(int);
     464           2 :                         f = realloc(fds, sizeof(int) * (n_fds + j));
     465           2 :                         if (!f)
     466           0 :                                 return -ENOMEM;
     467             : 
     468           2 :                         fds = f;
     469           2 :                         memcpy(fds + n_fds, d->fds, sizeof(int) * j);
     470           2 :                         n_fds += j;
     471           2 :                         break;
     472             :                 }
     473             : 
     474             :                 case KDBUS_ITEM_SECLABEL:
     475           0 :                         seclabel = d->str;
     476           0 :                         break;
     477             :                 }
     478             :         }
     479             : 
     480       15516 :         if (last_was_memfd) /* memfd cannot be last part */
     481           0 :                 return -EBADMSG;
     482             : 
     483       15516 :         if (!header)
     484           0 :                 return -EBADMSG;
     485             : 
     486       15516 :         if (header_size < sizeof(struct bus_header))
     487           0 :                 return -EBADMSG;
     488             : 
     489             :         /* on kdbus we only speak native endian gvariant, never dbus1
     490             :          * marshalling or reverse endian */
     491       31032 :         if (header->version != 2 ||
     492       15516 :             header->endian != BUS_NATIVE_ENDIAN)
     493           0 :                 return -EPROTOTYPE;
     494             : 
     495       15516 :         r = bus_message_from_header(
     496             :                         bus,
     497             :                         header, header_size,
     498             :                         footer, footer_size,
     499             :                         n_bytes,
     500             :                         fds, n_fds,
     501             :                         seclabel, 0, &m);
     502       15516 :         if (r < 0)
     503           0 :                 return r;
     504             : 
     505             :         /* The well-known names list is different from the other
     506             :         credentials. If we asked for it, but nothing is there, this
     507             :         means that the list of well-known names is simply empty, not
     508             :         that we lack any data */
     509             : 
     510       15516 :         m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
     511             : 
     512       61245 :         KDBUS_ITEM_FOREACH(d, k, items) {
     513             :                 size_t l;
     514             : 
     515       45729 :                 l = d->size - offsetof(struct kdbus_item, data);
     516             : 
     517       45729 :                 switch (d->type) {
     518             : 
     519             :                 case KDBUS_ITEM_PAYLOAD_OFF: {
     520             :                         size_t begin_body;
     521             : 
     522       38326 :                         begin_body = BUS_MESSAGE_BODY_BEGIN(m);
     523             : 
     524       38326 :                         if (idx + d->vec.size > begin_body) {
     525             :                                 struct bus_body_part *part;
     526             : 
     527             :                                 /* Contains body material */
     528             : 
     529       22810 :                                 part = message_append_part(m);
     530       22810 :                                 if (!part) {
     531           0 :                                         r = -ENOMEM;
     532           0 :                                         goto fail;
     533             :                                 }
     534             : 
     535             :                                 /* A -1 offset is NUL padding. */
     536       22810 :                                 part->is_zero = d->vec.offset == ~0ULL;
     537             : 
     538       22810 :                                 if (idx >= begin_body) {
     539       22810 :                                         if (!part->is_zero)
     540       22810 :                                                 part->data = (uint8_t* )k + d->vec.offset;
     541       22810 :                                         part->size = d->vec.size;
     542             :                                 } else {
     543           0 :                                         if (!part->is_zero)
     544           0 :                                                 part->data = (uint8_t*) k + d->vec.offset + (begin_body - idx);
     545           0 :                                         part->size = d->vec.size - (begin_body - idx);
     546             :                                 }
     547             : 
     548       22810 :                                 part->sealed = true;
     549             :                         }
     550             : 
     551       38326 :                         idx += d->vec.size;
     552       38326 :                         break;
     553             :                 }
     554             : 
     555             :                 case KDBUS_ITEM_PAYLOAD_MEMFD: {
     556             :                         struct bus_body_part *part;
     557             : 
     558        7347 :                         if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
     559           0 :                                 r = -EBADMSG;
     560           0 :                                 goto fail;
     561             :                         }
     562             : 
     563        7347 :                         part = message_append_part(m);
     564        7347 :                         if (!part) {
     565           0 :                                 r = -ENOMEM;
     566           0 :                                 goto fail;
     567             :                         }
     568             : 
     569        7347 :                         part->memfd = d->memfd.fd;
     570        7347 :                         part->memfd_offset = d->memfd.start;
     571        7347 :                         part->size = d->memfd.size;
     572        7347 :                         part->sealed = true;
     573             : 
     574        7347 :                         idx += d->memfd.size;
     575        7347 :                         break;
     576             :                 }
     577             : 
     578             :                 case KDBUS_ITEM_PIDS:
     579             : 
     580             :                         /* The PID/TID might be missing, when the data
     581             :                          * is faked by a bus proxy and it lacks that
     582             :                          * information about the real client (since
     583             :                          * SO_PEERCRED is used for that). Also kernel
     584             :                          * namespacing might make some of this data
     585             :                          * unavailable when untranslatable. */
     586             : 
     587           2 :                         if (d->pids.pid > 0) {
     588           2 :                                 m->creds.pid = (pid_t) d->pids.pid;
     589           2 :                                 m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
     590             :                         }
     591             : 
     592           2 :                         if (d->pids.tid > 0) {
     593           2 :                                 m->creds.tid = (pid_t) d->pids.tid;
     594           2 :                                 m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
     595             :                         }
     596             : 
     597           2 :                         if (d->pids.ppid > 0) {
     598           2 :                                 m->creds.ppid = (pid_t) d->pids.ppid;
     599           2 :                                 m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
     600           0 :                         } else if (d->pids.pid == 1) {
     601           0 :                                 m->creds.ppid = 0;
     602           0 :                                 m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
     603             :                         }
     604             : 
     605           2 :                         break;
     606             : 
     607             :                 case KDBUS_ITEM_CREDS:
     608             : 
     609             :                         /* EUID/SUID/FSUID/EGID/SGID/FSGID might be
     610             :                          * missing too (see above). */
     611             : 
     612           2 :                         if ((uid_t) d->creds.uid != UID_INVALID) {
     613           2 :                                 m->creds.uid = (uid_t) d->creds.uid;
     614           2 :                                 m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
     615             :                         }
     616             : 
     617           2 :                         if ((uid_t) d->creds.euid != UID_INVALID) {
     618           2 :                                 m->creds.euid = (uid_t) d->creds.euid;
     619           2 :                                 m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
     620             :                         }
     621             : 
     622           2 :                         if ((uid_t) d->creds.suid != UID_INVALID) {
     623           2 :                                 m->creds.suid = (uid_t) d->creds.suid;
     624           2 :                                 m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
     625             :                         }
     626             : 
     627           2 :                         if ((uid_t) d->creds.fsuid != UID_INVALID) {
     628           2 :                                 m->creds.fsuid = (uid_t) d->creds.fsuid;
     629           2 :                                 m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
     630             :                         }
     631             : 
     632           2 :                         if ((gid_t) d->creds.gid != GID_INVALID) {
     633           2 :                                 m->creds.gid = (gid_t) d->creds.gid;
     634           2 :                                 m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
     635             :                         }
     636             : 
     637           2 :                         if ((gid_t) d->creds.egid != GID_INVALID) {
     638           2 :                                 m->creds.egid = (gid_t) d->creds.egid;
     639           2 :                                 m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
     640             :                         }
     641             : 
     642           2 :                         if ((gid_t) d->creds.sgid != GID_INVALID) {
     643           2 :                                 m->creds.sgid = (gid_t) d->creds.sgid;
     644           2 :                                 m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
     645             :                         }
     646             : 
     647           2 :                         if ((gid_t) d->creds.fsgid != GID_INVALID) {
     648           2 :                                 m->creds.fsgid = (gid_t) d->creds.fsgid;
     649           2 :                                 m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
     650             :                         }
     651             : 
     652           2 :                         break;
     653             : 
     654             :                 case KDBUS_ITEM_TIMESTAMP:
     655           2 :                         message_set_timestamp(bus, m, &d->timestamp);
     656           2 :                         break;
     657             : 
     658             :                 case KDBUS_ITEM_PID_COMM:
     659           2 :                         m->creds.comm = d->str;
     660           2 :                         m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
     661           2 :                         break;
     662             : 
     663             :                 case KDBUS_ITEM_TID_COMM:
     664           2 :                         m->creds.tid_comm = d->str;
     665           2 :                         m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
     666           2 :                         break;
     667             : 
     668             :                 case KDBUS_ITEM_EXE:
     669           2 :                         m->creds.exe = d->str;
     670           2 :                         m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
     671           2 :                         break;
     672             : 
     673             :                 case KDBUS_ITEM_CMDLINE:
     674           2 :                         m->creds.cmdline = d->str;
     675           2 :                         m->creds.cmdline_size = l;
     676           2 :                         m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
     677           2 :                         break;
     678             : 
     679             :                 case KDBUS_ITEM_CGROUP:
     680           2 :                         m->creds.cgroup = d->str;
     681           2 :                         m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
     682             : 
     683           2 :                         r = bus_get_root_path(bus);
     684           2 :                         if (r < 0)
     685           0 :                                 goto fail;
     686             : 
     687           2 :                         m->creds.cgroup_root = bus->cgroup_root;
     688           2 :                         break;
     689             : 
     690             :                 case KDBUS_ITEM_AUDIT:
     691           0 :                         m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
     692           0 :                         m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
     693             : 
     694           0 :                         m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
     695           0 :                         m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
     696           0 :                         break;
     697             : 
     698             :                 case KDBUS_ITEM_CAPS:
     699           4 :                         if (d->caps.last_cap != cap_last_cap() ||
     700           2 :                             d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
     701           0 :                                 r = -EBADMSG;
     702           0 :                                 goto fail;
     703             :                         }
     704             : 
     705           2 :                         m->creds.capability = d->caps.caps;
     706           2 :                         m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
     707           2 :                         break;
     708             : 
     709             :                 case KDBUS_ITEM_DST_NAME:
     710           9 :                         if (!service_name_is_valid(d->str)) {
     711           0 :                                 r = -EBADMSG;
     712           0 :                                 goto fail;
     713             :                         }
     714             : 
     715           9 :                         destination = d->str;
     716           9 :                         break;
     717             : 
     718             :                 case KDBUS_ITEM_OWNED_NAME:
     719           3 :                         if (!service_name_is_valid(d->name.name)) {
     720           0 :                                 r = -EBADMSG;
     721           0 :                                 goto fail;
     722             :                         }
     723             : 
     724           3 :                         if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
     725             :                                 char **wkn;
     726             :                                 size_t n;
     727             : 
     728             :                                 /* We just extend the array here, but
     729             :                                  * do not allocate the strings inside
     730             :                                  * of it, instead we just point to our
     731             :                                  * buffer directly. */
     732           3 :                                 n = strv_length(m->creds.well_known_names);
     733           3 :                                 wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
     734           3 :                                 if (!wkn) {
     735           0 :                                         r = -ENOMEM;
     736           0 :                                         goto fail;
     737             :                                 }
     738             : 
     739           3 :                                 wkn[n] = d->name.name;
     740           3 :                                 wkn[n+1] = NULL;
     741           3 :                                 m->creds.well_known_names = wkn;
     742             : 
     743           3 :                                 m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
     744             :                         }
     745           3 :                         break;
     746             : 
     747             :                 case KDBUS_ITEM_CONN_DESCRIPTION:
     748           2 :                         m->creds.description = d->str;
     749           2 :                         m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
     750           2 :                         break;
     751             : 
     752             :                 case KDBUS_ITEM_AUXGROUPS:
     753             : 
     754           2 :                         if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
     755             :                                 size_t i, n;
     756             :                                 gid_t *g;
     757             : 
     758           2 :                                 n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
     759           2 :                                 g = new(gid_t, n);
     760           2 :                                 if (!g) {
     761           0 :                                         r = -ENOMEM;
     762           0 :                                         goto fail;
     763             :                                 }
     764             : 
     765           8 :                                 for (i = 0; i < n; i++)
     766           6 :                                         g[i] = d->data64[i];
     767             : 
     768           2 :                                 m->creds.supplementary_gids = g;
     769           2 :                                 m->creds.n_supplementary_gids = n;
     770           2 :                                 m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
     771             :                         }
     772             : 
     773           2 :                         break;
     774             : 
     775             :                 case KDBUS_ITEM_FDS:
     776             :                 case KDBUS_ITEM_SECLABEL:
     777           2 :                         break;
     778             : 
     779             :                 default:
     780          20 :                         log_debug("Got unknown field from kernel %llu", d->type);
     781             :                 }
     782             :         }
     783             : 
     784             :         /* If we requested the list of well-known names to be appended
     785             :          * and the sender had none no item for it will be
     786             :          * attached. However, this does *not* mean that the kernel
     787             :          * didn't want to provide this information to us. Hence, let's
     788             :          * explicitly mark this information as available if it was
     789             :          * requested. */
     790       15516 :         m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
     791             : 
     792       15516 :         r = bus_message_parse_fields(m);
     793       15516 :         if (r < 0)
     794           0 :                 goto fail;
     795             : 
     796             :         /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
     797       15516 :         if ((uint64_t) m->header->dbus2.cookie != k->cookie) {
     798           0 :                 r = -EBADMSG;
     799           0 :                 goto fail;
     800             :         }
     801             : 
     802             :         /* Refuse messages where the reply flag doesn't match up */
     803       15516 :         if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) {
     804           0 :                 r = -EBADMSG;
     805           0 :                 goto fail;
     806             :         }
     807             : 
     808             :         /* Refuse reply messages where the reply cookie doesn't match up */
     809       15516 :         if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
     810           0 :                 r = -EBADMSG;
     811           0 :                 goto fail;
     812             :         }
     813             : 
     814             :         /* Refuse messages where the autostart flag doesn't match up */
     815       15516 :         if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) {
     816           0 :                 r = -EBADMSG;
     817           0 :                 goto fail;
     818             :         }
     819             : 
     820             :         /* Override information from the user header with data from the kernel */
     821       15516 :         if (k->src_id == KDBUS_SRC_ID_KERNEL)
     822           0 :                 bus_message_set_sender_driver(bus, m);
     823             :         else {
     824       15516 :                 snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
     825       15516 :                 m->sender = m->creds.unique_name = m->sender_buffer;
     826             :         }
     827             : 
     828       15515 :         if (destination)
     829           8 :                 m->destination = destination;
     830       15507 :         else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
     831          20 :                 m->destination = NULL;
     832       15487 :         else if (k->dst_id == KDBUS_DST_ID_NAME)
     833           0 :                 m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
     834             :         else {
     835       15487 :                 snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
     836       15487 :                 m->destination = m->destination_buffer;
     837             :         }
     838             : 
     839             :         /* We take possession of the kmsg struct now */
     840       15515 :         m->kdbus = k;
     841       15515 :         m->release_kdbus = true;
     842       15515 :         m->free_fds = true;
     843       15515 :         fds = NULL;
     844             : 
     845       15515 :         bus->rqueue[bus->rqueue_size++] = m;
     846             : 
     847       15515 :         return 1;
     848             : 
     849             : fail:
     850           0 :         unset_memfds(m);
     851           0 :         sd_bus_message_unref(m);
     852             : 
     853           0 :         return r;
     854             : }
     855             : 
     856          76 : int bus_kernel_take_fd(sd_bus *b) {
     857          76 :         struct kdbus_bloom_parameter *bloom = NULL;
     858             :         struct kdbus_item *items, *item;
     859             :         struct kdbus_cmd_hello *hello;
     860         152 :         _cleanup_free_ char *g = NULL;
     861             :         const char *name;
     862          76 :         size_t l = 0, m = 0, sz;
     863             :         int r;
     864             : 
     865          76 :         assert(b);
     866             : 
     867          76 :         if (b->is_server)
     868           0 :                 return -EINVAL;
     869             : 
     870          76 :         b->use_memfd = 1;
     871             : 
     872          76 :         if (b->description) {
     873           1 :                 g = bus_label_escape(b->description);
     874           1 :                 if (!g)
     875           0 :                         return -ENOMEM;
     876             : 
     877           1 :                 name = g;
     878             :         } else {
     879          75 :                 char pr[17] = {};
     880             : 
     881             :                 /* If no name is explicitly set, we'll include a hint
     882             :                  * indicating the library implementation, a hint which
     883             :                  * kind of bus this is and the thread name */
     884             : 
     885          75 :                 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
     886             : 
     887          74 :                 if (isempty(pr)) {
     888           0 :                         name = b->is_system ? "sd-system" :
     889           0 :                                 b->is_user ? "sd-user" : "sd";
     890             :                 } else {
     891         148 :                         _cleanup_free_ char *e = NULL;
     892             : 
     893          74 :                         e = bus_label_escape(pr);
     894          75 :                         if (!e)
     895           0 :                                 return -ENOMEM;
     896             : 
     897         144 :                         g = strappend(b->is_system ? "sd-system-" :
     898          69 :                                       b->is_user ? "sd-user-" : "sd-",
     899             :                                       e);
     900          74 :                         if (!g)
     901           0 :                                 return -ENOMEM;
     902             : 
     903          74 :                         name = g;
     904             :                 }
     905             : 
     906          74 :                 b->description = bus_label_unescape(name);
     907          75 :                 if (!b->description)
     908           0 :                         return -ENOMEM;
     909             :         }
     910             : 
     911          76 :         m = strlen(name);
     912             : 
     913          76 :         sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
     914          76 :                 ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
     915             : 
     916          76 :         if (b->fake_creds_valid)
     917           0 :                 sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
     918             : 
     919          76 :         if (b->fake_pids_valid)
     920           0 :                 sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
     921             : 
     922          76 :         if (b->fake_label) {
     923           0 :                 l = strlen(b->fake_label);
     924           0 :                 sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
     925             :         }
     926             : 
     927          76 :         hello = alloca0_align(sz, 8);
     928          76 :         hello->size = sz;
     929          76 :         hello->flags = b->hello_flags;
     930          76 :         hello->attach_flags_send = _KDBUS_ATTACH_ANY;
     931          76 :         hello->attach_flags_recv = b->attach_flags;
     932          76 :         hello->pool_size = KDBUS_POOL_SIZE;
     933             : 
     934          76 :         item = hello->items;
     935             : 
     936          76 :         item->size = offsetof(struct kdbus_item, str) + m + 1;
     937          76 :         item->type = KDBUS_ITEM_CONN_DESCRIPTION;
     938          76 :         memcpy(item->str, name, m + 1);
     939          76 :         item = KDBUS_ITEM_NEXT(item);
     940             : 
     941          76 :         if (b->fake_creds_valid) {
     942           0 :                 item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
     943           0 :                 item->type = KDBUS_ITEM_CREDS;
     944           0 :                 item->creds = b->fake_creds;
     945             : 
     946           0 :                 item = KDBUS_ITEM_NEXT(item);
     947             :         }
     948             : 
     949          76 :         if (b->fake_pids_valid) {
     950           0 :                 item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
     951           0 :                 item->type = KDBUS_ITEM_PIDS;
     952           0 :                 item->pids = b->fake_pids;
     953             : 
     954           0 :                 item = KDBUS_ITEM_NEXT(item);
     955             :         }
     956             : 
     957          76 :         if (b->fake_label) {
     958           0 :                 item->size = offsetof(struct kdbus_item, str) + l + 1;
     959           0 :                 item->type = KDBUS_ITEM_SECLABEL;
     960           0 :                 memcpy(item->str, b->fake_label, l+1);
     961             :         }
     962             : 
     963          76 :         r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
     964          76 :         if (r < 0) {
     965           0 :                 if (errno == ENOTTY)
     966             :                         /* If the ioctl is not supported we assume that the
     967             :                          * API version changed in a major incompatible way,
     968             :                          * let's indicate an API incompatibility in this
     969             :                          * case. */
     970           0 :                         return -ESOCKTNOSUPPORT;
     971             : 
     972           0 :                 return -errno;
     973             :         }
     974             : 
     975          76 :         if (!b->kdbus_buffer) {
     976          76 :                 b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
     977          76 :                 if (b->kdbus_buffer == MAP_FAILED) {
     978           0 :                         b->kdbus_buffer = NULL;
     979           0 :                         r = -errno;
     980           0 :                         goto fail;
     981             :                 }
     982             :         }
     983             : 
     984             :         /* The higher 32bit of the bus_flags fields are considered
     985             :          * 'incompatible flags'. Refuse them all for now. */
     986          76 :         if (hello->bus_flags > 0xFFFFFFFFULL) {
     987           0 :                 r = -ESOCKTNOSUPPORT;
     988           0 :                 goto fail;
     989             :         }
     990             : 
     991             :         /* extract bloom parameters from items */
     992          76 :         items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
     993         152 :         KDBUS_FOREACH(item, items, hello->items_size) {
     994          76 :                 switch (item->type) {
     995             :                 case KDBUS_ITEM_BLOOM_PARAMETER:
     996          76 :                         bloom = &item->bloom_parameter;
     997          76 :                         break;
     998             :                 }
     999             :         }
    1000             : 
    1001          76 :         if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
    1002           0 :                 r = -EOPNOTSUPP;
    1003           0 :                 goto fail;
    1004             :         }
    1005             : 
    1006          76 :         b->bloom_size = (size_t) bloom->size;
    1007          76 :         b->bloom_n_hash = (unsigned) bloom->n_hash;
    1008             : 
    1009          76 :         if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) {
    1010           0 :                 r = -ENOMEM;
    1011           0 :                 goto fail;
    1012             :         }
    1013             : 
    1014          76 :         b->unique_id = hello->id;
    1015             : 
    1016          76 :         b->is_kernel = true;
    1017          76 :         b->bus_client = true;
    1018          76 :         b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
    1019          76 :         b->message_version = 2;
    1020          76 :         b->message_endian = BUS_NATIVE_ENDIAN;
    1021             : 
    1022             :         /* the kernel told us the UUID of the underlying bus */
    1023          76 :         memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
    1024             : 
    1025             :         /* free returned items */
    1026          76 :         (void) bus_kernel_cmd_free(b, hello->offset);
    1027          76 :         return bus_start_running(b);
    1028             : 
    1029             : fail:
    1030           0 :         (void) bus_kernel_cmd_free(b, hello->offset);
    1031           0 :         return r;
    1032             : }
    1033             : 
    1034          76 : int bus_kernel_connect(sd_bus *b) {
    1035          76 :         assert(b);
    1036          76 :         assert(b->input_fd < 0);
    1037          76 :         assert(b->output_fd < 0);
    1038          76 :         assert(b->kernel);
    1039             : 
    1040          76 :         if (b->is_server)
    1041           0 :                 return -EINVAL;
    1042             : 
    1043          76 :         b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
    1044          75 :         if (b->input_fd < 0)
    1045           0 :                 return -errno;
    1046             : 
    1047          75 :         b->output_fd = b->input_fd;
    1048             : 
    1049          75 :         return bus_kernel_take_fd(b);
    1050             : }
    1051             : 
    1052       15597 : int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
    1053       15597 :         struct kdbus_cmd_free cmd = {
    1054             :                 .size = sizeof(cmd),
    1055             :                 .offset = offset,
    1056             :         };
    1057             :         int r;
    1058             : 
    1059       15597 :         assert(bus);
    1060       15597 :         assert(bus->is_kernel);
    1061             : 
    1062       15597 :         r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
    1063       15597 :         if (r < 0)
    1064           1 :                 return -errno;
    1065             : 
    1066       15596 :         return 0;
    1067             : }
    1068             : 
    1069           4 : static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
    1070             :         struct kdbus_item *d;
    1071             : 
    1072           4 :         assert(bus);
    1073           4 :         assert(k);
    1074             : 
    1075          12 :         KDBUS_ITEM_FOREACH(d, k, items) {
    1076           8 :                 if (d->type == KDBUS_ITEM_FDS)
    1077           0 :                         close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
    1078           8 :                 else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
    1079           0 :                         safe_close(d->memfd.fd);
    1080             :         }
    1081             : 
    1082           4 :         bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
    1083           4 : }
    1084             : 
    1085       15531 : int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
    1086       15531 :         struct kdbus_cmd_send cmd = { };
    1087             :         int r;
    1088             : 
    1089       15531 :         assert(bus);
    1090       15531 :         assert(m);
    1091       15531 :         assert(bus->state == BUS_RUNNING);
    1092             : 
    1093             :         /* If we can't deliver, we want room for the error message */
    1094       15531 :         r = bus_rqueue_make_room(bus);
    1095       15531 :         if (r < 0)
    1096           0 :                 return r;
    1097             : 
    1098       15531 :         r = bus_message_setup_kmsg(bus, m);
    1099       15531 :         if (r < 0)
    1100           0 :                 return r;
    1101             : 
    1102       15531 :         cmd.size = sizeof(cmd);
    1103       15531 :         cmd.msg_address = (uintptr_t)m->kdbus;
    1104             : 
    1105             :         /* If this is a synchronous method call, then let's tell the
    1106             :          * kernel, so that it can pass CPU time/scheduling to the
    1107             :          * destination for the time, if it wants to. If we
    1108             :          * synchronously wait for the result anyway, we won't need CPU
    1109             :          * anyway. */
    1110       15531 :         if (hint_sync_call) {
    1111           5 :                 m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
    1112           5 :                 cmd.flags |= KDBUS_SEND_SYNC_REPLY;
    1113             :         }
    1114             : 
    1115       15531 :         r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
    1116       15531 :         if (r < 0) {
    1117           8 :                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
    1118             :                 sd_bus_message *reply;
    1119             : 
    1120           4 :                 if (errno == EAGAIN || errno == EINTR)
    1121           0 :                         return 0;
    1122           4 :                 else if (errno == ENXIO || errno == ESRCH) {
    1123             : 
    1124             :                         /* ENXIO: unique name not known
    1125             :                          * ESRCH: well-known name not known */
    1126             : 
    1127           4 :                         if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
    1128           1 :                                 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
    1129             :                         else {
    1130           2 :                                 log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
    1131           2 :                                 return 0;
    1132             :                         }
    1133             : 
    1134           1 :                 } else if (errno == EADDRNOTAVAIL) {
    1135             : 
    1136             :                         /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
    1137             : 
    1138           0 :                         if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
    1139           0 :                                 sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
    1140             :                         else {
    1141           0 :                                 log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
    1142           0 :                                 return 0;
    1143             :                         }
    1144             :                 } else
    1145           1 :                         return -errno;
    1146             : 
    1147           1 :                 r = bus_message_new_synthetic_error(
    1148             :                                 bus,
    1149             :                                 BUS_MESSAGE_COOKIE(m),
    1150             :                                 &error,
    1151             :                                 &reply);
    1152             : 
    1153           1 :                 if (r < 0)
    1154           0 :                         return r;
    1155             : 
    1156           1 :                 r = bus_seal_synthetic_message(bus, reply);
    1157           1 :                 if (r < 0)
    1158           0 :                         return r;
    1159             : 
    1160           1 :                 bus->rqueue[bus->rqueue_size++] = reply;
    1161             : 
    1162       15527 :         } else if (hint_sync_call) {
    1163             :                 struct kdbus_msg *k;
    1164             : 
    1165           3 :                 k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
    1166           3 :                 assert(k);
    1167             : 
    1168           3 :                 if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
    1169             : 
    1170           3 :                         r = bus_kernel_make_message(bus, k);
    1171           3 :                         if (r < 0) {
    1172           0 :                                 close_kdbus_msg(bus, k);
    1173             : 
    1174             :                                 /* Anybody can send us invalid messages, let's just drop them. */
    1175           0 :                                 if (r == -EBADMSG || r == -EPROTOTYPE)
    1176           0 :                                         log_debug_errno(r, "Ignoring invalid synchronous reply: %m");
    1177             :                                 else
    1178           0 :                                         return r;
    1179             :                         }
    1180             :                 } else {
    1181           0 :                         log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
    1182           0 :                         close_kdbus_msg(bus, k);
    1183             :                 }
    1184             :         }
    1185             : 
    1186       15528 :         return 1;
    1187             : }
    1188             : 
    1189           3 : static int push_name_owner_changed(
    1190             :                 sd_bus *bus,
    1191             :                 const char *name,
    1192             :                 const char *old_owner,
    1193             :                 const char *new_owner,
    1194             :                 const struct kdbus_timestamp *ts) {
    1195             : 
    1196           6 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
    1197             :         int r;
    1198             : 
    1199           3 :         assert(bus);
    1200             : 
    1201           3 :         r = sd_bus_message_new_signal(
    1202             :                         bus,
    1203             :                         &m,
    1204             :                         "/org/freedesktop/DBus",
    1205             :                         "org.freedesktop.DBus",
    1206             :                         "NameOwnerChanged");
    1207           3 :         if (r < 0)
    1208           0 :                 return r;
    1209             : 
    1210           3 :         r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
    1211           3 :         if (r < 0)
    1212           0 :                 return r;
    1213             : 
    1214           3 :         bus_message_set_sender_driver(bus, m);
    1215           3 :         message_set_timestamp(bus, m, ts);
    1216             : 
    1217           3 :         r = bus_seal_synthetic_message(bus, m);
    1218           3 :         if (r < 0)
    1219           0 :                 return r;
    1220             : 
    1221           3 :         bus->rqueue[bus->rqueue_size++] = m;
    1222           3 :         m = NULL;
    1223             : 
    1224           3 :         return 1;
    1225             : }
    1226             : 
    1227           0 : static int translate_name_change(
    1228             :                 sd_bus *bus,
    1229             :                 const struct kdbus_msg *k,
    1230             :                 const struct kdbus_item *d,
    1231             :                 const struct kdbus_timestamp *ts) {
    1232             : 
    1233             :         char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
    1234             : 
    1235           0 :         assert(bus);
    1236           0 :         assert(k);
    1237           0 :         assert(d);
    1238             : 
    1239           0 :         if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
    1240           0 :                 old_owner[0] = 0;
    1241             :         else
    1242           0 :                 sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
    1243             : 
    1244           0 :         if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
    1245             : 
    1246           0 :                 if (isempty(old_owner))
    1247           0 :                         return 0;
    1248             : 
    1249           0 :                 new_owner[0] = 0;
    1250             :         } else
    1251           0 :                 sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
    1252             : 
    1253           0 :         return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
    1254             : }
    1255             : 
    1256           3 : static int translate_id_change(
    1257             :                 sd_bus *bus,
    1258             :                 const struct kdbus_msg *k,
    1259             :                 const struct kdbus_item *d,
    1260             :                 const struct kdbus_timestamp *ts) {
    1261             : 
    1262             :         char owner[UNIQUE_NAME_MAX];
    1263             : 
    1264           3 :         assert(bus);
    1265           3 :         assert(k);
    1266           3 :         assert(d);
    1267             : 
    1268           3 :         sprintf(owner, ":1.%llu", d->id_change.id);
    1269             : 
    1270           6 :         return push_name_owner_changed(
    1271             :                         bus, owner,
    1272           3 :                         d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
    1273           3 :                         d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
    1274             :                         ts);
    1275             : }
    1276             : 
    1277           1 : static int translate_reply(
    1278             :                 sd_bus *bus,
    1279             :                 const struct kdbus_msg *k,
    1280             :                 const struct kdbus_item *d,
    1281             :                 const struct kdbus_timestamp *ts) {
    1282             : 
    1283           2 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
    1284             :         int r;
    1285             : 
    1286           1 :         assert(bus);
    1287           1 :         assert(k);
    1288           1 :         assert(d);
    1289             : 
    1290           3 :         r = bus_message_new_synthetic_error(
    1291             :                         bus,
    1292           1 :                         k->cookie_reply,
    1293           1 :                         d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
    1294           1 :                         &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
    1295           0 :                         &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
    1296             :                         &m);
    1297           1 :         if (r < 0)
    1298           0 :                 return r;
    1299             : 
    1300           1 :         message_set_timestamp(bus, m, ts);
    1301             : 
    1302           1 :         r = bus_seal_synthetic_message(bus, m);
    1303           1 :         if (r < 0)
    1304           0 :                 return r;
    1305             : 
    1306           1 :         bus->rqueue[bus->rqueue_size++] = m;
    1307           1 :         m = NULL;
    1308             : 
    1309           1 :         return 1;
    1310             : }
    1311             : 
    1312           4 : static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
    1313             :         static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
    1314             :                 [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
    1315             :                 [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
    1316             :                 [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
    1317             : 
    1318             :                 [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
    1319             :                 [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
    1320             : 
    1321             :                 [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
    1322             :                 [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
    1323             :         };
    1324             : 
    1325           4 :         struct kdbus_item *d, *found = NULL;
    1326           4 :         struct kdbus_timestamp *ts = NULL;
    1327             : 
    1328           4 :         assert(bus);
    1329           4 :         assert(k);
    1330           4 :         assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
    1331             : 
    1332          12 :         KDBUS_ITEM_FOREACH(d, k, items) {
    1333           8 :                 if (d->type == KDBUS_ITEM_TIMESTAMP)
    1334           4 :                         ts = &d->timestamp;
    1335           4 :                 else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
    1336           4 :                         if (found)
    1337           0 :                                 return -EBADMSG;
    1338           4 :                         found = d;
    1339             :                 } else
    1340           0 :                         log_debug("Got unknown field from kernel %llu", d->type);
    1341             :         }
    1342             : 
    1343           4 :         if (!found) {
    1344           0 :                 log_debug("Didn't find a kernel message to translate.");
    1345           0 :                 return 0;
    1346             :         }
    1347             : 
    1348           4 :         return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
    1349             : }
    1350             : 
    1351       31018 : int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
    1352       31018 :         struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
    1353             :         struct kdbus_msg *k;
    1354             :         int r;
    1355             : 
    1356       31018 :         assert(bus);
    1357             : 
    1358       31018 :         r = bus_rqueue_make_room(bus);
    1359       31018 :         if (r < 0)
    1360           0 :                 return r;
    1361             : 
    1362       31018 :         if (hint_priority) {
    1363           1 :                 recv.flags |= KDBUS_RECV_USE_PRIORITY;
    1364           1 :                 recv.priority = priority;
    1365             :         }
    1366             : 
    1367       31018 :         r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
    1368       31018 :         if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS)
    1369           0 :                 log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
    1370       31018 :         if (r < 0) {
    1371       15501 :                 if (errno == EAGAIN)
    1372       15501 :                         return 0;
    1373             : 
    1374           0 :                 return -errno;
    1375             :         }
    1376             : 
    1377       15517 :         k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
    1378       15517 :         if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
    1379       15513 :                 r = bus_kernel_make_message(bus, k);
    1380             : 
    1381             :                 /* Anybody can send us invalid messages, let's just drop them. */
    1382       15513 :                 if (r == -EBADMSG || r == -EPROTOTYPE) {
    1383           0 :                         log_debug_errno(r, "Ignoring invalid message: %m");
    1384           0 :                         r = 0;
    1385             :                 }
    1386             : 
    1387       15513 :                 if (r <= 0)
    1388           0 :                         close_kdbus_msg(bus, k);
    1389           4 :         } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
    1390           4 :                 r = bus_kernel_translate_message(bus, k);
    1391           4 :                 close_kdbus_msg(bus, k);
    1392             :         } else {
    1393           0 :                 log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
    1394           0 :                 r = 0;
    1395           0 :                 close_kdbus_msg(bus, k);
    1396             :         }
    1397             : 
    1398       15517 :         return r < 0 ? r : 1;
    1399             : }
    1400             : 
    1401       15578 : int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
    1402             :         struct memfd_cache *c;
    1403             :         int fd;
    1404             : 
    1405       15578 :         assert(address);
    1406       15578 :         assert(mapped);
    1407       15578 :         assert(allocated);
    1408             : 
    1409       15578 :         if (!bus || !bus->is_kernel)
    1410          35 :                 return -EOPNOTSUPP;
    1411             : 
    1412       15543 :         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
    1413             : 
    1414       15544 :         if (bus->n_memfd_cache <= 0) {
    1415             :                 int r;
    1416             : 
    1417          46 :                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
    1418             : 
    1419          46 :                 r = memfd_new(bus->description);
    1420          46 :                 if (r < 0)
    1421           0 :                         return r;
    1422             : 
    1423          46 :                 *address = NULL;
    1424          46 :                 *mapped = 0;
    1425          46 :                 *allocated = 0;
    1426          46 :                 return r;
    1427             :         }
    1428             : 
    1429       15498 :         c = &bus->memfd_cache[--bus->n_memfd_cache];
    1430             : 
    1431       15498 :         assert(c->fd >= 0);
    1432       15498 :         assert(c->mapped == 0 || c->address);
    1433             : 
    1434       15498 :         *address = c->address;
    1435       15498 :         *mapped = c->mapped;
    1436       15498 :         *allocated = c->allocated;
    1437       15498 :         fd = c->fd;
    1438             : 
    1439       15498 :         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
    1440             : 
    1441       15498 :         return fd;
    1442             : }
    1443             : 
    1444          46 : static void close_and_munmap(int fd, void *address, size_t size) {
    1445          46 :         if (size > 0)
    1446          46 :                 assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
    1447             : 
    1448          46 :         safe_close(fd);
    1449          46 : }
    1450             : 
    1451       15544 : void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
    1452             :         struct memfd_cache *c;
    1453       15544 :         uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
    1454             : 
    1455       15544 :         assert(fd >= 0);
    1456       15544 :         assert(mapped == 0 || address);
    1457             : 
    1458       15544 :         if (!bus || !bus->is_kernel) {
    1459           0 :                 close_and_munmap(fd, address, mapped);
    1460           0 :                 return;
    1461             :         }
    1462             : 
    1463       15544 :         assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
    1464             : 
    1465       15544 :         if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
    1466           0 :                 assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
    1467             : 
    1468           0 :                 close_and_munmap(fd, address, mapped);
    1469           0 :                 return;
    1470             :         }
    1471             : 
    1472       15544 :         c = &bus->memfd_cache[bus->n_memfd_cache++];
    1473       15544 :         c->fd = fd;
    1474       15544 :         c->address = address;
    1475             : 
    1476             :         /* If overly long, let's return a bit to the OS */
    1477       15544 :         if (mapped > max_mapped) {
    1478           0 :                 assert_se(memfd_set_size(fd, max_mapped) >= 0);
    1479           0 :                 assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
    1480           0 :                 c->mapped = c->allocated = max_mapped;
    1481             :         } else {
    1482       15544 :                 c->mapped = mapped;
    1483       15544 :                 c->allocated = allocated;
    1484             :         }
    1485             : 
    1486       15544 :         assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
    1487             : }
    1488             : 
    1489          94 : void bus_kernel_flush_memfd(sd_bus *b) {
    1490             :         unsigned i;
    1491             : 
    1492          94 :         assert(b);
    1493             : 
    1494         140 :         for (i = 0; i < b->n_memfd_cache; i++)
    1495          46 :                 close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
    1496          94 : }
    1497             : 
    1498           2 : uint64_t request_name_flags_to_kdbus(uint64_t flags) {
    1499           2 :         uint64_t f = 0;
    1500             : 
    1501           2 :         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
    1502           0 :                 f |= KDBUS_NAME_ALLOW_REPLACEMENT;
    1503             : 
    1504           2 :         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
    1505           0 :                 f |= KDBUS_NAME_REPLACE_EXISTING;
    1506             : 
    1507           2 :         if (flags & SD_BUS_NAME_QUEUE)
    1508           0 :                 f |= KDBUS_NAME_QUEUE;
    1509             : 
    1510           2 :         return f;
    1511             : }
    1512             : 
    1513           3 : uint64_t attach_flags_to_kdbus(uint64_t mask) {
    1514           3 :         uint64_t m = 0;
    1515             : 
    1516           3 :         if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
    1517             :                     SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
    1518           2 :                 m |= KDBUS_ATTACH_CREDS;
    1519             : 
    1520           3 :         if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
    1521           2 :                 m |= KDBUS_ATTACH_PIDS;
    1522             : 
    1523           3 :         if (mask & SD_BUS_CREDS_COMM)
    1524           2 :                 m |= KDBUS_ATTACH_PID_COMM;
    1525             : 
    1526           3 :         if (mask & SD_BUS_CREDS_TID_COMM)
    1527           2 :                 m |= KDBUS_ATTACH_TID_COMM;
    1528             : 
    1529           3 :         if (mask & SD_BUS_CREDS_EXE)
    1530           2 :                 m |= KDBUS_ATTACH_EXE;
    1531             : 
    1532           3 :         if (mask & SD_BUS_CREDS_CMDLINE)
    1533           2 :                 m |= KDBUS_ATTACH_CMDLINE;
    1534             : 
    1535           3 :         if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
    1536           2 :                 m |= KDBUS_ATTACH_CGROUP;
    1537             : 
    1538           3 :         if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
    1539           2 :                 m |= KDBUS_ATTACH_CAPS;
    1540             : 
    1541           3 :         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
    1542           2 :                 m |= KDBUS_ATTACH_SECLABEL;
    1543             : 
    1544           3 :         if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
    1545           2 :                 m |= KDBUS_ATTACH_AUDIT;
    1546             : 
    1547           3 :         if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
    1548           3 :                 m |= KDBUS_ATTACH_NAMES;
    1549             : 
    1550           3 :         if (mask & SD_BUS_CREDS_DESCRIPTION)
    1551           2 :                 m |= KDBUS_ATTACH_CONN_DESCRIPTION;
    1552             : 
    1553           3 :         if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
    1554           2 :                 m |= KDBUS_ATTACH_AUXGROUPS;
    1555             : 
    1556           3 :         return m;
    1557             : }
    1558             : 
    1559          34 : int bus_kernel_create_bus(const char *name, bool world, char **s) {
    1560             :         struct kdbus_cmd *make;
    1561             :         struct kdbus_item *n;
    1562             :         size_t l;
    1563             :         int fd;
    1564             : 
    1565          34 :         assert(name);
    1566          34 :         assert(s);
    1567             : 
    1568          34 :         fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
    1569          34 :         if (fd < 0)
    1570           0 :                 return -errno;
    1571             : 
    1572          34 :         l = strlen(name);
    1573          34 :         make = alloca0_align(offsetof(struct kdbus_cmd, items) +
    1574             :                              ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
    1575             :                              ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
    1576             :                              ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
    1577             :                              8);
    1578             : 
    1579          34 :         make->size = offsetof(struct kdbus_cmd, items);
    1580             : 
    1581             :         /* Set the bloom parameters */
    1582          34 :         n = make->items;
    1583          34 :         n->size = offsetof(struct kdbus_item, bloom_parameter) +
    1584             :                   sizeof(struct kdbus_bloom_parameter);
    1585          34 :         n->type = KDBUS_ITEM_BLOOM_PARAMETER;
    1586          34 :         n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
    1587          34 :         n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
    1588             : 
    1589             :         assert_cc(DEFAULT_BLOOM_SIZE > 0);
    1590             :         assert_cc(DEFAULT_BLOOM_N_HASH > 0);
    1591             : 
    1592          34 :         make->size += ALIGN8(n->size);
    1593             : 
    1594             :         /* Provide all metadata via bus-owner queries */
    1595          34 :         n = KDBUS_ITEM_NEXT(n);
    1596          34 :         n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
    1597          34 :         n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
    1598          34 :         n->data64[0] = _KDBUS_ATTACH_ANY;
    1599          34 :         make->size += ALIGN8(n->size);
    1600             : 
    1601             :         /* Set the a good name */
    1602          34 :         n = KDBUS_ITEM_NEXT(n);
    1603          34 :         sprintf(n->str, UID_FMT "-%s", getuid(), name);
    1604          34 :         n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
    1605          34 :         n->type = KDBUS_ITEM_MAKE_NAME;
    1606          34 :         make->size += ALIGN8(n->size);
    1607             : 
    1608          34 :         make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
    1609             : 
    1610          34 :         if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
    1611           0 :                 safe_close(fd);
    1612             : 
    1613             :                 /* Major API change? then the ioctls got shuffled around. */
    1614           0 :                 if (errno == ENOTTY)
    1615           0 :                         return -ESOCKTNOSUPPORT;
    1616             : 
    1617           0 :                 return -errno;
    1618             :         }
    1619             : 
    1620          34 :         if (s) {
    1621             :                 char *p;
    1622             : 
    1623          34 :                 p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
    1624          34 :                 if (!p) {
    1625           0 :                         safe_close(fd);
    1626           0 :                         return -ENOMEM;
    1627             :                 }
    1628             : 
    1629          34 :                 *s = p;
    1630             :         }
    1631             : 
    1632          34 :         return fd;
    1633             : }
    1634             : 
    1635           0 : int bus_kernel_open_bus_fd(const char *bus, char **path) {
    1636             :         char *p;
    1637             :         int fd;
    1638             :         size_t len;
    1639             : 
    1640           0 :         assert(bus);
    1641             : 
    1642           0 :         len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
    1643             : 
    1644           0 :         if (path) {
    1645           0 :                 p = new(char, len);
    1646           0 :                 if (!p)
    1647           0 :                         return -ENOMEM;
    1648             :         } else
    1649           0 :                 p = newa(char, len);
    1650             : 
    1651           0 :         sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
    1652             : 
    1653           0 :         fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
    1654           0 :         if (fd < 0) {
    1655           0 :                 if (path)
    1656           0 :                         free(p);
    1657             : 
    1658           0 :                 return -errno;
    1659             :         }
    1660             : 
    1661           0 :         if (path)
    1662           0 :                 *path = p;
    1663             : 
    1664           0 :         return fd;
    1665             : }
    1666             : 
    1667           0 : int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
    1668           0 :         _cleanup_free_ char *path = NULL;
    1669             :         struct kdbus_cmd *make;
    1670             :         struct kdbus_item *n;
    1671             :         const char *name;
    1672             :         int fd;
    1673             : 
    1674           0 :         fd = bus_kernel_open_bus_fd(bus_name, &path);
    1675           0 :         if (fd < 0)
    1676           0 :                 return fd;
    1677             : 
    1678           0 :         make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd, items)) +
    1679             :                              ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
    1680             :                              8);
    1681           0 :         make->size = ALIGN8(offsetof(struct kdbus_cmd, items));
    1682           0 :         make->flags = KDBUS_MAKE_ACCESS_WORLD;
    1683             : 
    1684           0 :         n = make->items;
    1685           0 :         sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
    1686           0 :         n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
    1687           0 :         n->type = KDBUS_ITEM_MAKE_NAME;
    1688           0 :         make->size += ALIGN8(n->size);
    1689           0 :         name = n->str;
    1690             : 
    1691           0 :         if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
    1692           0 :                 safe_close(fd);
    1693           0 :                 return -errno;
    1694             :         }
    1695             : 
    1696           0 :         if (ep_path) {
    1697             :                 char *p;
    1698             : 
    1699           0 :                 p = strjoin(dirname(path), "/", name, NULL);
    1700           0 :                 if (!p) {
    1701           0 :                         safe_close(fd);
    1702           0 :                         return -ENOMEM;
    1703             :                 }
    1704             : 
    1705           0 :                 *ep_path = p;
    1706             :         }
    1707             : 
    1708           0 :         return fd;
    1709             : }
    1710             : 
    1711           2 : int bus_kernel_try_close(sd_bus *bus) {
    1712           2 :         struct kdbus_cmd byebye = { .size = sizeof(byebye) };
    1713             : 
    1714           2 :         assert(bus);
    1715           2 :         assert(bus->is_kernel);
    1716             : 
    1717           2 :         if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
    1718           1 :                 return -errno;
    1719             : 
    1720           1 :         return 0;
    1721             : }
    1722             : 
    1723           0 : int bus_kernel_drop_one(int fd) {
    1724           0 :         struct kdbus_cmd_recv recv = {
    1725             :                 .size = sizeof(recv),
    1726             :                 .flags = KDBUS_RECV_DROP,
    1727             :         };
    1728             : 
    1729           0 :         assert(fd >= 0);
    1730             : 
    1731           0 :         if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
    1732           0 :                 return -errno;
    1733             : 
    1734           0 :         return 0;
    1735             : }
    1736             : 
    1737           2 : int bus_kernel_realize_attach_flags(sd_bus *bus) {
    1738             :         struct kdbus_cmd *update;
    1739             :         struct kdbus_item *n;
    1740             : 
    1741           2 :         assert(bus);
    1742           2 :         assert(bus->is_kernel);
    1743             : 
    1744           2 :         update = alloca0_align(offsetof(struct kdbus_cmd, items) +
    1745             :                                ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
    1746             :                                8);
    1747             : 
    1748           2 :         n = update->items;
    1749           2 :         n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
    1750           2 :         n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
    1751           2 :         n->data64[0] = bus->attach_flags;
    1752             : 
    1753           2 :         update->size =
    1754           2 :                 offsetof(struct kdbus_cmd, items) +
    1755           2 :                 ALIGN8(n->size);
    1756             : 
    1757           2 :         if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
    1758           0 :                 return -errno;
    1759             : 
    1760           2 :         return 0;
    1761             : }
    1762             : 
    1763           1 : int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
    1764           1 :         struct kdbus_cmd_info cmd = {
    1765             :                 .size = sizeof(struct kdbus_cmd_info),
    1766             :         };
    1767             :         struct kdbus_info *info;
    1768             :         struct kdbus_item *item;
    1769           1 :         char *n = NULL;
    1770             :         int r;
    1771             : 
    1772           1 :         assert(bus);
    1773           1 :         assert(name);
    1774           1 :         assert(bus->is_kernel);
    1775             : 
    1776           1 :         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
    1777           1 :         if (r < 0)
    1778           0 :                 return -errno;
    1779             : 
    1780           1 :         info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
    1781             : 
    1782           1 :         KDBUS_ITEM_FOREACH(item, info, items)
    1783           1 :                 if (item->type == KDBUS_ITEM_MAKE_NAME) {
    1784           1 :                         r = free_and_strdup(&n, item->str);
    1785           1 :                         break;
    1786             :                 }
    1787             : 
    1788           1 :         bus_kernel_cmd_free(bus, cmd.offset);
    1789             : 
    1790           1 :         if (r < 0)
    1791           0 :                 return r;
    1792           1 :         if (!n)
    1793           0 :                 return -EIO;
    1794             : 
    1795           1 :         *name = n;
    1796           1 :         return 0;
    1797             : }

Generated by: LCOV version 1.11