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/>.
23 #include <linux/capability.h>
26 #include "formats-util.h"
27 #include "capability.h"
28 #include "cgroup-util.h"
31 #include "bus-message.h"
34 #include "bus-creds.h"
35 #include "bus-label.h"
38 CAP_OFFSET_INHERITABLE = 0,
39 CAP_OFFSET_PERMITTED = 1,
40 CAP_OFFSET_EFFECTIVE = 2,
41 CAP_OFFSET_BOUNDING = 3
44 void bus_creds_done(sd_bus_creds *c) {
47 /* For internal bus cred structures that are allocated by
54 free(c->unescaped_description);
55 free(c->supplementary_gids);
57 free(c->well_known_names); /* note that this is an strv, but
58 * we only free the array, not the
59 * strings the array points to. The
60 * full strv we only free if
61 * c->allocated is set, see
64 strv_free(c->cmdline_array);
67 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
68 assert_return(c, NULL);
76 /* If this is an embedded creds structure, then
77 * forward ref counting to the message */
78 m = container_of(c, sd_bus_message, creds);
79 sd_bus_message_ref(m);
85 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
102 free(c->unique_name);
103 free(c->cgroup_root);
104 free(c->description);
106 free(c->supplementary_gids);
107 c->supplementary_gids = NULL;
109 strv_free(c->well_known_names);
110 c->well_known_names = NULL;
119 m = container_of(c, sd_bus_message, creds);
120 sd_bus_message_unref(m);
127 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
133 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
139 sd_bus_creds* bus_creds_new(void) {
142 c = new0(sd_bus_creds, 1);
151 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
155 assert_return(pid >= 0, -EINVAL);
156 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
157 assert_return(ret, -EINVAL);
166 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
168 sd_bus_creds_unref(c);
172 /* Check if the process existed at all, in case we haven't
173 * figured that out already */
174 if (!pid_is_alive(pid)) {
175 sd_bus_creds_unref(c);
183 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
184 assert_return(c, -EINVAL);
185 assert_return(uid, -EINVAL);
187 if (!(c->mask & SD_BUS_CREDS_UID))
194 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
195 assert_return(c, -EINVAL);
196 assert_return(euid, -EINVAL);
198 if (!(c->mask & SD_BUS_CREDS_EUID))
205 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
206 assert_return(c, -EINVAL);
207 assert_return(suid, -EINVAL);
209 if (!(c->mask & SD_BUS_CREDS_SUID))
217 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
218 assert_return(c, -EINVAL);
219 assert_return(fsuid, -EINVAL);
221 if (!(c->mask & SD_BUS_CREDS_FSUID))
228 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
229 assert_return(c, -EINVAL);
230 assert_return(gid, -EINVAL);
232 if (!(c->mask & SD_BUS_CREDS_GID))
239 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
240 assert_return(c, -EINVAL);
241 assert_return(egid, -EINVAL);
243 if (!(c->mask & SD_BUS_CREDS_EGID))
250 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
251 assert_return(c, -EINVAL);
252 assert_return(sgid, -EINVAL);
254 if (!(c->mask & SD_BUS_CREDS_SGID))
261 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
262 assert_return(c, -EINVAL);
263 assert_return(fsgid, -EINVAL);
265 if (!(c->mask & SD_BUS_CREDS_FSGID))
272 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
273 assert_return(c, -EINVAL);
274 assert_return(gids, -EINVAL);
276 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
279 *gids = c->supplementary_gids;
280 return (int) c->n_supplementary_gids;
283 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
284 assert_return(c, -EINVAL);
285 assert_return(pid, -EINVAL);
287 if (!(c->mask & SD_BUS_CREDS_PID))
295 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
296 assert_return(c, -EINVAL);
297 assert_return(tid, -EINVAL);
299 if (!(c->mask & SD_BUS_CREDS_TID))
307 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
308 assert_return(c, -EINVAL);
310 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
318 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
319 assert_return(c, -EINVAL);
320 assert_return(ret, -EINVAL);
322 if (!(c->mask & SD_BUS_CREDS_COMM))
330 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
331 assert_return(c, -EINVAL);
332 assert_return(ret, -EINVAL);
334 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
342 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
343 assert_return(c, -EINVAL);
344 assert_return(ret, -EINVAL);
346 if (!(c->mask & SD_BUS_CREDS_EXE))
354 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
355 assert_return(c, -EINVAL);
356 assert_return(ret, -EINVAL);
358 if (!(c->mask & SD_BUS_CREDS_CGROUP))
366 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
367 assert_return(c, -EINVAL);
368 assert_return(ret, -EINVAL);
370 if (!(c->mask & SD_BUS_CREDS_UNIT))
382 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
383 assert_return(c, -EINVAL);
384 assert_return(ret, -EINVAL);
386 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
398 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
399 assert_return(c, -EINVAL);
400 assert_return(ret, -EINVAL);
402 if (!(c->mask & SD_BUS_CREDS_SLICE))
414 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
417 assert_return(c, -EINVAL);
418 assert_return(ret, -EINVAL);
420 if (!(c->mask & SD_BUS_CREDS_SESSION))
428 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
432 r = cg_path_get_session(shifted, (char**) &c->session);
441 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
445 assert_return(c, -EINVAL);
446 assert_return(uid, -EINVAL);
448 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
453 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
460 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
461 assert_return(c, -EINVAL);
463 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
466 assert_return(c->cmdline, -ESRCH);
469 if (!c->cmdline_array) {
470 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
471 if (!c->cmdline_array)
475 *cmdline = c->cmdline_array;
479 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
480 assert_return(c, -EINVAL);
481 assert_return(sessionid, -EINVAL);
483 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
486 *sessionid = c->audit_session_id;
490 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
491 assert_return(c, -EINVAL);
492 assert_return(uid, -EINVAL);
494 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
497 *uid = c->audit_login_uid;
501 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
502 assert_return(c, -EINVAL);
503 assert_return(unique_name, -EINVAL);
505 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
508 *unique_name = c->unique_name;
512 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
513 assert_return(c, -EINVAL);
514 assert_return(well_known_names, -EINVAL);
516 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
519 /* As a special hack we return the bus driver as well-known
520 * names list when this is requested. */
521 if (c->well_known_names_driver) {
522 static const char* const wkn[] = {
523 "org.freedesktop.DBus",
527 *well_known_names = (char**) wkn;
531 if (c->well_known_names_local) {
532 static const char* const wkn[] = {
533 "org.freedesktop.DBus.Local",
537 *well_known_names = (char**) wkn;
541 *well_known_names = c->well_known_names;
545 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
546 assert_return(c, -EINVAL);
547 assert_return(ret, -EINVAL);
549 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
552 assert(c->description);
554 if (!c->unescaped_description) {
555 c->unescaped_description = bus_label_unescape(c->description);
556 if (!c->unescaped_description)
560 *ret = c->unescaped_description;
564 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
568 assert(capability >= 0);
569 assert(c->capability);
571 if ((unsigned) capability > cap_last_cap())
574 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
576 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
579 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
580 assert_return(c, -EINVAL);
581 assert_return(capability >= 0, -EINVAL);
583 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
586 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
589 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
590 assert_return(c, -EINVAL);
591 assert_return(capability >= 0, -EINVAL);
593 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
596 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
599 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
600 assert_return(c, -EINVAL);
601 assert_return(capability >= 0, -EINVAL);
603 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
606 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
609 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
610 assert_return(c, -EINVAL);
611 assert_return(capability >= 0, -EINVAL);
613 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
616 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
619 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
626 max = DIV_ROUND_UP(cap_last_cap(), 32U);
627 p += strspn(p, WHITESPACE);
637 if (!c->capability) {
638 c->capability = new0(uint32_t, max * 4);
643 for (i = 0; i < sz; i ++) {
646 for (j = 0; j < 8; ++j) {
656 c->capability[offset * max + (sz - i - 1)] = v;
662 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
667 assert(c->allocated);
669 if (!(mask & SD_BUS_CREDS_AUGMENT))
672 /* Try to retrieve PID from creds if it wasn't passed to us */
673 if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID))
676 /* Without pid we cannot do much... */
680 /* Try to retrieve TID from creds if it wasn't passed to us */
681 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
684 /* Calculate what we shall and can add */
685 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);
690 c->mask |= SD_BUS_CREDS_PID;
694 c->mask |= SD_BUS_CREDS_TID;
697 if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
698 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
699 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
700 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
701 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
703 _cleanup_fclose_ FILE *f = NULL;
706 p = procfs_file_alloca(pid, "status");
712 else if (errno != EPERM && errno != EACCES)
717 FOREACH_LINE(line, f, return -errno) {
720 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
721 p = startswith(line, "Uid:");
723 unsigned long uid, euid, suid, fsuid;
725 p += strspn(p, WHITESPACE);
726 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
729 if (missing & SD_BUS_CREDS_UID)
730 c->uid = (uid_t) uid;
731 if (missing & SD_BUS_CREDS_EUID)
732 c->euid = (uid_t) euid;
733 if (missing & SD_BUS_CREDS_SUID)
734 c->suid = (uid_t) suid;
735 if (missing & SD_BUS_CREDS_FSUID)
736 c->fsuid = (uid_t) fsuid;
738 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
743 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
744 p = startswith(line, "Gid:");
746 unsigned long gid, egid, sgid, fsgid;
748 p += strspn(p, WHITESPACE);
749 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
752 if (missing & SD_BUS_CREDS_GID)
753 c->gid = (gid_t) gid;
754 if (missing & SD_BUS_CREDS_EGID)
755 c->egid = (gid_t) egid;
756 if (missing & SD_BUS_CREDS_SGID)
757 c->sgid = (gid_t) sgid;
758 if (missing & SD_BUS_CREDS_FSGID)
759 c->fsgid = (gid_t) fsgid;
761 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
766 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
767 p = startswith(line, "Groups:");
769 size_t allocated = 0;
775 p += strspn(p, WHITESPACE);
779 if (sscanf(p, "%lu%n", &g, &n) != 1)
782 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
785 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
789 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
794 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
795 p = startswith(line, "CapEff:");
797 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
801 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
806 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
807 p = startswith(line, "CapPrm:");
809 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
813 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
818 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
819 p = startswith(line, "CapInh:");
821 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
825 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
830 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
831 p = startswith(line, "CapBnd:");
833 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
837 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
845 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
848 p = procfs_file_alloca(pid, "attr/current");
849 r = read_one_line_file(p, &c->label);
851 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
854 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
857 if (missing & SD_BUS_CREDS_COMM) {
858 r = get_process_comm(pid, &c->comm);
860 if (r != -EPERM && r != -EACCES)
863 c->mask |= SD_BUS_CREDS_COMM;
866 if (missing & SD_BUS_CREDS_EXE) {
867 r = get_process_exe(pid, &c->exe);
869 if (r != -EPERM && r != -EACCES)
872 c->mask |= SD_BUS_CREDS_EXE;
875 if (missing & SD_BUS_CREDS_CMDLINE) {
878 p = procfs_file_alloca(pid, "cmdline");
879 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
883 if (r != -EPERM && r != -EACCES)
886 if (c->cmdline_size == 0) {
890 c->mask |= SD_BUS_CREDS_CMDLINE;
894 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
895 _cleanup_free_ char *p = NULL;
897 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
900 r = read_one_line_file(p, &c->tid_comm);
904 if (r != -EPERM && r != -EACCES)
907 c->mask |= SD_BUS_CREDS_TID_COMM;
910 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)) {
913 r = cg_pid_get_path(NULL, pid, &c->cgroup);
915 if (r != -EPERM && r != -EACCES)
920 if (!c->cgroup_root) {
921 r = cg_get_root_path(&c->cgroup_root);
927 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);
930 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
931 r = audit_session_from_pid(pid, &c->audit_session_id);
933 if (r != -EOPNOTSUPP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
936 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
939 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
940 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
942 if (r != -EOPNOTSUPP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
945 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
948 c->augmented = missing & c->mask;
953 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
954 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
960 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
961 /* There's already all data we need, or augmentation
962 * wasn't turned on. */
964 *ret = sd_bus_creds_ref(c);
972 /* Copy the original data over */
974 if (c->mask & mask & SD_BUS_CREDS_PID) {
976 n->mask |= SD_BUS_CREDS_PID;
979 if (c->mask & mask & SD_BUS_CREDS_TID) {
981 n->mask |= SD_BUS_CREDS_TID;
984 if (c->mask & mask & SD_BUS_CREDS_UID) {
986 n->mask |= SD_BUS_CREDS_UID;
989 if (c->mask & mask & SD_BUS_CREDS_EUID) {
991 n->mask |= SD_BUS_CREDS_EUID;
994 if (c->mask & mask & SD_BUS_CREDS_SUID) {
996 n->mask |= SD_BUS_CREDS_SUID;
999 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1000 n->fsuid = c->fsuid;
1001 n->mask |= SD_BUS_CREDS_FSUID;
1004 if (c->mask & mask & SD_BUS_CREDS_GID) {
1006 n->mask |= SD_BUS_CREDS_GID;
1009 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1011 n->mask |= SD_BUS_CREDS_EGID;
1014 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1016 n->mask |= SD_BUS_CREDS_SGID;
1019 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1020 n->fsgid = c->fsgid;
1021 n->mask |= SD_BUS_CREDS_FSGID;
1024 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1025 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1026 if (!n->supplementary_gids)
1028 n->n_supplementary_gids = c->n_supplementary_gids;
1029 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1032 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1033 n->comm = strdup(c->comm);
1037 n->mask |= SD_BUS_CREDS_COMM;
1040 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1041 n->tid_comm = strdup(c->tid_comm);
1045 n->mask |= SD_BUS_CREDS_TID_COMM;
1048 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1049 n->exe = strdup(c->exe);
1053 n->mask |= SD_BUS_CREDS_EXE;
1056 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1057 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1061 n->cmdline_size = c->cmdline_size;
1062 n->mask |= SD_BUS_CREDS_CMDLINE;
1065 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)) {
1066 n->cgroup = strdup(c->cgroup);
1070 n->cgroup_root = strdup(c->cgroup_root);
1071 if (!n->cgroup_root)
1074 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);
1077 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1078 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1082 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);
1085 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1086 n->label = strdup(c->label);
1089 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1092 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1093 n->audit_session_id = c->audit_session_id;
1094 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1096 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1097 n->audit_login_uid = c->audit_login_uid;
1098 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1101 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1102 n->unique_name = strdup(c->unique_name);
1103 if (!n->unique_name)
1105 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1108 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1109 n->well_known_names = strv_copy(c->well_known_names);
1110 if (!n->well_known_names)
1112 n->well_known_names_driver = c->well_known_names_driver;
1113 n->well_known_names_local = c->well_known_names_local;
1114 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1117 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1118 n->description = strdup(c->description);
1119 if (!n->description)
1121 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1124 n->augmented = c->augmented & n->mask;
1128 r = bus_creds_add_more(n, mask, 0, 0);