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