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