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