2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/capability.h>
23 #include "alloc-util.h"
24 #include "audit-util.h"
25 #include "bus-creds.h"
26 #include "bus-label.h"
27 #include "bus-message.h"
29 #include "capability-util.h"
30 #include "cgroup-util.h"
33 #include "format-util.h"
34 #include "hexdecoct.h"
35 #include "parse-util.h"
36 #include "process-util.h"
37 #include "string-util.h"
39 #include "terminal-util.h"
40 #include "user-util.h"
44 CAP_OFFSET_INHERITABLE = 0,
45 CAP_OFFSET_PERMITTED = 1,
46 CAP_OFFSET_EFFECTIVE = 2,
47 CAP_OFFSET_BOUNDING = 3
50 void bus_creds_done(sd_bus_creds *c) {
53 /* For internal bus cred structures that are allocated by
61 free(c->unescaped_description);
62 free(c->supplementary_gids);
65 free(c->well_known_names); /* note that this is an strv, but
66 * we only free the array, not the
67 * strings the array points to. The
68 * full strv we only free if
69 * c->allocated is set, see
72 strv_free(c->cmdline_array);
75 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
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 #if 0 /// UNNEEDED by elogind
136 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
143 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
149 sd_bus_creds* bus_creds_new(void) {
152 c = new0(sd_bus_creds, 1);
161 #if 0 /// UNNEEDED by elogind
162 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
166 assert_return(pid >= 0, -EINVAL);
167 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
168 assert_return(ret, -EINVAL);
177 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
179 sd_bus_creds_unref(c);
183 /* Check if the process existed at all, in case we haven't
184 * figured that out already */
185 if (!pid_is_alive(pid)) {
186 sd_bus_creds_unref(c);
195 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
196 assert_return(c, -EINVAL);
197 assert_return(uid, -EINVAL);
199 if (!(c->mask & SD_BUS_CREDS_UID))
206 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
207 assert_return(c, -EINVAL);
208 assert_return(euid, -EINVAL);
210 if (!(c->mask & SD_BUS_CREDS_EUID))
217 #if 0 /// UNNEEDED by elogind
218 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
219 assert_return(c, -EINVAL);
220 assert_return(suid, -EINVAL);
222 if (!(c->mask & SD_BUS_CREDS_SUID))
230 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
231 assert_return(c, -EINVAL);
232 assert_return(fsuid, -EINVAL);
234 if (!(c->mask & SD_BUS_CREDS_FSUID))
241 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
242 assert_return(c, -EINVAL);
243 assert_return(gid, -EINVAL);
245 if (!(c->mask & SD_BUS_CREDS_GID))
253 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
254 assert_return(c, -EINVAL);
255 assert_return(egid, -EINVAL);
257 if (!(c->mask & SD_BUS_CREDS_EGID))
264 #if 0 /// UNNEEDED by elogind
265 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
266 assert_return(c, -EINVAL);
267 assert_return(sgid, -EINVAL);
269 if (!(c->mask & SD_BUS_CREDS_SGID))
276 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
277 assert_return(c, -EINVAL);
278 assert_return(fsgid, -EINVAL);
280 if (!(c->mask & SD_BUS_CREDS_FSGID))
287 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
288 assert_return(c, -EINVAL);
289 assert_return(gids, -EINVAL);
291 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
294 *gids = c->supplementary_gids;
295 return (int) c->n_supplementary_gids;
299 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
300 assert_return(c, -EINVAL);
301 assert_return(pid, -EINVAL);
303 if (!(c->mask & SD_BUS_CREDS_PID))
311 #if 0 /// UNNEEDED by elogind
312 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
313 assert_return(c, -EINVAL);
314 assert_return(ppid, -EINVAL);
316 if (!(c->mask & SD_BUS_CREDS_PPID))
319 /* PID 1 has no parent process. Let's distinguish the case of
320 * not knowing and not having a parent process by the returned
330 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
331 assert_return(c, -EINVAL);
332 assert_return(tid, -EINVAL);
334 if (!(c->mask & SD_BUS_CREDS_TID))
342 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
343 assert_return(c, -EINVAL);
345 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
353 #if 0 /// UNNEEDED by elogind
354 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
355 assert_return(c, -EINVAL);
356 assert_return(ret, -EINVAL);
358 if (!(c->mask & SD_BUS_CREDS_COMM))
366 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
367 assert_return(c, -EINVAL);
368 assert_return(ret, -EINVAL);
370 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
378 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
379 assert_return(c, -EINVAL);
380 assert_return(ret, -EINVAL);
382 if (!(c->mask & SD_BUS_CREDS_EXE))
392 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
393 assert_return(c, -EINVAL);
394 assert_return(ret, -EINVAL);
396 if (!(c->mask & SD_BUS_CREDS_CGROUP))
404 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
407 assert_return(c, -EINVAL);
408 assert_return(ret, -EINVAL);
410 if (!(c->mask & SD_BUS_CREDS_UNIT))
418 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
422 r = cg_path_get_unit(shifted, (char**) &c->unit);
431 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
434 assert_return(c, -EINVAL);
435 assert_return(ret, -EINVAL);
437 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
445 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
449 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
458 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
461 assert_return(c, -EINVAL);
462 assert_return(ret, -EINVAL);
464 if (!(c->mask & SD_BUS_CREDS_SLICE))
472 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
476 r = cg_path_get_slice(shifted, (char**) &c->slice);
485 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
488 assert_return(c, -EINVAL);
489 assert_return(ret, -EINVAL);
491 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
496 if (!c->user_slice) {
499 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
503 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
508 *ret = c->user_slice;
513 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
516 assert_return(c, -EINVAL);
517 assert_return(ret, -EINVAL);
519 if (!(c->mask & SD_BUS_CREDS_SESSION))
527 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
528 c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
529 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
533 log_debug_elogind("Shifted: \"%s\"", shifted);
534 r = cg_path_get_session(shifted, (char**) &c->session);
543 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
547 assert_return(c, -EINVAL);
548 assert_return(uid, -EINVAL);
550 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
555 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
559 #if 0 /// elogind does not support systemd slices
560 return cg_path_get_owner_uid(shifted, uid);
567 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
568 assert_return(c, -EINVAL);
570 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
576 if (!c->cmdline_array) {
577 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
578 if (!c->cmdline_array)
582 *cmdline = c->cmdline_array;
586 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
587 assert_return(c, -EINVAL);
588 assert_return(sessionid, -EINVAL);
590 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
593 if (c->audit_session_id == AUDIT_SESSION_INVALID)
596 *sessionid = c->audit_session_id;
600 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
601 assert_return(c, -EINVAL);
602 assert_return(uid, -EINVAL);
604 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
607 if (c->audit_login_uid == UID_INVALID)
610 *uid = c->audit_login_uid;
614 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
615 assert_return(c, -EINVAL);
616 assert_return(ret, -EINVAL);
618 if (!(c->mask & SD_BUS_CREDS_TTY))
628 #if 0 /// UNNEEDED by elogind
629 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
630 assert_return(c, -EINVAL);
631 assert_return(unique_name, -EINVAL);
633 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
636 *unique_name = c->unique_name;
640 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
641 assert_return(c, -EINVAL);
642 assert_return(well_known_names, -EINVAL);
644 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
647 /* As a special hack we return the bus driver as well-known
648 * names list when this is requested. */
649 if (c->well_known_names_driver) {
650 static const char* const wkn[] = {
651 "org.freedesktop.DBus",
655 *well_known_names = (char**) wkn;
659 if (c->well_known_names_local) {
660 static const char* const wkn[] = {
661 "org.freedesktop.DBus.Local",
665 *well_known_names = (char**) wkn;
669 *well_known_names = c->well_known_names;
673 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
674 assert_return(c, -EINVAL);
675 assert_return(ret, -EINVAL);
677 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
680 assert(c->description);
682 if (!c->unescaped_description) {
683 c->unescaped_description = bus_label_unescape(c->description);
684 if (!c->unescaped_description)
688 *ret = c->unescaped_description;
693 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
697 assert(capability >= 0);
698 assert(c->capability);
700 if ((unsigned) capability > cap_last_cap())
703 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
705 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
708 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
709 assert_return(c, -EINVAL);
710 assert_return(capability >= 0, -EINVAL);
712 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
715 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
718 #if 0 /// UNNEEDED by elogind
719 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
720 assert_return(c, -EINVAL);
721 assert_return(capability >= 0, -EINVAL);
723 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
726 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
729 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
730 assert_return(c, -EINVAL);
731 assert_return(capability >= 0, -EINVAL);
733 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
736 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
739 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
740 assert_return(c, -EINVAL);
741 assert_return(capability >= 0, -EINVAL);
743 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
746 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
750 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
757 max = DIV_ROUND_UP(cap_last_cap(), 32U);
758 p += strspn(p, WHITESPACE);
768 if (!c->capability) {
769 c->capability = new0(uint32_t, max * 4);
774 for (i = 0; i < sz; i ++) {
777 for (j = 0; j < 8; ++j) {
787 c->capability[offset * max + (sz - i - 1)] = v;
793 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
798 assert(c->allocated);
800 if (!(mask & SD_BUS_CREDS_AUGMENT))
803 /* Try to retrieve PID from creds if it wasn't passed to us */
806 c->mask |= SD_BUS_CREDS_PID;
807 } else if (c->mask & SD_BUS_CREDS_PID)
810 /* Without pid we cannot do much... */
813 /* Try to retrieve TID from creds if it wasn't passed to us */
814 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
817 /* Calculate what we shall and can add */
818 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);
824 c->mask |= SD_BUS_CREDS_TID;
827 if (missing & (SD_BUS_CREDS_PPID |
828 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
829 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
830 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
831 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
832 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
834 _cleanup_fclose_ FILE *f = NULL;
837 p = procfs_file_alloca(pid, "status");
843 else if (errno != EPERM && errno != EACCES)
848 FOREACH_LINE(line, f, return -errno) {
851 if (missing & SD_BUS_CREDS_PPID) {
852 p = startswith(line, "PPid:");
854 p += strspn(p, WHITESPACE);
856 /* Explicitly check for PPID 0 (which is the case for PID 1) */
857 if (!streq(p, "0")) {
858 r = parse_pid(p, &c->ppid);
865 c->mask |= SD_BUS_CREDS_PPID;
870 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
871 p = startswith(line, "Uid:");
873 unsigned long uid, euid, suid, fsuid;
875 p += strspn(p, WHITESPACE);
876 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
879 if (missing & SD_BUS_CREDS_UID)
880 c->uid = (uid_t) uid;
881 if (missing & SD_BUS_CREDS_EUID)
882 c->euid = (uid_t) euid;
883 if (missing & SD_BUS_CREDS_SUID)
884 c->suid = (uid_t) suid;
885 if (missing & SD_BUS_CREDS_FSUID)
886 c->fsuid = (uid_t) fsuid;
888 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
893 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
894 p = startswith(line, "Gid:");
896 unsigned long gid, egid, sgid, fsgid;
898 p += strspn(p, WHITESPACE);
899 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
902 if (missing & SD_BUS_CREDS_GID)
903 c->gid = (gid_t) gid;
904 if (missing & SD_BUS_CREDS_EGID)
905 c->egid = (gid_t) egid;
906 if (missing & SD_BUS_CREDS_SGID)
907 c->sgid = (gid_t) sgid;
908 if (missing & SD_BUS_CREDS_FSGID)
909 c->fsgid = (gid_t) fsgid;
911 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
916 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
917 p = startswith(line, "Groups:");
919 size_t allocated = 0;
925 p += strspn(p, WHITESPACE);
929 if (sscanf(p, "%lu%n", &g, &n) != 1)
932 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
935 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
939 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
944 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
945 p = startswith(line, "CapEff:");
947 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
951 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
956 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
957 p = startswith(line, "CapPrm:");
959 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
963 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
968 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
969 p = startswith(line, "CapInh:");
971 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
975 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
980 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
981 p = startswith(line, "CapBnd:");
983 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
987 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
995 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
998 p = procfs_file_alloca(pid, "attr/current");
999 r = read_one_line_file(p, &c->label);
1001 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1004 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1007 if (missing & SD_BUS_CREDS_COMM) {
1008 r = get_process_comm(pid, &c->comm);
1010 if (r != -EPERM && r != -EACCES)
1013 c->mask |= SD_BUS_CREDS_COMM;
1016 if (missing & SD_BUS_CREDS_EXE) {
1017 r = get_process_exe(pid, &c->exe);
1019 /* Unfortunately we cannot really distinguish
1020 * the case here where the process does not
1021 * exist, and /proc/$PID/exe being unreadable
1022 * because $PID is a kernel thread. Hence,
1023 * assume it is a kernel thread, and rely on
1024 * that this case is caught with a later
1027 c->mask |= SD_BUS_CREDS_EXE;
1029 if (r != -EPERM && r != -EACCES)
1032 c->mask |= SD_BUS_CREDS_EXE;
1035 if (missing & SD_BUS_CREDS_CMDLINE) {
1038 p = procfs_file_alloca(pid, "cmdline");
1039 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1043 if (r != -EPERM && r != -EACCES)
1046 if (c->cmdline_size == 0)
1047 c->cmdline = mfree(c->cmdline);
1049 c->mask |= SD_BUS_CREDS_CMDLINE;
1053 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1054 _cleanup_free_ char *p = NULL;
1056 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1059 r = read_one_line_file(p, &c->tid_comm);
1063 if (r != -EPERM && r != -EACCES)
1066 c->mask |= SD_BUS_CREDS_TID_COMM;
1069 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)) {
1072 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1074 if (r != -EPERM && r != -EACCES)
1079 if (!c->cgroup_root) {
1080 r = cg_get_root_path(&c->cgroup_root);
1086 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);
1089 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1090 r = audit_session_from_pid(pid, &c->audit_session_id);
1091 if (r == -ENODATA) {
1092 /* ENODATA means: no audit session id assigned */
1093 c->audit_session_id = AUDIT_SESSION_INVALID;
1094 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1096 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1099 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1102 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1103 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1104 if (r == -ENODATA) {
1105 /* ENODATA means: no audit login uid assigned */
1106 c->audit_login_uid = UID_INVALID;
1107 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1109 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1112 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1115 if (missing & SD_BUS_CREDS_TTY) {
1116 r = get_ctty(pid, NULL, &c->tty);
1118 /* ENXIO means: process has no controlling TTY */
1120 c->mask |= SD_BUS_CREDS_TTY;
1122 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1125 c->mask |= SD_BUS_CREDS_TTY;
1128 /* In case only the exe path was to be read we cannot
1129 * distinguish the case where the exe path was unreadable
1130 * because the process was a kernel thread, or when the
1131 * process didn't exist at all. Hence, let's do a final check,
1133 if (!pid_is_alive(pid))
1136 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1139 c->augmented = missing & c->mask;
1144 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1145 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
1151 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1152 /* There's already all data we need, or augmentation
1153 * wasn't turned on. */
1155 *ret = sd_bus_creds_ref(c);
1159 n = bus_creds_new();
1163 /* Copy the original data over */
1165 if (c->mask & mask & SD_BUS_CREDS_PID) {
1167 n->mask |= SD_BUS_CREDS_PID;
1170 if (c->mask & mask & SD_BUS_CREDS_TID) {
1172 n->mask |= SD_BUS_CREDS_TID;
1175 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1177 n->mask |= SD_BUS_CREDS_PPID;
1180 if (c->mask & mask & SD_BUS_CREDS_UID) {
1182 n->mask |= SD_BUS_CREDS_UID;
1185 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1187 n->mask |= SD_BUS_CREDS_EUID;
1190 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1192 n->mask |= SD_BUS_CREDS_SUID;
1195 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1196 n->fsuid = c->fsuid;
1197 n->mask |= SD_BUS_CREDS_FSUID;
1200 if (c->mask & mask & SD_BUS_CREDS_GID) {
1202 n->mask |= SD_BUS_CREDS_GID;
1205 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1207 n->mask |= SD_BUS_CREDS_EGID;
1210 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1212 n->mask |= SD_BUS_CREDS_SGID;
1215 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1216 n->fsgid = c->fsgid;
1217 n->mask |= SD_BUS_CREDS_FSGID;
1220 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1221 if (c->supplementary_gids) {
1222 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1223 if (!n->supplementary_gids)
1225 n->n_supplementary_gids = c->n_supplementary_gids;
1227 n->supplementary_gids = NULL;
1228 n->n_supplementary_gids = 0;
1231 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1234 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1237 n->comm = strdup(c->comm);
1241 n->mask |= SD_BUS_CREDS_COMM;
1244 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1245 assert(c->tid_comm);
1247 n->tid_comm = strdup(c->tid_comm);
1251 n->mask |= SD_BUS_CREDS_TID_COMM;
1254 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1256 n->exe = strdup(c->exe);
1262 n->mask |= SD_BUS_CREDS_EXE;
1265 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1267 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1271 n->cmdline_size = c->cmdline_size;
1274 n->cmdline_size = 0;
1277 n->mask |= SD_BUS_CREDS_CMDLINE;
1280 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)) {
1283 n->cgroup = strdup(c->cgroup);
1287 n->cgroup_root = strdup(c->cgroup_root);
1288 if (!n->cgroup_root)
1291 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);
1294 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1295 assert(c->capability);
1297 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1301 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);
1304 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1307 n->label = strdup(c->label);
1310 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1313 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1314 n->audit_session_id = c->audit_session_id;
1315 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1317 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1318 n->audit_login_uid = c->audit_login_uid;
1319 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1322 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1324 n->tty = strdup(c->tty);
1329 n->mask |= SD_BUS_CREDS_TTY;
1332 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1333 assert(c->unique_name);
1335 n->unique_name = strdup(c->unique_name);
1336 if (!n->unique_name)
1338 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1341 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1342 if (strv_isempty(c->well_known_names))
1343 n->well_known_names = NULL;
1345 n->well_known_names = strv_copy(c->well_known_names);
1346 if (!n->well_known_names)
1349 n->well_known_names_driver = c->well_known_names_driver;
1350 n->well_known_names_local = c->well_known_names_local;
1351 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1354 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1355 assert(c->description);
1356 n->description = strdup(c->description);
1357 if (!n->description)
1359 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1362 n->augmented = c->augmented & n->mask;
1366 r = bus_creds_add_more(n, mask, 0, 0);