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) {
88 /* If this is an embedded creds structure, then
89 * forward ref counting to the message */
90 m = container_of(c, sd_bus_message, creds);
91 sd_bus_message_ref(m);
97 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
103 assert(c->n_ref > 0);
114 free(c->unique_name);
115 free(c->cgroup_root);
116 free(c->description);
118 c->supplementary_gids = mfree(c->supplementary_gids);
120 c->well_known_names = strv_free(c->well_known_names);
129 m = container_of(c, sd_bus_message, creds);
130 sd_bus_message_unref(m);
137 #if 0 /// UNNEEDED by elogind
138 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
145 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
151 sd_bus_creds* bus_creds_new(void) {
154 c = new0(sd_bus_creds, 1);
163 #if 0 /// UNNEEDED by elogind
164 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
168 assert_return(pid >= 0, -EINVAL);
169 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
170 assert_return(ret, -EINVAL);
179 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
181 sd_bus_creds_unref(c);
185 /* Check if the process existed at all, in case we haven't
186 * figured that out already */
187 if (!pid_is_alive(pid)) {
188 sd_bus_creds_unref(c);
197 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
198 assert_return(c, -EINVAL);
199 assert_return(uid, -EINVAL);
201 if (!(c->mask & SD_BUS_CREDS_UID))
208 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
209 assert_return(c, -EINVAL);
210 assert_return(euid, -EINVAL);
212 if (!(c->mask & SD_BUS_CREDS_EUID))
219 #if 0 /// UNNEEDED by elogind
220 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
221 assert_return(c, -EINVAL);
222 assert_return(suid, -EINVAL);
224 if (!(c->mask & SD_BUS_CREDS_SUID))
232 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
233 assert_return(c, -EINVAL);
234 assert_return(fsuid, -EINVAL);
236 if (!(c->mask & SD_BUS_CREDS_FSUID))
243 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
244 assert_return(c, -EINVAL);
245 assert_return(gid, -EINVAL);
247 if (!(c->mask & SD_BUS_CREDS_GID))
255 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
256 assert_return(c, -EINVAL);
257 assert_return(egid, -EINVAL);
259 if (!(c->mask & SD_BUS_CREDS_EGID))
266 #if 0 /// UNNEEDED by elogind
267 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
268 assert_return(c, -EINVAL);
269 assert_return(sgid, -EINVAL);
271 if (!(c->mask & SD_BUS_CREDS_SGID))
278 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
279 assert_return(c, -EINVAL);
280 assert_return(fsgid, -EINVAL);
282 if (!(c->mask & SD_BUS_CREDS_FSGID))
289 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
290 assert_return(c, -EINVAL);
291 assert_return(gids, -EINVAL);
293 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
296 *gids = c->supplementary_gids;
297 return (int) c->n_supplementary_gids;
301 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
302 assert_return(c, -EINVAL);
303 assert_return(pid, -EINVAL);
305 if (!(c->mask & SD_BUS_CREDS_PID))
313 #if 0 /// UNNEEDED by elogind
314 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
315 assert_return(c, -EINVAL);
316 assert_return(ppid, -EINVAL);
318 if (!(c->mask & SD_BUS_CREDS_PPID))
321 /* PID 1 has no parent process. Let's distinguish the case of
322 * not knowing and not having a parent process by the returned
332 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
333 assert_return(c, -EINVAL);
334 assert_return(tid, -EINVAL);
336 if (!(c->mask & SD_BUS_CREDS_TID))
344 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
345 assert_return(c, -EINVAL);
347 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
355 #if 0 /// 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 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
530 c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
531 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
535 log_debug_elogind("Shifted: \"%s\"", shifted);
536 r = cg_path_get_session(shifted, (char**) &c->session);
545 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
549 assert_return(c, -EINVAL);
550 assert_return(uid, -EINVAL);
552 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
557 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
561 #if 0 /// elogind does not support systemd slices
562 return cg_path_get_owner_uid(shifted, uid);
569 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
570 assert_return(c, -EINVAL);
572 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
578 if (!c->cmdline_array) {
579 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
580 if (!c->cmdline_array)
584 *cmdline = c->cmdline_array;
588 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
589 assert_return(c, -EINVAL);
590 assert_return(sessionid, -EINVAL);
592 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
595 if (c->audit_session_id == AUDIT_SESSION_INVALID)
598 *sessionid = c->audit_session_id;
602 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
603 assert_return(c, -EINVAL);
604 assert_return(uid, -EINVAL);
606 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
609 if (c->audit_login_uid == UID_INVALID)
612 *uid = c->audit_login_uid;
616 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
617 assert_return(c, -EINVAL);
618 assert_return(ret, -EINVAL);
620 if (!(c->mask & SD_BUS_CREDS_TTY))
630 #if 0 /// 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 #if 0 /// 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)
1049 c->cmdline = mfree(c->cmdline);
1051 c->mask |= SD_BUS_CREDS_CMDLINE;
1055 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1056 _cleanup_free_ char *p = NULL;
1058 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1061 r = read_one_line_file(p, &c->tid_comm);
1065 if (r != -EPERM && r != -EACCES)
1068 c->mask |= SD_BUS_CREDS_TID_COMM;
1071 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)) {
1074 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1076 if (r != -EPERM && r != -EACCES)
1081 if (!c->cgroup_root) {
1082 r = cg_get_root_path(&c->cgroup_root);
1088 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);
1091 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1092 r = audit_session_from_pid(pid, &c->audit_session_id);
1093 if (r == -ENODATA) {
1094 /* ENODATA means: no audit session id assigned */
1095 c->audit_session_id = AUDIT_SESSION_INVALID;
1096 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1098 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1101 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1104 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1105 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1106 if (r == -ENODATA) {
1107 /* ENODATA means: no audit login uid assigned */
1108 c->audit_login_uid = UID_INVALID;
1109 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1111 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1114 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1117 if (missing & SD_BUS_CREDS_TTY) {
1118 r = get_ctty(pid, NULL, &c->tty);
1120 /* ENXIO means: process has no controlling TTY */
1122 c->mask |= SD_BUS_CREDS_TTY;
1124 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1127 c->mask |= SD_BUS_CREDS_TTY;
1130 /* In case only the exe path was to be read we cannot
1131 * distinguish the case where the exe path was unreadable
1132 * because the process was a kernel thread, or when the
1133 * process didn't exist at all. Hence, let's do a final check,
1135 if (!pid_is_alive(pid))
1138 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1141 c->augmented = missing & c->mask;
1146 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1147 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
1153 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1154 /* There's already all data we need, or augmentation
1155 * wasn't turned on. */
1157 *ret = sd_bus_creds_ref(c);
1161 n = bus_creds_new();
1165 /* Copy the original data over */
1167 if (c->mask & mask & SD_BUS_CREDS_PID) {
1169 n->mask |= SD_BUS_CREDS_PID;
1172 if (c->mask & mask & SD_BUS_CREDS_TID) {
1174 n->mask |= SD_BUS_CREDS_TID;
1177 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1179 n->mask |= SD_BUS_CREDS_PPID;
1182 if (c->mask & mask & SD_BUS_CREDS_UID) {
1184 n->mask |= SD_BUS_CREDS_UID;
1187 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1189 n->mask |= SD_BUS_CREDS_EUID;
1192 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1194 n->mask |= SD_BUS_CREDS_SUID;
1197 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1198 n->fsuid = c->fsuid;
1199 n->mask |= SD_BUS_CREDS_FSUID;
1202 if (c->mask & mask & SD_BUS_CREDS_GID) {
1204 n->mask |= SD_BUS_CREDS_GID;
1207 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1209 n->mask |= SD_BUS_CREDS_EGID;
1212 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1214 n->mask |= SD_BUS_CREDS_SGID;
1217 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1218 n->fsgid = c->fsgid;
1219 n->mask |= SD_BUS_CREDS_FSGID;
1222 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1223 if (c->supplementary_gids) {
1224 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1225 if (!n->supplementary_gids)
1227 n->n_supplementary_gids = c->n_supplementary_gids;
1229 n->supplementary_gids = NULL;
1230 n->n_supplementary_gids = 0;
1233 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1236 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1239 n->comm = strdup(c->comm);
1243 n->mask |= SD_BUS_CREDS_COMM;
1246 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1247 assert(c->tid_comm);
1249 n->tid_comm = strdup(c->tid_comm);
1253 n->mask |= SD_BUS_CREDS_TID_COMM;
1256 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1258 n->exe = strdup(c->exe);
1264 n->mask |= SD_BUS_CREDS_EXE;
1267 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1269 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1273 n->cmdline_size = c->cmdline_size;
1276 n->cmdline_size = 0;
1279 n->mask |= SD_BUS_CREDS_CMDLINE;
1282 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)) {
1285 n->cgroup = strdup(c->cgroup);
1289 n->cgroup_root = strdup(c->cgroup_root);
1290 if (!n->cgroup_root)
1293 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);
1296 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1297 assert(c->capability);
1299 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1303 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);
1306 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1309 n->label = strdup(c->label);
1312 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1315 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1316 n->audit_session_id = c->audit_session_id;
1317 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1319 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1320 n->audit_login_uid = c->audit_login_uid;
1321 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1324 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1326 n->tty = strdup(c->tty);
1331 n->mask |= SD_BUS_CREDS_TTY;
1334 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1335 assert(c->unique_name);
1337 n->unique_name = strdup(c->unique_name);
1338 if (!n->unique_name)
1340 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1343 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1344 if (strv_isempty(c->well_known_names))
1345 n->well_known_names = NULL;
1347 n->well_known_names = strv_copy(c->well_known_names);
1348 if (!n->well_known_names)
1351 n->well_known_names_driver = c->well_known_names_driver;
1352 n->well_known_names_local = c->well_known_names_local;
1353 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1356 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1357 assert(c->description);
1358 n->description = strdup(c->description);
1359 if (!n->description)
1361 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1364 n->augmented = c->augmented & n->mask;
1368 r = bus_creds_add_more(n, mask, 0, 0);