LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-control.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 240 769 31.2 %
Date: 2015-07-29 18:47:03 Functions: 14 26 53.8 %

          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 <stddef.h>
      27             : #include <errno.h>
      28             : 
      29             : #include "strv.h"
      30             : #include "sd-bus.h"
      31             : #include "bus-internal.h"
      32             : #include "bus-message.h"
      33             : #include "bus-control.h"
      34             : #include "bus-bloom.h"
      35             : #include "bus-util.h"
      36             : #include "capability.h"
      37             : 
      38           6 : _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
      39             :         int r;
      40             : 
      41           6 :         assert_return(bus, -EINVAL);
      42           6 :         assert_return(unique, -EINVAL);
      43           6 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      44             : 
      45           6 :         if (!bus->bus_client)
      46           0 :                 return -EINVAL;
      47             : 
      48           6 :         r = bus_ensure_running(bus);
      49           6 :         if (r < 0)
      50           0 :                 return r;
      51             : 
      52           6 :         *unique = bus->unique_name;
      53           6 :         return 0;
      54             : }
      55             : 
      56           2 : static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
      57             :         struct kdbus_cmd *n;
      58             :         size_t size, l;
      59             :         int r;
      60             : 
      61           2 :         assert(bus);
      62           2 :         assert(name);
      63             : 
      64           2 :         l = strlen(name) + 1;
      65           2 :         size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
      66           2 :         n = alloca0_align(size, 8);
      67           2 :         n->size = size;
      68           2 :         n->flags = request_name_flags_to_kdbus(flags);
      69             : 
      70           2 :         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
      71           2 :         n->items[0].type = KDBUS_ITEM_NAME;
      72           2 :         memcpy(n->items[0].str, name, l);
      73             : 
      74             : #ifdef HAVE_VALGRIND_MEMCHECK_H
      75           2 :         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
      76             : #endif
      77             : 
      78           2 :         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
      79           2 :         if (r < 0)
      80           0 :                 return -errno;
      81             : 
      82           2 :         if (n->return_flags & KDBUS_NAME_IN_QUEUE)
      83           0 :                 return 0;
      84             : 
      85           2 :         return 1;
      86             : }
      87             : 
      88           0 : static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
      89           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
      90           0 :         uint32_t ret, param = 0;
      91             :         int r;
      92             : 
      93           0 :         assert(bus);
      94           0 :         assert(name);
      95             : 
      96           0 :         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
      97           0 :                 param |= BUS_NAME_ALLOW_REPLACEMENT;
      98           0 :         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
      99           0 :                 param |= BUS_NAME_REPLACE_EXISTING;
     100           0 :         if (!(flags & SD_BUS_NAME_QUEUE))
     101           0 :                 param |= BUS_NAME_DO_NOT_QUEUE;
     102             : 
     103           0 :         r = sd_bus_call_method(
     104             :                         bus,
     105             :                         "org.freedesktop.DBus",
     106             :                         "/org/freedesktop/DBus",
     107             :                         "org.freedesktop.DBus",
     108             :                         "RequestName",
     109             :                         NULL,
     110             :                         &reply,
     111             :                         "su",
     112             :                         name,
     113             :                         param);
     114           0 :         if (r < 0)
     115           0 :                 return r;
     116             : 
     117           0 :         r = sd_bus_message_read(reply, "u", &ret);
     118           0 :         if (r < 0)
     119           0 :                 return r;
     120             : 
     121           0 :         if (ret == BUS_NAME_ALREADY_OWNER)
     122           0 :                 return -EALREADY;
     123           0 :         else if (ret == BUS_NAME_EXISTS)
     124           0 :                 return -EEXIST;
     125           0 :         else if (ret == BUS_NAME_IN_QUEUE)
     126           0 :                 return 0;
     127           0 :         else if (ret == BUS_NAME_PRIMARY_OWNER)
     128           0 :                 return 1;
     129             : 
     130           0 :         return -EIO;
     131             : }
     132             : 
     133           2 : _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
     134           2 :         assert_return(bus, -EINVAL);
     135           2 :         assert_return(name, -EINVAL);
     136           2 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     137           2 :         assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
     138           2 :         assert_return(service_name_is_valid(name), -EINVAL);
     139           2 :         assert_return(name[0] != ':', -EINVAL);
     140             : 
     141           2 :         if (!bus->bus_client)
     142           0 :                 return -EINVAL;
     143             : 
     144             :         /* Don't allow requesting the special driver and local names */
     145           2 :         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
     146           0 :                 return -EINVAL;
     147             : 
     148           2 :         if (!BUS_IS_OPEN(bus->state))
     149           0 :                 return -ENOTCONN;
     150             : 
     151           2 :         if (bus->is_kernel)
     152           2 :                 return bus_request_name_kernel(bus, name, flags);
     153             :         else
     154           0 :                 return bus_request_name_dbus1(bus, name, flags);
     155             : }
     156             : 
     157           2 : static int bus_release_name_kernel(sd_bus *bus, const char *name) {
     158             :         struct kdbus_cmd *n;
     159             :         size_t size, l;
     160             :         int r;
     161             : 
     162           2 :         assert(bus);
     163           2 :         assert(name);
     164             : 
     165           2 :         l = strlen(name) + 1;
     166           2 :         size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
     167           2 :         n = alloca0_align(size, 8);
     168           2 :         n->size = size;
     169             : 
     170           2 :         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
     171           2 :         n->items[0].type = KDBUS_ITEM_NAME;
     172           2 :         memcpy(n->items[0].str, name, l);
     173             : 
     174             : #ifdef HAVE_VALGRIND_MEMCHECK_H
     175           2 :         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
     176             : #endif
     177           2 :         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
     178           2 :         if (r < 0)
     179           1 :                 return -errno;
     180             : 
     181           1 :         return 0;
     182             : }
     183             : 
     184           0 : static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
     185           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
     186             :         uint32_t ret;
     187             :         int r;
     188             : 
     189           0 :         assert(bus);
     190           0 :         assert(name);
     191             : 
     192           0 :         r = sd_bus_call_method(
     193             :                         bus,
     194             :                         "org.freedesktop.DBus",
     195             :                         "/org/freedesktop/DBus",
     196             :                         "org.freedesktop.DBus",
     197             :                         "ReleaseName",
     198             :                         NULL,
     199             :                         &reply,
     200             :                         "s",
     201             :                         name);
     202           0 :         if (r < 0)
     203           0 :                 return r;
     204             : 
     205           0 :         r = sd_bus_message_read(reply, "u", &ret);
     206           0 :         if (r < 0)
     207           0 :                 return r;
     208           0 :         if (ret == BUS_NAME_NON_EXISTENT)
     209           0 :                 return -ESRCH;
     210           0 :         if (ret == BUS_NAME_NOT_OWNER)
     211           0 :                 return -EADDRINUSE;
     212           0 :         if (ret == BUS_NAME_RELEASED)
     213           0 :                 return 0;
     214             : 
     215           0 :         return -EINVAL;
     216             : }
     217             : 
     218           2 : _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
     219           2 :         assert_return(bus, -EINVAL);
     220           2 :         assert_return(name, -EINVAL);
     221           2 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     222           2 :         assert_return(service_name_is_valid(name), -EINVAL);
     223           2 :         assert_return(name[0] != ':', -EINVAL);
     224             : 
     225           2 :         if (!bus->bus_client)
     226           0 :                 return -EINVAL;
     227             : 
     228             :         /* Don't allow releasing the special driver and local names */
     229           2 :         if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
     230           0 :                 return -EINVAL;
     231             : 
     232           2 :         if (!BUS_IS_OPEN(bus->state))
     233           0 :                 return -ENOTCONN;
     234             : 
     235           2 :         if (bus->is_kernel)
     236           2 :                 return bus_release_name_kernel(bus, name);
     237             :         else
     238           0 :                 return bus_release_name_dbus1(bus, name);
     239             : }
     240             : 
     241           0 : static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
     242           0 :         struct kdbus_cmd_list cmd = {
     243             :                 .size = sizeof(cmd),
     244             :                 .flags = flags,
     245             :         };
     246             :         struct kdbus_info *name_list, *name;
     247           0 :         uint64_t previous_id = 0;
     248             :         int r;
     249             : 
     250             :         /* Caller will free half-constructed list on failure... */
     251             : 
     252           0 :         r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
     253           0 :         if (r < 0)
     254           0 :                 return -errno;
     255             : 
     256           0 :         name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
     257             : 
     258           0 :         KDBUS_FOREACH(name, name_list, cmd.list_size) {
     259             : 
     260             :                 struct kdbus_item *item;
     261           0 :                 const char *entry_name = NULL;
     262             : 
     263           0 :                 if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id) {
     264             :                         char *n;
     265             : 
     266           0 :                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
     267           0 :                                 r = -ENOMEM;
     268           0 :                                 goto fail;
     269             :                         }
     270             : 
     271           0 :                         r = strv_consume(x, n);
     272           0 :                         if (r < 0)
     273           0 :                                 goto fail;
     274             : 
     275           0 :                         previous_id = name->id;
     276             :                 }
     277             : 
     278           0 :                 KDBUS_ITEM_FOREACH(item, name, items)
     279           0 :                         if (item->type == KDBUS_ITEM_OWNED_NAME)
     280           0 :                                 entry_name = item->name.name;
     281             : 
     282           0 :                 if (entry_name && service_name_is_valid(entry_name)) {
     283           0 :                         r = strv_extend(x, entry_name);
     284           0 :                         if (r < 0) {
     285           0 :                                 r = -ENOMEM;
     286           0 :                                 goto fail;
     287             :                         }
     288             :                 }
     289             :         }
     290             : 
     291           0 :         r = 0;
     292             : 
     293             : fail:
     294           0 :         bus_kernel_cmd_free(bus, cmd.offset);
     295           0 :         return r;
     296             : }
     297             : 
     298           0 : static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
     299           0 :         _cleanup_strv_free_ char **x = NULL, **y = NULL;
     300             :         int r;
     301             : 
     302           0 :         if (acquired) {
     303           0 :                 r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
     304           0 :                 if (r < 0)
     305           0 :                         return r;
     306             :         }
     307             : 
     308           0 :         if (activatable) {
     309           0 :                 r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
     310           0 :                 if (r < 0)
     311           0 :                         return r;
     312             : 
     313           0 :                 *activatable = y;
     314           0 :                 y = NULL;
     315             :         }
     316             : 
     317           0 :         if (acquired) {
     318           0 :                 *acquired = x;
     319           0 :                 x = NULL;
     320             :         }
     321             : 
     322           0 :         return 0;
     323             : }
     324             : 
     325           0 : static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
     326           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
     327           0 :         _cleanup_strv_free_ char **x = NULL, **y = NULL;
     328             :         int r;
     329             : 
     330           0 :         if (acquired) {
     331           0 :                 r = sd_bus_call_method(
     332             :                                 bus,
     333             :                                 "org.freedesktop.DBus",
     334             :                                 "/org/freedesktop/DBus",
     335             :                                 "org.freedesktop.DBus",
     336             :                                 "ListNames",
     337             :                                 NULL,
     338             :                                 &reply,
     339             :                                 NULL);
     340           0 :                 if (r < 0)
     341           0 :                         return r;
     342             : 
     343           0 :                 r = sd_bus_message_read_strv(reply, &x);
     344           0 :                 if (r < 0)
     345           0 :                         return r;
     346             : 
     347           0 :                 reply = sd_bus_message_unref(reply);
     348             :         }
     349             : 
     350           0 :         if (activatable) {
     351           0 :                 r = sd_bus_call_method(
     352             :                                 bus,
     353             :                                 "org.freedesktop.DBus",
     354             :                                 "/org/freedesktop/DBus",
     355             :                                 "org.freedesktop.DBus",
     356             :                                 "ListActivatableNames",
     357             :                                 NULL,
     358             :                                 &reply,
     359             :                                 NULL);
     360           0 :                 if (r < 0)
     361           0 :                         return r;
     362             : 
     363           0 :                 r = sd_bus_message_read_strv(reply, &y);
     364           0 :                 if (r < 0)
     365           0 :                         return r;
     366             : 
     367           0 :                 *activatable = y;
     368           0 :                 y = NULL;
     369             :         }
     370             : 
     371           0 :         if (acquired) {
     372           0 :                 *acquired = x;
     373           0 :                 x = NULL;
     374             :         }
     375             : 
     376           0 :         return 0;
     377             : }
     378             : 
     379           0 : _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
     380           0 :         assert_return(bus, -EINVAL);
     381           0 :         assert_return(acquired || activatable, -EINVAL);
     382           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     383             : 
     384           0 :         if (!bus->bus_client)
     385           0 :                 return -EINVAL;
     386             : 
     387           0 :         if (!BUS_IS_OPEN(bus->state))
     388           0 :                 return -ENOTCONN;
     389             : 
     390           0 :         if (bus->is_kernel)
     391           0 :                 return bus_list_names_kernel(bus, acquired, activatable);
     392             :         else
     393           0 :                 return bus_list_names_dbus1(bus, acquired, activatable);
     394             : }
     395             : 
     396           0 : static int bus_populate_creds_from_items(
     397             :                 sd_bus *bus,
     398             :                 struct kdbus_info *info,
     399             :                 uint64_t mask,
     400             :                 sd_bus_creds *c) {
     401             : 
     402             :         struct kdbus_item *item;
     403             :         uint64_t m;
     404             :         int r;
     405             : 
     406           0 :         assert(bus);
     407           0 :         assert(info);
     408           0 :         assert(c);
     409             : 
     410           0 :         KDBUS_ITEM_FOREACH(item, info, items) {
     411             : 
     412           0 :                 switch (item->type) {
     413             : 
     414             :                 case KDBUS_ITEM_PIDS:
     415             : 
     416           0 :                         if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
     417           0 :                                 c->pid = (pid_t) item->pids.pid;
     418           0 :                                 c->mask |= SD_BUS_CREDS_PID;
     419             :                         }
     420             : 
     421           0 :                         if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
     422           0 :                                 c->tid = (pid_t) item->pids.tid;
     423           0 :                                 c->mask |= SD_BUS_CREDS_TID;
     424             :                         }
     425             : 
     426           0 :                         if (mask & SD_BUS_CREDS_PPID) {
     427           0 :                                 if (item->pids.ppid > 0) {
     428           0 :                                         c->ppid = (pid_t) item->pids.ppid;
     429           0 :                                         c->mask |= SD_BUS_CREDS_PPID;
     430           0 :                                 } else if (item->pids.pid == 1) {
     431             :                                         /* The structure doesn't
     432             :                                          * really distinguish the case
     433             :                                          * where a process has no
     434             :                                          * parent and where we don't
     435             :                                          * know it because it could
     436             :                                          * not be translated due to
     437             :                                          * namespaces. However, we
     438             :                                          * know that PID 1 has no
     439             :                                          * parent process, hence let's
     440             :                                          * patch that in, manually. */
     441           0 :                                         c->ppid = 0;
     442           0 :                                         c->mask |= SD_BUS_CREDS_PPID;
     443             :                                 }
     444             :                         }
     445             : 
     446           0 :                         break;
     447             : 
     448             :                 case KDBUS_ITEM_CREDS:
     449             : 
     450           0 :                         if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
     451           0 :                                 c->uid = (uid_t) item->creds.uid;
     452           0 :                                 c->mask |= SD_BUS_CREDS_UID;
     453             :                         }
     454             : 
     455           0 :                         if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
     456           0 :                                 c->euid = (uid_t) item->creds.euid;
     457           0 :                                 c->mask |= SD_BUS_CREDS_EUID;
     458             :                         }
     459             : 
     460           0 :                         if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
     461           0 :                                 c->suid = (uid_t) item->creds.suid;
     462           0 :                                 c->mask |= SD_BUS_CREDS_SUID;
     463             :                         }
     464             : 
     465           0 :                         if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
     466           0 :                                 c->fsuid = (uid_t) item->creds.fsuid;
     467           0 :                                 c->mask |= SD_BUS_CREDS_FSUID;
     468             :                         }
     469             : 
     470           0 :                         if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
     471           0 :                                 c->gid = (gid_t) item->creds.gid;
     472           0 :                                 c->mask |= SD_BUS_CREDS_GID;
     473             :                         }
     474             : 
     475           0 :                         if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
     476           0 :                                 c->egid = (gid_t) item->creds.egid;
     477           0 :                                 c->mask |= SD_BUS_CREDS_EGID;
     478             :                         }
     479             : 
     480           0 :                         if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
     481           0 :                                 c->sgid = (gid_t) item->creds.sgid;
     482           0 :                                 c->mask |= SD_BUS_CREDS_SGID;
     483             :                         }
     484             : 
     485           0 :                         if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
     486           0 :                                 c->fsgid = (gid_t) item->creds.fsgid;
     487           0 :                                 c->mask |= SD_BUS_CREDS_FSGID;
     488             :                         }
     489             : 
     490           0 :                         break;
     491             : 
     492             :                 case KDBUS_ITEM_PID_COMM:
     493           0 :                         if (mask & SD_BUS_CREDS_COMM) {
     494           0 :                                 r = free_and_strdup(&c->comm, item->str);
     495           0 :                                 if (r < 0)
     496           0 :                                         return r;
     497             : 
     498           0 :                                 c->mask |= SD_BUS_CREDS_COMM;
     499             :                         }
     500           0 :                         break;
     501             : 
     502             :                 case KDBUS_ITEM_TID_COMM:
     503           0 :                         if (mask & SD_BUS_CREDS_TID_COMM) {
     504           0 :                                 r = free_and_strdup(&c->tid_comm, item->str);
     505           0 :                                 if (r < 0)
     506           0 :                                         return r;
     507             : 
     508           0 :                                 c->mask |= SD_BUS_CREDS_TID_COMM;
     509             :                         }
     510           0 :                         break;
     511             : 
     512             :                 case KDBUS_ITEM_EXE:
     513           0 :                         if (mask & SD_BUS_CREDS_EXE) {
     514           0 :                                 r = free_and_strdup(&c->exe, item->str);
     515           0 :                                 if (r < 0)
     516           0 :                                         return r;
     517             : 
     518           0 :                                 c->mask |= SD_BUS_CREDS_EXE;
     519             :                         }
     520           0 :                         break;
     521             : 
     522             :                 case KDBUS_ITEM_CMDLINE:
     523           0 :                         if (mask & SD_BUS_CREDS_CMDLINE) {
     524           0 :                                 c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
     525           0 :                                 c->cmdline = memdup(item->data, c->cmdline_size);
     526           0 :                                 if (!c->cmdline)
     527           0 :                                         return -ENOMEM;
     528             : 
     529           0 :                                 c->mask |= SD_BUS_CREDS_CMDLINE;
     530             :                         }
     531           0 :                         break;
     532             : 
     533             :                 case KDBUS_ITEM_CGROUP:
     534           0 :                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
     535             :                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
     536             :                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
     537             : 
     538           0 :                         if (m) {
     539           0 :                                 r = free_and_strdup(&c->cgroup, item->str);
     540           0 :                                 if (r < 0)
     541           0 :                                         return r;
     542             : 
     543           0 :                                 r = bus_get_root_path(bus);
     544           0 :                                 if (r < 0)
     545           0 :                                         return r;
     546             : 
     547           0 :                                 r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
     548           0 :                                 if (r < 0)
     549           0 :                                         return r;
     550             : 
     551           0 :                                 c->mask |= m;
     552             :                         }
     553           0 :                         break;
     554             : 
     555             :                 case KDBUS_ITEM_CAPS:
     556           0 :                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
     557             :                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
     558             : 
     559           0 :                         if (m) {
     560           0 :                                 if (item->caps.last_cap != cap_last_cap() ||
     561           0 :                                     item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
     562           0 :                                         return -EBADMSG;
     563             : 
     564           0 :                                 c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
     565           0 :                                 if (!c->capability)
     566           0 :                                         return -ENOMEM;
     567             : 
     568           0 :                                 c->mask |= m;
     569             :                         }
     570           0 :                         break;
     571             : 
     572             :                 case KDBUS_ITEM_SECLABEL:
     573           0 :                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
     574           0 :                                 r = free_and_strdup(&c->label, item->str);
     575           0 :                                 if (r < 0)
     576           0 :                                         return r;
     577             : 
     578           0 :                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
     579             :                         }
     580           0 :                         break;
     581             : 
     582             :                 case KDBUS_ITEM_AUDIT:
     583           0 :                         if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
     584           0 :                                 c->audit_session_id = (uint32_t) item->audit.sessionid;
     585           0 :                                 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
     586             :                         }
     587             : 
     588           0 :                         if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
     589           0 :                                 c->audit_login_uid = (uid_t) item->audit.loginuid;
     590           0 :                                 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
     591             :                         }
     592           0 :                         break;
     593             : 
     594             :                 case KDBUS_ITEM_OWNED_NAME:
     595           0 :                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
     596           0 :                                 r = strv_extend(&c->well_known_names, item->name.name);
     597           0 :                                 if (r < 0)
     598           0 :                                         return r;
     599             : 
     600           0 :                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
     601             :                         }
     602           0 :                         break;
     603             : 
     604             :                 case KDBUS_ITEM_CONN_DESCRIPTION:
     605           0 :                         if (mask & SD_BUS_CREDS_DESCRIPTION) {
     606           0 :                                 r = free_and_strdup(&c->description, item->str);
     607           0 :                                 if (r < 0)
     608           0 :                                         return r;
     609             : 
     610           0 :                                 c->mask |= SD_BUS_CREDS_DESCRIPTION;
     611             :                         }
     612           0 :                         break;
     613             : 
     614             :                 case KDBUS_ITEM_AUXGROUPS:
     615           0 :                         if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
     616             :                                 size_t i, n;
     617             :                                 uid_t *g;
     618             : 
     619           0 :                                 n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
     620           0 :                                 g = new(gid_t, n);
     621           0 :                                 if (!g)
     622           0 :                                         return -ENOMEM;
     623             : 
     624           0 :                                 for (i = 0; i < n; i++)
     625           0 :                                         g[i] = item->data64[i];
     626             : 
     627           0 :                                 free(c->supplementary_gids);
     628           0 :                                 c->supplementary_gids = g;
     629           0 :                                 c->n_supplementary_gids = n;
     630             : 
     631           0 :                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
     632             :                         }
     633           0 :                         break;
     634             :                 }
     635             :         }
     636             : 
     637           0 :         return 0;
     638             : }
     639             : 
     640           0 : int bus_get_name_creds_kdbus(
     641             :                 sd_bus *bus,
     642             :                 const char *name,
     643             :                 uint64_t mask,
     644             :                 bool allow_activator,
     645             :                 sd_bus_creds **creds) {
     646             : 
     647           0 :         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
     648             :         struct kdbus_cmd_info *cmd;
     649             :         struct kdbus_info *conn_info;
     650             :         size_t size, l;
     651             :         uint64_t id;
     652             :         int r;
     653             : 
     654           0 :         if (streq(name, "org.freedesktop.DBus"))
     655           0 :                 return -EOPNOTSUPP;
     656             : 
     657           0 :         r = bus_kernel_parse_unique_name(name, &id);
     658           0 :         if (r < 0)
     659           0 :                 return r;
     660           0 :         if (r > 0) {
     661           0 :                 size = offsetof(struct kdbus_cmd_info, items);
     662           0 :                 cmd = alloca0_align(size, 8);
     663           0 :                 cmd->id = id;
     664             :         } else {
     665           0 :                 l = strlen(name) + 1;
     666           0 :                 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
     667           0 :                 cmd = alloca0_align(size, 8);
     668           0 :                 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
     669           0 :                 cmd->items[0].type = KDBUS_ITEM_NAME;
     670           0 :                 memcpy(cmd->items[0].str, name, l);
     671             :         }
     672             : 
     673             :         /* If augmentation is on, and the bus didn't provide us
     674             :          * the bits we want, then ask for the PID/TID so that we
     675             :          * can read the rest from /proc. */
     676           0 :         if ((mask & SD_BUS_CREDS_AUGMENT) &&
     677           0 :             (mask & (SD_BUS_CREDS_PPID|
     678             :                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
     679             :                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
     680             :                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
     681             :                      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|
     682             :                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
     683             :                      SD_BUS_CREDS_SELINUX_CONTEXT|
     684             :                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
     685           0 :                 mask |= SD_BUS_CREDS_PID;
     686             : 
     687           0 :         cmd->size = size;
     688           0 :         cmd->attach_flags = attach_flags_to_kdbus(mask);
     689             : 
     690           0 :         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
     691           0 :         if (r < 0)
     692           0 :                 return -errno;
     693             : 
     694           0 :         conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
     695             : 
     696             :         /* Non-activated names are considered not available */
     697           0 :         if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
     698           0 :                 if (name[0] == ':')
     699           0 :                         r = -ENXIO;
     700             :                 else
     701           0 :                         r = -ESRCH;
     702           0 :                 goto fail;
     703             :         }
     704             : 
     705           0 :         c = bus_creds_new();
     706           0 :         if (!c) {
     707           0 :                 r = -ENOMEM;
     708           0 :                 goto fail;
     709             :         }
     710             : 
     711           0 :         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
     712           0 :                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
     713           0 :                         r = -ENOMEM;
     714           0 :                         goto fail;
     715             :                 }
     716             : 
     717           0 :                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
     718             :         }
     719             : 
     720             :         /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
     721             :            them in case the service has no names. This does not mean
     722             :            however that the list of owned names could not be
     723             :            acquired. Hence, let's explicitly clarify that the data is
     724             :            complete. */
     725           0 :         c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
     726             : 
     727           0 :         r = bus_populate_creds_from_items(bus, conn_info, mask, c);
     728           0 :         if (r < 0)
     729           0 :                 goto fail;
     730             : 
     731           0 :         r = bus_creds_add_more(c, mask, 0, 0);
     732           0 :         if (r < 0)
     733           0 :                 goto fail;
     734             : 
     735           0 :         if (creds) {
     736           0 :                 *creds = c;
     737           0 :                 c = NULL;
     738             :         }
     739             : 
     740           0 :         r = 0;
     741             : 
     742             : fail:
     743           0 :         bus_kernel_cmd_free(bus, cmd->offset);
     744           0 :         return r;
     745             : }
     746             : 
     747           0 : static int bus_get_name_creds_dbus1(
     748             :                 sd_bus *bus,
     749             :                 const char *name,
     750             :                 uint64_t mask,
     751             :                 sd_bus_creds **creds) {
     752             : 
     753           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
     754           0 :         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
     755           0 :         const char *unique = NULL;
     756           0 :         pid_t pid = 0;
     757             :         int r;
     758             : 
     759             :         /* Only query the owner if the caller wants to know it or if
     760             :          * the caller just wants to check whether a name exists */
     761           0 :         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
     762           0 :                 r = sd_bus_call_method(
     763             :                                 bus,
     764             :                                 "org.freedesktop.DBus",
     765             :                                 "/org/freedesktop/DBus",
     766             :                                 "org.freedesktop.DBus",
     767             :                                 "GetNameOwner",
     768             :                                 NULL,
     769             :                                 &reply_unique,
     770             :                                 "s",
     771             :                                 name);
     772           0 :                 if (r < 0)
     773           0 :                         return r;
     774             : 
     775           0 :                 r = sd_bus_message_read(reply_unique, "s", &unique);
     776           0 :                 if (r < 0)
     777           0 :                         return r;
     778             :         }
     779             : 
     780           0 :         if (mask != 0) {
     781           0 :                 c = bus_creds_new();
     782           0 :                 if (!c)
     783           0 :                         return -ENOMEM;
     784             : 
     785           0 :                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
     786           0 :                         c->unique_name = strdup(unique);
     787           0 :                         if (!c->unique_name)
     788           0 :                                 return -ENOMEM;
     789             : 
     790           0 :                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
     791             :                 }
     792             : 
     793           0 :                 if ((mask & SD_BUS_CREDS_PID) ||
     794           0 :                     ((mask & SD_BUS_CREDS_AUGMENT) &&
     795           0 :                      (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
     796             :                               SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
     797             :                               SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
     798             :                               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|
     799             :                               SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
     800             :                               SD_BUS_CREDS_SELINUX_CONTEXT|
     801             :                               SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
     802             : 
     803             :                         uint32_t u;
     804             : 
     805           0 :                         r = sd_bus_call_method(
     806             :                                         bus,
     807             :                                         "org.freedesktop.DBus",
     808             :                                         "/org/freedesktop/DBus",
     809             :                                         "org.freedesktop.DBus",
     810             :                                         "GetConnectionUnixProcessID",
     811             :                                         NULL,
     812             :                                         &reply,
     813             :                                         "s",
     814           0 :                                         unique ? unique : name);
     815           0 :                         if (r < 0)
     816           0 :                                 return r;
     817             : 
     818           0 :                         r = sd_bus_message_read(reply, "u", &u);
     819           0 :                         if (r < 0)
     820           0 :                                 return r;
     821             : 
     822           0 :                         pid = u;
     823           0 :                         if (mask & SD_BUS_CREDS_PID) {
     824           0 :                                 c->pid = u;
     825           0 :                                 c->mask |= SD_BUS_CREDS_PID;
     826             :                         }
     827             : 
     828           0 :                         reply = sd_bus_message_unref(reply);
     829             :                 }
     830             : 
     831           0 :                 if (mask & SD_BUS_CREDS_EUID) {
     832             :                         uint32_t u;
     833             : 
     834           0 :                         r = sd_bus_call_method(
     835             :                                         bus,
     836             :                                         "org.freedesktop.DBus",
     837             :                                         "/org/freedesktop/DBus",
     838             :                                         "org.freedesktop.DBus",
     839             :                                         "GetConnectionUnixUser",
     840             :                                         NULL,
     841             :                                         &reply,
     842             :                                         "s",
     843           0 :                                         unique ? unique : name);
     844           0 :                         if (r < 0)
     845           0 :                                 return r;
     846             : 
     847           0 :                         r = sd_bus_message_read(reply, "u", &u);
     848           0 :                         if (r < 0)
     849           0 :                                 return r;
     850             : 
     851           0 :                         c->euid = u;
     852           0 :                         c->mask |= SD_BUS_CREDS_EUID;
     853             : 
     854           0 :                         reply = sd_bus_message_unref(reply);
     855             :                 }
     856             : 
     857           0 :                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
     858           0 :                         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
     859           0 :                         const void *p = NULL;
     860           0 :                         size_t sz = 0;
     861             : 
     862           0 :                         r = sd_bus_call_method(
     863             :                                         bus,
     864             :                                         "org.freedesktop.DBus",
     865             :                                         "/org/freedesktop/DBus",
     866             :                                         "org.freedesktop.DBus",
     867             :                                         "GetConnectionSELinuxSecurityContext",
     868             :                                         &error,
     869             :                                         &reply,
     870             :                                         "s",
     871           0 :                                         unique ? unique : name);
     872           0 :                         if (r < 0) {
     873           0 :                                 if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
     874           0 :                                         return r;
     875             :                         } else {
     876           0 :                                 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
     877           0 :                                 if (r < 0)
     878           0 :                                         return r;
     879             : 
     880           0 :                                 c->label = strndup(p, sz);
     881           0 :                                 if (!c->label)
     882           0 :                                         return -ENOMEM;
     883             : 
     884           0 :                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
     885             :                         }
     886             :                 }
     887             : 
     888           0 :                 r = bus_creds_add_more(c, mask, pid, 0);
     889           0 :                 if (r < 0)
     890           0 :                         return r;
     891             :         }
     892             : 
     893           0 :         if (creds) {
     894           0 :                 *creds = c;
     895           0 :                 c = NULL;
     896             :         }
     897             : 
     898           0 :         return 0;
     899             : }
     900             : 
     901           0 : _public_ int sd_bus_get_name_creds(
     902             :                 sd_bus *bus,
     903             :                 const char *name,
     904             :                 uint64_t mask,
     905             :                 sd_bus_creds **creds) {
     906             : 
     907           0 :         assert_return(bus, -EINVAL);
     908           0 :         assert_return(name, -EINVAL);
     909           0 :         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
     910           0 :         assert_return(mask == 0 || creds, -EINVAL);
     911           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     912           0 :         assert_return(service_name_is_valid(name), -EINVAL);
     913             : 
     914           0 :         if (!bus->bus_client)
     915           0 :                 return -EINVAL;
     916             : 
     917           0 :         if (streq(name, "org.freedesktop.DBus.Local"))
     918           0 :                 return -EINVAL;
     919             : 
     920           0 :         if (!BUS_IS_OPEN(bus->state))
     921           0 :                 return -ENOTCONN;
     922             : 
     923           0 :         if (bus->is_kernel)
     924           0 :                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
     925             :         else
     926           0 :                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
     927             : }
     928             : 
     929           0 : static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
     930           0 :         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
     931           0 :         struct kdbus_cmd_info cmd = {
     932             :                 .size = sizeof(struct kdbus_cmd_info),
     933             :         };
     934             :         struct kdbus_info *creator_info;
     935           0 :         pid_t pid = 0;
     936             :         int r;
     937             : 
     938           0 :         c = bus_creds_new();
     939           0 :         if (!c)
     940           0 :                 return -ENOMEM;
     941             : 
     942             :         /* If augmentation is on, and the bus doesn't didn't allow us
     943             :          * to get the bits we want, then ask for the PID/TID so that we
     944             :          * can read the rest from /proc. */
     945           0 :         if ((mask & SD_BUS_CREDS_AUGMENT) &&
     946           0 :             (mask & (SD_BUS_CREDS_PPID|
     947             :                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
     948             :                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
     949             :                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
     950             :                      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|
     951             :                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
     952             :                      SD_BUS_CREDS_SELINUX_CONTEXT|
     953             :                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
     954           0 :                 mask |= SD_BUS_CREDS_PID;
     955             : 
     956           0 :         cmd.attach_flags = attach_flags_to_kdbus(mask);
     957             : 
     958           0 :         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
     959           0 :         if (r < 0)
     960           0 :                 return -errno;
     961             : 
     962           0 :         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
     963             : 
     964           0 :         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
     965           0 :         bus_kernel_cmd_free(bus, cmd.offset);
     966           0 :         if (r < 0)
     967           0 :                 return r;
     968             : 
     969           0 :         r = bus_creds_add_more(c, mask, pid, 0);
     970           0 :         if (r < 0)
     971           0 :                 return r;
     972             : 
     973           0 :         *ret = c;
     974           0 :         c = NULL;
     975           0 :         return 0;
     976             : }
     977             : 
     978          13 : static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
     979          26 :         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
     980          13 :         pid_t pid = 0;
     981             :         int r;
     982          13 :         bool do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
     983             : 
     984             :         /* Avoid allocating anything if we have no chance of returning useful data */
     985          13 :         if (!bus->ucred_valid && !do_label)
     986           0 :                 return -ENODATA;
     987             : 
     988          13 :         c = bus_creds_new();
     989          13 :         if (!c)
     990           0 :                 return -ENOMEM;
     991             : 
     992          13 :         if (bus->ucred_valid) {
     993          13 :                 if (bus->ucred.pid > 0) {
     994          13 :                         pid = c->pid = bus->ucred.pid;
     995          13 :                         c->mask |= SD_BUS_CREDS_PID & mask;
     996             :                 }
     997             : 
     998          13 :                 if (bus->ucred.uid != UID_INVALID) {
     999          13 :                         c->euid = bus->ucred.uid;
    1000          13 :                         c->mask |= SD_BUS_CREDS_EUID & mask;
    1001             :                 }
    1002             : 
    1003          13 :                 if (bus->ucred.gid != GID_INVALID) {
    1004          13 :                         c->egid = bus->ucred.gid;
    1005          13 :                         c->mask |= SD_BUS_CREDS_EGID & mask;
    1006             :                 }
    1007             :         }
    1008             : 
    1009          13 :         if (do_label) {
    1010           0 :                 c->label = strdup(bus->label);
    1011           0 :                 if (!c->label)
    1012           0 :                         return -ENOMEM;
    1013             : 
    1014           0 :                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
    1015             :         }
    1016             : 
    1017          13 :         r = bus_creds_add_more(c, mask, pid, 0);
    1018          13 :         if (r < 0)
    1019           0 :                 return r;
    1020             : 
    1021          13 :         *ret = c;
    1022          13 :         c = NULL;
    1023          13 :         return 0;
    1024             : }
    1025             : 
    1026          13 : _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
    1027          13 :         assert_return(bus, -EINVAL);
    1028          13 :         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
    1029          13 :         assert_return(ret, -EINVAL);
    1030          13 :         assert_return(!bus_pid_changed(bus), -ECHILD);
    1031             : 
    1032          13 :         if (!BUS_IS_OPEN(bus->state))
    1033           0 :                 return -ENOTCONN;
    1034             : 
    1035          13 :         if (bus->is_kernel)
    1036           0 :                 return bus_get_owner_creds_kdbus(bus, mask, ret);
    1037             :         else
    1038          13 :                 return bus_get_owner_creds_dbus1(bus, mask, ret);
    1039             : }
    1040             : 
    1041          18 : static int add_name_change_match(sd_bus *bus,
    1042             :                                  uint64_t cookie,
    1043             :                                  const char *name,
    1044             :                                  const char *old_owner,
    1045             :                                  const char *new_owner) {
    1046             : 
    1047          18 :         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
    1048          18 :         int is_name_id = -1, r;
    1049             :         struct kdbus_item *item;
    1050             : 
    1051          18 :         assert(bus);
    1052             : 
    1053             :         /* If we encounter a match that could match against
    1054             :          * NameOwnerChanged messages, then we need to create
    1055             :          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
    1056             :          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
    1057             :          * multiple if the match is underspecified.
    1058             :          *
    1059             :          * The NameOwnerChanged signals take three parameters with
    1060             :          * unique or well-known names, but only some forms actually
    1061             :          * exist:
    1062             :          *
    1063             :          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
    1064             :          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
    1065             :          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
    1066             :          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
    1067             :          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
    1068             :          *
    1069             :          * For the latter two the two unique names must be identical.
    1070             :          *
    1071             :          * */
    1072             : 
    1073          18 :         if (name) {
    1074           4 :                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
    1075           4 :                 if (is_name_id < 0)
    1076           0 :                         return 0;
    1077             :         }
    1078             : 
    1079          18 :         if (!isempty(old_owner)) {
    1080           0 :                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
    1081           0 :                 if (r < 0)
    1082           0 :                         return 0;
    1083           0 :                 if (r == 0)
    1084           0 :                         return 0;
    1085           0 :                 if (is_name_id > 0 && old_owner_id != name_id)
    1086           0 :                         return 0;
    1087             :         } else
    1088          18 :                 old_owner_id = KDBUS_MATCH_ID_ANY;
    1089             : 
    1090          18 :         if (!isempty(new_owner)) {
    1091           0 :                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
    1092           0 :                 if (r < 0)
    1093           0 :                         return r;
    1094           0 :                 if (r == 0)
    1095           0 :                         return 0;
    1096           0 :                 if (is_name_id > 0 && new_owner_id != name_id)
    1097           0 :                         return 0;
    1098             :         } else
    1099          18 :                 new_owner_id = KDBUS_MATCH_ID_ANY;
    1100             : 
    1101          18 :         if (is_name_id <= 0) {
    1102             :                 struct kdbus_cmd_match *m;
    1103             :                 size_t sz, l;
    1104             : 
    1105             :                 /* If the name argument is missing or is a well-known
    1106             :                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
    1107             :                  * matches for it */
    1108             : 
    1109          18 :                 l = name ? strlen(name) + 1 : 0;
    1110             : 
    1111          18 :                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
    1112             :                             offsetof(struct kdbus_item, name_change) +
    1113             :                             offsetof(struct kdbus_notify_name_change, name) +
    1114             :                             l);
    1115             : 
    1116          18 :                 m = alloca0_align(sz, 8);
    1117          18 :                 m->size = sz;
    1118          18 :                 m->cookie = cookie;
    1119             : 
    1120          18 :                 item = m->items;
    1121          18 :                 item->size =
    1122             :                         offsetof(struct kdbus_item, name_change) +
    1123          18 :                         offsetof(struct kdbus_notify_name_change, name) +
    1124             :                         l;
    1125             : 
    1126          18 :                 item->name_change.old_id.id = old_owner_id;
    1127          18 :                 item->name_change.new_id.id = new_owner_id;
    1128             : 
    1129          18 :                 if (name)
    1130           4 :                         memcpy(item->name_change.name, name, l);
    1131             : 
    1132             :                 /* If the old name is unset or empty, then
    1133             :                  * this can match against added names */
    1134          18 :                 if (isempty(old_owner)) {
    1135          18 :                         item->type = KDBUS_ITEM_NAME_ADD;
    1136             : 
    1137          18 :                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
    1138          18 :                         if (r < 0)
    1139           0 :                                 return -errno;
    1140             :                 }
    1141             : 
    1142             :                 /* If the new name is unset or empty, then
    1143             :                  * this can match against removed names */
    1144          18 :                 if (isempty(new_owner)) {
    1145          18 :                         item->type = KDBUS_ITEM_NAME_REMOVE;
    1146             : 
    1147          18 :                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
    1148          18 :                         if (r < 0)
    1149           0 :                                 return -errno;
    1150             :                 }
    1151             : 
    1152             :                 /* The CHANGE match we need in either case, because
    1153             :                  * what is reported as a name change by the kernel
    1154             :                  * might just be an owner change between starter and
    1155             :                  * normal clients. For userspace such a change should
    1156             :                  * be considered a removal/addition, hence let's
    1157             :                  * subscribe to this unconditionally. */
    1158          18 :                 item->type = KDBUS_ITEM_NAME_CHANGE;
    1159          18 :                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
    1160          18 :                 if (r < 0)
    1161           0 :                         return -errno;
    1162             :         }
    1163             : 
    1164          18 :         if (is_name_id != 0) {
    1165             :                 struct kdbus_cmd_match *m;
    1166             :                 uint64_t sz;
    1167             : 
    1168             :                 /* If the name argument is missing or is a unique
    1169             :                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
    1170             :                  * for it */
    1171             : 
    1172          14 :                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
    1173             :                             offsetof(struct kdbus_item, id_change) +
    1174             :                             sizeof(struct kdbus_notify_id_change));
    1175             : 
    1176          14 :                 m = alloca0_align(sz, 8);
    1177          14 :                 m->size = sz;
    1178          14 :                 m->cookie = cookie;
    1179             : 
    1180          14 :                 item = m->items;
    1181          14 :                 item->size =
    1182             :                         offsetof(struct kdbus_item, id_change) +
    1183             :                         sizeof(struct kdbus_notify_id_change);
    1184          14 :                 item->id_change.id = name_id;
    1185             : 
    1186             :                 /* If the old name is unset or empty, then this can
    1187             :                  * match against added ids */
    1188          14 :                 if (isempty(old_owner)) {
    1189          14 :                         item->type = KDBUS_ITEM_ID_ADD;
    1190          14 :                         if (!isempty(new_owner))
    1191           0 :                                 item->id_change.id = new_owner_id;
    1192             : 
    1193          14 :                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
    1194          14 :                         if (r < 0)
    1195           0 :                                 return -errno;
    1196             :                 }
    1197             : 
    1198             :                 /* If thew new name is unset or empty, then this can
    1199             :                  * match against removed ids */
    1200          14 :                 if (isempty(new_owner)) {
    1201          14 :                         item->type = KDBUS_ITEM_ID_REMOVE;
    1202          14 :                         if (!isempty(old_owner))
    1203           0 :                                 item->id_change.id = old_owner_id;
    1204             : 
    1205          14 :                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
    1206          14 :                         if (r < 0)
    1207           0 :                                 return -errno;
    1208             :                 }
    1209             :         }
    1210             : 
    1211          18 :         return 0;
    1212             : }
    1213             : 
    1214          34 : int bus_add_match_internal_kernel(
    1215             :                 sd_bus *bus,
    1216             :                 struct bus_match_component *components,
    1217             :                 unsigned n_components,
    1218             :                 uint64_t cookie) {
    1219             : 
    1220             :         struct kdbus_cmd_match *m;
    1221             :         struct kdbus_item *item;
    1222             :         uint64_t *bloom;
    1223             :         size_t sz;
    1224          34 :         const char *sender = NULL;
    1225          34 :         size_t sender_length = 0;
    1226          34 :         uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
    1227          34 :         bool using_bloom = false;
    1228             :         unsigned i;
    1229          34 :         bool matches_name_change = true;
    1230          34 :         const char *name_change_arg[3] = {};
    1231             :         int r;
    1232             : 
    1233          34 :         assert(bus);
    1234             : 
    1235             :         /* Monitor streams don't support matches, make this a NOP */
    1236          34 :         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
    1237           0 :                 return 0;
    1238             : 
    1239          34 :         bloom = alloca0(bus->bloom_size);
    1240             : 
    1241          34 :         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
    1242             : 
    1243          78 :         for (i = 0; i < n_components; i++) {
    1244          44 :                 struct bus_match_component *c = &components[i];
    1245             : 
    1246          44 :                 switch (c->type) {
    1247             : 
    1248             :                 case BUS_MATCH_SENDER:
    1249           0 :                         if (!streq(c->value_str, "org.freedesktop.DBus"))
    1250           0 :                                 matches_name_change = false;
    1251             : 
    1252           0 :                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
    1253           0 :                         if (r < 0)
    1254           0 :                                 return r;
    1255           0 :                         else if (r > 0)
    1256           0 :                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
    1257             :                         else  {
    1258           0 :                                 sender = c->value_str;
    1259           0 :                                 sender_length = strlen(sender);
    1260           0 :                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
    1261             :                         }
    1262             : 
    1263           0 :                         break;
    1264             : 
    1265             :                 case BUS_MATCH_MESSAGE_TYPE:
    1266           2 :                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
    1267           0 :                                 matches_name_change = false;
    1268             : 
    1269           2 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
    1270           2 :                         using_bloom = true;
    1271           2 :                         break;
    1272             : 
    1273             :                 case BUS_MATCH_INTERFACE:
    1274           6 :                         if (!streq(c->value_str, "org.freedesktop.DBus"))
    1275           5 :                                 matches_name_change = false;
    1276             : 
    1277           6 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
    1278           6 :                         using_bloom = true;
    1279           6 :                         break;
    1280             : 
    1281             :                 case BUS_MATCH_MEMBER:
    1282           7 :                         if (!streq(c->value_str, "NameOwnerChanged"))
    1283           6 :                                 matches_name_change = false;
    1284             : 
    1285           7 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
    1286           7 :                         using_bloom = true;
    1287           7 :                         break;
    1288             : 
    1289             :                 case BUS_MATCH_PATH:
    1290          11 :                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
    1291          11 :                                 matches_name_change = false;
    1292             : 
    1293          11 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
    1294          11 :                         using_bloom = true;
    1295          11 :                         break;
    1296             : 
    1297             :                 case BUS_MATCH_PATH_NAMESPACE:
    1298           8 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
    1299           8 :                         using_bloom = true;
    1300           8 :                         break;
    1301             : 
    1302             :                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
    1303             :                         char buf[sizeof("arg")-1 + 2 + 1];
    1304             : 
    1305           6 :                         if (c->type - BUS_MATCH_ARG < 3)
    1306           6 :                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
    1307             : 
    1308           6 :                         xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
    1309           6 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
    1310           6 :                         using_bloom = true;
    1311           6 :                         break;
    1312             :                 }
    1313             : 
    1314             :                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
    1315             :                         /*
    1316             :                          * XXX: DBus spec defines arg[0..63]path= matching to be
    1317             :                          * a two-way glob. That is, if either string is a prefix
    1318             :                          * of the other, it matches.
    1319             :                          * This is really hard to realize in bloom-filters, as
    1320             :                          * we would have to create a bloom-match for each prefix
    1321             :                          * of @c->value_str. This is excessive, hence we just
    1322             :                          * ignore all those matches and accept everything from
    1323             :                          * the kernel. People should really avoid those matches.
    1324             :                          * If they're used in real-life some day, we will have
    1325             :                          * to properly support multiple-matches here.
    1326             :                          */
    1327           4 :                         break;
    1328             :                 }
    1329             : 
    1330             :                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
    1331             :                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
    1332             : 
    1333           0 :                         xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
    1334           0 :                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
    1335           0 :                         using_bloom = true;
    1336           0 :                         break;
    1337             :                 }
    1338             : 
    1339             :                 case BUS_MATCH_DESTINATION: {
    1340             :                         /*
    1341             :                          * Kernel only supports matching on destination IDs, but
    1342             :                          * not on destination names. So just skip the
    1343             :                          * destination name restriction and verify it in
    1344             :                          * user-space on retrieval.
    1345             :                          */
    1346           0 :                         r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
    1347           0 :                         if (r < 0)
    1348           0 :                                 return r;
    1349           0 :                         else if (r > 0)
    1350           0 :                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
    1351             : 
    1352             :                         /* if not a broadcast, it cannot be a name-change */
    1353           0 :                         if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
    1354           0 :                                 matches_name_change = false;
    1355             : 
    1356           0 :                         break;
    1357             :                 }
    1358             : 
    1359             :                 case BUS_MATCH_ROOT:
    1360             :                 case BUS_MATCH_VALUE:
    1361             :                 case BUS_MATCH_LEAF:
    1362             :                 case _BUS_MATCH_NODE_TYPE_MAX:
    1363             :                 case _BUS_MATCH_NODE_TYPE_INVALID:
    1364           0 :                         assert_not_reached("Invalid match type?");
    1365             :                 }
    1366             :         }
    1367             : 
    1368          34 :         if (using_bloom)
    1369          29 :                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
    1370             : 
    1371          34 :         m = alloca0_align(sz, 8);
    1372          34 :         m->size = sz;
    1373          34 :         m->cookie = cookie;
    1374             : 
    1375          34 :         item = m->items;
    1376             : 
    1377          34 :         if (src_id != KDBUS_MATCH_ID_ANY) {
    1378           0 :                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
    1379           0 :                 item->type = KDBUS_ITEM_ID;
    1380           0 :                 item->id = src_id;
    1381           0 :                 item = KDBUS_ITEM_NEXT(item);
    1382             :         }
    1383             : 
    1384          34 :         if (dst_id != KDBUS_MATCH_ID_ANY) {
    1385           0 :                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
    1386           0 :                 item->type = KDBUS_ITEM_DST_ID;
    1387           0 :                 item->id = dst_id;
    1388           0 :                 item = KDBUS_ITEM_NEXT(item);
    1389             :         }
    1390             : 
    1391          34 :         if (using_bloom) {
    1392          29 :                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
    1393          29 :                 item->type = KDBUS_ITEM_BLOOM_MASK;
    1394          29 :                 memcpy(item->data64, bloom, bus->bloom_size);
    1395          29 :                 item = KDBUS_ITEM_NEXT(item);
    1396             :         }
    1397             : 
    1398          34 :         if (sender) {
    1399           0 :                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
    1400           0 :                 item->type = KDBUS_ITEM_NAME;
    1401           0 :                 memcpy(item->str, sender, sender_length + 1);
    1402             :         }
    1403             : 
    1404          34 :         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
    1405          34 :         if (r < 0)
    1406           0 :                 return -errno;
    1407             : 
    1408          34 :         if (matches_name_change) {
    1409             : 
    1410             :                 /* If this match could theoretically match
    1411             :                  * NameOwnerChanged messages, we need to
    1412             :                  * install a second non-bloom filter explitly
    1413             :                  * for it */
    1414             : 
    1415          18 :                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
    1416          18 :                 if (r < 0)
    1417           0 :                         return r;
    1418             :         }
    1419             : 
    1420          34 :         return 0;
    1421             : }
    1422             : 
    1423             : #define internal_match(bus, m)                                          \
    1424             :         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
    1425             :          ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
    1426             :          : (m))
    1427             : 
    1428           1 : static int bus_add_match_internal_dbus1(
    1429             :                 sd_bus *bus,
    1430             :                 const char *match) {
    1431             : 
    1432             :         const char *e;
    1433             : 
    1434           1 :         assert(bus);
    1435           1 :         assert(match);
    1436             : 
    1437           1 :         e = internal_match(bus, match);
    1438             : 
    1439           1 :         return sd_bus_call_method(
    1440             :                         bus,
    1441             :                         "org.freedesktop.DBus",
    1442             :                         "/org/freedesktop/DBus",
    1443             :                         "org.freedesktop.DBus",
    1444             :                         "AddMatch",
    1445             :                         NULL,
    1446             :                         NULL,
    1447             :                         "s",
    1448             :                         e);
    1449             : }
    1450             : 
    1451          35 : int bus_add_match_internal(
    1452             :                 sd_bus *bus,
    1453             :                 const char *match,
    1454             :                 struct bus_match_component *components,
    1455             :                 unsigned n_components,
    1456             :                 uint64_t cookie) {
    1457             : 
    1458          35 :         assert(bus);
    1459             : 
    1460          35 :         if (!bus->bus_client)
    1461           0 :                 return -EINVAL;
    1462             : 
    1463          35 :         if (bus->is_kernel)
    1464          34 :                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
    1465             :         else
    1466           1 :                 return bus_add_match_internal_dbus1(bus, match);
    1467             : }
    1468             : 
    1469          34 : int bus_remove_match_internal_kernel(
    1470             :                 sd_bus *bus,
    1471             :                 uint64_t cookie) {
    1472             : 
    1473          34 :         struct kdbus_cmd_match m = {
    1474             :                 .size = offsetof(struct kdbus_cmd_match, items),
    1475             :                 .cookie = cookie,
    1476             :         };
    1477             :         int r;
    1478             : 
    1479          34 :         assert(bus);
    1480             : 
    1481             :         /* Monitor streams don't support matches, make this a NOP */
    1482          34 :         if (bus->hello_flags & KDBUS_HELLO_MONITOR)
    1483           0 :                 return 0;
    1484             : 
    1485          34 :         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
    1486          34 :         if (r < 0)
    1487           0 :                 return -errno;
    1488             : 
    1489          34 :         return 0;
    1490             : }
    1491             : 
    1492           1 : static int bus_remove_match_internal_dbus1(
    1493             :                 sd_bus *bus,
    1494             :                 const char *match) {
    1495             : 
    1496             :         const char *e;
    1497             : 
    1498           1 :         assert(bus);
    1499           1 :         assert(match);
    1500             : 
    1501           1 :         e = internal_match(bus, match);
    1502             : 
    1503           1 :         return sd_bus_call_method(
    1504             :                         bus,
    1505             :                         "org.freedesktop.DBus",
    1506             :                         "/org/freedesktop/DBus",
    1507             :                         "org.freedesktop.DBus",
    1508             :                         "RemoveMatch",
    1509             :                         NULL,
    1510             :                         NULL,
    1511             :                         "s",
    1512             :                         e);
    1513             : }
    1514             : 
    1515          35 : int bus_remove_match_internal(
    1516             :                 sd_bus *bus,
    1517             :                 const char *match,
    1518             :                 uint64_t cookie) {
    1519             : 
    1520          35 :         assert(bus);
    1521             : 
    1522          35 :         if (!bus->bus_client)
    1523           0 :                 return -EINVAL;
    1524             : 
    1525          35 :         if (bus->is_kernel)
    1526          34 :                 return bus_remove_match_internal_kernel(bus, cookie);
    1527             :         else
    1528           1 :                 return bus_remove_match_internal_dbus1(bus, match);
    1529             : }
    1530             : 
    1531           0 : _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
    1532           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
    1533             :         const char *mid;
    1534             :         int r;
    1535             : 
    1536           0 :         assert_return(bus, -EINVAL);
    1537           0 :         assert_return(name, -EINVAL);
    1538           0 :         assert_return(machine, -EINVAL);
    1539           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
    1540           0 :         assert_return(service_name_is_valid(name), -EINVAL);
    1541             : 
    1542           0 :         if (!bus->bus_client)
    1543           0 :                 return -EINVAL;
    1544             : 
    1545           0 :         if (!BUS_IS_OPEN(bus->state))
    1546           0 :                 return -ENOTCONN;
    1547             : 
    1548           0 :         if (streq_ptr(name, bus->unique_name))
    1549           0 :                 return sd_id128_get_machine(machine);
    1550             : 
    1551           0 :         r = sd_bus_message_new_method_call(
    1552             :                         bus,
    1553             :                         &m,
    1554             :                         name,
    1555             :                         "/",
    1556             :                         "org.freedesktop.DBus.Peer",
    1557             :                         "GetMachineId");
    1558           0 :         if (r < 0)
    1559           0 :                 return r;
    1560             : 
    1561           0 :         r = sd_bus_message_set_auto_start(m, false);
    1562           0 :         if (r < 0)
    1563           0 :                 return r;
    1564             : 
    1565           0 :         r = sd_bus_call(bus, m, 0, NULL, &reply);
    1566           0 :         if (r < 0)
    1567           0 :                 return r;
    1568             : 
    1569           0 :         r = sd_bus_message_read(reply, "s", &mid);
    1570           0 :         if (r < 0)
    1571           0 :                 return r;
    1572             : 
    1573           0 :         return sd_id128_from_string(mid, machine);
    1574             : }

Generated by: LCOV version 1.11