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