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 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 /// elogind does not support systemd slices
563 return cg_path_get_owner_uid(shifted, uid);
570 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
571 assert_return(c, -EINVAL);
573 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
579 if (!c->cmdline_array) {
580 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
581 if (!c->cmdline_array)
585 *cmdline = c->cmdline_array;
589 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
590 assert_return(c, -EINVAL);
591 assert_return(sessionid, -EINVAL);
593 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
596 if (c->audit_session_id == AUDIT_SESSION_INVALID)
599 *sessionid = c->audit_session_id;
603 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
604 assert_return(c, -EINVAL);
605 assert_return(uid, -EINVAL);
607 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
610 if (c->audit_login_uid == UID_INVALID)
613 *uid = c->audit_login_uid;
617 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
618 assert_return(c, -EINVAL);
619 assert_return(ret, -EINVAL);
621 if (!(c->mask & SD_BUS_CREDS_TTY))
631 /// UNNEEDED by elogind
633 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
634 assert_return(c, -EINVAL);
635 assert_return(unique_name, -EINVAL);
637 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
640 *unique_name = c->unique_name;
644 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
645 assert_return(c, -EINVAL);
646 assert_return(well_known_names, -EINVAL);
648 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
651 /* As a special hack we return the bus driver as well-known
652 * names list when this is requested. */
653 if (c->well_known_names_driver) {
654 static const char* const wkn[] = {
655 "org.freedesktop.DBus",
659 *well_known_names = (char**) wkn;
663 if (c->well_known_names_local) {
664 static const char* const wkn[] = {
665 "org.freedesktop.DBus.Local",
669 *well_known_names = (char**) wkn;
673 *well_known_names = c->well_known_names;
677 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
678 assert_return(c, -EINVAL);
679 assert_return(ret, -EINVAL);
681 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
684 assert(c->description);
686 if (!c->unescaped_description) {
687 c->unescaped_description = bus_label_unescape(c->description);
688 if (!c->unescaped_description)
692 *ret = c->unescaped_description;
697 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
701 assert(capability >= 0);
702 assert(c->capability);
704 if ((unsigned) capability > cap_last_cap())
707 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
709 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
712 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
713 assert_return(c, -EINVAL);
714 assert_return(capability >= 0, -EINVAL);
716 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
719 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
722 /// UNNEEDED by elogind
724 _public_ int sd_bus_creds_has_permitted_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_PERMITTED_CAPS))
731 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
734 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
735 assert_return(c, -EINVAL);
736 assert_return(capability >= 0, -EINVAL);
738 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
741 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
744 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
745 assert_return(c, -EINVAL);
746 assert_return(capability >= 0, -EINVAL);
748 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
751 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
755 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
762 max = DIV_ROUND_UP(cap_last_cap(), 32U);
763 p += strspn(p, WHITESPACE);
773 if (!c->capability) {
774 c->capability = new0(uint32_t, max * 4);
779 for (i = 0; i < sz; i ++) {
782 for (j = 0; j < 8; ++j) {
792 c->capability[offset * max + (sz - i - 1)] = v;
798 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
803 assert(c->allocated);
805 if (!(mask & SD_BUS_CREDS_AUGMENT))
808 /* Try to retrieve PID from creds if it wasn't passed to us */
811 c->mask |= SD_BUS_CREDS_PID;
812 } else if (c->mask & SD_BUS_CREDS_PID)
815 /* Without pid we cannot do much... */
818 /* Try to retrieve TID from creds if it wasn't passed to us */
819 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
822 /* Calculate what we shall and can add */
823 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);
829 c->mask |= SD_BUS_CREDS_TID;
832 if (missing & (SD_BUS_CREDS_PPID |
833 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
834 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
835 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
836 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
837 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
839 _cleanup_fclose_ FILE *f = NULL;
842 p = procfs_file_alloca(pid, "status");
848 else if (errno != EPERM && errno != EACCES)
853 FOREACH_LINE(line, f, return -errno) {
856 if (missing & SD_BUS_CREDS_PPID) {
857 p = startswith(line, "PPid:");
859 p += strspn(p, WHITESPACE);
861 /* Explicitly check for PPID 0 (which is the case for PID 1) */
862 if (!streq(p, "0")) {
863 r = parse_pid(p, &c->ppid);
870 c->mask |= SD_BUS_CREDS_PPID;
875 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
876 p = startswith(line, "Uid:");
878 unsigned long uid, euid, suid, fsuid;
880 p += strspn(p, WHITESPACE);
881 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
884 if (missing & SD_BUS_CREDS_UID)
885 c->uid = (uid_t) uid;
886 if (missing & SD_BUS_CREDS_EUID)
887 c->euid = (uid_t) euid;
888 if (missing & SD_BUS_CREDS_SUID)
889 c->suid = (uid_t) suid;
890 if (missing & SD_BUS_CREDS_FSUID)
891 c->fsuid = (uid_t) fsuid;
893 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
898 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
899 p = startswith(line, "Gid:");
901 unsigned long gid, egid, sgid, fsgid;
903 p += strspn(p, WHITESPACE);
904 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
907 if (missing & SD_BUS_CREDS_GID)
908 c->gid = (gid_t) gid;
909 if (missing & SD_BUS_CREDS_EGID)
910 c->egid = (gid_t) egid;
911 if (missing & SD_BUS_CREDS_SGID)
912 c->sgid = (gid_t) sgid;
913 if (missing & SD_BUS_CREDS_FSGID)
914 c->fsgid = (gid_t) fsgid;
916 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
921 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
922 p = startswith(line, "Groups:");
924 size_t allocated = 0;
930 p += strspn(p, WHITESPACE);
934 if (sscanf(p, "%lu%n", &g, &n) != 1)
937 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
940 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
944 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
949 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
950 p = startswith(line, "CapEff:");
952 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
956 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
961 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
962 p = startswith(line, "CapPrm:");
964 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
968 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
973 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
974 p = startswith(line, "CapInh:");
976 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
980 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
985 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
986 p = startswith(line, "CapBnd:");
988 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
992 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
1000 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1003 p = procfs_file_alloca(pid, "attr/current");
1004 r = read_one_line_file(p, &c->label);
1006 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1009 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1012 if (missing & SD_BUS_CREDS_COMM) {
1013 r = get_process_comm(pid, &c->comm);
1015 if (r != -EPERM && r != -EACCES)
1018 c->mask |= SD_BUS_CREDS_COMM;
1021 if (missing & SD_BUS_CREDS_EXE) {
1022 r = get_process_exe(pid, &c->exe);
1024 /* Unfortunately we cannot really distinguish
1025 * the case here where the process does not
1026 * exist, and /proc/$PID/exe being unreadable
1027 * because $PID is a kernel thread. Hence,
1028 * assume it is a kernel thread, and rely on
1029 * that this case is caught with a later
1032 c->mask |= SD_BUS_CREDS_EXE;
1034 if (r != -EPERM && r != -EACCES)
1037 c->mask |= SD_BUS_CREDS_EXE;
1040 if (missing & SD_BUS_CREDS_CMDLINE) {
1043 p = procfs_file_alloca(pid, "cmdline");
1044 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1048 if (r != -EPERM && r != -EACCES)
1051 if (c->cmdline_size == 0) {
1056 c->mask |= SD_BUS_CREDS_CMDLINE;
1060 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1061 _cleanup_free_ char *p = NULL;
1063 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1066 r = read_one_line_file(p, &c->tid_comm);
1070 if (r != -EPERM && r != -EACCES)
1073 c->mask |= SD_BUS_CREDS_TID_COMM;
1076 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)) {
1079 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1081 if (r != -EPERM && r != -EACCES)
1086 if (!c->cgroup_root) {
1087 r = cg_get_root_path(&c->cgroup_root);
1093 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);
1096 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1097 r = audit_session_from_pid(pid, &c->audit_session_id);
1098 if (r == -ENODATA) {
1099 /* ENODATA means: no audit session id assigned */
1100 c->audit_session_id = AUDIT_SESSION_INVALID;
1101 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1103 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1106 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1109 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1110 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1111 if (r == -ENODATA) {
1112 /* ENODATA means: no audit login uid assigned */
1113 c->audit_login_uid = UID_INVALID;
1114 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1116 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1119 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1122 if (missing & SD_BUS_CREDS_TTY) {
1123 r = get_ctty(pid, NULL, &c->tty);
1125 /* ENXIO means: process has no controlling TTY */
1127 c->mask |= SD_BUS_CREDS_TTY;
1129 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1132 c->mask |= SD_BUS_CREDS_TTY;
1135 /* In case only the exe path was to be read we cannot
1136 * distinguish the case where the exe path was unreadable
1137 * because the process was a kernel thread, or when the
1138 * process didn't exist at all. Hence, let's do a final check,
1140 if (!pid_is_alive(pid))
1143 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1146 c->augmented = missing & c->mask;
1151 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1152 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1158 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1159 /* There's already all data we need, or augmentation
1160 * wasn't turned on. */
1162 *ret = sd_bus_creds_ref(c);
1166 n = bus_creds_new();
1170 /* Copy the original data over */
1172 if (c->mask & mask & SD_BUS_CREDS_PID) {
1174 n->mask |= SD_BUS_CREDS_PID;
1177 if (c->mask & mask & SD_BUS_CREDS_TID) {
1179 n->mask |= SD_BUS_CREDS_TID;
1182 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1184 n->mask |= SD_BUS_CREDS_PPID;
1187 if (c->mask & mask & SD_BUS_CREDS_UID) {
1189 n->mask |= SD_BUS_CREDS_UID;
1192 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1194 n->mask |= SD_BUS_CREDS_EUID;
1197 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1199 n->mask |= SD_BUS_CREDS_SUID;
1202 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1203 n->fsuid = c->fsuid;
1204 n->mask |= SD_BUS_CREDS_FSUID;
1207 if (c->mask & mask & SD_BUS_CREDS_GID) {
1209 n->mask |= SD_BUS_CREDS_GID;
1212 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1214 n->mask |= SD_BUS_CREDS_EGID;
1217 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1219 n->mask |= SD_BUS_CREDS_SGID;
1222 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1223 n->fsgid = c->fsgid;
1224 n->mask |= SD_BUS_CREDS_FSGID;
1227 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1228 if (c->supplementary_gids) {
1229 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1230 if (!n->supplementary_gids)
1232 n->n_supplementary_gids = c->n_supplementary_gids;
1234 n->supplementary_gids = NULL;
1235 n->n_supplementary_gids = 0;
1238 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1241 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1244 n->comm = strdup(c->comm);
1248 n->mask |= SD_BUS_CREDS_COMM;
1251 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1252 assert(c->tid_comm);
1254 n->tid_comm = strdup(c->tid_comm);
1258 n->mask |= SD_BUS_CREDS_TID_COMM;
1261 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1263 n->exe = strdup(c->exe);
1269 n->mask |= SD_BUS_CREDS_EXE;
1272 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1274 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1278 n->cmdline_size = c->cmdline_size;
1281 n->cmdline_size = 0;
1284 n->mask |= SD_BUS_CREDS_CMDLINE;
1287 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)) {
1290 n->cgroup = strdup(c->cgroup);
1294 n->cgroup_root = strdup(c->cgroup_root);
1295 if (!n->cgroup_root)
1298 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);
1301 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1302 assert(c->capability);
1304 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1308 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);
1311 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1314 n->label = strdup(c->label);
1317 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1320 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1321 n->audit_session_id = c->audit_session_id;
1322 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1324 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1325 n->audit_login_uid = c->audit_login_uid;
1326 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1329 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1331 n->tty = strdup(c->tty);
1336 n->mask |= SD_BUS_CREDS_TTY;
1339 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1340 assert(c->unique_name);
1342 n->unique_name = strdup(c->unique_name);
1343 if (!n->unique_name)
1345 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1348 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1349 if (strv_isempty(c->well_known_names))
1350 n->well_known_names = NULL;
1352 n->well_known_names = strv_copy(c->well_known_names);
1353 if (!n->well_known_names)
1356 n->well_known_names_driver = c->well_known_names_driver;
1357 n->well_known_names_local = c->well_known_names_local;
1358 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1361 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1362 assert(c->description);
1363 n->description = strdup(c->description);
1364 if (!n->description)
1366 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1369 n->augmented = c->augmented & n->mask;
1373 r = bus_creds_add_more(n, mask, 0, 0);