LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-convenience.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 141 288 49.0 %
Date: 2015-07-29 18:47:03 Functions: 9 15 60.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include "bus-internal.h"
      23             : #include "bus-message.h"
      24             : #include "bus-signature.h"
      25             : #include "bus-util.h"
      26             : #include "bus-type.h"
      27             : 
      28          32 : _public_ int sd_bus_emit_signal(
      29             :                 sd_bus *bus,
      30             :                 const char *path,
      31             :                 const char *interface,
      32             :                 const char *member,
      33             :                 const char *types, ...) {
      34             : 
      35          64 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
      36             :         int r;
      37             : 
      38          32 :         assert_return(bus, -EINVAL);
      39          32 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      40             : 
      41          32 :         if (!BUS_IS_OPEN(bus->state))
      42           0 :                 return -ENOTCONN;
      43             : 
      44          32 :         r = sd_bus_message_new_signal(bus, &m, path, interface, member);
      45          32 :         if (r < 0)
      46           0 :                 return r;
      47             : 
      48          32 :         if (!isempty(types)) {
      49             :                 va_list ap;
      50             : 
      51          32 :                 va_start(ap, types);
      52          32 :                 r = bus_message_append_ap(m, types, ap);
      53          32 :                 va_end(ap);
      54          32 :                 if (r < 0)
      55           0 :                         return r;
      56             :         }
      57             : 
      58          32 :         return sd_bus_send(bus, m, NULL);
      59             : }
      60             : 
      61           0 : _public_ int sd_bus_call_method_async(
      62             :                 sd_bus *bus,
      63             :                 sd_bus_slot **slot,
      64             :                 const char *destination,
      65             :                 const char *path,
      66             :                 const char *interface,
      67             :                 const char *member,
      68             :                 sd_bus_message_handler_t callback,
      69             :                 void *userdata,
      70             :                 const char *types, ...) {
      71             : 
      72           0 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
      73             :         int r;
      74             : 
      75           0 :         assert_return(bus, -EINVAL);
      76           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
      77             : 
      78           0 :         if (!BUS_IS_OPEN(bus->state))
      79           0 :                 return -ENOTCONN;
      80             : 
      81           0 :         r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
      82           0 :         if (r < 0)
      83           0 :                 return r;
      84             : 
      85           0 :         if (!isempty(types)) {
      86             :                 va_list ap;
      87             : 
      88           0 :                 va_start(ap, types);
      89           0 :                 r = bus_message_append_ap(m, types, ap);
      90           0 :                 va_end(ap);
      91           0 :                 if (r < 0)
      92           0 :                         return r;
      93             :         }
      94             : 
      95           0 :         return sd_bus_call_async(bus, slot, m, callback, userdata, 0);
      96             : }
      97             : 
      98          28 : _public_ int sd_bus_call_method(
      99             :                 sd_bus *bus,
     100             :                 const char *destination,
     101             :                 const char *path,
     102             :                 const char *interface,
     103             :                 const char *member,
     104             :                 sd_bus_error *error,
     105             :                 sd_bus_message **reply,
     106             :                 const char *types, ...) {
     107             : 
     108          56 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
     109             :         int r;
     110             : 
     111          28 :         assert_return(bus, -EINVAL);
     112          28 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     113             : 
     114          28 :         if (!BUS_IS_OPEN(bus->state))
     115           1 :                 return -ENOTCONN;
     116             : 
     117          27 :         r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
     118          27 :         if (r < 0)
     119           0 :                 return r;
     120             : 
     121          27 :         if (!isempty(types)) {
     122             :                 va_list ap;
     123             : 
     124          11 :                 va_start(ap, types);
     125          11 :                 r = bus_message_append_ap(m, types, ap);
     126          11 :                 va_end(ap);
     127          11 :                 if (r < 0)
     128           0 :                         return r;
     129             :         }
     130             : 
     131          27 :         return sd_bus_call(bus, m, 0, error, reply);
     132             : }
     133             : 
     134       15499 : _public_ int sd_bus_reply_method_return(
     135             :                 sd_bus_message *call,
     136             :                 const char *types, ...) {
     137             : 
     138       30998 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
     139             :         int r;
     140             : 
     141       15499 :         assert_return(call, -EINVAL);
     142       15499 :         assert_return(call->sealed, -EPERM);
     143       15499 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     144       15499 :         assert_return(call->bus, -EINVAL);
     145       15499 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     146             : 
     147       15499 :         if (!BUS_IS_OPEN(call->bus->state))
     148           0 :                 return -ENOTCONN;
     149             : 
     150       15499 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     151           3 :                 return 0;
     152             : 
     153       15496 :         r = sd_bus_message_new_method_return(call, &m);
     154       15496 :         if (r < 0)
     155           0 :                 return r;
     156             : 
     157       15496 :         if (!isempty(types)) {
     158             :                 va_list ap;
     159             : 
     160           3 :                 va_start(ap, types);
     161           3 :                 r = bus_message_append_ap(m, types, ap);
     162           3 :                 va_end(ap);
     163           3 :                 if (r < 0)
     164           0 :                         return r;
     165             :         }
     166             : 
     167       15496 :         return sd_bus_send(call->bus, m, NULL);
     168             : }
     169             : 
     170           4 : _public_ int sd_bus_reply_method_error(
     171             :                 sd_bus_message *call,
     172             :                 const sd_bus_error *e) {
     173             : 
     174           8 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
     175             :         int r;
     176             : 
     177           4 :         assert_return(call, -EINVAL);
     178           4 :         assert_return(call->sealed, -EPERM);
     179           4 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     180           4 :         assert_return(sd_bus_error_is_set(e), -EINVAL);
     181           4 :         assert_return(call->bus, -EINVAL);
     182           4 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     183             : 
     184           4 :         if (!BUS_IS_OPEN(call->bus->state))
     185           0 :                 return -ENOTCONN;
     186             : 
     187           4 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     188           0 :                 return 0;
     189             : 
     190           4 :         r = sd_bus_message_new_method_error(call, &m, e);
     191           4 :         if (r < 0)
     192           0 :                 return r;
     193             : 
     194           4 :         return sd_bus_send(call->bus, m, NULL);
     195             : }
     196             : 
     197           4 : _public_ int sd_bus_reply_method_errorf(
     198             :                 sd_bus_message *call,
     199             :                 const char *name,
     200             :                 const char *format,
     201             :                 ...) {
     202             : 
     203           8 :         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
     204             :         va_list ap;
     205             : 
     206           4 :         assert_return(call, -EINVAL);
     207           4 :         assert_return(call->sealed, -EPERM);
     208           4 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     209           4 :         assert_return(call->bus, -EINVAL);
     210           4 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     211             : 
     212           4 :         if (!BUS_IS_OPEN(call->bus->state))
     213           0 :                 return -ENOTCONN;
     214             : 
     215           4 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     216           0 :                 return 0;
     217             : 
     218           4 :         va_start(ap, format);
     219           4 :         bus_error_setfv(&error, name, format, ap);
     220           4 :         va_end(ap);
     221             : 
     222           4 :         return sd_bus_reply_method_error(call, &error);
     223             : }
     224             : 
     225           0 : _public_ int sd_bus_reply_method_errno(
     226             :                 sd_bus_message *call,
     227             :                 int error,
     228             :                 const sd_bus_error *p) {
     229             : 
     230           0 :         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
     231             : 
     232           0 :         assert_return(call, -EINVAL);
     233           0 :         assert_return(call->sealed, -EPERM);
     234           0 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     235           0 :         assert_return(call->bus, -EINVAL);
     236           0 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     237             : 
     238           0 :         if (!BUS_IS_OPEN(call->bus->state))
     239           0 :                 return -ENOTCONN;
     240             : 
     241           0 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     242           0 :                 return 0;
     243             : 
     244           0 :         if (sd_bus_error_is_set(p))
     245           0 :                 return sd_bus_reply_method_error(call, p);
     246             : 
     247           0 :         sd_bus_error_set_errno(&berror, error);
     248             : 
     249           0 :         return sd_bus_reply_method_error(call, &berror);
     250             : }
     251             : 
     252           0 : _public_ int sd_bus_reply_method_errnof(
     253             :                 sd_bus_message *call,
     254             :                 int error,
     255             :                 const char *format,
     256             :                 ...) {
     257             : 
     258           0 :         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
     259             :         va_list ap;
     260             : 
     261           0 :         assert_return(call, -EINVAL);
     262           0 :         assert_return(call->sealed, -EPERM);
     263           0 :         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
     264           0 :         assert_return(call->bus, -EINVAL);
     265           0 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     266             : 
     267           0 :         if (!BUS_IS_OPEN(call->bus->state))
     268           0 :                 return -ENOTCONN;
     269             : 
     270           0 :         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
     271           0 :                 return 0;
     272             : 
     273           0 :         va_start(ap, format);
     274           0 :         sd_bus_error_set_errnofv(&berror, error, format, ap);
     275           0 :         va_end(ap);
     276             : 
     277           0 :         return sd_bus_reply_method_error(call, &berror);
     278             : }
     279             : 
     280           3 : _public_ int sd_bus_get_property(
     281             :                 sd_bus *bus,
     282             :                 const char *destination,
     283             :                 const char *path,
     284             :                 const char *interface,
     285             :                 const char *member,
     286             :                 sd_bus_error *error,
     287             :                 sd_bus_message **reply,
     288             :                 const char *type) {
     289             : 
     290           3 :         sd_bus_message *rep = NULL;
     291             :         int r;
     292             : 
     293           3 :         assert_return(bus, -EINVAL);
     294           3 :         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
     295           3 :         assert_return(member_name_is_valid(member), -EINVAL);
     296           3 :         assert_return(reply, -EINVAL);
     297           3 :         assert_return(signature_is_single(type, false), -EINVAL);
     298           3 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     299             : 
     300           3 :         if (!BUS_IS_OPEN(bus->state))
     301           0 :                 return -ENOTCONN;
     302             : 
     303           3 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
     304           3 :         if (r < 0)
     305           0 :                 return r;
     306             : 
     307           3 :         r = sd_bus_message_enter_container(rep, 'v', type);
     308           3 :         if (r < 0) {
     309           0 :                 sd_bus_message_unref(rep);
     310           0 :                 return r;
     311             :         }
     312             : 
     313           3 :         *reply = rep;
     314           3 :         return 0;
     315             : }
     316             : 
     317           0 : _public_ int sd_bus_get_property_trivial(
     318             :                 sd_bus *bus,
     319             :                 const char *destination,
     320             :                 const char *path,
     321             :                 const char *interface,
     322             :                 const char *member,
     323             :                 sd_bus_error *error,
     324             :                 char type, void *ptr) {
     325             : 
     326           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
     327             :         int r;
     328             : 
     329           0 :         assert_return(bus, -EINVAL);
     330           0 :         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
     331           0 :         assert_return(member_name_is_valid(member), -EINVAL);
     332           0 :         assert_return(bus_type_is_trivial(type), -EINVAL);
     333           0 :         assert_return(ptr, -EINVAL);
     334           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     335             : 
     336           0 :         if (!BUS_IS_OPEN(bus->state))
     337           0 :                 return -ENOTCONN;
     338             : 
     339           0 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
     340           0 :         if (r < 0)
     341           0 :                 return r;
     342             : 
     343           0 :         r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
     344           0 :         if (r < 0)
     345           0 :                 return r;
     346             : 
     347           0 :         r = sd_bus_message_read_basic(reply, type, ptr);
     348           0 :         if (r < 0)
     349           0 :                 return r;
     350             : 
     351           0 :         return 0;
     352             : }
     353             : 
     354           0 : _public_ int sd_bus_get_property_string(
     355             :                 sd_bus *bus,
     356             :                 const char *destination,
     357             :                 const char *path,
     358             :                 const char *interface,
     359             :                 const char *member,
     360             :                 sd_bus_error *error,
     361             :                 char **ret) {
     362             : 
     363           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
     364             :         const char *s;
     365             :         char *n;
     366             :         int r;
     367             : 
     368           0 :         assert_return(bus, -EINVAL);
     369           0 :         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
     370           0 :         assert_return(member_name_is_valid(member), -EINVAL);
     371           0 :         assert_return(ret, -EINVAL);
     372           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     373             : 
     374           0 :         if (!BUS_IS_OPEN(bus->state))
     375           0 :                 return -ENOTCONN;
     376             : 
     377           0 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
     378           0 :         if (r < 0)
     379           0 :                 return r;
     380             : 
     381           0 :         r = sd_bus_message_enter_container(reply, 'v', "s");
     382           0 :         if (r < 0)
     383           0 :                 return r;
     384             : 
     385           0 :         r = sd_bus_message_read_basic(reply, 's', &s);
     386           0 :         if (r < 0)
     387           0 :                 return r;
     388             : 
     389           0 :         n = strdup(s);
     390           0 :         if (!n)
     391           0 :                 return -ENOMEM;
     392             : 
     393           0 :         *ret = n;
     394           0 :         return 0;
     395             : }
     396             : 
     397           0 : _public_ int sd_bus_get_property_strv(
     398             :                 sd_bus *bus,
     399             :                 const char *destination,
     400             :                 const char *path,
     401             :                 const char *interface,
     402             :                 const char *member,
     403             :                 sd_bus_error *error,
     404             :                 char ***ret) {
     405             : 
     406           0 :         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
     407             :         int r;
     408             : 
     409           0 :         assert_return(bus, -EINVAL);
     410           0 :         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
     411           0 :         assert_return(member_name_is_valid(member), -EINVAL);
     412           0 :         assert_return(ret, -EINVAL);
     413           0 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     414             : 
     415           0 :         if (!BUS_IS_OPEN(bus->state))
     416           0 :                 return -ENOTCONN;
     417             : 
     418           0 :         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
     419           0 :         if (r < 0)
     420           0 :                 return r;
     421             : 
     422           0 :         r = sd_bus_message_enter_container(reply, 'v', NULL);
     423           0 :         if (r < 0)
     424           0 :                 return r;
     425             : 
     426           0 :         r = sd_bus_message_read_strv(reply, ret);
     427           0 :         if (r < 0)
     428           0 :                 return r;
     429             : 
     430           0 :         return 0;
     431             : }
     432             : 
     433           3 : _public_ int sd_bus_set_property(
     434             :                 sd_bus *bus,
     435             :                 const char *destination,
     436             :                 const char *path,
     437             :                 const char *interface,
     438             :                 const char *member,
     439             :                 sd_bus_error *error,
     440             :                 const char *type, ...) {
     441             : 
     442           6 :         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
     443             :         va_list ap;
     444             :         int r;
     445             : 
     446           3 :         assert_return(bus, -EINVAL);
     447           3 :         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
     448           3 :         assert_return(member_name_is_valid(member), -EINVAL);
     449           3 :         assert_return(signature_is_single(type, false), -EINVAL);
     450           3 :         assert_return(!bus_pid_changed(bus), -ECHILD);
     451             : 
     452           3 :         if (!BUS_IS_OPEN(bus->state))
     453           0 :                 return -ENOTCONN;
     454             : 
     455           3 :         r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
     456           3 :         if (r < 0)
     457           0 :                 return r;
     458             : 
     459           3 :         r = sd_bus_message_append(m, "ss", strempty(interface), member);
     460           3 :         if (r < 0)
     461           0 :                 return r;
     462             : 
     463           3 :         r = sd_bus_message_open_container(m, 'v', type);
     464           3 :         if (r < 0)
     465           0 :                 return r;
     466             : 
     467           3 :         va_start(ap, type);
     468           3 :         r = bus_message_append_ap(m, type, ap);
     469           3 :         va_end(ap);
     470           3 :         if (r < 0)
     471           0 :                 return r;
     472             : 
     473           3 :         r = sd_bus_message_close_container(m);
     474           3 :         if (r < 0)
     475           0 :                 return r;
     476             : 
     477           3 :         return sd_bus_call(bus, m, 0, error, NULL);
     478             : }
     479             : 
     480          13 : _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
     481             :         sd_bus_creds *c;
     482             : 
     483          13 :         assert_return(call, -EINVAL);
     484          13 :         assert_return(call->sealed, -EPERM);
     485          13 :         assert_return(call->bus, -EINVAL);
     486          13 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     487             : 
     488          13 :         if (!BUS_IS_OPEN(call->bus->state))
     489           0 :                 return -ENOTCONN;
     490             : 
     491          13 :         c = sd_bus_message_get_creds(call);
     492             : 
     493             :         /* All data we need? */
     494          13 :         if (c && (mask & ~c->mask) == 0) {
     495           0 :                 *creds = sd_bus_creds_ref(c);
     496           0 :                 return 0;
     497             :         }
     498             : 
     499             :         /* No data passed? Or not enough data passed to retrieve the missing bits? */
     500          13 :         if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
     501             :                 /* We couldn't read anything from the call, let's try
     502             :                  * to get it from the sender or peer. */
     503             : 
     504          13 :                 if (call->sender)
     505             :                         /* There's a sender, but the creds are
     506             :                          * missing. This means we are talking via
     507             :                          * dbus1, or are getting a message that was
     508             :                          * sent to us via kdbus, but was converted
     509             :                          * from a dbus1 message by the bus-proxy and
     510             :                          * thus also lacks the creds. */
     511           0 :                         return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
     512             :                 else
     513             :                         /* There's no sender, hence we are on a dbus1
     514             :                          * direct connection. For direct connections
     515             :                          * the credentials of the AF_UNIX peer matter,
     516             :                          * which may be queried via
     517             :                          * sd_bus_get_owner_creds(). */
     518          13 :                         return sd_bus_get_owner_creds(call->bus, mask, creds);
     519             :         }
     520             : 
     521           0 :         return bus_creds_extend_by_pid(c, mask, creds);
     522             : }
     523             : 
     524          13 : _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
     525          26 :         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
     526             :         uid_t our_uid;
     527          13 :         bool know_caps = false;
     528             :         int r;
     529             : 
     530          13 :         assert_return(call, -EINVAL);
     531          13 :         assert_return(call->sealed, -EPERM);
     532          13 :         assert_return(call->bus, -EINVAL);
     533          13 :         assert_return(!bus_pid_changed(call->bus), -ECHILD);
     534             : 
     535          13 :         if (!BUS_IS_OPEN(call->bus->state))
     536           0 :                 return -ENOTCONN;
     537             : 
     538          13 :         if (capability >= 0) {
     539             : 
     540          13 :                 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
     541          13 :                 if (r < 0)
     542           0 :                         return r;
     543             : 
     544             :                 /* We cannot use augmented caps for authorization,
     545             :                  * since then data is acquired raceful from
     546             :                  * /proc. This can never actually happen, but let's
     547             :                  * better be safe than sorry, and do an extra check
     548             :                  * here. */
     549          13 :                 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
     550             : 
     551             :                 /* Note that not even on kdbus we might have the caps
     552             :                  * field, due to faked identities, or namespace
     553             :                  * translation issues. */
     554          13 :                 r = sd_bus_creds_has_effective_cap(creds, capability);
     555          13 :                 if (r > 0)
     556           0 :                         return 1;
     557          13 :                 if (r == 0)
     558           0 :                         know_caps = true;
     559             :         } else {
     560           0 :                 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
     561           0 :                 if (r < 0)
     562           0 :                         return r;
     563             :         }
     564             : 
     565             :         /* Now, check the UID, but only if the capability check wasn't
     566             :          * sufficient */
     567          13 :         our_uid = getuid();
     568          13 :         if (our_uid != 0 || !know_caps || capability < 0) {
     569             :                 uid_t sender_uid;
     570             : 
     571             :                 /* We cannot use augmented uid/euid for authorization,
     572             :                  * since then data is acquired raceful from
     573             :                  * /proc. This can never actually happen, but let's
     574             :                  * better be safe than sorry, and do an extra check
     575             :                  * here. */
     576          26 :                 assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);
     577             : 
     578             :                 /* Try to use the EUID, if we have it. */
     579          13 :                 r = sd_bus_creds_get_euid(creds, &sender_uid);
     580          13 :                 if (r < 0)
     581           0 :                         r = sd_bus_creds_get_uid(creds, &sender_uid);
     582             : 
     583          13 :                 if (r >= 0) {
     584             :                         /* Sender has same UID as us, then let's grant access */
     585          13 :                         if (sender_uid == our_uid)
     586          13 :                                 return 1;
     587             : 
     588             :                         /* Sender is root, we are not root. */
     589           0 :                         if (our_uid != 0 && sender_uid == 0)
     590           0 :                                 return 1;
     591             :                 }
     592             :         }
     593             : 
     594           0 :         return 0;
     595             : }

Generated by: LCOV version 1.11