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