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 #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_bus_creds_unref_ 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);