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/>.
22 #include <linux/capability.h>
25 #include "alloc-util.h"
26 #include "audit-util.h"
27 #include "bus-creds.h"
28 #include "bus-label.h"
29 #include "bus-message.h"
31 #include "capability-util.h"
32 #include "cgroup-util.h"
35 #include "formats-util.h"
36 #include "hexdecoct.h"
37 #include "parse-util.h"
38 #include "process-util.h"
39 #include "string-util.h"
41 #include "terminal-util.h"
42 #include "user-util.h"
46 CAP_OFFSET_INHERITABLE = 0,
47 CAP_OFFSET_PERMITTED = 1,
48 CAP_OFFSET_EFFECTIVE = 2,
49 CAP_OFFSET_BOUNDING = 3
52 void bus_creds_done(sd_bus_creds *c) {
55 /* For internal bus cred structures that are allocated by
63 free(c->unescaped_description);
64 free(c->supplementary_gids);
67 free(c->well_known_names); /* note that this is an strv, but
68 * we only free the array, not the
69 * strings the array points to. The
70 * full strv we only free if
71 * c->allocated is set, see
74 strv_free(c->cmdline_array);
77 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
78 assert_return(c, NULL);
86 /* If this is an embedded creds structure, then
87 * forward ref counting to the message */
88 m = container_of(c, sd_bus_message, creds);
89 sd_bus_message_ref(m);
95 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
101 assert(c->n_ref > 0);
112 free(c->unique_name);
113 free(c->cgroup_root);
114 free(c->description);
116 c->supplementary_gids = mfree(c->supplementary_gids);
118 c->well_known_names = strv_free(c->well_known_names);
127 m = container_of(c, sd_bus_message, creds);
128 sd_bus_message_unref(m);
135 /// UNNEEDED by elogind
137 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
144 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
150 sd_bus_creds* bus_creds_new(void) {
153 c = new0(sd_bus_creds, 1);
162 /// UNNEEDED by elogind
164 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
168 assert_return(pid >= 0, -EINVAL);
169 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
170 assert_return(ret, -EINVAL);
179 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
181 sd_bus_creds_unref(c);
185 /* Check if the process existed at all, in case we haven't
186 * figured that out already */
187 if (!pid_is_alive(pid)) {
188 sd_bus_creds_unref(c);
197 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
198 assert_return(c, -EINVAL);
199 assert_return(uid, -EINVAL);
201 if (!(c->mask & SD_BUS_CREDS_UID))
208 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
209 assert_return(c, -EINVAL);
210 assert_return(euid, -EINVAL);
212 if (!(c->mask & SD_BUS_CREDS_EUID))
219 /// UNNEEDED by elogind
221 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
222 assert_return(c, -EINVAL);
223 assert_return(suid, -EINVAL);
225 if (!(c->mask & SD_BUS_CREDS_SUID))
233 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
234 assert_return(c, -EINVAL);
235 assert_return(fsuid, -EINVAL);
237 if (!(c->mask & SD_BUS_CREDS_FSUID))
244 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
245 assert_return(c, -EINVAL);
246 assert_return(gid, -EINVAL);
248 if (!(c->mask & SD_BUS_CREDS_GID))
256 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
257 assert_return(c, -EINVAL);
258 assert_return(egid, -EINVAL);
260 if (!(c->mask & SD_BUS_CREDS_EGID))
267 /// UNNEEDED by elogind
269 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
270 assert_return(c, -EINVAL);
271 assert_return(sgid, -EINVAL);
273 if (!(c->mask & SD_BUS_CREDS_SGID))
280 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
281 assert_return(c, -EINVAL);
282 assert_return(fsgid, -EINVAL);
284 if (!(c->mask & SD_BUS_CREDS_FSGID))
291 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
292 assert_return(c, -EINVAL);
293 assert_return(gids, -EINVAL);
295 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
298 *gids = c->supplementary_gids;
299 return (int) c->n_supplementary_gids;
303 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
304 assert_return(c, -EINVAL);
305 assert_return(pid, -EINVAL);
307 if (!(c->mask & SD_BUS_CREDS_PID))
315 /// UNNEEDED by elogind
317 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
318 assert_return(c, -EINVAL);
319 assert_return(ppid, -EINVAL);
321 if (!(c->mask & SD_BUS_CREDS_PPID))
324 /* PID 1 has no parent process. Let's distinguish the case of
325 * not knowing and not having a parent process by the returned
335 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
336 assert_return(c, -EINVAL);
337 assert_return(tid, -EINVAL);
339 if (!(c->mask & SD_BUS_CREDS_TID))
347 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
348 assert_return(c, -EINVAL);
350 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
358 /// UNNEEDED by elogind
360 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
361 assert_return(c, -EINVAL);
362 assert_return(ret, -EINVAL);
364 if (!(c->mask & SD_BUS_CREDS_COMM))
372 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
373 assert_return(c, -EINVAL);
374 assert_return(ret, -EINVAL);
376 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
384 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
385 assert_return(c, -EINVAL);
386 assert_return(ret, -EINVAL);
388 if (!(c->mask & SD_BUS_CREDS_EXE))
398 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
399 assert_return(c, -EINVAL);
400 assert_return(ret, -EINVAL);
402 if (!(c->mask & SD_BUS_CREDS_CGROUP))
410 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
413 assert_return(c, -EINVAL);
414 assert_return(ret, -EINVAL);
416 if (!(c->mask & SD_BUS_CREDS_UNIT))
424 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
428 r = cg_path_get_unit(shifted, (char**) &c->unit);
437 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
440 assert_return(c, -EINVAL);
441 assert_return(ret, -EINVAL);
443 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
451 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
455 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
464 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
467 assert_return(c, -EINVAL);
468 assert_return(ret, -EINVAL);
470 if (!(c->mask & SD_BUS_CREDS_SLICE))
478 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
482 r = cg_path_get_slice(shifted, (char**) &c->slice);
491 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
494 assert_return(c, -EINVAL);
495 assert_return(ret, -EINVAL);
497 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
502 if (!c->user_slice) {
505 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
509 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
514 *ret = c->user_slice;
519 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
522 assert_return(c, -EINVAL);
523 assert_return(ret, -EINVAL);
525 if (!(c->mask & SD_BUS_CREDS_SESSION))
533 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
534 c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
535 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
539 log_debug_elogind("Shifted: \"%s\"", shifted);
540 r = cg_path_get_session(shifted, (char**) &c->session);
549 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
553 assert_return(c, -EINVAL);
554 assert_return(uid, -EINVAL);
556 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
561 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
565 /// elogind does not support systemd slices
567 return cg_path_get_owner_uid(shifted, uid);
574 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
575 assert_return(c, -EINVAL);
577 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
583 if (!c->cmdline_array) {
584 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
585 if (!c->cmdline_array)
589 *cmdline = c->cmdline_array;
593 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
594 assert_return(c, -EINVAL);
595 assert_return(sessionid, -EINVAL);
597 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
600 if (c->audit_session_id == AUDIT_SESSION_INVALID)
603 *sessionid = c->audit_session_id;
607 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
608 assert_return(c, -EINVAL);
609 assert_return(uid, -EINVAL);
611 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
614 if (c->audit_login_uid == UID_INVALID)
617 *uid = c->audit_login_uid;
621 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
622 assert_return(c, -EINVAL);
623 assert_return(ret, -EINVAL);
625 if (!(c->mask & SD_BUS_CREDS_TTY))
635 /// UNNEEDED by elogind
637 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
638 assert_return(c, -EINVAL);
639 assert_return(unique_name, -EINVAL);
641 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
644 *unique_name = c->unique_name;
648 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
649 assert_return(c, -EINVAL);
650 assert_return(well_known_names, -EINVAL);
652 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
655 /* As a special hack we return the bus driver as well-known
656 * names list when this is requested. */
657 if (c->well_known_names_driver) {
658 static const char* const wkn[] = {
659 "org.freedesktop.DBus",
663 *well_known_names = (char**) wkn;
667 if (c->well_known_names_local) {
668 static const char* const wkn[] = {
669 "org.freedesktop.DBus.Local",
673 *well_known_names = (char**) wkn;
677 *well_known_names = c->well_known_names;
681 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
682 assert_return(c, -EINVAL);
683 assert_return(ret, -EINVAL);
685 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
688 assert(c->description);
690 if (!c->unescaped_description) {
691 c->unescaped_description = bus_label_unescape(c->description);
692 if (!c->unescaped_description)
696 *ret = c->unescaped_description;
701 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
705 assert(capability >= 0);
706 assert(c->capability);
708 if ((unsigned) capability > cap_last_cap())
711 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
713 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
716 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
717 assert_return(c, -EINVAL);
718 assert_return(capability >= 0, -EINVAL);
720 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
723 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
726 /// UNNEEDED by elogind
728 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
729 assert_return(c, -EINVAL);
730 assert_return(capability >= 0, -EINVAL);
732 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
735 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
738 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
739 assert_return(c, -EINVAL);
740 assert_return(capability >= 0, -EINVAL);
742 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
745 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
748 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
749 assert_return(c, -EINVAL);
750 assert_return(capability >= 0, -EINVAL);
752 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
755 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
759 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
766 max = DIV_ROUND_UP(cap_last_cap(), 32U);
767 p += strspn(p, WHITESPACE);
777 if (!c->capability) {
778 c->capability = new0(uint32_t, max * 4);
783 for (i = 0; i < sz; i ++) {
786 for (j = 0; j < 8; ++j) {
796 c->capability[offset * max + (sz - i - 1)] = v;
802 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
807 assert(c->allocated);
809 if (!(mask & SD_BUS_CREDS_AUGMENT))
812 /* Try to retrieve PID from creds if it wasn't passed to us */
815 c->mask |= SD_BUS_CREDS_PID;
816 } else if (c->mask & SD_BUS_CREDS_PID)
819 /* Without pid we cannot do much... */
822 /* Try to retrieve TID from creds if it wasn't passed to us */
823 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
826 /* Calculate what we shall and can add */
827 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);
833 c->mask |= SD_BUS_CREDS_TID;
836 if (missing & (SD_BUS_CREDS_PPID |
837 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
838 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
839 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
840 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
841 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
843 _cleanup_fclose_ FILE *f = NULL;
846 p = procfs_file_alloca(pid, "status");
852 else if (errno != EPERM && errno != EACCES)
857 FOREACH_LINE(line, f, return -errno) {
860 if (missing & SD_BUS_CREDS_PPID) {
861 p = startswith(line, "PPid:");
863 p += strspn(p, WHITESPACE);
865 /* Explicitly check for PPID 0 (which is the case for PID 1) */
866 if (!streq(p, "0")) {
867 r = parse_pid(p, &c->ppid);
874 c->mask |= SD_BUS_CREDS_PPID;
879 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
880 p = startswith(line, "Uid:");
882 unsigned long uid, euid, suid, fsuid;
884 p += strspn(p, WHITESPACE);
885 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
888 if (missing & SD_BUS_CREDS_UID)
889 c->uid = (uid_t) uid;
890 if (missing & SD_BUS_CREDS_EUID)
891 c->euid = (uid_t) euid;
892 if (missing & SD_BUS_CREDS_SUID)
893 c->suid = (uid_t) suid;
894 if (missing & SD_BUS_CREDS_FSUID)
895 c->fsuid = (uid_t) fsuid;
897 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
902 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
903 p = startswith(line, "Gid:");
905 unsigned long gid, egid, sgid, fsgid;
907 p += strspn(p, WHITESPACE);
908 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
911 if (missing & SD_BUS_CREDS_GID)
912 c->gid = (gid_t) gid;
913 if (missing & SD_BUS_CREDS_EGID)
914 c->egid = (gid_t) egid;
915 if (missing & SD_BUS_CREDS_SGID)
916 c->sgid = (gid_t) sgid;
917 if (missing & SD_BUS_CREDS_FSGID)
918 c->fsgid = (gid_t) fsgid;
920 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
925 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
926 p = startswith(line, "Groups:");
928 size_t allocated = 0;
934 p += strspn(p, WHITESPACE);
938 if (sscanf(p, "%lu%n", &g, &n) != 1)
941 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
944 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
948 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
953 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
954 p = startswith(line, "CapEff:");
956 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
960 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
965 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
966 p = startswith(line, "CapPrm:");
968 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
972 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
977 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
978 p = startswith(line, "CapInh:");
980 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
984 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
989 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
990 p = startswith(line, "CapBnd:");
992 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
996 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
1004 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1007 p = procfs_file_alloca(pid, "attr/current");
1008 r = read_one_line_file(p, &c->label);
1010 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1013 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1016 if (missing & SD_BUS_CREDS_COMM) {
1017 r = get_process_comm(pid, &c->comm);
1019 if (r != -EPERM && r != -EACCES)
1022 c->mask |= SD_BUS_CREDS_COMM;
1025 if (missing & SD_BUS_CREDS_EXE) {
1026 r = get_process_exe(pid, &c->exe);
1028 /* Unfortunately we cannot really distinguish
1029 * the case here where the process does not
1030 * exist, and /proc/$PID/exe being unreadable
1031 * because $PID is a kernel thread. Hence,
1032 * assume it is a kernel thread, and rely on
1033 * that this case is caught with a later
1036 c->mask |= SD_BUS_CREDS_EXE;
1038 if (r != -EPERM && r != -EACCES)
1041 c->mask |= SD_BUS_CREDS_EXE;
1044 if (missing & SD_BUS_CREDS_CMDLINE) {
1047 p = procfs_file_alloca(pid, "cmdline");
1048 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1052 if (r != -EPERM && r != -EACCES)
1055 if (c->cmdline_size == 0)
1056 c->cmdline = mfree(c->cmdline);
1058 c->mask |= SD_BUS_CREDS_CMDLINE;
1062 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1063 _cleanup_free_ char *p = NULL;
1065 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1068 r = read_one_line_file(p, &c->tid_comm);
1072 if (r != -EPERM && r != -EACCES)
1075 c->mask |= SD_BUS_CREDS_TID_COMM;
1078 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)) {
1081 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1083 if (r != -EPERM && r != -EACCES)
1088 if (!c->cgroup_root) {
1089 r = cg_get_root_path(&c->cgroup_root);
1095 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);
1098 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1099 r = audit_session_from_pid(pid, &c->audit_session_id);
1100 if (r == -ENODATA) {
1101 /* ENODATA means: no audit session id assigned */
1102 c->audit_session_id = AUDIT_SESSION_INVALID;
1103 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1105 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1108 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1111 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1112 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1113 if (r == -ENODATA) {
1114 /* ENODATA means: no audit login uid assigned */
1115 c->audit_login_uid = UID_INVALID;
1116 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1118 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1121 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1124 if (missing & SD_BUS_CREDS_TTY) {
1125 r = get_ctty(pid, NULL, &c->tty);
1127 /* ENXIO means: process has no controlling TTY */
1129 c->mask |= SD_BUS_CREDS_TTY;
1131 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1134 c->mask |= SD_BUS_CREDS_TTY;
1137 /* In case only the exe path was to be read we cannot
1138 * distinguish the case where the exe path was unreadable
1139 * because the process was a kernel thread, or when the
1140 * process didn't exist at all. Hence, let's do a final check,
1142 if (!pid_is_alive(pid))
1145 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1148 c->augmented = missing & c->mask;
1153 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1154 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1160 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1161 /* There's already all data we need, or augmentation
1162 * wasn't turned on. */
1164 *ret = sd_bus_creds_ref(c);
1168 n = bus_creds_new();
1172 /* Copy the original data over */
1174 if (c->mask & mask & SD_BUS_CREDS_PID) {
1176 n->mask |= SD_BUS_CREDS_PID;
1179 if (c->mask & mask & SD_BUS_CREDS_TID) {
1181 n->mask |= SD_BUS_CREDS_TID;
1184 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1186 n->mask |= SD_BUS_CREDS_PPID;
1189 if (c->mask & mask & SD_BUS_CREDS_UID) {
1191 n->mask |= SD_BUS_CREDS_UID;
1194 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1196 n->mask |= SD_BUS_CREDS_EUID;
1199 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1201 n->mask |= SD_BUS_CREDS_SUID;
1204 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1205 n->fsuid = c->fsuid;
1206 n->mask |= SD_BUS_CREDS_FSUID;
1209 if (c->mask & mask & SD_BUS_CREDS_GID) {
1211 n->mask |= SD_BUS_CREDS_GID;
1214 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1216 n->mask |= SD_BUS_CREDS_EGID;
1219 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1221 n->mask |= SD_BUS_CREDS_SGID;
1224 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1225 n->fsgid = c->fsgid;
1226 n->mask |= SD_BUS_CREDS_FSGID;
1229 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1230 if (c->supplementary_gids) {
1231 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1232 if (!n->supplementary_gids)
1234 n->n_supplementary_gids = c->n_supplementary_gids;
1236 n->supplementary_gids = NULL;
1237 n->n_supplementary_gids = 0;
1240 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1243 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1246 n->comm = strdup(c->comm);
1250 n->mask |= SD_BUS_CREDS_COMM;
1253 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1254 assert(c->tid_comm);
1256 n->tid_comm = strdup(c->tid_comm);
1260 n->mask |= SD_BUS_CREDS_TID_COMM;
1263 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1265 n->exe = strdup(c->exe);
1271 n->mask |= SD_BUS_CREDS_EXE;
1274 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1276 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1280 n->cmdline_size = c->cmdline_size;
1283 n->cmdline_size = 0;
1286 n->mask |= SD_BUS_CREDS_CMDLINE;
1289 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)) {
1292 n->cgroup = strdup(c->cgroup);
1296 n->cgroup_root = strdup(c->cgroup_root);
1297 if (!n->cgroup_root)
1300 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);
1303 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1304 assert(c->capability);
1306 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1310 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);
1313 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1316 n->label = strdup(c->label);
1319 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1322 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1323 n->audit_session_id = c->audit_session_id;
1324 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1326 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1327 n->audit_login_uid = c->audit_login_uid;
1328 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1331 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1333 n->tty = strdup(c->tty);
1338 n->mask |= SD_BUS_CREDS_TTY;
1341 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1342 assert(c->unique_name);
1344 n->unique_name = strdup(c->unique_name);
1345 if (!n->unique_name)
1347 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1350 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1351 if (strv_isempty(c->well_known_names))
1352 n->well_known_names = NULL;
1354 n->well_known_names = strv_copy(c->well_known_names);
1355 if (!n->well_known_names)
1358 n->well_known_names_driver = c->well_known_names_driver;
1359 n->well_known_names_local = c->well_known_names_local;
1360 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1363 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1364 assert(c->description);
1365 n->description = strdup(c->description);
1366 if (!n->description)
1368 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1371 n->augmented = c->augmented & n->mask;
1375 r = bus_creds_add_more(n, mask, 0, 0);