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