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