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