chiark / gitweb /
Prep v228: Condense elogind source masks (5/5)
[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 #if 0 /// elogind does not support systemd slices
560         return cg_path_get_owner_uid(shifted, uid);
561 #else
562         *uid = c->uid;
563         return 0;
564 #endif // 0
565 }
566
567 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
568         assert_return(c, -EINVAL);
569
570         if (!(c->mask & SD_BUS_CREDS_CMDLINE))
571                 return -ENODATA;
572
573         if (!c->cmdline)
574                 return -ENXIO;
575
576         if (!c->cmdline_array) {
577                 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
578                 if (!c->cmdline_array)
579                         return -ENOMEM;
580         }
581
582         *cmdline = c->cmdline_array;
583         return 0;
584 }
585
586 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
587         assert_return(c, -EINVAL);
588         assert_return(sessionid, -EINVAL);
589
590         if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
591                 return -ENODATA;
592
593         if (c->audit_session_id == AUDIT_SESSION_INVALID)
594                 return -ENXIO;
595
596         *sessionid = c->audit_session_id;
597         return 0;
598 }
599
600 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
601         assert_return(c, -EINVAL);
602         assert_return(uid, -EINVAL);
603
604         if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
605                 return -ENODATA;
606
607         if (c->audit_login_uid == UID_INVALID)
608                 return -ENXIO;
609
610         *uid = c->audit_login_uid;
611         return 0;
612 }
613
614 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
615         assert_return(c, -EINVAL);
616         assert_return(ret, -EINVAL);
617
618         if (!(c->mask & SD_BUS_CREDS_TTY))
619                 return -ENODATA;
620
621         if (!c->tty)
622                 return -ENXIO;
623
624         *ret = c->tty;
625         return 0;
626 }
627
628 #if 0 /// UNNEEDED by elogind
629 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
630         assert_return(c, -EINVAL);
631         assert_return(unique_name, -EINVAL);
632
633         if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
634                 return -ENODATA;
635
636         *unique_name = c->unique_name;
637         return 0;
638 }
639
640 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
641         assert_return(c, -EINVAL);
642         assert_return(well_known_names, -EINVAL);
643
644         if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
645                 return -ENODATA;
646
647         /* As a special hack we return the bus driver as well-known
648          * names list when this is requested. */
649         if (c->well_known_names_driver) {
650                 static const char* const wkn[] = {
651                         "org.freedesktop.DBus",
652                         NULL
653                 };
654
655                 *well_known_names = (char**) wkn;
656                 return 0;
657         }
658
659         if (c->well_known_names_local) {
660                 static const char* const wkn[] = {
661                         "org.freedesktop.DBus.Local",
662                         NULL
663                 };
664
665                 *well_known_names = (char**) wkn;
666                 return 0;
667         }
668
669         *well_known_names = c->well_known_names;
670         return 0;
671 }
672
673 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
674         assert_return(c, -EINVAL);
675         assert_return(ret, -EINVAL);
676
677         if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
678                 return -ENODATA;
679
680         assert(c->description);
681
682         if (!c->unescaped_description) {
683                 c->unescaped_description = bus_label_unescape(c->description);
684                 if (!c->unescaped_description)
685                         return -ENOMEM;
686         }
687
688         *ret = c->unescaped_description;
689         return 0;
690 }
691 #endif // 0
692
693 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
694         size_t sz;
695
696         assert(c);
697         assert(capability >= 0);
698         assert(c->capability);
699
700         if ((unsigned) capability > cap_last_cap())
701                 return 0;
702
703         sz = DIV_ROUND_UP(cap_last_cap(), 32U);
704
705         return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
706 }
707
708 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
709         assert_return(c, -EINVAL);
710         assert_return(capability >= 0, -EINVAL);
711
712         if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
713                 return -ENODATA;
714
715         return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
716 }
717
718 #if 0 /// UNNEEDED by elogind
719 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
720         assert_return(c, -EINVAL);
721         assert_return(capability >= 0, -EINVAL);
722
723         if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
724                 return -ENODATA;
725
726         return has_cap(c, CAP_OFFSET_PERMITTED, capability);
727 }
728
729 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
730         assert_return(c, -EINVAL);
731         assert_return(capability >= 0, -EINVAL);
732
733         if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
734                 return -ENODATA;
735
736         return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
737 }
738
739 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
740         assert_return(c, -EINVAL);
741         assert_return(capability >= 0, -EINVAL);
742
743         if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
744                 return -ENODATA;
745
746         return has_cap(c, CAP_OFFSET_BOUNDING, capability);
747 }
748 #endif // 0
749
750 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
751         size_t sz, max;
752         unsigned i, j;
753
754         assert(c);
755         assert(p);
756
757         max = DIV_ROUND_UP(cap_last_cap(), 32U);
758         p += strspn(p, WHITESPACE);
759
760         sz = strlen(p);
761         if (sz % 8 != 0)
762                 return -EINVAL;
763
764         sz /= 8;
765         if (sz > max)
766                 return -EINVAL;
767
768         if (!c->capability) {
769                 c->capability = new0(uint32_t, max * 4);
770                 if (!c->capability)
771                         return -ENOMEM;
772         }
773
774         for (i = 0; i < sz; i ++) {
775                 uint32_t v = 0;
776
777                 for (j = 0; j < 8; ++j) {
778                         int t;
779
780                         t = unhexchar(*p++);
781                         if (t < 0)
782                                 return -EINVAL;
783
784                         v = (v << 4) | t;
785                 }
786
787                 c->capability[offset * max + (sz - i - 1)] = v;
788         }
789
790         return 0;
791 }
792
793 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
794         uint64_t missing;
795         int r;
796
797         assert(c);
798         assert(c->allocated);
799
800         if (!(mask & SD_BUS_CREDS_AUGMENT))
801                 return 0;
802
803         /* Try to retrieve PID from creds if it wasn't passed to us */
804         if (pid > 0) {
805                 c->pid = pid;
806                 c->mask |= SD_BUS_CREDS_PID;
807         } else if (c->mask & SD_BUS_CREDS_PID)
808                 pid = c->pid;
809         else
810                 /* Without pid we cannot do much... */
811                 return 0;
812
813         /* Try to retrieve TID from creds if it wasn't passed to us */
814         if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
815                 tid = c->tid;
816
817         /* Calculate what we shall and can add */
818         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);
819         if (missing == 0)
820                 return 0;
821
822         if (tid > 0) {
823                 c->tid = tid;
824                 c->mask |= SD_BUS_CREDS_TID;
825         }
826
827         if (missing & (SD_BUS_CREDS_PPID |
828                        SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
829                        SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
830                        SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
831                        SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
832                        SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
833
834                 _cleanup_fclose_ FILE *f = NULL;
835                 const char *p;
836
837                 p = procfs_file_alloca(pid, "status");
838
839                 f = fopen(p, "re");
840                 if (!f) {
841                         if (errno == ENOENT)
842                                 return -ESRCH;
843                         else if (errno != EPERM && errno != EACCES)
844                                 return -errno;
845                 } else {
846                         char line[LINE_MAX];
847
848                         FOREACH_LINE(line, f, return -errno) {
849                                 truncate_nl(line);
850
851                                 if (missing & SD_BUS_CREDS_PPID) {
852                                         p = startswith(line, "PPid:");
853                                         if (p) {
854                                                 p += strspn(p, WHITESPACE);
855
856                                                 /* Explicitly check for PPID 0 (which is the case for PID 1) */
857                                                 if (!streq(p, "0")) {
858                                                         r = parse_pid(p, &c->ppid);
859                                                         if (r < 0)
860                                                                 return r;
861
862                                                 } else
863                                                         c->ppid = 0;
864
865                                                 c->mask |= SD_BUS_CREDS_PPID;
866                                                 continue;
867                                         }
868                                 }
869
870                                 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
871                                         p = startswith(line, "Uid:");
872                                         if (p) {
873                                                 unsigned long uid, euid, suid, fsuid;
874
875                                                 p += strspn(p, WHITESPACE);
876                                                 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
877                                                         return -EIO;
878
879                                                 if (missing & SD_BUS_CREDS_UID)
880                                                         c->uid = (uid_t) uid;
881                                                 if (missing & SD_BUS_CREDS_EUID)
882                                                         c->euid = (uid_t) euid;
883                                                 if (missing & SD_BUS_CREDS_SUID)
884                                                         c->suid = (uid_t) suid;
885                                                 if (missing & SD_BUS_CREDS_FSUID)
886                                                         c->fsuid = (uid_t) fsuid;
887
888                                                 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
889                                                 continue;
890                                         }
891                                 }
892
893                                 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
894                                         p = startswith(line, "Gid:");
895                                         if (p) {
896                                                 unsigned long gid, egid, sgid, fsgid;
897
898                                                 p += strspn(p, WHITESPACE);
899                                                 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
900                                                         return -EIO;
901
902                                                 if (missing & SD_BUS_CREDS_GID)
903                                                         c->gid = (gid_t) gid;
904                                                 if (missing & SD_BUS_CREDS_EGID)
905                                                         c->egid = (gid_t) egid;
906                                                 if (missing & SD_BUS_CREDS_SGID)
907                                                         c->sgid = (gid_t) sgid;
908                                                 if (missing & SD_BUS_CREDS_FSGID)
909                                                         c->fsgid = (gid_t) fsgid;
910
911                                                 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
912                                                 continue;
913                                         }
914                                 }
915
916                                 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
917                                         p = startswith(line, "Groups:");
918                                         if (p) {
919                                                 size_t allocated = 0;
920
921                                                 for (;;) {
922                                                         unsigned long g;
923                                                         int n = 0;
924
925                                                         p += strspn(p, WHITESPACE);
926                                                         if (*p == 0)
927                                                                 break;
928
929                                                         if (sscanf(p, "%lu%n", &g, &n) != 1)
930                                                                 return -EIO;
931
932                                                         if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
933                                                                 return -ENOMEM;
934
935                                                         c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
936                                                         p += n;
937                                                 }
938
939                                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
940                                                 continue;
941                                         }
942                                 }
943
944                                 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
945                                         p = startswith(line, "CapEff:");
946                                         if (p) {
947                                                 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
948                                                 if (r < 0)
949                                                         return r;
950
951                                                 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
952                                                 continue;
953                                         }
954                                 }
955
956                                 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
957                                         p = startswith(line, "CapPrm:");
958                                         if (p) {
959                                                 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
960                                                 if (r < 0)
961                                                         return r;
962
963                                                 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
964                                                 continue;
965                                         }
966                                 }
967
968                                 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
969                                         p = startswith(line, "CapInh:");
970                                         if (p) {
971                                                 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
972                                                 if (r < 0)
973                                                         return r;
974
975                                                 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
976                                                 continue;
977                                         }
978                                 }
979
980                                 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
981                                         p = startswith(line, "CapBnd:");
982                                         if (p) {
983                                                 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
984                                                 if (r < 0)
985                                                         return r;
986
987                                                 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
988                                                 continue;
989                                         }
990                                 }
991                         }
992                 }
993         }
994
995         if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
996                 const char *p;
997
998                 p = procfs_file_alloca(pid, "attr/current");
999                 r = read_one_line_file(p, &c->label);
1000                 if (r < 0) {
1001                         if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1002                                 return r;
1003                 } else
1004                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1005         }
1006
1007         if (missing & SD_BUS_CREDS_COMM) {
1008                 r = get_process_comm(pid, &c->comm);
1009                 if (r < 0) {
1010                         if (r != -EPERM && r != -EACCES)
1011                                 return r;
1012                 } else
1013                         c->mask |= SD_BUS_CREDS_COMM;
1014         }
1015
1016         if (missing & SD_BUS_CREDS_EXE) {
1017                 r = get_process_exe(pid, &c->exe);
1018                 if (r == -ESRCH) {
1019                         /* Unfortunately we cannot really distinguish
1020                          * the case here where the process does not
1021                          * exist, and /proc/$PID/exe being unreadable
1022                          * because $PID is a kernel thread. Hence,
1023                          * assume it is a kernel thread, and rely on
1024                          * that this case is caught with a later
1025                          * call. */
1026                         c->exe = NULL;
1027                         c->mask |= SD_BUS_CREDS_EXE;
1028                 } else if (r < 0) {
1029                         if (r != -EPERM && r != -EACCES)
1030                                 return r;
1031                 } else
1032                         c->mask |= SD_BUS_CREDS_EXE;
1033         }
1034
1035         if (missing & SD_BUS_CREDS_CMDLINE) {
1036                 const char *p;
1037
1038                 p = procfs_file_alloca(pid, "cmdline");
1039                 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1040                 if (r == -ENOENT)
1041                         return -ESRCH;
1042                 if (r < 0) {
1043                         if (r != -EPERM && r != -EACCES)
1044                                 return r;
1045                 } else {
1046                         if (c->cmdline_size == 0)
1047                                 c->cmdline = mfree(c->cmdline);
1048
1049                         c->mask |= SD_BUS_CREDS_CMDLINE;
1050                 }
1051         }
1052
1053         if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1054                 _cleanup_free_ char *p = NULL;
1055
1056                 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1057                         return -ENOMEM;
1058
1059                 r = read_one_line_file(p, &c->tid_comm);
1060                 if (r == -ENOENT)
1061                         return -ESRCH;
1062                 if (r < 0) {
1063                         if (r != -EPERM && r != -EACCES)
1064                                 return r;
1065                 } else
1066                         c->mask |= SD_BUS_CREDS_TID_COMM;
1067         }
1068
1069         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)) {
1070
1071                 if (!c->cgroup) {
1072                         r = cg_pid_get_path(NULL, pid, &c->cgroup);
1073                         if (r < 0) {
1074                                 if (r != -EPERM && r != -EACCES)
1075                                         return r;
1076                         }
1077                 }
1078
1079                 if (!c->cgroup_root) {
1080                         r = cg_get_root_path(&c->cgroup_root);
1081                         if (r < 0)
1082                                 return r;
1083                 }
1084
1085                 if (c->cgroup)
1086                         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);
1087         }
1088
1089         if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1090                 r = audit_session_from_pid(pid, &c->audit_session_id);
1091                 if (r == -ENODATA) {
1092                         /* ENODATA means: no audit session id assigned */
1093                         c->audit_session_id = AUDIT_SESSION_INVALID;
1094                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1095                 } else if (r < 0) {
1096                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1097                                 return r;
1098                 } else
1099                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1100         }
1101
1102         if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1103                 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1104                 if (r == -ENODATA) {
1105                         /* ENODATA means: no audit login uid assigned */
1106                         c->audit_login_uid = UID_INVALID;
1107                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1108                 } else if (r < 0) {
1109                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1110                                 return r;
1111                 } else
1112                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1113         }
1114
1115         if (missing & SD_BUS_CREDS_TTY) {
1116                 r = get_ctty(pid, NULL, &c->tty);
1117                 if (r == -ENXIO) {
1118                         /* ENXIO means: process has no controlling TTY */
1119                         c->tty = NULL;
1120                         c->mask |= SD_BUS_CREDS_TTY;
1121                 } else if (r < 0) {
1122                         if (r != -EPERM && r != -EACCES && r != -ENOENT)
1123                                 return r;
1124                 } else
1125                         c->mask |= SD_BUS_CREDS_TTY;
1126         }
1127
1128         /* In case only the exe path was to be read we cannot
1129          * distinguish the case where the exe path was unreadable
1130          * because the process was a kernel thread, or when the
1131          * process didn't exist at all. Hence, let's do a final check,
1132          * to be sure. */
1133         if (!pid_is_alive(pid))
1134                 return -ESRCH;
1135
1136         if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1137                 return -ESRCH;
1138
1139         c->augmented = missing & c->mask;
1140
1141         return 0;
1142 }
1143
1144 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1145         _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1146         int r;
1147
1148         assert(c);
1149         assert(ret);
1150
1151         if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1152                 /* There's already all data we need, or augmentation
1153                  * wasn't turned on. */
1154
1155                 *ret = sd_bus_creds_ref(c);
1156                 return 0;
1157         }
1158
1159         n = bus_creds_new();
1160         if (!n)
1161                 return -ENOMEM;
1162
1163         /* Copy the original data over */
1164
1165         if (c->mask & mask & SD_BUS_CREDS_PID) {
1166                 n->pid = c->pid;
1167                 n->mask |= SD_BUS_CREDS_PID;
1168         }
1169
1170         if (c->mask & mask & SD_BUS_CREDS_TID) {
1171                 n->tid = c->tid;
1172                 n->mask |= SD_BUS_CREDS_TID;
1173         }
1174
1175         if (c->mask & mask & SD_BUS_CREDS_PPID) {
1176                 n->ppid = c->ppid;
1177                 n->mask |= SD_BUS_CREDS_PPID;
1178         }
1179
1180         if (c->mask & mask & SD_BUS_CREDS_UID) {
1181                 n->uid = c->uid;
1182                 n->mask |= SD_BUS_CREDS_UID;
1183         }
1184
1185         if (c->mask & mask & SD_BUS_CREDS_EUID) {
1186                 n->euid = c->euid;
1187                 n->mask |= SD_BUS_CREDS_EUID;
1188         }
1189
1190         if (c->mask & mask & SD_BUS_CREDS_SUID) {
1191                 n->suid = c->suid;
1192                 n->mask |= SD_BUS_CREDS_SUID;
1193         }
1194
1195         if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1196                 n->fsuid = c->fsuid;
1197                 n->mask |= SD_BUS_CREDS_FSUID;
1198         }
1199
1200         if (c->mask & mask & SD_BUS_CREDS_GID) {
1201                 n->gid = c->gid;
1202                 n->mask |= SD_BUS_CREDS_GID;
1203         }
1204
1205         if (c->mask & mask & SD_BUS_CREDS_EGID) {
1206                 n->egid = c->egid;
1207                 n->mask |= SD_BUS_CREDS_EGID;
1208         }
1209
1210         if (c->mask & mask & SD_BUS_CREDS_SGID) {
1211                 n->sgid = c->sgid;
1212                 n->mask |= SD_BUS_CREDS_SGID;
1213         }
1214
1215         if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1216                 n->fsgid = c->fsgid;
1217                 n->mask |= SD_BUS_CREDS_FSGID;
1218         }
1219
1220         if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1221                 if (c->supplementary_gids) {
1222                         n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1223                         if (!n->supplementary_gids)
1224                                 return -ENOMEM;
1225                         n->n_supplementary_gids = c->n_supplementary_gids;
1226                 } else {
1227                         n->supplementary_gids = NULL;
1228                         n->n_supplementary_gids = 0;
1229                 }
1230
1231                 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1232         }
1233
1234         if (c->mask & mask & SD_BUS_CREDS_COMM) {
1235                 assert(c->comm);
1236
1237                 n->comm = strdup(c->comm);
1238                 if (!n->comm)
1239                         return -ENOMEM;
1240
1241                 n->mask |= SD_BUS_CREDS_COMM;
1242         }
1243
1244         if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1245                 assert(c->tid_comm);
1246
1247                 n->tid_comm = strdup(c->tid_comm);
1248                 if (!n->tid_comm)
1249                         return -ENOMEM;
1250
1251                 n->mask |= SD_BUS_CREDS_TID_COMM;
1252         }
1253
1254         if (c->mask & mask & SD_BUS_CREDS_EXE) {
1255                 if (c->exe) {
1256                         n->exe = strdup(c->exe);
1257                         if (!n->exe)
1258                                 return -ENOMEM;
1259                 } else
1260                         n->exe = NULL;
1261
1262                 n->mask |= SD_BUS_CREDS_EXE;
1263         }
1264
1265         if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1266                 if (c->cmdline) {
1267                         n->cmdline = memdup(c->cmdline, c->cmdline_size);
1268                         if (!n->cmdline)
1269                                 return -ENOMEM;
1270
1271                         n->cmdline_size = c->cmdline_size;
1272                 } else {
1273                         n->cmdline = NULL;
1274                         n->cmdline_size = 0;
1275                 }
1276
1277                 n->mask |= SD_BUS_CREDS_CMDLINE;
1278         }
1279
1280         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)) {
1281                 assert(c->cgroup);
1282
1283                 n->cgroup = strdup(c->cgroup);
1284                 if (!n->cgroup)
1285                         return -ENOMEM;
1286
1287                 n->cgroup_root = strdup(c->cgroup_root);
1288                 if (!n->cgroup_root)
1289                         return -ENOMEM;
1290
1291                 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);
1292         }
1293
1294         if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1295                 assert(c->capability);
1296
1297                 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1298                 if (!n->capability)
1299                         return -ENOMEM;
1300
1301                 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);
1302         }
1303
1304         if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1305                 assert(c->label);
1306
1307                 n->label = strdup(c->label);
1308                 if (!n->label)
1309                         return -ENOMEM;
1310                 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1311         }
1312
1313         if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1314                 n->audit_session_id = c->audit_session_id;
1315                 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1316         }
1317         if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1318                 n->audit_login_uid = c->audit_login_uid;
1319                 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1320         }
1321
1322         if (c->mask & mask & SD_BUS_CREDS_TTY) {
1323                 if (c->tty) {
1324                         n->tty = strdup(c->tty);
1325                         if (!n->tty)
1326                                 return -ENOMEM;
1327                 } else
1328                         n->tty = NULL;
1329                 n->mask |= SD_BUS_CREDS_TTY;
1330         }
1331
1332         if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1333                 assert(c->unique_name);
1334
1335                 n->unique_name = strdup(c->unique_name);
1336                 if (!n->unique_name)
1337                         return -ENOMEM;
1338                 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1339         }
1340
1341         if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1342                 if (strv_isempty(c->well_known_names))
1343                         n->well_known_names = NULL;
1344                 else {
1345                         n->well_known_names = strv_copy(c->well_known_names);
1346                         if (!n->well_known_names)
1347                                 return -ENOMEM;
1348                 }
1349                 n->well_known_names_driver = c->well_known_names_driver;
1350                 n->well_known_names_local = c->well_known_names_local;
1351                 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1352         }
1353
1354         if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1355                 assert(c->description);
1356                 n->description = strdup(c->description);
1357                 if (!n->description)
1358                         return -ENOMEM;
1359                 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1360         }
1361
1362         n->augmented = c->augmented & n->mask;
1363
1364         /* Get more data */
1365
1366         r = bus_creds_add_more(n, mask, 0, 0);
1367         if (r < 0)
1368                 return r;
1369
1370         *ret = n;
1371         n = NULL;
1372         return 0;
1373 }