LCOV - code coverage report
Current view: top level - libsystemd/sd-bus - bus-creds.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 389 773 50.3 %
Date: 2015-07-29 18:47:03 Functions: 25 45 55.6 %

          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 <stdlib.h>
      23             : #include <linux/capability.h>
      24             : 
      25             : #include "util.h"
      26             : #include "formats-util.h"
      27             : #include "process-util.h"
      28             : #include "terminal-util.h"
      29             : #include "capability.h"
      30             : #include "cgroup-util.h"
      31             : #include "fileio.h"
      32             : #include "audit.h"
      33             : #include "bus-message.h"
      34             : #include "bus-util.h"
      35             : #include "strv.h"
      36             : #include "bus-creds.h"
      37             : #include "bus-label.h"
      38             : 
      39             : enum {
      40             :         CAP_OFFSET_INHERITABLE = 0,
      41             :         CAP_OFFSET_PERMITTED = 1,
      42             :         CAP_OFFSET_EFFECTIVE = 2,
      43             :         CAP_OFFSET_BOUNDING = 3
      44             : };
      45             : 
      46       31225 : void bus_creds_done(sd_bus_creds *c) {
      47       31225 :         assert(c);
      48             : 
      49             :         /* For internal bus cred structures that are allocated by
      50             :          * something else */
      51             : 
      52       31225 :         free(c->session);
      53       31225 :         free(c->unit);
      54       31225 :         free(c->user_unit);
      55       31225 :         free(c->slice);
      56       31225 :         free(c->user_slice);
      57       31225 :         free(c->unescaped_description);
      58       31225 :         free(c->supplementary_gids);
      59       31225 :         free(c->tty);
      60             : 
      61       31225 :         free(c->well_known_names); /* note that this is an strv, but
      62             :                                     * we only free the array, not the
      63             :                                     * strings the array points to. The
      64             :                                     * full strv we only free if
      65             :                                     * c->allocated is set, see
      66             :                                     * below. */
      67             : 
      68       31225 :         strv_free(c->cmdline_array);
      69       31225 : }
      70             : 
      71           0 : _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
      72           0 :         assert_return(c, NULL);
      73             : 
      74           0 :         if (c->allocated) {
      75           0 :                 assert(c->n_ref > 0);
      76           0 :                 c->n_ref++;
      77             :         } else {
      78             :                 sd_bus_message *m;
      79             : 
      80             :                 /* If this is an embedded creds structure, then
      81             :                  * forward ref counting to the message */
      82           0 :                 m = container_of(c, sd_bus_message, creds);
      83           0 :                 sd_bus_message_ref(m);
      84             :         }
      85             : 
      86           0 :         return c;
      87             : }
      88             : 
      89          15 : _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
      90             : 
      91          15 :         if (!c)
      92           0 :                 return NULL;
      93             : 
      94          15 :         if (c->allocated) {
      95          15 :                 assert(c->n_ref > 0);
      96          15 :                 c->n_ref--;
      97             : 
      98          15 :                 if (c->n_ref == 0) {
      99          15 :                         free(c->comm);
     100          15 :                         free(c->tid_comm);
     101          15 :                         free(c->exe);
     102          15 :                         free(c->cmdline);
     103          15 :                         free(c->cgroup);
     104          15 :                         free(c->capability);
     105          15 :                         free(c->label);
     106          15 :                         free(c->unique_name);
     107          15 :                         free(c->cgroup_root);
     108          15 :                         free(c->description);
     109             : 
     110          15 :                         free(c->supplementary_gids);
     111          15 :                         c->supplementary_gids = NULL;
     112             : 
     113          15 :                         strv_free(c->well_known_names);
     114          15 :                         c->well_known_names = NULL;
     115             : 
     116          15 :                         bus_creds_done(c);
     117             : 
     118          15 :                         free(c);
     119             :                 }
     120             :         } else {
     121             :                 sd_bus_message *m;
     122             : 
     123           0 :                 m = container_of(c, sd_bus_message, creds);
     124           0 :                 sd_bus_message_unref(m);
     125             :         }
     126             : 
     127             : 
     128          15 :         return NULL;
     129             : }
     130             : 
     131           0 : _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
     132           0 :         assert_return(c, 0);
     133             : 
     134           0 :         return c->mask;
     135             : }
     136             : 
     137          26 : _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
     138          26 :         assert_return(c, 0);
     139             : 
     140          26 :         return c->augmented;
     141             : }
     142             : 
     143          15 : sd_bus_creds* bus_creds_new(void) {
     144             :         sd_bus_creds *c;
     145             : 
     146          15 :         c = new0(sd_bus_creds, 1);
     147          15 :         if (!c)
     148           0 :                 return NULL;
     149             : 
     150          15 :         c->allocated = true;
     151          15 :         c->n_ref = 1;
     152          15 :         return c;
     153             : }
     154             : 
     155           2 : _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
     156             :         sd_bus_creds *c;
     157             :         int r;
     158             : 
     159           2 :         assert_return(pid >= 0, -EINVAL);
     160           2 :         assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
     161           2 :         assert_return(ret, -EINVAL);
     162             : 
     163           2 :         if (pid == 0)
     164           1 :                 pid = getpid();
     165             : 
     166           2 :         c = bus_creds_new();
     167           2 :         if (!c)
     168           0 :                 return -ENOMEM;
     169             : 
     170           2 :         r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
     171           2 :         if (r < 0) {
     172           0 :                 sd_bus_creds_unref(c);
     173           0 :                 return r;
     174             :         }
     175             : 
     176             :         /* Check if the process existed at all, in case we haven't
     177             :          * figured that out already */
     178           2 :         if (!pid_is_alive(pid)) {
     179           0 :                 sd_bus_creds_unref(c);
     180           0 :                 return -ESRCH;
     181             :         }
     182             : 
     183           2 :         *ret = c;
     184           2 :         return 0;
     185             : }
     186             : 
     187           0 : _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
     188           0 :         assert_return(c, -EINVAL);
     189           0 :         assert_return(uid, -EINVAL);
     190             : 
     191           0 :         if (!(c->mask & SD_BUS_CREDS_UID))
     192           0 :                 return -ENODATA;
     193             : 
     194           0 :         *uid = c->uid;
     195           0 :         return 0;
     196             : }
     197             : 
     198          13 : _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
     199          13 :         assert_return(c, -EINVAL);
     200          13 :         assert_return(euid, -EINVAL);
     201             : 
     202          13 :         if (!(c->mask & SD_BUS_CREDS_EUID))
     203           0 :                 return -ENODATA;
     204             : 
     205          13 :         *euid = c->euid;
     206          13 :         return 0;
     207             : }
     208             : 
     209           0 : _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
     210           0 :         assert_return(c, -EINVAL);
     211           0 :         assert_return(suid, -EINVAL);
     212             : 
     213           0 :         if (!(c->mask & SD_BUS_CREDS_SUID))
     214           0 :                 return -ENODATA;
     215             : 
     216           0 :         *suid = c->suid;
     217           0 :         return 0;
     218             : }
     219             : 
     220             : 
     221           0 : _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
     222           0 :         assert_return(c, -EINVAL);
     223           0 :         assert_return(fsuid, -EINVAL);
     224             : 
     225           0 :         if (!(c->mask & SD_BUS_CREDS_FSUID))
     226           0 :                 return -ENODATA;
     227             : 
     228           0 :         *fsuid = c->fsuid;
     229           0 :         return 0;
     230             : }
     231             : 
     232           0 : _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
     233           0 :         assert_return(c, -EINVAL);
     234           0 :         assert_return(gid, -EINVAL);
     235             : 
     236           0 :         if (!(c->mask & SD_BUS_CREDS_GID))
     237           0 :                 return -ENODATA;
     238             : 
     239           0 :         *gid = c->gid;
     240           0 :         return 0;
     241             : }
     242             : 
     243           0 : _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
     244           0 :         assert_return(c, -EINVAL);
     245           0 :         assert_return(egid, -EINVAL);
     246             : 
     247           0 :         if (!(c->mask & SD_BUS_CREDS_EGID))
     248           0 :                 return -ENODATA;
     249             : 
     250           0 :         *egid = c->egid;
     251           0 :         return 0;
     252             : }
     253             : 
     254           0 : _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
     255           0 :         assert_return(c, -EINVAL);
     256           0 :         assert_return(sgid, -EINVAL);
     257             : 
     258           0 :         if (!(c->mask & SD_BUS_CREDS_SGID))
     259           0 :                 return -ENODATA;
     260             : 
     261           0 :         *sgid = c->sgid;
     262           0 :         return 0;
     263             : }
     264             : 
     265           0 : _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
     266           0 :         assert_return(c, -EINVAL);
     267           0 :         assert_return(fsgid, -EINVAL);
     268             : 
     269           0 :         if (!(c->mask & SD_BUS_CREDS_FSGID))
     270           0 :                 return -ENODATA;
     271             : 
     272           0 :         *fsgid = c->fsgid;
     273           0 :         return 0;
     274             : }
     275             : 
     276           0 : _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
     277           0 :         assert_return(c, -EINVAL);
     278           0 :         assert_return(gids, -EINVAL);
     279             : 
     280           0 :         if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
     281           0 :                 return -ENODATA;
     282             : 
     283           0 :         *gids = c->supplementary_gids;
     284           0 :         return (int) c->n_supplementary_gids;
     285             : }
     286             : 
     287          10 : _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
     288          10 :         assert_return(c, -EINVAL);
     289          10 :         assert_return(pid, -EINVAL);
     290             : 
     291          10 :         if (!(c->mask & SD_BUS_CREDS_PID))
     292          10 :                 return -ENODATA;
     293             : 
     294           0 :         assert(c->pid > 0);
     295           0 :         *pid = c->pid;
     296           0 :         return 0;
     297             : }
     298             : 
     299           0 : _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
     300           0 :         assert_return(c, -EINVAL);
     301           0 :         assert_return(ppid, -EINVAL);
     302             : 
     303           0 :         if (!(c->mask & SD_BUS_CREDS_PPID))
     304           0 :                 return -ENODATA;
     305             : 
     306             :         /* PID 1 has no parent process. Let's distinguish the case of
     307             :          * not knowing and not having a parent process by the returned
     308             :          * error code. */
     309           0 :         if (c->ppid == 0)
     310           0 :                 return -ENXIO;
     311             : 
     312           0 :         *ppid = c->ppid;
     313           0 :         return 0;
     314             : }
     315             : 
     316           0 : _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
     317           0 :         assert_return(c, -EINVAL);
     318           0 :         assert_return(tid, -EINVAL);
     319             : 
     320           0 :         if (!(c->mask & SD_BUS_CREDS_TID))
     321           0 :                 return -ENODATA;
     322             : 
     323           0 :         assert(c->tid > 0);
     324           0 :         *tid = c->tid;
     325           0 :         return 0;
     326             : }
     327             : 
     328          10 : _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
     329          10 :         assert_return(c, -EINVAL);
     330             : 
     331          10 :         if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
     332          10 :                 return -ENODATA;
     333             : 
     334           0 :         assert(c->label);
     335           0 :         *ret = c->label;
     336           0 :         return 0;
     337             : }
     338             : 
     339           0 : _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
     340           0 :         assert_return(c, -EINVAL);
     341           0 :         assert_return(ret, -EINVAL);
     342             : 
     343           0 :         if (!(c->mask & SD_BUS_CREDS_COMM))
     344           0 :                 return -ENODATA;
     345             : 
     346           0 :         assert(c->comm);
     347           0 :         *ret = c->comm;
     348           0 :         return 0;
     349             : }
     350             : 
     351           0 : _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
     352           0 :         assert_return(c, -EINVAL);
     353           0 :         assert_return(ret, -EINVAL);
     354             : 
     355           0 :         if (!(c->mask & SD_BUS_CREDS_TID_COMM))
     356           0 :                 return -ENODATA;
     357             : 
     358           0 :         assert(c->tid_comm);
     359           0 :         *ret = c->tid_comm;
     360           0 :         return 0;
     361             : }
     362             : 
     363           0 : _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
     364           0 :         assert_return(c, -EINVAL);
     365           0 :         assert_return(ret, -EINVAL);
     366             : 
     367           0 :         if (!(c->mask & SD_BUS_CREDS_EXE))
     368           0 :                 return -ENODATA;
     369             : 
     370           0 :         if (!c->exe)
     371           0 :                 return -ENXIO;
     372             : 
     373           0 :         *ret = c->exe;
     374           0 :         return 0;
     375             : }
     376             : 
     377           0 : _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
     378           0 :         assert_return(c, -EINVAL);
     379           0 :         assert_return(ret, -EINVAL);
     380             : 
     381           0 :         if (!(c->mask & SD_BUS_CREDS_CGROUP))
     382           0 :                 return -ENODATA;
     383             : 
     384           0 :         assert(c->cgroup);
     385           0 :         *ret = c->cgroup;
     386           0 :         return 0;
     387             : }
     388             : 
     389          19 : _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
     390             :         int r;
     391             : 
     392          19 :         assert_return(c, -EINVAL);
     393          19 :         assert_return(ret, -EINVAL);
     394             : 
     395          19 :         if (!(c->mask & SD_BUS_CREDS_UNIT))
     396          15 :                 return -ENODATA;
     397             : 
     398           4 :         assert(c->cgroup);
     399             : 
     400           4 :         if (!c->unit) {
     401             :                 const char *shifted;
     402             : 
     403           4 :                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
     404           4 :                 if (r < 0)
     405           1 :                         return r;
     406             : 
     407           4 :                 r = cg_path_get_unit(shifted, (char**) &c->unit);
     408           4 :                 if (r < 0)
     409           1 :                         return r;
     410             :         }
     411             : 
     412           3 :         *ret = c->unit;
     413           3 :         return 0;
     414             : }
     415             : 
     416          19 : _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
     417             :         int r;
     418             : 
     419          19 :         assert_return(c, -EINVAL);
     420          19 :         assert_return(ret, -EINVAL);
     421             : 
     422          19 :         if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
     423          15 :                 return -ENODATA;
     424             : 
     425           4 :         assert(c->cgroup);
     426             : 
     427           4 :         if (!c->user_unit) {
     428             :                 const char *shifted;
     429             : 
     430           4 :                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
     431           4 :                 if (r < 0)
     432           4 :                         return r;
     433             : 
     434           4 :                 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
     435           4 :                 if (r < 0)
     436           4 :                         return r;
     437             :         }
     438             : 
     439           0 :         *ret = c->user_unit;
     440           0 :         return 0;
     441             : }
     442             : 
     443          19 : _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
     444             :         int r;
     445             : 
     446          19 :         assert_return(c, -EINVAL);
     447          19 :         assert_return(ret, -EINVAL);
     448             : 
     449          19 :         if (!(c->mask & SD_BUS_CREDS_SLICE))
     450          15 :                 return -ENODATA;
     451             : 
     452           4 :         assert(c->cgroup);
     453             : 
     454           4 :         if (!c->slice) {
     455             :                 const char *shifted;
     456             : 
     457           4 :                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
     458           4 :                 if (r < 0)
     459           0 :                         return r;
     460             : 
     461           4 :                 r = cg_path_get_slice(shifted, (char**) &c->slice);
     462           4 :                 if (r < 0)
     463           0 :                         return r;
     464             :         }
     465             : 
     466           4 :         *ret = c->slice;
     467           4 :         return 0;
     468             : }
     469             : 
     470          19 : _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
     471             :         int r;
     472             : 
     473          19 :         assert_return(c, -EINVAL);
     474          19 :         assert_return(ret, -EINVAL);
     475             : 
     476          19 :         if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
     477          17 :                 return -ENODATA;
     478             : 
     479           2 :         assert(c->cgroup);
     480             : 
     481           2 :         if (!c->user_slice) {
     482             :                 const char *shifted;
     483             : 
     484           2 :                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
     485           2 :                 if (r < 0)
     486           1 :                         return r;
     487             : 
     488           2 :                 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
     489           2 :                 if (r < 0)
     490           1 :                         return r;
     491             :         }
     492             : 
     493           1 :         *ret = c->user_slice;
     494           1 :         return 0;
     495             : }
     496             : 
     497          19 : _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
     498             :         int r;
     499             : 
     500          19 :         assert_return(c, -EINVAL);
     501          19 :         assert_return(ret, -EINVAL);
     502             : 
     503          19 :         if (!(c->mask & SD_BUS_CREDS_SESSION))
     504          15 :                 return -ENODATA;
     505             : 
     506           4 :         assert(c->cgroup);
     507             : 
     508           4 :         if (!c->session) {
     509             :                 const char *shifted;
     510             : 
     511           4 :                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
     512           4 :                 if (r < 0)
     513           1 :                         return r;
     514             : 
     515           4 :                 r = cg_path_get_session(shifted, (char**) &c->session);
     516           4 :                 if (r < 0)
     517           1 :                         return r;
     518             :         }
     519             : 
     520           3 :         *ret = c->session;
     521           3 :         return 0;
     522             : }
     523             : 
     524          19 : _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
     525             :         const char *shifted;
     526             :         int r;
     527             : 
     528          19 :         assert_return(c, -EINVAL);
     529          19 :         assert_return(uid, -EINVAL);
     530             : 
     531          19 :         if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
     532          15 :                 return -ENODATA;
     533             : 
     534           4 :         assert(c->cgroup);
     535             : 
     536           4 :         r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
     537           4 :         if (r < 0)
     538           0 :                 return r;
     539             : 
     540           4 :         return cg_path_get_owner_uid(shifted, uid);
     541             : }
     542             : 
     543          19 : _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
     544          19 :         assert_return(c, -EINVAL);
     545             : 
     546          19 :         if (!(c->mask & SD_BUS_CREDS_CMDLINE))
     547          15 :                 return -ENODATA;
     548             : 
     549           4 :         if (!c->cmdline)
     550           0 :                 return -ENXIO;
     551             : 
     552           4 :         if (!c->cmdline_array) {
     553           4 :                 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
     554           4 :                 if (!c->cmdline_array)
     555           0 :                         return -ENOMEM;
     556             :         }
     557             : 
     558           4 :         *cmdline = c->cmdline_array;
     559           4 :         return 0;
     560             : }
     561             : 
     562          19 : _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
     563          19 :         assert_return(c, -EINVAL);
     564          19 :         assert_return(sessionid, -EINVAL);
     565             : 
     566          19 :         if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
     567          19 :                 return -ENODATA;
     568             : 
     569           0 :         if (c->audit_session_id == AUDIT_SESSION_INVALID)
     570           0 :                 return -ENXIO;
     571             : 
     572           0 :         *sessionid = c->audit_session_id;
     573           0 :         return 0;
     574             : }
     575             : 
     576          19 : _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
     577          19 :         assert_return(c, -EINVAL);
     578          19 :         assert_return(uid, -EINVAL);
     579             : 
     580          19 :         if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
     581          19 :                 return -ENODATA;
     582             : 
     583           0 :         if (c->audit_login_uid == UID_INVALID)
     584           0 :                 return -ENXIO;
     585             : 
     586           0 :         *uid = c->audit_login_uid;
     587           0 :         return 0;
     588             : }
     589             : 
     590           0 : _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
     591           0 :         assert_return(c, -EINVAL);
     592           0 :         assert_return(ret, -EINVAL);
     593             : 
     594           0 :         if (!(c->mask & SD_BUS_CREDS_TTY))
     595           0 :                 return -ENODATA;
     596             : 
     597           0 :         if (!c->tty)
     598           0 :                 return -ENXIO;
     599             : 
     600           0 :         *ret = c->tty;
     601           0 :         return 0;
     602             : }
     603             : 
     604           0 : _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
     605           0 :         assert_return(c, -EINVAL);
     606           0 :         assert_return(unique_name, -EINVAL);
     607             : 
     608           0 :         if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
     609           0 :                 return -ENODATA;
     610             : 
     611           0 :         *unique_name = c->unique_name;
     612           0 :         return 0;
     613             : }
     614             : 
     615          19 : _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
     616          19 :         assert_return(c, -EINVAL);
     617          19 :         assert_return(well_known_names, -EINVAL);
     618             : 
     619          19 :         if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
     620          16 :                 return -ENODATA;
     621             : 
     622             :         /* As a special hack we return the bus driver as well-known
     623             :          * names list when this is requested. */
     624           3 :         if (c->well_known_names_driver) {
     625             :                 static const char* const wkn[] = {
     626             :                         "org.freedesktop.DBus",
     627             :                         NULL
     628             :                 };
     629             : 
     630           0 :                 *well_known_names = (char**) wkn;
     631           0 :                 return 0;
     632             :         }
     633             : 
     634           3 :         if (c->well_known_names_local) {
     635             :                 static const char* const wkn[] = {
     636             :                         "org.freedesktop.DBus.Local",
     637             :                         NULL
     638             :                 };
     639             : 
     640           0 :                 *well_known_names = (char**) wkn;
     641           0 :                 return 0;
     642             :         }
     643             : 
     644           3 :         *well_known_names = c->well_known_names;
     645           3 :         return 0;
     646             : }
     647             : 
     648           0 : _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
     649           0 :         assert_return(c, -EINVAL);
     650           0 :         assert_return(ret, -EINVAL);
     651             : 
     652           0 :         if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
     653           0 :                 return -ENODATA;
     654             : 
     655           0 :         assert(c->description);
     656             : 
     657           0 :         if (!c->unescaped_description) {
     658           0 :                 c->unescaped_description = bus_label_unescape(c->description);
     659           0 :                 if (!c->unescaped_description)
     660           0 :                         return -ENOMEM;
     661             :         }
     662             : 
     663           0 :         *ret = c->unescaped_description;
     664           0 :         return 0;
     665             : }
     666             : 
     667         608 : static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
     668             :         size_t sz;
     669             : 
     670         608 :         assert(c);
     671         608 :         assert(capability >= 0);
     672         608 :         assert(c->capability);
     673             : 
     674         608 :         if ((unsigned) capability > cap_last_cap())
     675           0 :                 return 0;
     676             : 
     677         608 :         sz = DIV_ROUND_UP(cap_last_cap(), 32U);
     678             : 
     679         608 :         return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
     680             : }
     681             : 
     682         180 : _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
     683         180 :         assert_return(c, -EINVAL);
     684         180 :         assert_return(capability >= 0, -EINVAL);
     685             : 
     686         180 :         if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
     687          28 :                 return -ENODATA;
     688             : 
     689         152 :         return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
     690             : }
     691             : 
     692         167 : _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
     693         167 :         assert_return(c, -EINVAL);
     694         167 :         assert_return(capability >= 0, -EINVAL);
     695             : 
     696         167 :         if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
     697          15 :                 return -ENODATA;
     698             : 
     699         152 :         return has_cap(c, CAP_OFFSET_PERMITTED, capability);
     700             : }
     701             : 
     702         167 : _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
     703         167 :         assert_return(c, -EINVAL);
     704         167 :         assert_return(capability >= 0, -EINVAL);
     705             : 
     706         167 :         if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
     707          15 :                 return -ENODATA;
     708             : 
     709         152 :         return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
     710             : }
     711             : 
     712         167 : _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
     713         167 :         assert_return(c, -EINVAL);
     714         167 :         assert_return(capability >= 0, -EINVAL);
     715             : 
     716         167 :         if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
     717          15 :                 return -ENODATA;
     718             : 
     719         152 :         return has_cap(c, CAP_OFFSET_BOUNDING, capability);
     720             : }
     721             : 
     722           8 : static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
     723             :         size_t sz, max;
     724             :         unsigned i, j;
     725             : 
     726           8 :         assert(c);
     727           8 :         assert(p);
     728             : 
     729           8 :         max = DIV_ROUND_UP(cap_last_cap(), 32U);
     730           8 :         p += strspn(p, WHITESPACE);
     731             : 
     732           8 :         sz = strlen(p);
     733           8 :         if (sz % 8 != 0)
     734           0 :                 return -EINVAL;
     735             : 
     736           8 :         sz /= 8;
     737           8 :         if (sz > max)
     738           0 :                 return -EINVAL;
     739             : 
     740           8 :         if (!c->capability) {
     741           2 :                 c->capability = new0(uint32_t, max * 4);
     742           2 :                 if (!c->capability)
     743           0 :                         return -ENOMEM;
     744             :         }
     745             : 
     746          24 :         for (i = 0; i < sz; i ++) {
     747          16 :                 uint32_t v = 0;
     748             : 
     749         144 :                 for (j = 0; j < 8; ++j) {
     750             :                         int t;
     751             : 
     752         128 :                         t = unhexchar(*p++);
     753         128 :                         if (t < 0)
     754           0 :                                 return -EINVAL;
     755             : 
     756         128 :                         v = (v << 4) | t;
     757             :                 }
     758             : 
     759          16 :                 c->capability[offset * max + (sz - i - 1)] = v;
     760             :         }
     761             : 
     762           8 :         return 0;
     763             : }
     764             : 
     765          15 : int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
     766             :         uint64_t missing;
     767             :         int r;
     768             : 
     769          15 :         assert(c);
     770          15 :         assert(c->allocated);
     771             : 
     772          15 :         if (!(mask & SD_BUS_CREDS_AUGMENT))
     773          13 :                 return 0;
     774             : 
     775             :         /* Try to retrieve PID from creds if it wasn't passed to us */
     776           2 :         if (pid > 0) {
     777           2 :                 c->pid = pid;
     778           2 :                 c->mask |= SD_BUS_CREDS_PID;
     779           0 :         } else if (c->mask & SD_BUS_CREDS_PID)
     780           0 :                 pid = c->pid;
     781             :         else
     782             :                 /* Without pid we cannot do much... */
     783           0 :                 return 0;
     784             : 
     785             :         /* Try to retrieve TID from creds if it wasn't passed to us */
     786           2 :         if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
     787           0 :                 tid = c->tid;
     788             : 
     789             :         /* Calculate what we shall and can add */
     790           2 :         missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT);
     791           2 :         if (missing == 0)
     792           0 :                 return 0;
     793             : 
     794           2 :         if (tid > 0) {
     795           0 :                 c->tid = tid;
     796           0 :                 c->mask |= SD_BUS_CREDS_TID;
     797             :         }
     798             : 
     799           2 :         if (missing & (SD_BUS_CREDS_PPID |
     800             :                        SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
     801             :                        SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
     802             :                        SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
     803             :                        SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
     804             :                        SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
     805             : 
     806           4 :                 _cleanup_fclose_ FILE *f = NULL;
     807             :                 const char *p;
     808             : 
     809           2 :                 p = procfs_file_alloca(pid, "status");
     810             : 
     811           2 :                 f = fopen(p, "re");
     812           2 :                 if (!f) {
     813           0 :                         if (errno == ENOENT)
     814           0 :                                 return -ESRCH;
     815           0 :                         else if (errno != EPERM && errno != EACCES)
     816           0 :                                 return -errno;
     817             :                 } else {
     818             :                         char line[LINE_MAX];
     819             : 
     820          94 :                         FOREACH_LINE(line, f, return -errno) {
     821          92 :                                 truncate_nl(line);
     822             : 
     823          92 :                                 if (missing & SD_BUS_CREDS_PPID) {
     824          92 :                                         p = startswith(line, "PPid:");
     825          92 :                                         if (p) {
     826           2 :                                                 p += strspn(p, WHITESPACE);
     827             : 
     828             :                                                 /* Explicitly check for PPID 0 (which is the case for PID 1) */
     829           2 :                                                 if (!streq(p, "0")) {
     830           1 :                                                         r = parse_pid(p, &c->ppid);
     831           1 :                                                         if (r < 0)
     832           0 :                                                                 return r;
     833             : 
     834             :                                                 } else
     835           1 :                                                         c->ppid = 0;
     836             : 
     837           2 :                                                 c->mask |= SD_BUS_CREDS_PPID;
     838           2 :                                                 continue;
     839             :                                         }
     840             :                                 }
     841             : 
     842          90 :                                 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
     843          90 :                                         p = startswith(line, "Uid:");
     844          90 :                                         if (p) {
     845             :                                                 unsigned long uid, euid, suid, fsuid;
     846             : 
     847           2 :                                                 p += strspn(p, WHITESPACE);
     848           2 :                                                 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
     849           0 :                                                         return -EIO;
     850             : 
     851           2 :                                                 if (missing & SD_BUS_CREDS_UID)
     852           2 :                                                         c->uid = (uid_t) uid;
     853           2 :                                                 if (missing & SD_BUS_CREDS_EUID)
     854           2 :                                                         c->euid = (uid_t) euid;
     855           2 :                                                 if (missing & SD_BUS_CREDS_SUID)
     856           2 :                                                         c->suid = (uid_t) suid;
     857           2 :                                                 if (missing & SD_BUS_CREDS_FSUID)
     858           2 :                                                         c->fsuid = (uid_t) fsuid;
     859             : 
     860           2 :                                                 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
     861           2 :                                                 continue;
     862             :                                         }
     863             :                                 }
     864             : 
     865          88 :                                 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
     866          88 :                                         p = startswith(line, "Gid:");
     867          88 :                                         if (p) {
     868             :                                                 unsigned long gid, egid, sgid, fsgid;
     869             : 
     870           2 :                                                 p += strspn(p, WHITESPACE);
     871           2 :                                                 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
     872           0 :                                                         return -EIO;
     873             : 
     874           2 :                                                 if (missing & SD_BUS_CREDS_GID)
     875           2 :                                                         c->gid = (gid_t) gid;
     876           2 :                                                 if (missing & SD_BUS_CREDS_EGID)
     877           2 :                                                         c->egid = (gid_t) egid;
     878           2 :                                                 if (missing & SD_BUS_CREDS_SGID)
     879           2 :                                                         c->sgid = (gid_t) sgid;
     880           2 :                                                 if (missing & SD_BUS_CREDS_FSGID)
     881           2 :                                                         c->fsgid = (gid_t) fsgid;
     882             : 
     883           2 :                                                 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
     884           2 :                                                 continue;
     885             :                                         }
     886             :                                 }
     887             : 
     888          86 :                                 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
     889          86 :                                         p = startswith(line, "Groups:");
     890          86 :                                         if (p) {
     891           2 :                                                 size_t allocated = 0;
     892             : 
     893             :                                                 for (;;) {
     894             :                                                         unsigned long g;
     895           5 :                                                         int n = 0;
     896             : 
     897           5 :                                                         p += strspn(p, WHITESPACE);
     898           5 :                                                         if (*p == 0)
     899           2 :                                                                 break;
     900             : 
     901           3 :                                                         if (sscanf(p, "%lu%n", &g, &n) != 1)
     902           0 :                                                                 return -EIO;
     903             : 
     904           3 :                                                         if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
     905           0 :                                                                 return -ENOMEM;
     906             : 
     907           3 :                                                         c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
     908           3 :                                                         p += n;
     909           3 :                                                 }
     910             : 
     911           2 :                                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
     912           2 :                                                 continue;
     913             :                                         }
     914             :                                 }
     915             : 
     916          84 :                                 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
     917          84 :                                         p = startswith(line, "CapEff:");
     918          84 :                                         if (p) {
     919           2 :                                                 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
     920           2 :                                                 if (r < 0)
     921           0 :                                                         return r;
     922             : 
     923           2 :                                                 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
     924           2 :                                                 continue;
     925             :                                         }
     926             :                                 }
     927             : 
     928          82 :                                 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
     929          82 :                                         p = startswith(line, "CapPrm:");
     930          82 :                                         if (p) {
     931           2 :                                                 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
     932           2 :                                                 if (r < 0)
     933           0 :                                                         return r;
     934             : 
     935           2 :                                                 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
     936           2 :                                                 continue;
     937             :                                         }
     938             :                                 }
     939             : 
     940          80 :                                 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
     941          80 :                                         p = startswith(line, "CapInh:");
     942          80 :                                         if (p) {
     943           2 :                                                 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
     944           2 :                                                 if (r < 0)
     945           0 :                                                         return r;
     946             : 
     947           2 :                                                 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
     948           2 :                                                 continue;
     949             :                                         }
     950             :                                 }
     951             : 
     952          78 :                                 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
     953          78 :                                         p = startswith(line, "CapBnd:");
     954          78 :                                         if (p) {
     955           2 :                                                 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
     956           2 :                                                 if (r < 0)
     957           0 :                                                         return r;
     958             : 
     959           2 :                                                 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
     960           2 :                                                 continue;
     961             :                                         }
     962             :                                 }
     963          92 :                         }
     964             :                 }
     965             :         }
     966             : 
     967           2 :         if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
     968             :                 const char *p;
     969             : 
     970           2 :                 p = procfs_file_alloca(pid, "attr/current");
     971           2 :                 r = read_one_line_file(p, &c->label);
     972           2 :                 if (r < 0) {
     973           2 :                         if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
     974           0 :                                 return r;
     975             :                 } else
     976           0 :                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
     977             :         }
     978             : 
     979           2 :         if (missing & SD_BUS_CREDS_COMM) {
     980           2 :                 r = get_process_comm(pid, &c->comm);
     981           2 :                 if (r < 0) {
     982           0 :                         if (r != -EPERM && r != -EACCES)
     983           0 :                                 return r;
     984             :                 } else
     985           2 :                         c->mask |= SD_BUS_CREDS_COMM;
     986             :         }
     987             : 
     988           2 :         if (missing & SD_BUS_CREDS_EXE) {
     989           2 :                 r = get_process_exe(pid, &c->exe);
     990           2 :                 if (r == -ESRCH) {
     991             :                         /* Unfortunately we cannot really distinguish
     992             :                          * the case here where the process does not
     993             :                          * exist, and /proc/$PID/exe being unreadable
     994             :                          * because $PID is a kernel thread. Hence,
     995             :                          * assume it is a kernel thread, and rely on
     996             :                          * that this case is caught with a later
     997             :                          * call. */
     998           0 :                         c->exe = NULL;
     999           0 :                         c->mask |= SD_BUS_CREDS_EXE;
    1000           2 :                 } else if (r < 0) {
    1001           1 :                         if (r != -EPERM && r != -EACCES)
    1002           0 :                                 return r;
    1003             :                 } else
    1004           1 :                         c->mask |= SD_BUS_CREDS_EXE;
    1005             :         }
    1006             : 
    1007           2 :         if (missing & SD_BUS_CREDS_CMDLINE) {
    1008             :                 const char *p;
    1009             : 
    1010           2 :                 p = procfs_file_alloca(pid, "cmdline");
    1011           2 :                 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
    1012           2 :                 if (r == -ENOENT)
    1013           0 :                         return -ESRCH;
    1014           2 :                 if (r < 0) {
    1015           0 :                         if (r != -EPERM && r != -EACCES)
    1016           0 :                                 return r;
    1017             :                 } else {
    1018           2 :                         if (c->cmdline_size == 0) {
    1019           0 :                                 free(c->cmdline);
    1020           0 :                                 c->cmdline = NULL;
    1021             :                         }
    1022             : 
    1023           2 :                         c->mask |= SD_BUS_CREDS_CMDLINE;
    1024             :                 }
    1025             :         }
    1026             : 
    1027           2 :         if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
    1028           0 :                 _cleanup_free_ char *p = NULL;
    1029             : 
    1030           0 :                 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
    1031           0 :                         return -ENOMEM;
    1032             : 
    1033           0 :                 r = read_one_line_file(p, &c->tid_comm);
    1034           0 :                 if (r == -ENOENT)
    1035           0 :                         return -ESRCH;
    1036           0 :                 if (r < 0) {
    1037           0 :                         if (r != -EPERM && r != -EACCES)
    1038           0 :                                 return r;
    1039             :                 } else
    1040           0 :                         c->mask |= SD_BUS_CREDS_TID_COMM;
    1041             :         }
    1042             : 
    1043           2 :         if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
    1044             : 
    1045           2 :                 if (!c->cgroup) {
    1046           2 :                         r = cg_pid_get_path(NULL, pid, &c->cgroup);
    1047           2 :                         if (r < 0) {
    1048           0 :                                 if (r != -EPERM && r != -EACCES)
    1049           0 :                                         return r;
    1050             :                         }
    1051             :                 }
    1052             : 
    1053           2 :                 if (!c->cgroup_root) {
    1054           2 :                         r = cg_get_root_path(&c->cgroup_root);
    1055           2 :                         if (r < 0)
    1056           0 :                                 return r;
    1057             :                 }
    1058             : 
    1059           2 :                 if (c->cgroup)
    1060           2 :                         c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
    1061             :         }
    1062             : 
    1063           2 :         if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
    1064           2 :                 r = audit_session_from_pid(pid, &c->audit_session_id);
    1065           2 :                 if (r == -ENXIO) {
    1066             :                         /* ENXIO means: no audit session id assigned */
    1067           0 :                         c->audit_session_id = AUDIT_SESSION_INVALID;
    1068           0 :                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
    1069           2 :                 } else if (r < 0) {
    1070           2 :                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
    1071           0 :                                 return r;
    1072             :                 } else
    1073           0 :                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
    1074             :         }
    1075             : 
    1076           2 :         if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
    1077           2 :                 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
    1078           2 :                 if (r == -ENXIO) {
    1079             :                         /* ENXIO means: no audit login uid assigned */
    1080           0 :                         c->audit_login_uid = UID_INVALID;
    1081           0 :                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
    1082           2 :                 } else if (r < 0) {
    1083           2 :                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
    1084           0 :                                 return r;
    1085             :                 } else
    1086           0 :                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
    1087             :         }
    1088             : 
    1089           2 :         if (missing & SD_BUS_CREDS_TTY) {
    1090           2 :                 r = get_ctty(pid, NULL, &c->tty);
    1091           2 :                 if (r == -ENXIO) {
    1092             :                         /* ENXIO means: process has no controlling TTY */
    1093           1 :                         c->tty = NULL;
    1094           1 :                         c->mask |= SD_BUS_CREDS_TTY;
    1095           1 :                 } else if (r < 0) {
    1096           0 :                         if (r != -EPERM && r != -EACCES && r != -ENOENT)
    1097           0 :                                 return r;
    1098             :                 } else
    1099           1 :                         c->mask |= SD_BUS_CREDS_TTY;
    1100             :         }
    1101             : 
    1102             :         /* In case only the exe path was to be read we cannot
    1103             :          * distinguish the case where the exe path was unreadable
    1104             :          * because the process was a kernel thread, or when the
    1105             :          * process didn't exist at all. Hence, let's do a final check,
    1106             :          * to be sure. */
    1107           2 :         if (!pid_is_alive(pid))
    1108           0 :                 return -ESRCH;
    1109             : 
    1110           2 :         if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
    1111           0 :                 return -ESRCH;
    1112             : 
    1113           2 :         c->augmented = missing & c->mask;
    1114             : 
    1115           2 :         return 0;
    1116             : }
    1117             : 
    1118           0 : int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
    1119           0 :         _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
    1120             :         int r;
    1121             : 
    1122           0 :         assert(c);
    1123           0 :         assert(ret);
    1124             : 
    1125           0 :         if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
    1126             :                 /* There's already all data we need, or augmentation
    1127             :                  * wasn't turned on. */
    1128             : 
    1129           0 :                 *ret = sd_bus_creds_ref(c);
    1130           0 :                 return 0;
    1131             :         }
    1132             : 
    1133           0 :         n = bus_creds_new();
    1134           0 :         if (!n)
    1135           0 :                 return -ENOMEM;
    1136             : 
    1137             :         /* Copy the original data over */
    1138             : 
    1139           0 :         if (c->mask & mask & SD_BUS_CREDS_PID) {
    1140           0 :                 n->pid = c->pid;
    1141           0 :                 n->mask |= SD_BUS_CREDS_PID;
    1142             :         }
    1143             : 
    1144           0 :         if (c->mask & mask & SD_BUS_CREDS_TID) {
    1145           0 :                 n->tid = c->tid;
    1146           0 :                 n->mask |= SD_BUS_CREDS_TID;
    1147             :         }
    1148             : 
    1149           0 :         if (c->mask & mask & SD_BUS_CREDS_PPID) {
    1150           0 :                 n->ppid = c->ppid;
    1151           0 :                 n->mask |= SD_BUS_CREDS_PPID;
    1152             :         }
    1153             : 
    1154           0 :         if (c->mask & mask & SD_BUS_CREDS_UID) {
    1155           0 :                 n->uid = c->uid;
    1156           0 :                 n->mask |= SD_BUS_CREDS_UID;
    1157             :         }
    1158             : 
    1159           0 :         if (c->mask & mask & SD_BUS_CREDS_EUID) {
    1160           0 :                 n->euid = c->euid;
    1161           0 :                 n->mask |= SD_BUS_CREDS_EUID;
    1162             :         }
    1163             : 
    1164           0 :         if (c->mask & mask & SD_BUS_CREDS_SUID) {
    1165           0 :                 n->suid = c->suid;
    1166           0 :                 n->mask |= SD_BUS_CREDS_SUID;
    1167             :         }
    1168             : 
    1169           0 :         if (c->mask & mask & SD_BUS_CREDS_FSUID) {
    1170           0 :                 n->fsuid = c->fsuid;
    1171           0 :                 n->mask |= SD_BUS_CREDS_FSUID;
    1172             :         }
    1173             : 
    1174           0 :         if (c->mask & mask & SD_BUS_CREDS_GID) {
    1175           0 :                 n->gid = c->gid;
    1176           0 :                 n->mask |= SD_BUS_CREDS_GID;
    1177             :         }
    1178             : 
    1179           0 :         if (c->mask & mask & SD_BUS_CREDS_EGID) {
    1180           0 :                 n->egid = c->egid;
    1181           0 :                 n->mask |= SD_BUS_CREDS_EGID;
    1182             :         }
    1183             : 
    1184           0 :         if (c->mask & mask & SD_BUS_CREDS_SGID) {
    1185           0 :                 n->sgid = c->sgid;
    1186           0 :                 n->mask |= SD_BUS_CREDS_SGID;
    1187             :         }
    1188             : 
    1189           0 :         if (c->mask & mask & SD_BUS_CREDS_FSGID) {
    1190           0 :                 n->fsgid = c->fsgid;
    1191           0 :                 n->mask |= SD_BUS_CREDS_FSGID;
    1192             :         }
    1193             : 
    1194           0 :         if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
    1195           0 :                 if (c->supplementary_gids) {
    1196           0 :                         n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
    1197           0 :                         if (!n->supplementary_gids)
    1198           0 :                                 return -ENOMEM;
    1199           0 :                         n->n_supplementary_gids = c->n_supplementary_gids;
    1200             :                 } else {
    1201           0 :                         n->supplementary_gids = NULL;
    1202           0 :                         n->n_supplementary_gids = 0;
    1203             :                 }
    1204             : 
    1205           0 :                 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
    1206             :         }
    1207             : 
    1208           0 :         if (c->mask & mask & SD_BUS_CREDS_COMM) {
    1209           0 :                 assert(c->comm);
    1210             : 
    1211           0 :                 n->comm = strdup(c->comm);
    1212           0 :                 if (!n->comm)
    1213           0 :                         return -ENOMEM;
    1214             : 
    1215           0 :                 n->mask |= SD_BUS_CREDS_COMM;
    1216             :         }
    1217             : 
    1218           0 :         if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
    1219           0 :                 assert(c->tid_comm);
    1220             : 
    1221           0 :                 n->tid_comm = strdup(c->tid_comm);
    1222           0 :                 if (!n->tid_comm)
    1223           0 :                         return -ENOMEM;
    1224             : 
    1225           0 :                 n->mask |= SD_BUS_CREDS_TID_COMM;
    1226             :         }
    1227             : 
    1228           0 :         if (c->mask & mask & SD_BUS_CREDS_EXE) {
    1229           0 :                 if (c->exe) {
    1230           0 :                         n->exe = strdup(c->exe);
    1231           0 :                         if (!n->exe)
    1232           0 :                                 return -ENOMEM;
    1233             :                 } else
    1234           0 :                         n->exe = NULL;
    1235             : 
    1236           0 :                 n->mask |= SD_BUS_CREDS_EXE;
    1237             :         }
    1238             : 
    1239           0 :         if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
    1240           0 :                 if (c->cmdline) {
    1241           0 :                         n->cmdline = memdup(c->cmdline, c->cmdline_size);
    1242           0 :                         if (!n->cmdline)
    1243           0 :                                 return -ENOMEM;
    1244             : 
    1245           0 :                         n->cmdline_size = c->cmdline_size;
    1246             :                 } else {
    1247           0 :                         n->cmdline = NULL;
    1248           0 :                         n->cmdline_size = 0;
    1249             :                 }
    1250             : 
    1251           0 :                 n->mask |= SD_BUS_CREDS_CMDLINE;
    1252             :         }
    1253             : 
    1254           0 :         if (c->mask & mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) {
    1255           0 :                 assert(c->cgroup);
    1256             : 
    1257           0 :                 n->cgroup = strdup(c->cgroup);
    1258           0 :                 if (!n->cgroup)
    1259           0 :                         return -ENOMEM;
    1260             : 
    1261           0 :                 n->cgroup_root = strdup(c->cgroup_root);
    1262           0 :                 if (!n->cgroup_root)
    1263           0 :                         return -ENOMEM;
    1264             : 
    1265           0 :                 n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID);
    1266             :         }
    1267             : 
    1268           0 :         if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
    1269           0 :                 assert(c->capability);
    1270             : 
    1271           0 :                 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
    1272           0 :                 if (!n->capability)
    1273           0 :                         return -ENOMEM;
    1274             : 
    1275           0 :                 n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS);
    1276             :         }
    1277             : 
    1278           0 :         if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
    1279           0 :                 assert(c->label);
    1280             : 
    1281           0 :                 n->label = strdup(c->label);
    1282           0 :                 if (!n->label)
    1283           0 :                         return -ENOMEM;
    1284           0 :                 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
    1285             :         }
    1286             : 
    1287           0 :         if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
    1288           0 :                 n->audit_session_id = c->audit_session_id;
    1289           0 :                 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
    1290             :         }
    1291           0 :         if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
    1292           0 :                 n->audit_login_uid = c->audit_login_uid;
    1293           0 :                 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
    1294             :         }
    1295             : 
    1296           0 :         if (c->mask & mask & SD_BUS_CREDS_TTY) {
    1297           0 :                 if (c->tty) {
    1298           0 :                         n->tty = strdup(c->tty);
    1299           0 :                         if (!n->tty)
    1300           0 :                                 return -ENOMEM;
    1301             :                 } else
    1302           0 :                         n->tty = NULL;
    1303           0 :                 n->mask |= SD_BUS_CREDS_TTY;
    1304             :         }
    1305             : 
    1306           0 :         if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
    1307           0 :                 assert(c->unique_name);
    1308             : 
    1309           0 :                 n->unique_name = strdup(c->unique_name);
    1310           0 :                 if (!n->unique_name)
    1311           0 :                         return -ENOMEM;
    1312           0 :                 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
    1313             :         }
    1314             : 
    1315           0 :         if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
    1316           0 :                 if (strv_isempty(c->well_known_names))
    1317           0 :                         n->well_known_names = NULL;
    1318             :                 else {
    1319           0 :                         n->well_known_names = strv_copy(c->well_known_names);
    1320           0 :                         if (!n->well_known_names)
    1321           0 :                                 return -ENOMEM;
    1322             :                 }
    1323           0 :                 n->well_known_names_driver = c->well_known_names_driver;
    1324           0 :                 n->well_known_names_local = c->well_known_names_local;
    1325           0 :                 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
    1326             :         }
    1327             : 
    1328           0 :         if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
    1329           0 :                 assert(c->description);
    1330           0 :                 n->description = strdup(c->description);
    1331           0 :                 if (!n->description)
    1332           0 :                         return -ENOMEM;
    1333           0 :                 n->mask |= SD_BUS_CREDS_DESCRIPTION;
    1334             :         }
    1335             : 
    1336           0 :         n->augmented = c->augmented & n->mask;
    1337             : 
    1338             :         /* Get more data */
    1339             : 
    1340           0 :         r = bus_creds_add_more(n, mask, 0, 0);
    1341           0 :         if (r < 0)
    1342           0 :                 return r;
    1343             : 
    1344           0 :         *ret = n;
    1345           0 :         n = NULL;
    1346           0 :         return 0;
    1347             : }

Generated by: LCOV version 1.11