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 free(c->supplementary_gids);
111 c->supplementary_gids = NULL;
113 strv_free(c->well_known_names);
114 c->well_known_names = NULL;
123 m = container_of(c, sd_bus_message, creds);
124 sd_bus_message_unref(m);
131 /// UNNEEDED by elogind
133 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
140 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
146 sd_bus_creds* bus_creds_new(void) {
149 c = new0(sd_bus_creds, 1);
158 /// UNNEEDED by elogind
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);
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);
193 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
194 assert_return(c, -EINVAL);
195 assert_return(uid, -EINVAL);
197 if (!(c->mask & SD_BUS_CREDS_UID))
204 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
205 assert_return(c, -EINVAL);
206 assert_return(euid, -EINVAL);
208 if (!(c->mask & SD_BUS_CREDS_EUID))
215 /// UNNEEDED by elogind
217 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
218 assert_return(c, -EINVAL);
219 assert_return(suid, -EINVAL);
221 if (!(c->mask & SD_BUS_CREDS_SUID))
229 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
230 assert_return(c, -EINVAL);
231 assert_return(fsuid, -EINVAL);
233 if (!(c->mask & SD_BUS_CREDS_FSUID))
240 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
241 assert_return(c, -EINVAL);
242 assert_return(gid, -EINVAL);
244 if (!(c->mask & SD_BUS_CREDS_GID))
252 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
253 assert_return(c, -EINVAL);
254 assert_return(egid, -EINVAL);
256 if (!(c->mask & SD_BUS_CREDS_EGID))
263 /// 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 /// UNNEEDED by elogind
313 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
314 assert_return(c, -EINVAL);
315 assert_return(ppid, -EINVAL);
317 if (!(c->mask & SD_BUS_CREDS_PPID))
320 /* PID 1 has no parent process. Let's distinguish the case of
321 * not knowing and not having a parent process by the returned
331 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
332 assert_return(c, -EINVAL);
333 assert_return(tid, -EINVAL);
335 if (!(c->mask & SD_BUS_CREDS_TID))
343 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
344 assert_return(c, -EINVAL);
346 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
354 /// UNNEEDED by elogind
356 _public_ int sd_bus_creds_get_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_COMM))
368 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
369 assert_return(c, -EINVAL);
370 assert_return(ret, -EINVAL);
372 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
380 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
381 assert_return(c, -EINVAL);
382 assert_return(ret, -EINVAL);
384 if (!(c->mask & SD_BUS_CREDS_EXE))
394 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
395 assert_return(c, -EINVAL);
396 assert_return(ret, -EINVAL);
398 if (!(c->mask & SD_BUS_CREDS_CGROUP))
406 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
409 assert_return(c, -EINVAL);
410 assert_return(ret, -EINVAL);
412 if (!(c->mask & SD_BUS_CREDS_UNIT))
420 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
424 r = cg_path_get_unit(shifted, (char**) &c->unit);
433 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
436 assert_return(c, -EINVAL);
437 assert_return(ret, -EINVAL);
439 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
447 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
451 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
460 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
463 assert_return(c, -EINVAL);
464 assert_return(ret, -EINVAL);
466 if (!(c->mask & SD_BUS_CREDS_SLICE))
474 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
478 r = cg_path_get_slice(shifted, (char**) &c->slice);
487 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
490 assert_return(c, -EINVAL);
491 assert_return(ret, -EINVAL);
493 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
498 if (!c->user_slice) {
501 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
505 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
510 *ret = c->user_slice;
515 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
518 assert_return(c, -EINVAL);
519 assert_return(ret, -EINVAL);
521 if (!(c->mask & SD_BUS_CREDS_SESSION))
529 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
533 r = cg_path_get_session(shifted, (char**) &c->session);
542 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
546 assert_return(c, -EINVAL);
547 assert_return(uid, -EINVAL);
549 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
554 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
558 /// 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 /// UNNEEDED by elogind
630 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
631 assert_return(c, -EINVAL);
632 assert_return(unique_name, -EINVAL);
634 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
637 *unique_name = c->unique_name;
641 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
642 assert_return(c, -EINVAL);
643 assert_return(well_known_names, -EINVAL);
645 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
648 /* As a special hack we return the bus driver as well-known
649 * names list when this is requested. */
650 if (c->well_known_names_driver) {
651 static const char* const wkn[] = {
652 "org.freedesktop.DBus",
656 *well_known_names = (char**) wkn;
660 if (c->well_known_names_local) {
661 static const char* const wkn[] = {
662 "org.freedesktop.DBus.Local",
666 *well_known_names = (char**) wkn;
670 *well_known_names = c->well_known_names;
674 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
675 assert_return(c, -EINVAL);
676 assert_return(ret, -EINVAL);
678 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
681 assert(c->description);
683 if (!c->unescaped_description) {
684 c->unescaped_description = bus_label_unescape(c->description);
685 if (!c->unescaped_description)
689 *ret = c->unescaped_description;
694 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
698 assert(capability >= 0);
699 assert(c->capability);
701 if ((unsigned) capability > cap_last_cap())
704 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
706 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
709 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
710 assert_return(c, -EINVAL);
711 assert_return(capability >= 0, -EINVAL);
713 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
716 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
719 /// UNNEEDED by elogind
721 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
722 assert_return(c, -EINVAL);
723 assert_return(capability >= 0, -EINVAL);
725 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
728 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
731 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
732 assert_return(c, -EINVAL);
733 assert_return(capability >= 0, -EINVAL);
735 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
738 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
741 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
742 assert_return(c, -EINVAL);
743 assert_return(capability >= 0, -EINVAL);
745 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
748 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
752 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
759 max = DIV_ROUND_UP(cap_last_cap(), 32U);
760 p += strspn(p, WHITESPACE);
770 if (!c->capability) {
771 c->capability = new0(uint32_t, max * 4);
776 for (i = 0; i < sz; i ++) {
779 for (j = 0; j < 8; ++j) {
789 c->capability[offset * max + (sz - i - 1)] = v;
795 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
800 assert(c->allocated);
802 if (!(mask & SD_BUS_CREDS_AUGMENT))
805 /* Try to retrieve PID from creds if it wasn't passed to us */
808 c->mask |= SD_BUS_CREDS_PID;
809 } else if (c->mask & SD_BUS_CREDS_PID)
812 /* Without pid we cannot do much... */
815 /* Try to retrieve TID from creds if it wasn't passed to us */
816 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
819 /* Calculate what we shall and can add */
820 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);
826 c->mask |= SD_BUS_CREDS_TID;
829 if (missing & (SD_BUS_CREDS_PPID |
830 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
831 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
832 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
833 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
834 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
836 _cleanup_fclose_ FILE *f = NULL;
839 p = procfs_file_alloca(pid, "status");
845 else if (errno != EPERM && errno != EACCES)
850 FOREACH_LINE(line, f, return -errno) {
853 if (missing & SD_BUS_CREDS_PPID) {
854 p = startswith(line, "PPid:");
856 p += strspn(p, WHITESPACE);
858 /* Explicitly check for PPID 0 (which is the case for PID 1) */
859 if (!streq(p, "0")) {
860 r = parse_pid(p, &c->ppid);
867 c->mask |= SD_BUS_CREDS_PPID;
872 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
873 p = startswith(line, "Uid:");
875 unsigned long uid, euid, suid, fsuid;
877 p += strspn(p, WHITESPACE);
878 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
881 if (missing & SD_BUS_CREDS_UID)
882 c->uid = (uid_t) uid;
883 if (missing & SD_BUS_CREDS_EUID)
884 c->euid = (uid_t) euid;
885 if (missing & SD_BUS_CREDS_SUID)
886 c->suid = (uid_t) suid;
887 if (missing & SD_BUS_CREDS_FSUID)
888 c->fsuid = (uid_t) fsuid;
890 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
895 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
896 p = startswith(line, "Gid:");
898 unsigned long gid, egid, sgid, fsgid;
900 p += strspn(p, WHITESPACE);
901 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
904 if (missing & SD_BUS_CREDS_GID)
905 c->gid = (gid_t) gid;
906 if (missing & SD_BUS_CREDS_EGID)
907 c->egid = (gid_t) egid;
908 if (missing & SD_BUS_CREDS_SGID)
909 c->sgid = (gid_t) sgid;
910 if (missing & SD_BUS_CREDS_FSGID)
911 c->fsgid = (gid_t) fsgid;
913 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
918 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
919 p = startswith(line, "Groups:");
921 size_t allocated = 0;
927 p += strspn(p, WHITESPACE);
931 if (sscanf(p, "%lu%n", &g, &n) != 1)
934 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
937 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
941 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
946 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
947 p = startswith(line, "CapEff:");
949 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
953 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
958 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
959 p = startswith(line, "CapPrm:");
961 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
965 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
970 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
971 p = startswith(line, "CapInh:");
973 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
977 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
982 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
983 p = startswith(line, "CapBnd:");
985 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
989 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
997 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1000 p = procfs_file_alloca(pid, "attr/current");
1001 r = read_one_line_file(p, &c->label);
1003 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1006 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1009 if (missing & SD_BUS_CREDS_COMM) {
1010 r = get_process_comm(pid, &c->comm);
1012 if (r != -EPERM && r != -EACCES)
1015 c->mask |= SD_BUS_CREDS_COMM;
1018 if (missing & SD_BUS_CREDS_EXE) {
1019 r = get_process_exe(pid, &c->exe);
1021 /* Unfortunately we cannot really distinguish
1022 * the case here where the process does not
1023 * exist, and /proc/$PID/exe being unreadable
1024 * because $PID is a kernel thread. Hence,
1025 * assume it is a kernel thread, and rely on
1026 * that this case is caught with a later
1029 c->mask |= SD_BUS_CREDS_EXE;
1031 if (r != -EPERM && r != -EACCES)
1034 c->mask |= SD_BUS_CREDS_EXE;
1037 if (missing & SD_BUS_CREDS_CMDLINE) {
1040 p = procfs_file_alloca(pid, "cmdline");
1041 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1045 if (r != -EPERM && r != -EACCES)
1048 if (c->cmdline_size == 0) {
1053 c->mask |= SD_BUS_CREDS_CMDLINE;
1057 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1058 _cleanup_free_ char *p = NULL;
1060 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1063 r = read_one_line_file(p, &c->tid_comm);
1067 if (r != -EPERM && r != -EACCES)
1070 c->mask |= SD_BUS_CREDS_TID_COMM;
1073 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)) {
1076 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1078 if (r != -EPERM && r != -EACCES)
1083 if (!c->cgroup_root) {
1084 r = cg_get_root_path(&c->cgroup_root);
1090 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);
1093 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1094 r = audit_session_from_pid(pid, &c->audit_session_id);
1095 if (r == -ENODATA) {
1096 /* ENODATA means: no audit session id assigned */
1097 c->audit_session_id = AUDIT_SESSION_INVALID;
1098 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1100 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1103 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1106 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1107 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1108 if (r == -ENODATA) {
1109 /* ENODATA means: no audit login uid assigned */
1110 c->audit_login_uid = UID_INVALID;
1111 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1113 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1116 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1119 if (missing & SD_BUS_CREDS_TTY) {
1120 r = get_ctty(pid, NULL, &c->tty);
1122 /* ENXIO means: process has no controlling TTY */
1124 c->mask |= SD_BUS_CREDS_TTY;
1126 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1129 c->mask |= SD_BUS_CREDS_TTY;
1132 /* In case only the exe path was to be read we cannot
1133 * distinguish the case where the exe path was unreadable
1134 * because the process was a kernel thread, or when the
1135 * process didn't exist at all. Hence, let's do a final check,
1137 if (!pid_is_alive(pid))
1140 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1143 c->augmented = missing & c->mask;
1148 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1149 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1155 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1156 /* There's already all data we need, or augmentation
1157 * wasn't turned on. */
1159 *ret = sd_bus_creds_ref(c);
1163 n = bus_creds_new();
1167 /* Copy the original data over */
1169 if (c->mask & mask & SD_BUS_CREDS_PID) {
1171 n->mask |= SD_BUS_CREDS_PID;
1174 if (c->mask & mask & SD_BUS_CREDS_TID) {
1176 n->mask |= SD_BUS_CREDS_TID;
1179 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1181 n->mask |= SD_BUS_CREDS_PPID;
1184 if (c->mask & mask & SD_BUS_CREDS_UID) {
1186 n->mask |= SD_BUS_CREDS_UID;
1189 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1191 n->mask |= SD_BUS_CREDS_EUID;
1194 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1196 n->mask |= SD_BUS_CREDS_SUID;
1199 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1200 n->fsuid = c->fsuid;
1201 n->mask |= SD_BUS_CREDS_FSUID;
1204 if (c->mask & mask & SD_BUS_CREDS_GID) {
1206 n->mask |= SD_BUS_CREDS_GID;
1209 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1211 n->mask |= SD_BUS_CREDS_EGID;
1214 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1216 n->mask |= SD_BUS_CREDS_SGID;
1219 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1220 n->fsgid = c->fsgid;
1221 n->mask |= SD_BUS_CREDS_FSGID;
1224 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1225 if (c->supplementary_gids) {
1226 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1227 if (!n->supplementary_gids)
1229 n->n_supplementary_gids = c->n_supplementary_gids;
1231 n->supplementary_gids = NULL;
1232 n->n_supplementary_gids = 0;
1235 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1238 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1241 n->comm = strdup(c->comm);
1245 n->mask |= SD_BUS_CREDS_COMM;
1248 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1249 assert(c->tid_comm);
1251 n->tid_comm = strdup(c->tid_comm);
1255 n->mask |= SD_BUS_CREDS_TID_COMM;
1258 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1260 n->exe = strdup(c->exe);
1266 n->mask |= SD_BUS_CREDS_EXE;
1269 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1271 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1275 n->cmdline_size = c->cmdline_size;
1278 n->cmdline_size = 0;
1281 n->mask |= SD_BUS_CREDS_CMDLINE;
1284 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)) {
1287 n->cgroup = strdup(c->cgroup);
1291 n->cgroup_root = strdup(c->cgroup_root);
1292 if (!n->cgroup_root)
1295 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);
1298 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1299 assert(c->capability);
1301 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1305 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);
1308 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1311 n->label = strdup(c->label);
1314 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1317 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1318 n->audit_session_id = c->audit_session_id;
1319 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1321 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1322 n->audit_login_uid = c->audit_login_uid;
1323 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1326 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1328 n->tty = strdup(c->tty);
1333 n->mask |= SD_BUS_CREDS_TTY;
1336 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1337 assert(c->unique_name);
1339 n->unique_name = strdup(c->unique_name);
1340 if (!n->unique_name)
1342 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1345 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1346 if (strv_isempty(c->well_known_names))
1347 n->well_known_names = NULL;
1349 n->well_known_names = strv_copy(c->well_known_names);
1350 if (!n->well_known_names)
1353 n->well_known_names_driver = c->well_known_names_driver;
1354 n->well_known_names_local = c->well_known_names_local;
1355 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1358 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1359 assert(c->description);
1360 n->description = strdup(c->description);
1361 if (!n->description)
1363 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1366 n->augmented = c->augmented & n->mask;
1370 r = bus_creds_add_more(n, mask, 0, 0);