]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-creds.c
libsystemd: use IN_SET macro
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-creds.c
CommitLineData
5b12334d
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2013 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
7d9fcc2b 20#include <linux/capability.h>
07630cea 21#include <stdlib.h>
5b12334d 22
b5efdb8a 23#include "alloc-util.h"
430f0182 24#include "audit-util.h"
07630cea
LP
25#include "bus-creds.h"
26#include "bus-label.h"
5b12334d 27#include "bus-message.h"
057171ef 28#include "bus-util.h"
430f0182 29#include "capability-util.h"
07630cea 30#include "cgroup-util.h"
3ffd4af2 31#include "fd-util.h"
07630cea 32#include "fileio.h"
f97b34a6 33#include "format-util.h"
e4e73a63 34#include "hexdecoct.h"
6bedfcbb 35#include "parse-util.h"
07630cea
LP
36#include "process-util.h"
37#include "string-util.h"
49b832c5 38#include "strv.h"
07630cea 39#include "terminal-util.h"
ee104e11 40#include "user-util.h"
07630cea 41#include "util.h"
5b12334d
LP
42
43enum {
44 CAP_OFFSET_INHERITABLE = 0,
45 CAP_OFFSET_PERMITTED = 1,
46 CAP_OFFSET_EFFECTIVE = 2,
47 CAP_OFFSET_BOUNDING = 3
48};
49
50void bus_creds_done(sd_bus_creds *c) {
51 assert(c);
52
53 /* For internal bus cred structures that are allocated by
54 * something else */
55
56 free(c->session);
57 free(c->unit);
58 free(c->user_unit);
59 free(c->slice);
329ac4bc 60 free(c->user_slice);
455971c1 61 free(c->unescaped_description);
606303a9 62 free(c->supplementary_gids);
4761e880 63 free(c->tty);
5b12334d 64
50c45216
LP
65 free(c->well_known_names); /* note that this is an strv, but
66 * we only free the array, not the
67 * strings the array points to. The
68 * full strv we only free if
69 * c->allocated is set, see
70 * below. */
71
49b832c5 72 strv_free(c->cmdline_array);
5b12334d
LP
73}
74
75_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
4afd3348
LP
76
77 if (!c)
78 return NULL;
5b12334d
LP
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)
df0ff127 168 pid = getpid_cached();
5b12334d
LP
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
3a87a86e 573 if (!audit_session_is_valid(c->audit_session_id))
cfeaa44a
LP
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
cad93f29 587 if (!uid_is_valid(c->audit_login_uid))
cfeaa44a
LP
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;
945c2931 819 else if (!IN_SET(errno, EPERM, EACCES))
705a415f
LP
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 976 if (r < 0) {
945c2931 977 if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
705a415f
LP
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 985 if (r < 0) {
945c2931 986 if (!IN_SET(r, -EPERM, -EACCES))
705a415f
LP
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) {
945c2931 1005 if (!IN_SET(r, -EPERM, -EACCES))
705a415f
LP
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) {
945c2931 1019 if (!IN_SET(r, -EPERM, -EACCES))
705a415f
LP
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) {
945c2931 1039 if (!IN_SET(r, -EPERM, -EACCES))
705a415f
LP
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) {
945c2931 1050 if (!IN_SET(r, -EPERM, -EACCES))
822d9b6e
LP
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) {
945c2931 1072 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -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) {
945c2931 1085 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -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) {
945c2931 1098 if (!IN_SET(r, -EPERM, -EACCES, -ENOENT))
4761e880
LP
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) {
4afd3348 1121 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
5b12334d
LP
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}