1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
25 #include "cgroup-util.h"
28 #include "bus-message.h"
30 #include "time-util.h"
32 #include "bus-creds.h"
33 #include "bus-label.h"
36 CAP_OFFSET_INHERITABLE = 0,
37 CAP_OFFSET_PERMITTED = 1,
38 CAP_OFFSET_EFFECTIVE = 2,
39 CAP_OFFSET_BOUNDING = 3
42 void bus_creds_done(sd_bus_creds *c) {
45 /* For internal bus cred structures that are allocated by
52 free(c->unescaped_description);
54 free(c->well_known_names); /* note that this is an strv, but
55 * we only free the array, not the
56 * strings the array points to. The
57 * full strv we only free if
58 * c->allocated is set, see
61 strv_free(c->cmdline_array);
64 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
65 assert_return(c, NULL);
73 /* If this is an embedded creds structure, then
74 * forward ref counting to the message */
75 m = container_of(c, sd_bus_message, creds);
76 sd_bus_message_ref(m);
82 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
100 free(c->cgroup_root);
101 free(c->description);
102 free(c->supplementary_gids);
104 strv_free(c->well_known_names);
105 c->well_known_names = NULL;
114 m = container_of(c, sd_bus_message, creds);
115 sd_bus_message_unref(m);
122 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
128 sd_bus_creds* bus_creds_new(void) {
131 c = new0(sd_bus_creds, 1);
140 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
144 assert_return(pid >= 0, -EINVAL);
145 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
146 assert_return(ret, -EINVAL);
155 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
157 sd_bus_creds_unref(c);
161 /* Check if the process existed at all, in case we haven't
162 * figured that out already */
163 if (!pid_is_alive(pid)) {
164 sd_bus_creds_unref(c);
172 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
173 assert_return(c, -EINVAL);
174 assert_return(uid, -EINVAL);
176 if (!(c->mask & SD_BUS_CREDS_UID))
183 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
184 assert_return(c, -EINVAL);
185 assert_return(euid, -EINVAL);
187 if (!(c->mask & SD_BUS_CREDS_EUID))
194 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
195 assert_return(c, -EINVAL);
196 assert_return(suid, -EINVAL);
198 if (!(c->mask & SD_BUS_CREDS_SUID))
206 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
207 assert_return(c, -EINVAL);
208 assert_return(fsuid, -EINVAL);
210 if (!(c->mask & SD_BUS_CREDS_FSUID))
217 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
218 assert_return(c, -EINVAL);
219 assert_return(gid, -EINVAL);
221 if (!(c->mask & SD_BUS_CREDS_UID))
229 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
230 assert_return(c, -EINVAL);
231 assert_return(egid, -EINVAL);
233 if (!(c->mask & SD_BUS_CREDS_EGID))
240 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
241 assert_return(c, -EINVAL);
242 assert_return(sgid, -EINVAL);
244 if (!(c->mask & SD_BUS_CREDS_SGID))
251 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
252 assert_return(c, -EINVAL);
253 assert_return(fsgid, -EINVAL);
255 if (!(c->mask & SD_BUS_CREDS_FSGID))
262 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
263 assert_return(c, -EINVAL);
264 assert_return(gids, -EINVAL);
266 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
269 *gids = c->supplementary_gids;
270 return (int) c->n_supplementary_gids;
273 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
274 assert_return(c, -EINVAL);
275 assert_return(pid, -EINVAL);
277 if (!(c->mask & SD_BUS_CREDS_PID))
285 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
286 assert_return(c, -EINVAL);
287 assert_return(tid, -EINVAL);
289 if (!(c->mask & SD_BUS_CREDS_TID))
297 _public_ int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec) {
298 assert_return(c, -EINVAL);
299 assert_return(usec, -EINVAL);
301 if (!(c->mask & SD_BUS_CREDS_PID_STARTTIME))
304 assert(c->pid_starttime > 0);
305 *usec = c->pid_starttime;
309 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
310 assert_return(c, -EINVAL);
312 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
320 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
321 assert_return(c, -EINVAL);
322 assert_return(ret, -EINVAL);
324 if (!(c->mask & SD_BUS_CREDS_COMM))
332 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
333 assert_return(c, -EINVAL);
334 assert_return(ret, -EINVAL);
336 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
344 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
345 assert_return(c, -EINVAL);
346 assert_return(ret, -EINVAL);
348 if (!(c->mask & SD_BUS_CREDS_EXE))
356 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
357 assert_return(c, -EINVAL);
358 assert_return(ret, -EINVAL);
360 if (!(c->mask & SD_BUS_CREDS_CGROUP))
368 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
371 assert_return(c, -EINVAL);
372 assert_return(ret, -EINVAL);
374 if (!(c->mask & SD_BUS_CREDS_UNIT))
382 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
386 r = cg_path_get_unit(shifted, (char**) &c->unit);
395 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
398 assert_return(c, -EINVAL);
399 assert_return(ret, -EINVAL);
401 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
409 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
413 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
422 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
425 assert_return(c, -EINVAL);
426 assert_return(ret, -EINVAL);
428 if (!(c->mask & SD_BUS_CREDS_SLICE))
436 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
440 r = cg_path_get_slice(shifted, (char**) &c->slice);
449 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
452 assert_return(c, -EINVAL);
453 assert_return(ret, -EINVAL);
455 if (!(c->mask & SD_BUS_CREDS_SESSION))
463 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
467 r = cg_path_get_session(shifted, (char**) &c->session);
476 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
480 assert_return(c, -EINVAL);
481 assert_return(uid, -EINVAL);
483 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
488 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
492 return cg_path_get_owner_uid(shifted, uid);
495 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
496 assert_return(c, -EINVAL);
498 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
501 assert_return(c->cmdline, -ESRCH);
504 if (!c->cmdline_array) {
505 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
506 if (!c->cmdline_array)
510 *cmdline = c->cmdline_array;
514 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
515 assert_return(c, -EINVAL);
516 assert_return(sessionid, -EINVAL);
518 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
521 *sessionid = c->audit_session_id;
525 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
526 assert_return(c, -EINVAL);
527 assert_return(uid, -EINVAL);
529 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
532 *uid = c->audit_login_uid;
536 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
537 assert_return(c, -EINVAL);
538 assert_return(unique_name, -EINVAL);
540 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
543 *unique_name = c->unique_name;
547 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
548 assert_return(c, -EINVAL);
549 assert_return(well_known_names, -EINVAL);
551 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
554 /* As a special hack we return the bus driver as well-known
555 * names list when this is requested. */
556 if (c->well_known_names_driver) {
557 static const char* const wkn[] = {
558 "org.freedesktop.DBus",
562 *well_known_names = (char**) wkn;
566 if (c->well_known_names_local) {
567 static const char* const wkn[] = {
568 "org.freedesktop.DBus.Local",
572 *well_known_names = (char**) wkn;
576 *well_known_names = c->well_known_names;
580 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
581 assert_return(c, -EINVAL);
582 assert_return(ret, -EINVAL);
584 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
587 assert(c->description);
589 if (!c->unescaped_description) {
590 c->unescaped_description = bus_label_unescape(c->description);
591 if (!c->unescaped_description)
595 *ret = c->unescaped_description;
599 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
603 assert(c->capability);
605 sz = c->capability_size / 4;
606 if ((size_t) capability >= sz*8)
609 return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8)));
612 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
613 assert_return(c, -EINVAL);
614 assert_return(capability >= 0, -EINVAL);
616 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
619 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
622 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
623 assert_return(c, -EINVAL);
624 assert_return(capability >= 0, -EINVAL);
626 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
629 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
632 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
633 assert_return(c, -EINVAL);
634 assert_return(capability >= 0, -EINVAL);
636 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
639 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
642 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
643 assert_return(c, -EINVAL);
644 assert_return(capability >= 0, -EINVAL);
646 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
649 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
652 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
659 p += strspn(p, WHITESPACE);
666 if (!c->capability) {
667 c->capability = new0(uint8_t, sz * 4);
671 c->capability_size = sz * 4;
674 for (i = 0; i < sz; i ++) {
677 x = unhexchar(p[i*2]);
678 y = unhexchar(p[i*2+1]);
683 c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y;
689 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
694 assert(c->allocated);
696 if (!(mask & SD_BUS_CREDS_AUGMENT))
699 missing = mask & ~c->mask;
703 /* Try to retrieve PID from creds if it wasn't passed to us */
704 if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID))
707 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
710 /* Without pid we cannot do much... */
716 c->mask |= SD_BUS_CREDS_PID;
721 c->mask |= SD_BUS_CREDS_TID;
724 if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
725 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
726 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
727 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
728 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
730 _cleanup_fclose_ FILE *f = NULL;
733 p = procfs_file_alloca(pid, "status");
739 else if (errno != EPERM && errno != EACCES)
744 FOREACH_LINE(line, f, return -errno) {
747 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
748 p = startswith(line, "Uid:");
750 unsigned long uid, euid, suid, fsuid;
752 p += strspn(p, WHITESPACE);
753 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
756 c->uid = (uid_t) uid;
757 c->euid = (uid_t) euid;
758 c->suid = (uid_t) suid;
759 c->fsuid = (uid_t) fsuid;
760 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
765 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
766 p = startswith(line, "Gid:");
768 unsigned long gid, egid, sgid, fsgid;
770 p += strspn(p, WHITESPACE);
771 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
774 c->gid = (gid_t) gid;
775 c->egid = (gid_t) egid;
776 c->sgid = (gid_t) sgid;
777 c->fsgid = (gid_t) fsgid;
778 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
783 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
784 p = startswith(line, "Groups:");
786 size_t allocated = 0;
792 p += strspn(p, WHITESPACE);
796 if (sscanf(p, "%lu%n", &g, &n) != 1)
799 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
802 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
806 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
811 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
812 p = startswith(line, "CapEff:");
814 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
818 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
823 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
824 p = startswith(line, "CapPrm:");
826 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
830 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
835 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
836 p = startswith(line, "CapInh:");
838 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
842 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
847 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
848 p = startswith(line, "CapBnd:");
850 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
854 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
862 if (missing & (SD_BUS_CREDS_PID_STARTTIME)) {
863 unsigned long long st;
865 r = get_starttime_of_pid(pid, &st);
867 if (r != -EPERM && r != -EACCES)
870 c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK);
871 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
875 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
878 p = procfs_file_alloca(pid, "attr/current");
879 r = read_one_line_file(p, &c->label);
881 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
884 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
887 if (missing & SD_BUS_CREDS_COMM) {
888 r = get_process_comm(pid, &c->comm);
890 if (r != -EPERM && r != -EACCES)
893 c->mask |= SD_BUS_CREDS_COMM;
896 if (missing & SD_BUS_CREDS_EXE) {
897 r = get_process_exe(pid, &c->exe);
899 if (r != -EPERM && r != -EACCES)
902 c->mask |= SD_BUS_CREDS_EXE;
905 if (missing & SD_BUS_CREDS_CMDLINE) {
908 p = procfs_file_alloca(pid, "cmdline");
909 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
913 if (r != -EPERM && r != -EACCES)
916 if (c->cmdline_size == 0) {
920 c->mask |= SD_BUS_CREDS_CMDLINE;
924 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
925 _cleanup_free_ char *p = NULL;
927 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
930 r = read_one_line_file(p, &c->tid_comm);
934 if (r != -EPERM && r != -EACCES)
937 c->mask |= SD_BUS_CREDS_TID_COMM;
940 if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
942 r = cg_pid_get_path(NULL, pid, &c->cgroup);
944 if (r != -EPERM && r != -EACCES)
947 r = cg_get_root_path(&c->cgroup_root);
951 c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
955 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
956 r = audit_session_from_pid(pid, &c->audit_session_id);
958 if (r != -ENOTSUP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
961 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
964 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
965 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
967 if (r != -ENOTSUP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
970 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
976 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
977 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
983 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
984 /* There's already all data we need, or augmentation
985 * wasn't turned on. */
987 *ret = sd_bus_creds_ref(c);
995 /* Copy the original data over */
997 if (c->mask & mask & SD_BUS_CREDS_UID) {
999 n->mask |= SD_BUS_CREDS_UID;
1002 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1004 n->mask |= SD_BUS_CREDS_EUID;
1007 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1009 n->mask |= SD_BUS_CREDS_SUID;
1012 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1013 n->fsuid = c->fsuid;
1014 n->mask |= SD_BUS_CREDS_FSUID;
1017 if (c->mask & mask & SD_BUS_CREDS_GID) {
1019 n->mask |= SD_BUS_CREDS_GID;
1022 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1024 n->mask |= SD_BUS_CREDS_EGID;
1027 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1029 n->mask |= SD_BUS_CREDS_SGID;
1032 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1033 n->fsgid = c->fsgid;
1034 n->mask |= SD_BUS_CREDS_FSGID;
1037 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1038 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1039 if (!n->supplementary_gids)
1041 n->n_supplementary_gids = c->n_supplementary_gids;
1042 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1045 if (c->mask & mask & SD_BUS_CREDS_PID) {
1047 n->mask |= SD_BUS_CREDS_PID;
1050 if (c->mask & mask & SD_BUS_CREDS_TID) {
1052 n->mask |= SD_BUS_CREDS_TID;
1055 if (c->mask & mask & SD_BUS_CREDS_PID_STARTTIME) {
1056 n->pid_starttime = c->pid_starttime;
1057 n->mask |= SD_BUS_CREDS_PID_STARTTIME;
1060 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1061 n->comm = strdup(c->comm);
1065 n->mask |= SD_BUS_CREDS_COMM;
1068 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1069 n->tid_comm = strdup(c->tid_comm);
1073 n->mask |= SD_BUS_CREDS_TID_COMM;
1076 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1077 n->exe = strdup(c->exe);
1081 n->mask |= SD_BUS_CREDS_EXE;
1084 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1085 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1089 n->cmdline_size = c->cmdline_size;
1090 n->mask |= SD_BUS_CREDS_CMDLINE;
1093 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_OWNER_UID)) {
1094 n->cgroup = strdup(c->cgroup);
1098 n->cgroup_root = strdup(c->cgroup_root);
1099 if (!n->cgroup_root)
1102 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_OWNER_UID);
1105 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1106 n->capability = memdup(c->capability, c->capability_size);
1110 n->capability_size = c->capability_size;
1111 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);
1114 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1115 n->label = strdup(c->label);
1118 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1121 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1122 n->audit_session_id = c->audit_session_id;
1123 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1125 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1126 n->audit_login_uid = c->audit_login_uid;
1127 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1130 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1131 n->unique_name = strdup(c->unique_name);
1132 if (!n->unique_name)
1134 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1137 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1138 n->well_known_names = strv_copy(c->well_known_names);
1139 if (!n->well_known_names)
1141 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1144 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1145 n->description = strdup(c->description);
1146 if (!n->description)
1148 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1153 r = bus_creds_add_more(n, mask,
1154 c->mask & SD_BUS_CREDS_PID ? c->pid : 0,
1155 c->mask & SD_BUS_CREDS_TID ? c->tid : 0);