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