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 "process-util.h"
28 #include "terminal-util.h"
29 #include "capability.h"
30 #include "cgroup-util.h"
33 #include "bus-message.h"
36 #include "bus-creds.h"
37 #include "bus-label.h"
40 CAP_OFFSET_INHERITABLE = 0,
41 CAP_OFFSET_PERMITTED = 1,
42 CAP_OFFSET_EFFECTIVE = 2,
43 CAP_OFFSET_BOUNDING = 3
46 void bus_creds_done(sd_bus_creds *c) {
49 /* For internal bus cred structures that are allocated by
57 free(c->unescaped_description);
58 free(c->supplementary_gids);
61 free(c->well_known_names); /* note that this is an strv, but
62 * we only free the array, not the
63 * strings the array points to. The
64 * full strv we only free if
65 * c->allocated is set, see
68 strv_free(c->cmdline_array);
71 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
72 assert_return(c, NULL);
80 /* If this is an embedded creds structure, then
81 * forward ref counting to the message */
82 m = container_of(c, sd_bus_message, creds);
83 sd_bus_message_ref(m);
89 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
106 free(c->unique_name);
107 free(c->cgroup_root);
108 free(c->description);
110 c->supplementary_gids = mfree(c->supplementary_gids);
112 c->well_known_names = strv_free(c->well_known_names);
121 m = container_of(c, sd_bus_message, creds);
122 sd_bus_message_unref(m);
129 /// UNNEEDED by elogind
131 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
138 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
144 sd_bus_creds* bus_creds_new(void) {
147 c = new0(sd_bus_creds, 1);
156 /// UNNEEDED by elogind
158 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
162 assert_return(pid >= 0, -EINVAL);
163 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
164 assert_return(ret, -EINVAL);
173 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
175 sd_bus_creds_unref(c);
179 /* Check if the process existed at all, in case we haven't
180 * figured that out already */
181 if (!pid_is_alive(pid)) {
182 sd_bus_creds_unref(c);
191 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
192 assert_return(c, -EINVAL);
193 assert_return(uid, -EINVAL);
195 if (!(c->mask & SD_BUS_CREDS_UID))
202 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
203 assert_return(c, -EINVAL);
204 assert_return(euid, -EINVAL);
206 if (!(c->mask & SD_BUS_CREDS_EUID))
213 /// UNNEEDED by elogind
215 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
216 assert_return(c, -EINVAL);
217 assert_return(suid, -EINVAL);
219 if (!(c->mask & SD_BUS_CREDS_SUID))
227 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
228 assert_return(c, -EINVAL);
229 assert_return(fsuid, -EINVAL);
231 if (!(c->mask & SD_BUS_CREDS_FSUID))
238 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
239 assert_return(c, -EINVAL);
240 assert_return(gid, -EINVAL);
242 if (!(c->mask & SD_BUS_CREDS_GID))
250 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
251 assert_return(c, -EINVAL);
252 assert_return(egid, -EINVAL);
254 if (!(c->mask & SD_BUS_CREDS_EGID))
261 /// UNNEEDED by elogind
263 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
264 assert_return(c, -EINVAL);
265 assert_return(sgid, -EINVAL);
267 if (!(c->mask & SD_BUS_CREDS_SGID))
274 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
275 assert_return(c, -EINVAL);
276 assert_return(fsgid, -EINVAL);
278 if (!(c->mask & SD_BUS_CREDS_FSGID))
285 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
286 assert_return(c, -EINVAL);
287 assert_return(gids, -EINVAL);
289 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
292 *gids = c->supplementary_gids;
293 return (int) c->n_supplementary_gids;
297 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
298 assert_return(c, -EINVAL);
299 assert_return(pid, -EINVAL);
301 if (!(c->mask & SD_BUS_CREDS_PID))
309 /// UNNEEDED by elogind
311 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
312 assert_return(c, -EINVAL);
313 assert_return(ppid, -EINVAL);
315 if (!(c->mask & SD_BUS_CREDS_PPID))
318 /* PID 1 has no parent process. Let's distinguish the case of
319 * not knowing and not having a parent process by the returned
329 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
330 assert_return(c, -EINVAL);
331 assert_return(tid, -EINVAL);
333 if (!(c->mask & SD_BUS_CREDS_TID))
341 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
342 assert_return(c, -EINVAL);
344 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
352 /// 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 /// elogind does not support systemd slices
561 return cg_path_get_owner_uid(shifted, uid);
568 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
569 assert_return(c, -EINVAL);
571 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
577 if (!c->cmdline_array) {
578 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
579 if (!c->cmdline_array)
583 *cmdline = c->cmdline_array;
587 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
588 assert_return(c, -EINVAL);
589 assert_return(sessionid, -EINVAL);
591 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
594 if (c->audit_session_id == AUDIT_SESSION_INVALID)
597 *sessionid = c->audit_session_id;
601 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
602 assert_return(c, -EINVAL);
603 assert_return(uid, -EINVAL);
605 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
608 if (c->audit_login_uid == UID_INVALID)
611 *uid = c->audit_login_uid;
615 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
616 assert_return(c, -EINVAL);
617 assert_return(ret, -EINVAL);
619 if (!(c->mask & SD_BUS_CREDS_TTY))
629 /// UNNEEDED by elogind
631 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
632 assert_return(c, -EINVAL);
633 assert_return(unique_name, -EINVAL);
635 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
638 *unique_name = c->unique_name;
642 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
643 assert_return(c, -EINVAL);
644 assert_return(well_known_names, -EINVAL);
646 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
649 /* As a special hack we return the bus driver as well-known
650 * names list when this is requested. */
651 if (c->well_known_names_driver) {
652 static const char* const wkn[] = {
653 "org.freedesktop.DBus",
657 *well_known_names = (char**) wkn;
661 if (c->well_known_names_local) {
662 static const char* const wkn[] = {
663 "org.freedesktop.DBus.Local",
667 *well_known_names = (char**) wkn;
671 *well_known_names = c->well_known_names;
675 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
676 assert_return(c, -EINVAL);
677 assert_return(ret, -EINVAL);
679 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
682 assert(c->description);
684 if (!c->unescaped_description) {
685 c->unescaped_description = bus_label_unescape(c->description);
686 if (!c->unescaped_description)
690 *ret = c->unescaped_description;
695 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
699 assert(capability >= 0);
700 assert(c->capability);
702 if ((unsigned) capability > cap_last_cap())
705 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
707 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
710 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
711 assert_return(c, -EINVAL);
712 assert_return(capability >= 0, -EINVAL);
714 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
717 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
720 /// UNNEEDED by elogind
722 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
723 assert_return(c, -EINVAL);
724 assert_return(capability >= 0, -EINVAL);
726 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
729 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
732 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
733 assert_return(c, -EINVAL);
734 assert_return(capability >= 0, -EINVAL);
736 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
739 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
742 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
743 assert_return(c, -EINVAL);
744 assert_return(capability >= 0, -EINVAL);
746 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
749 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
753 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
760 max = DIV_ROUND_UP(cap_last_cap(), 32U);
761 p += strspn(p, WHITESPACE);
771 if (!c->capability) {
772 c->capability = new0(uint32_t, max * 4);
777 for (i = 0; i < sz; i ++) {
780 for (j = 0; j < 8; ++j) {
790 c->capability[offset * max + (sz - i - 1)] = v;
796 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
801 assert(c->allocated);
803 if (!(mask & SD_BUS_CREDS_AUGMENT))
806 /* Try to retrieve PID from creds if it wasn't passed to us */
809 c->mask |= SD_BUS_CREDS_PID;
810 } else if (c->mask & SD_BUS_CREDS_PID)
813 /* Without pid we cannot do much... */
816 /* Try to retrieve TID from creds if it wasn't passed to us */
817 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
820 /* Calculate what we shall and can add */
821 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);
827 c->mask |= SD_BUS_CREDS_TID;
830 if (missing & (SD_BUS_CREDS_PPID |
831 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
832 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
833 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
834 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
835 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
837 _cleanup_fclose_ FILE *f = NULL;
840 p = procfs_file_alloca(pid, "status");
846 else if (errno != EPERM && errno != EACCES)
851 FOREACH_LINE(line, f, return -errno) {
854 if (missing & SD_BUS_CREDS_PPID) {
855 p = startswith(line, "PPid:");
857 p += strspn(p, WHITESPACE);
859 /* Explicitly check for PPID 0 (which is the case for PID 1) */
860 if (!streq(p, "0")) {
861 r = parse_pid(p, &c->ppid);
868 c->mask |= SD_BUS_CREDS_PPID;
873 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
874 p = startswith(line, "Uid:");
876 unsigned long uid, euid, suid, fsuid;
878 p += strspn(p, WHITESPACE);
879 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
882 if (missing & SD_BUS_CREDS_UID)
883 c->uid = (uid_t) uid;
884 if (missing & SD_BUS_CREDS_EUID)
885 c->euid = (uid_t) euid;
886 if (missing & SD_BUS_CREDS_SUID)
887 c->suid = (uid_t) suid;
888 if (missing & SD_BUS_CREDS_FSUID)
889 c->fsuid = (uid_t) fsuid;
891 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
896 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
897 p = startswith(line, "Gid:");
899 unsigned long gid, egid, sgid, fsgid;
901 p += strspn(p, WHITESPACE);
902 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
905 if (missing & SD_BUS_CREDS_GID)
906 c->gid = (gid_t) gid;
907 if (missing & SD_BUS_CREDS_EGID)
908 c->egid = (gid_t) egid;
909 if (missing & SD_BUS_CREDS_SGID)
910 c->sgid = (gid_t) sgid;
911 if (missing & SD_BUS_CREDS_FSGID)
912 c->fsgid = (gid_t) fsgid;
914 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
919 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
920 p = startswith(line, "Groups:");
922 size_t allocated = 0;
928 p += strspn(p, WHITESPACE);
932 if (sscanf(p, "%lu%n", &g, &n) != 1)
935 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
938 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
942 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
947 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
948 p = startswith(line, "CapEff:");
950 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
954 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
959 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
960 p = startswith(line, "CapPrm:");
962 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
966 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
971 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
972 p = startswith(line, "CapInh:");
974 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
978 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
983 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
984 p = startswith(line, "CapBnd:");
986 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
990 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
998 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1001 p = procfs_file_alloca(pid, "attr/current");
1002 r = read_one_line_file(p, &c->label);
1004 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1007 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1010 if (missing & SD_BUS_CREDS_COMM) {
1011 r = get_process_comm(pid, &c->comm);
1013 if (r != -EPERM && r != -EACCES)
1016 c->mask |= SD_BUS_CREDS_COMM;
1019 if (missing & SD_BUS_CREDS_EXE) {
1020 r = get_process_exe(pid, &c->exe);
1022 /* Unfortunately we cannot really distinguish
1023 * the case here where the process does not
1024 * exist, and /proc/$PID/exe being unreadable
1025 * because $PID is a kernel thread. Hence,
1026 * assume it is a kernel thread, and rely on
1027 * that this case is caught with a later
1030 c->mask |= SD_BUS_CREDS_EXE;
1032 if (r != -EPERM && r != -EACCES)
1035 c->mask |= SD_BUS_CREDS_EXE;
1038 if (missing & SD_BUS_CREDS_CMDLINE) {
1041 p = procfs_file_alloca(pid, "cmdline");
1042 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1046 if (r != -EPERM && r != -EACCES)
1049 if (c->cmdline_size == 0)
1050 c->cmdline = mfree(c->cmdline);
1052 c->mask |= SD_BUS_CREDS_CMDLINE;
1056 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1057 _cleanup_free_ char *p = NULL;
1059 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1062 r = read_one_line_file(p, &c->tid_comm);
1066 if (r != -EPERM && r != -EACCES)
1069 c->mask |= SD_BUS_CREDS_TID_COMM;
1072 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)) {
1075 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1077 if (r != -EPERM && r != -EACCES)
1082 if (!c->cgroup_root) {
1083 r = cg_get_root_path(&c->cgroup_root);
1089 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);
1092 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1093 r = audit_session_from_pid(pid, &c->audit_session_id);
1094 if (r == -ENODATA) {
1095 /* ENODATA means: no audit session id assigned */
1096 c->audit_session_id = AUDIT_SESSION_INVALID;
1097 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1099 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1102 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1105 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1106 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1107 if (r == -ENODATA) {
1108 /* ENODATA means: no audit login uid assigned */
1109 c->audit_login_uid = UID_INVALID;
1110 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1112 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1115 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1118 if (missing & SD_BUS_CREDS_TTY) {
1119 r = get_ctty(pid, NULL, &c->tty);
1121 /* ENXIO means: process has no controlling TTY */
1123 c->mask |= SD_BUS_CREDS_TTY;
1125 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1128 c->mask |= SD_BUS_CREDS_TTY;
1131 /* In case only the exe path was to be read we cannot
1132 * distinguish the case where the exe path was unreadable
1133 * because the process was a kernel thread, or when the
1134 * process didn't exist at all. Hence, let's do a final check,
1136 if (!pid_is_alive(pid))
1139 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1142 c->augmented = missing & c->mask;
1147 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1148 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1154 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1155 /* There's already all data we need, or augmentation
1156 * wasn't turned on. */
1158 *ret = sd_bus_creds_ref(c);
1162 n = bus_creds_new();
1166 /* Copy the original data over */
1168 if (c->mask & mask & SD_BUS_CREDS_PID) {
1170 n->mask |= SD_BUS_CREDS_PID;
1173 if (c->mask & mask & SD_BUS_CREDS_TID) {
1175 n->mask |= SD_BUS_CREDS_TID;
1178 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1180 n->mask |= SD_BUS_CREDS_PPID;
1183 if (c->mask & mask & SD_BUS_CREDS_UID) {
1185 n->mask |= SD_BUS_CREDS_UID;
1188 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1190 n->mask |= SD_BUS_CREDS_EUID;
1193 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1195 n->mask |= SD_BUS_CREDS_SUID;
1198 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1199 n->fsuid = c->fsuid;
1200 n->mask |= SD_BUS_CREDS_FSUID;
1203 if (c->mask & mask & SD_BUS_CREDS_GID) {
1205 n->mask |= SD_BUS_CREDS_GID;
1208 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1210 n->mask |= SD_BUS_CREDS_EGID;
1213 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1215 n->mask |= SD_BUS_CREDS_SGID;
1218 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1219 n->fsgid = c->fsgid;
1220 n->mask |= SD_BUS_CREDS_FSGID;
1223 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1224 if (c->supplementary_gids) {
1225 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1226 if (!n->supplementary_gids)
1228 n->n_supplementary_gids = c->n_supplementary_gids;
1230 n->supplementary_gids = NULL;
1231 n->n_supplementary_gids = 0;
1234 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1237 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1240 n->comm = strdup(c->comm);
1244 n->mask |= SD_BUS_CREDS_COMM;
1247 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1248 assert(c->tid_comm);
1250 n->tid_comm = strdup(c->tid_comm);
1254 n->mask |= SD_BUS_CREDS_TID_COMM;
1257 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1259 n->exe = strdup(c->exe);
1265 n->mask |= SD_BUS_CREDS_EXE;
1268 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1270 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1274 n->cmdline_size = c->cmdline_size;
1277 n->cmdline_size = 0;
1280 n->mask |= SD_BUS_CREDS_CMDLINE;
1283 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)) {
1286 n->cgroup = strdup(c->cgroup);
1290 n->cgroup_root = strdup(c->cgroup_root);
1291 if (!n->cgroup_root)
1294 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);
1297 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1298 assert(c->capability);
1300 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1304 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);
1307 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1310 n->label = strdup(c->label);
1313 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1316 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1317 n->audit_session_id = c->audit_session_id;
1318 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1320 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1321 n->audit_login_uid = c->audit_login_uid;
1322 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1325 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1327 n->tty = strdup(c->tty);
1332 n->mask |= SD_BUS_CREDS_TTY;
1335 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1336 assert(c->unique_name);
1338 n->unique_name = strdup(c->unique_name);
1339 if (!n->unique_name)
1341 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1344 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1345 if (strv_isempty(c->well_known_names))
1346 n->well_known_names = NULL;
1348 n->well_known_names = strv_copy(c->well_known_names);
1349 if (!n->well_known_names)
1352 n->well_known_names_driver = c->well_known_names_driver;
1353 n->well_known_names_local = c->well_known_names_local;
1354 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1357 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1358 assert(c->description);
1359 n->description = strdup(c->description);
1360 if (!n->description)
1362 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1365 n->augmented = c->augmented & n->mask;
1369 r = bus_creds_add_more(n, mask, 0, 0);