1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/capability.h>
24 #include "alloc-util.h"
25 #include "audit-util.h"
26 #include "bus-creds.h"
27 #include "bus-label.h"
28 #include "bus-message.h"
30 #include "capability-util.h"
31 #include "cgroup-util.h"
34 #include "format-util.h"
35 #include "hexdecoct.h"
36 #include "parse-util.h"
37 #include "process-util.h"
38 #include "string-util.h"
40 #include "terminal-util.h"
41 #include "user-util.h"
45 CAP_OFFSET_INHERITABLE = 0,
46 CAP_OFFSET_PERMITTED = 1,
47 CAP_OFFSET_EFFECTIVE = 2,
48 CAP_OFFSET_BOUNDING = 3
51 void bus_creds_done(sd_bus_creds *c) {
54 /* For internal bus cred structures that are allocated by
62 free(c->unescaped_description);
63 free(c->supplementary_gids);
66 free(c->well_known_names); /* note that this is an strv, but
67 * we only free the array, not the
68 * strings the array points to. The
69 * full strv we only free if
70 * c->allocated is set, see
73 strv_free(c->cmdline_array);
76 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
87 /* If this is an embedded creds structure, then
88 * forward ref counting to the message */
89 m = container_of(c, sd_bus_message, creds);
90 sd_bus_message_ref(m);
96 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
102 assert(c->n_ref > 0);
113 free(c->unique_name);
114 free(c->cgroup_root);
115 free(c->description);
117 c->supplementary_gids = mfree(c->supplementary_gids);
119 c->well_known_names = strv_free(c->well_known_names);
128 m = container_of(c, sd_bus_message, creds);
129 sd_bus_message_unref(m);
136 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
142 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
148 sd_bus_creds* bus_creds_new(void) {
151 c = new0(sd_bus_creds, 1);
160 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
164 assert_return(pid >= 0, -EINVAL);
165 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
166 assert_return(ret, -EINVAL);
169 pid = getpid_cached();
175 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
177 sd_bus_creds_unref(c);
181 /* Check if the process existed at all, in case we haven't
182 * figured that out already */
183 if (!pid_is_alive(pid)) {
184 sd_bus_creds_unref(c);
192 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
193 assert_return(c, -EINVAL);
194 assert_return(uid, -EINVAL);
196 if (!(c->mask & SD_BUS_CREDS_UID))
203 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
204 assert_return(c, -EINVAL);
205 assert_return(euid, -EINVAL);
207 if (!(c->mask & SD_BUS_CREDS_EUID))
214 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
215 assert_return(c, -EINVAL);
216 assert_return(suid, -EINVAL);
218 if (!(c->mask & SD_BUS_CREDS_SUID))
226 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
227 assert_return(c, -EINVAL);
228 assert_return(fsuid, -EINVAL);
230 if (!(c->mask & SD_BUS_CREDS_FSUID))
237 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
238 assert_return(c, -EINVAL);
239 assert_return(gid, -EINVAL);
241 if (!(c->mask & SD_BUS_CREDS_GID))
248 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
249 assert_return(c, -EINVAL);
250 assert_return(egid, -EINVAL);
252 if (!(c->mask & SD_BUS_CREDS_EGID))
259 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
260 assert_return(c, -EINVAL);
261 assert_return(sgid, -EINVAL);
263 if (!(c->mask & SD_BUS_CREDS_SGID))
270 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
271 assert_return(c, -EINVAL);
272 assert_return(fsgid, -EINVAL);
274 if (!(c->mask & SD_BUS_CREDS_FSGID))
281 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
282 assert_return(c, -EINVAL);
283 assert_return(gids, -EINVAL);
285 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
288 *gids = c->supplementary_gids;
289 return (int) c->n_supplementary_gids;
292 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
293 assert_return(c, -EINVAL);
294 assert_return(pid, -EINVAL);
296 if (!(c->mask & SD_BUS_CREDS_PID))
304 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
305 assert_return(c, -EINVAL);
306 assert_return(ppid, -EINVAL);
308 if (!(c->mask & SD_BUS_CREDS_PPID))
311 /* PID 1 has no parent process. Let's distinguish the case of
312 * not knowing and not having a parent process by the returned
321 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
322 assert_return(c, -EINVAL);
323 assert_return(tid, -EINVAL);
325 if (!(c->mask & SD_BUS_CREDS_TID))
333 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
334 assert_return(c, -EINVAL);
336 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
344 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
345 assert_return(c, -EINVAL);
346 assert_return(ret, -EINVAL);
348 if (!(c->mask & SD_BUS_CREDS_COMM))
356 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
357 assert_return(c, -EINVAL);
358 assert_return(ret, -EINVAL);
360 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
368 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
369 assert_return(c, -EINVAL);
370 assert_return(ret, -EINVAL);
372 if (!(c->mask & SD_BUS_CREDS_EXE))
382 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
383 assert_return(c, -EINVAL);
384 assert_return(ret, -EINVAL);
386 if (!(c->mask & SD_BUS_CREDS_CGROUP))
394 #if 0 /// UNNEEDED by elogind
395 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
398 assert_return(c, -EINVAL);
399 assert_return(ret, -EINVAL);
401 if (!(c->mask & SD_BUS_CREDS_UNIT))
409 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
413 r = cg_path_get_unit(shifted, (char**) &c->unit);
422 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
425 assert_return(c, -EINVAL);
426 assert_return(ret, -EINVAL);
428 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
436 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
440 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
450 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
453 assert_return(c, -EINVAL);
454 assert_return(ret, -EINVAL);
456 if (!(c->mask & SD_BUS_CREDS_SLICE))
464 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
468 r = cg_path_get_slice(shifted, (char**) &c->slice);
477 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
480 assert_return(c, -EINVAL);
481 assert_return(ret, -EINVAL);
483 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
488 if (!c->user_slice) {
491 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
495 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
500 *ret = c->user_slice;
504 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
507 assert_return(c, -EINVAL);
508 assert_return(ret, -EINVAL);
510 if (!(c->mask & SD_BUS_CREDS_SESSION))
518 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
519 c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
520 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
524 log_debug_elogind("Shifted: \"%s\"", shifted);
525 r = cg_path_get_session(shifted, (char**) &c->session);
534 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
538 assert_return(c, -EINVAL);
539 assert_return(uid, -EINVAL);
541 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
546 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
547 log_debug_elogind("Shifted to %s from %s/%s for c->uid %u (result %d)",
548 shifted, c->cgroup_root, c->cgroup, c->uid, r);
552 return cg_path_get_owner_uid(shifted, uid);
555 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
556 assert_return(c, -EINVAL);
558 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
564 if (!c->cmdline_array) {
565 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
566 if (!c->cmdline_array)
570 *cmdline = c->cmdline_array;
574 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
575 assert_return(c, -EINVAL);
576 assert_return(sessionid, -EINVAL);
578 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
581 if (!audit_session_is_valid(c->audit_session_id))
584 *sessionid = c->audit_session_id;
588 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
589 assert_return(c, -EINVAL);
590 assert_return(uid, -EINVAL);
592 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
595 if (!uid_is_valid(c->audit_login_uid))
598 *uid = c->audit_login_uid;
602 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
603 assert_return(c, -EINVAL);
604 assert_return(ret, -EINVAL);
606 if (!(c->mask & SD_BUS_CREDS_TTY))
616 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
617 assert_return(c, -EINVAL);
618 assert_return(unique_name, -EINVAL);
620 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
623 *unique_name = c->unique_name;
627 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
628 assert_return(c, -EINVAL);
629 assert_return(well_known_names, -EINVAL);
631 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
634 /* As a special hack we return the bus driver as well-known
635 * names list when this is requested. */
636 if (c->well_known_names_driver) {
637 static const char* const wkn[] = {
638 "org.freedesktop.DBus",
642 *well_known_names = (char**) wkn;
646 if (c->well_known_names_local) {
647 static const char* const wkn[] = {
648 "org.freedesktop.DBus.Local",
652 *well_known_names = (char**) wkn;
656 *well_known_names = c->well_known_names;
660 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
661 assert_return(c, -EINVAL);
662 assert_return(ret, -EINVAL);
664 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
667 assert(c->description);
669 if (!c->unescaped_description) {
670 c->unescaped_description = bus_label_unescape(c->description);
671 if (!c->unescaped_description)
675 *ret = c->unescaped_description;
679 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
683 assert(capability >= 0);
684 assert(c->capability);
686 if ((unsigned) capability > cap_last_cap())
689 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
691 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
694 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
695 assert_return(c, -EINVAL);
696 assert_return(capability >= 0, -EINVAL);
698 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
701 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
704 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
705 assert_return(c, -EINVAL);
706 assert_return(capability >= 0, -EINVAL);
708 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
711 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
714 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
715 assert_return(c, -EINVAL);
716 assert_return(capability >= 0, -EINVAL);
718 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
721 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
724 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
725 assert_return(c, -EINVAL);
726 assert_return(capability >= 0, -EINVAL);
728 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
731 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
734 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
741 max = DIV_ROUND_UP(cap_last_cap(), 32U);
742 p += strspn(p, WHITESPACE);
752 if (!c->capability) {
753 c->capability = new0(uint32_t, max * 4);
758 for (i = 0; i < sz; i ++) {
761 for (j = 0; j < 8; ++j) {
771 c->capability[offset * max + (sz - i - 1)] = v;
777 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
782 assert(c->allocated);
784 if (!(mask & SD_BUS_CREDS_AUGMENT))
787 /* Try to retrieve PID from creds if it wasn't passed to us */
790 c->mask |= SD_BUS_CREDS_PID;
791 } else if (c->mask & SD_BUS_CREDS_PID)
794 /* Without pid we cannot do much... */
797 /* Try to retrieve TID from creds if it wasn't passed to us */
798 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
801 /* Calculate what we shall and can add */
802 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);
808 c->mask |= SD_BUS_CREDS_TID;
811 if (missing & (SD_BUS_CREDS_PPID |
812 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
813 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
814 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
815 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
816 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
818 _cleanup_fclose_ FILE *f = NULL;
821 p = procfs_file_alloca(pid, "status");
827 else if (!IN_SET(errno, EPERM, EACCES))
832 FOREACH_LINE(line, f, return -errno) {
835 if (missing & SD_BUS_CREDS_PPID) {
836 p = startswith(line, "PPid:");
838 p += strspn(p, WHITESPACE);
840 /* Explicitly check for PPID 0 (which is the case for PID 1) */
841 if (!streq(p, "0")) {
842 r = parse_pid(p, &c->ppid);
849 c->mask |= SD_BUS_CREDS_PPID;
854 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
855 p = startswith(line, "Uid:");
857 unsigned long uid, euid, suid, fsuid;
859 p += strspn(p, WHITESPACE);
860 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
863 if (missing & SD_BUS_CREDS_UID)
864 c->uid = (uid_t) uid;
865 if (missing & SD_BUS_CREDS_EUID)
866 c->euid = (uid_t) euid;
867 if (missing & SD_BUS_CREDS_SUID)
868 c->suid = (uid_t) suid;
869 if (missing & SD_BUS_CREDS_FSUID)
870 c->fsuid = (uid_t) fsuid;
872 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
877 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
878 p = startswith(line, "Gid:");
880 unsigned long gid, egid, sgid, fsgid;
882 p += strspn(p, WHITESPACE);
883 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
886 if (missing & SD_BUS_CREDS_GID)
887 c->gid = (gid_t) gid;
888 if (missing & SD_BUS_CREDS_EGID)
889 c->egid = (gid_t) egid;
890 if (missing & SD_BUS_CREDS_SGID)
891 c->sgid = (gid_t) sgid;
892 if (missing & SD_BUS_CREDS_FSGID)
893 c->fsgid = (gid_t) fsgid;
895 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
900 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
901 p = startswith(line, "Groups:");
903 size_t allocated = 0;
909 p += strspn(p, WHITESPACE);
913 if (sscanf(p, "%lu%n", &g, &n) != 1)
916 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
919 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
923 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
928 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
929 p = startswith(line, "CapEff:");
931 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
935 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
940 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
941 p = startswith(line, "CapPrm:");
943 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
947 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
952 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
953 p = startswith(line, "CapInh:");
955 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
959 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
964 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
965 p = startswith(line, "CapBnd:");
967 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
971 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
979 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
982 p = procfs_file_alloca(pid, "attr/current");
983 r = read_one_line_file(p, &c->label);
985 if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
988 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
991 if (missing & SD_BUS_CREDS_COMM) {
992 r = get_process_comm(pid, &c->comm);
994 if (!IN_SET(r, -EPERM, -EACCES))
997 c->mask |= SD_BUS_CREDS_COMM;
1000 if (missing & SD_BUS_CREDS_EXE) {
1001 r = get_process_exe(pid, &c->exe);
1003 /* Unfortunately we cannot really distinguish
1004 * the case here where the process does not
1005 * exist, and /proc/$PID/exe being unreadable
1006 * because $PID is a kernel thread. Hence,
1007 * assume it is a kernel thread, and rely on
1008 * that this case is caught with a later
1011 c->mask |= SD_BUS_CREDS_EXE;
1013 if (!IN_SET(r, -EPERM, -EACCES))
1016 c->mask |= SD_BUS_CREDS_EXE;
1019 if (missing & SD_BUS_CREDS_CMDLINE) {
1022 p = procfs_file_alloca(pid, "cmdline");
1023 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1027 if (!IN_SET(r, -EPERM, -EACCES))
1030 if (c->cmdline_size == 0)
1031 c->cmdline = mfree(c->cmdline);
1033 c->mask |= SD_BUS_CREDS_CMDLINE;
1037 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1038 _cleanup_free_ char *p = NULL;
1040 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1043 r = read_one_line_file(p, &c->tid_comm);
1047 if (!IN_SET(r, -EPERM, -EACCES))
1050 c->mask |= SD_BUS_CREDS_TID_COMM;
1053 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)) {
1056 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1058 if (!IN_SET(r, -EPERM, -EACCES))
1063 if (!c->cgroup_root) {
1064 r = cg_get_root_path(&c->cgroup_root);
1070 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);
1073 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1074 r = audit_session_from_pid(pid, &c->audit_session_id);
1075 if (r == -ENODATA) {
1076 /* ENODATA means: no audit session id assigned */
1077 c->audit_session_id = AUDIT_SESSION_INVALID;
1078 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1080 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
1083 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1086 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1087 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1088 if (r == -ENODATA) {
1089 /* ENODATA means: no audit login uid assigned */
1090 c->audit_login_uid = UID_INVALID;
1091 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1093 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
1096 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1099 if (missing & SD_BUS_CREDS_TTY) {
1100 r = get_ctty(pid, NULL, &c->tty);
1102 /* ENXIO means: process has no controlling TTY */
1104 c->mask |= SD_BUS_CREDS_TTY;
1106 if (!IN_SET(r, -EPERM, -EACCES, -ENOENT))
1109 c->mask |= SD_BUS_CREDS_TTY;
1112 /* In case only the exe path was to be read we cannot
1113 * distinguish the case where the exe path was unreadable
1114 * because the process was a kernel thread, or when the
1115 * process didn't exist at all. Hence, let's do a final check,
1117 if (!pid_is_alive(pid))
1120 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1123 c->augmented = missing & c->mask;
1128 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1129 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
1135 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1136 /* There's already all data we need, or augmentation
1137 * wasn't turned on. */
1139 *ret = sd_bus_creds_ref(c);
1143 n = bus_creds_new();
1147 /* Copy the original data over */
1149 if (c->mask & mask & SD_BUS_CREDS_PID) {
1151 n->mask |= SD_BUS_CREDS_PID;
1154 if (c->mask & mask & SD_BUS_CREDS_TID) {
1156 n->mask |= SD_BUS_CREDS_TID;
1159 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1161 n->mask |= SD_BUS_CREDS_PPID;
1164 if (c->mask & mask & SD_BUS_CREDS_UID) {
1166 n->mask |= SD_BUS_CREDS_UID;
1169 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1171 n->mask |= SD_BUS_CREDS_EUID;
1174 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1176 n->mask |= SD_BUS_CREDS_SUID;
1179 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1180 n->fsuid = c->fsuid;
1181 n->mask |= SD_BUS_CREDS_FSUID;
1184 if (c->mask & mask & SD_BUS_CREDS_GID) {
1186 n->mask |= SD_BUS_CREDS_GID;
1189 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1191 n->mask |= SD_BUS_CREDS_EGID;
1194 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1196 n->mask |= SD_BUS_CREDS_SGID;
1199 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1200 n->fsgid = c->fsgid;
1201 n->mask |= SD_BUS_CREDS_FSGID;
1204 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1205 if (c->supplementary_gids) {
1206 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1207 if (!n->supplementary_gids)
1209 n->n_supplementary_gids = c->n_supplementary_gids;
1211 n->supplementary_gids = NULL;
1212 n->n_supplementary_gids = 0;
1215 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1218 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1221 n->comm = strdup(c->comm);
1225 n->mask |= SD_BUS_CREDS_COMM;
1228 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1229 assert(c->tid_comm);
1231 n->tid_comm = strdup(c->tid_comm);
1235 n->mask |= SD_BUS_CREDS_TID_COMM;
1238 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1240 n->exe = strdup(c->exe);
1246 n->mask |= SD_BUS_CREDS_EXE;
1249 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1251 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1255 n->cmdline_size = c->cmdline_size;
1258 n->cmdline_size = 0;
1261 n->mask |= SD_BUS_CREDS_CMDLINE;
1264 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)) {
1267 n->cgroup = strdup(c->cgroup);
1271 n->cgroup_root = strdup(c->cgroup_root);
1272 if (!n->cgroup_root)
1275 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);
1278 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1279 assert(c->capability);
1281 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1285 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);
1288 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1291 n->label = strdup(c->label);
1294 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1297 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1298 n->audit_session_id = c->audit_session_id;
1299 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1301 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1302 n->audit_login_uid = c->audit_login_uid;
1303 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1306 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1308 n->tty = strdup(c->tty);
1313 n->mask |= SD_BUS_CREDS_TTY;
1316 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1317 assert(c->unique_name);
1319 n->unique_name = strdup(c->unique_name);
1320 if (!n->unique_name)
1322 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1325 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1326 if (strv_isempty(c->well_known_names))
1327 n->well_known_names = NULL;
1329 n->well_known_names = strv_copy(c->well_known_names);
1330 if (!n->well_known_names)
1333 n->well_known_names_driver = c->well_known_names_driver;
1334 n->well_known_names_local = c->well_known_names_local;
1335 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1338 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1339 assert(c->description);
1340 n->description = strdup(c->description);
1341 if (!n->description)
1343 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1346 n->augmented = c->augmented & n->mask;
1350 r = bus_creds_add_more(n, mask, 0, 0);