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) {
78 assert_return(c, NULL);
86 /* If this is an embedded creds structure, then
87 * forward ref counting to the message */
88 m = container_of(c, sd_bus_message, creds);
89 sd_bus_message_ref(m);
95 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
101 assert(c->n_ref > 0);
112 free(c->unique_name);
113 free(c->cgroup_root);
114 free(c->description);
116 c->supplementary_gids = mfree(c->supplementary_gids);
118 c->well_known_names = strv_free(c->well_known_names);
127 m = container_of(c, sd_bus_message, creds);
128 sd_bus_message_unref(m);
135 #if 0 /// UNNEEDED by elogind
136 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
143 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
149 sd_bus_creds* bus_creds_new(void) {
152 c = new0(sd_bus_creds, 1);
161 #if 0 /// UNNEEDED by elogind
162 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
166 assert_return(pid >= 0, -EINVAL);
167 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
168 assert_return(ret, -EINVAL);
177 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
179 sd_bus_creds_unref(c);
183 /* Check if the process existed at all, in case we haven't
184 * figured that out already */
185 if (!pid_is_alive(pid)) {
186 sd_bus_creds_unref(c);
195 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
196 assert_return(c, -EINVAL);
197 assert_return(uid, -EINVAL);
199 if (!(c->mask & SD_BUS_CREDS_UID))
206 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
207 assert_return(c, -EINVAL);
208 assert_return(euid, -EINVAL);
210 if (!(c->mask & SD_BUS_CREDS_EUID))
217 #if 0 /// UNNEEDED by elogind
218 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
219 assert_return(c, -EINVAL);
220 assert_return(suid, -EINVAL);
222 if (!(c->mask & SD_BUS_CREDS_SUID))
230 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
231 assert_return(c, -EINVAL);
232 assert_return(fsuid, -EINVAL);
234 if (!(c->mask & SD_BUS_CREDS_FSUID))
241 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
242 assert_return(c, -EINVAL);
243 assert_return(gid, -EINVAL);
245 if (!(c->mask & SD_BUS_CREDS_GID))
253 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
254 assert_return(c, -EINVAL);
255 assert_return(egid, -EINVAL);
257 if (!(c->mask & SD_BUS_CREDS_EGID))
264 #if 0 /// 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 #if 0 /// UNNEEDED by elogind
312 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
313 assert_return(c, -EINVAL);
314 assert_return(ppid, -EINVAL);
316 if (!(c->mask & SD_BUS_CREDS_PPID))
319 /* PID 1 has no parent process. Let's distinguish the case of
320 * not knowing and not having a parent process by the returned
330 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
331 assert_return(c, -EINVAL);
332 assert_return(tid, -EINVAL);
334 if (!(c->mask & SD_BUS_CREDS_TID))
342 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
343 assert_return(c, -EINVAL);
345 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
353 #if 0 /// UNNEEDED by elogind
354 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
355 assert_return(c, -EINVAL);
356 assert_return(ret, -EINVAL);
358 if (!(c->mask & SD_BUS_CREDS_COMM))
366 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
367 assert_return(c, -EINVAL);
368 assert_return(ret, -EINVAL);
370 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
378 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
379 assert_return(c, -EINVAL);
380 assert_return(ret, -EINVAL);
382 if (!(c->mask & SD_BUS_CREDS_EXE))
392 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
393 assert_return(c, -EINVAL);
394 assert_return(ret, -EINVAL);
396 if (!(c->mask & SD_BUS_CREDS_CGROUP))
404 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
407 assert_return(c, -EINVAL);
408 assert_return(ret, -EINVAL);
410 if (!(c->mask & SD_BUS_CREDS_UNIT))
418 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
422 r = cg_path_get_unit(shifted, (char**) &c->unit);
431 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
434 assert_return(c, -EINVAL);
435 assert_return(ret, -EINVAL);
437 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
445 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
449 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
458 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
461 assert_return(c, -EINVAL);
462 assert_return(ret, -EINVAL);
464 if (!(c->mask & SD_BUS_CREDS_SLICE))
472 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
476 r = cg_path_get_slice(shifted, (char**) &c->slice);
485 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
488 assert_return(c, -EINVAL);
489 assert_return(ret, -EINVAL);
491 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
496 if (!c->user_slice) {
499 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
503 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
508 *ret = c->user_slice;
513 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
516 assert_return(c, -EINVAL);
517 assert_return(ret, -EINVAL);
519 if (!(c->mask & SD_BUS_CREDS_SESSION))
527 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
528 c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
529 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
533 log_debug_elogind("Shifted: \"%s\"", shifted);
534 r = cg_path_get_session(shifted, (char**) &c->session);
543 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
547 assert_return(c, -EINVAL);
548 assert_return(uid, -EINVAL);
550 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
555 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
559 /// elogind does not support systemd slices
561 return cg_path_get_owner_uid(shifted, uid);
568 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
569 assert_return(c, -EINVAL);
571 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
577 if (!c->cmdline_array) {
578 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
579 if (!c->cmdline_array)
583 *cmdline = c->cmdline_array;
587 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
588 assert_return(c, -EINVAL);
589 assert_return(sessionid, -EINVAL);
591 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
594 if (c->audit_session_id == AUDIT_SESSION_INVALID)
597 *sessionid = c->audit_session_id;
601 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
602 assert_return(c, -EINVAL);
603 assert_return(uid, -EINVAL);
605 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
608 if (c->audit_login_uid == UID_INVALID)
611 *uid = c->audit_login_uid;
615 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
616 assert_return(c, -EINVAL);
617 assert_return(ret, -EINVAL);
619 if (!(c->mask & SD_BUS_CREDS_TTY))
629 #if 0 /// 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 #if 0 /// UNNEEDED by elogind
720 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
721 assert_return(c, -EINVAL);
722 assert_return(capability >= 0, -EINVAL);
724 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
727 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
730 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
731 assert_return(c, -EINVAL);
732 assert_return(capability >= 0, -EINVAL);
734 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
737 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
740 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
741 assert_return(c, -EINVAL);
742 assert_return(capability >= 0, -EINVAL);
744 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
747 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
751 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
758 max = DIV_ROUND_UP(cap_last_cap(), 32U);
759 p += strspn(p, WHITESPACE);
769 if (!c->capability) {
770 c->capability = new0(uint32_t, max * 4);
775 for (i = 0; i < sz; i ++) {
778 for (j = 0; j < 8; ++j) {
788 c->capability[offset * max + (sz - i - 1)] = v;
794 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
799 assert(c->allocated);
801 if (!(mask & SD_BUS_CREDS_AUGMENT))
804 /* Try to retrieve PID from creds if it wasn't passed to us */
807 c->mask |= SD_BUS_CREDS_PID;
808 } else if (c->mask & SD_BUS_CREDS_PID)
811 /* Without pid we cannot do much... */
814 /* Try to retrieve TID from creds if it wasn't passed to us */
815 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
818 /* Calculate what we shall and can add */
819 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);
825 c->mask |= SD_BUS_CREDS_TID;
828 if (missing & (SD_BUS_CREDS_PPID |
829 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
830 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
831 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
832 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
833 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
835 _cleanup_fclose_ FILE *f = NULL;
838 p = procfs_file_alloca(pid, "status");
844 else if (errno != EPERM && errno != EACCES)
849 FOREACH_LINE(line, f, return -errno) {
852 if (missing & SD_BUS_CREDS_PPID) {
853 p = startswith(line, "PPid:");
855 p += strspn(p, WHITESPACE);
857 /* Explicitly check for PPID 0 (which is the case for PID 1) */
858 if (!streq(p, "0")) {
859 r = parse_pid(p, &c->ppid);
866 c->mask |= SD_BUS_CREDS_PPID;
871 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
872 p = startswith(line, "Uid:");
874 unsigned long uid, euid, suid, fsuid;
876 p += strspn(p, WHITESPACE);
877 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
880 if (missing & SD_BUS_CREDS_UID)
881 c->uid = (uid_t) uid;
882 if (missing & SD_BUS_CREDS_EUID)
883 c->euid = (uid_t) euid;
884 if (missing & SD_BUS_CREDS_SUID)
885 c->suid = (uid_t) suid;
886 if (missing & SD_BUS_CREDS_FSUID)
887 c->fsuid = (uid_t) fsuid;
889 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
894 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
895 p = startswith(line, "Gid:");
897 unsigned long gid, egid, sgid, fsgid;
899 p += strspn(p, WHITESPACE);
900 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
903 if (missing & SD_BUS_CREDS_GID)
904 c->gid = (gid_t) gid;
905 if (missing & SD_BUS_CREDS_EGID)
906 c->egid = (gid_t) egid;
907 if (missing & SD_BUS_CREDS_SGID)
908 c->sgid = (gid_t) sgid;
909 if (missing & SD_BUS_CREDS_FSGID)
910 c->fsgid = (gid_t) fsgid;
912 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
917 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
918 p = startswith(line, "Groups:");
920 size_t allocated = 0;
926 p += strspn(p, WHITESPACE);
930 if (sscanf(p, "%lu%n", &g, &n) != 1)
933 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
936 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
940 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
945 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
946 p = startswith(line, "CapEff:");
948 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
952 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
957 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
958 p = startswith(line, "CapPrm:");
960 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
964 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
969 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
970 p = startswith(line, "CapInh:");
972 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
976 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
981 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
982 p = startswith(line, "CapBnd:");
984 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
988 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
996 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
999 p = procfs_file_alloca(pid, "attr/current");
1000 r = read_one_line_file(p, &c->label);
1002 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1005 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1008 if (missing & SD_BUS_CREDS_COMM) {
1009 r = get_process_comm(pid, &c->comm);
1011 if (r != -EPERM && r != -EACCES)
1014 c->mask |= SD_BUS_CREDS_COMM;
1017 if (missing & SD_BUS_CREDS_EXE) {
1018 r = get_process_exe(pid, &c->exe);
1020 /* Unfortunately we cannot really distinguish
1021 * the case here where the process does not
1022 * exist, and /proc/$PID/exe being unreadable
1023 * because $PID is a kernel thread. Hence,
1024 * assume it is a kernel thread, and rely on
1025 * that this case is caught with a later
1028 c->mask |= SD_BUS_CREDS_EXE;
1030 if (r != -EPERM && r != -EACCES)
1033 c->mask |= SD_BUS_CREDS_EXE;
1036 if (missing & SD_BUS_CREDS_CMDLINE) {
1039 p = procfs_file_alloca(pid, "cmdline");
1040 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1044 if (r != -EPERM && r != -EACCES)
1047 if (c->cmdline_size == 0)
1048 c->cmdline = mfree(c->cmdline);
1050 c->mask |= SD_BUS_CREDS_CMDLINE;
1054 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1055 _cleanup_free_ char *p = NULL;
1057 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1060 r = read_one_line_file(p, &c->tid_comm);
1064 if (r != -EPERM && r != -EACCES)
1067 c->mask |= SD_BUS_CREDS_TID_COMM;
1070 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)) {
1073 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1075 if (r != -EPERM && r != -EACCES)
1080 if (!c->cgroup_root) {
1081 r = cg_get_root_path(&c->cgroup_root);
1087 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);
1090 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1091 r = audit_session_from_pid(pid, &c->audit_session_id);
1092 if (r == -ENODATA) {
1093 /* ENODATA means: no audit session id assigned */
1094 c->audit_session_id = AUDIT_SESSION_INVALID;
1095 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1097 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1100 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1103 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1104 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1105 if (r == -ENODATA) {
1106 /* ENODATA means: no audit login uid assigned */
1107 c->audit_login_uid = UID_INVALID;
1108 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1110 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1113 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1116 if (missing & SD_BUS_CREDS_TTY) {
1117 r = get_ctty(pid, NULL, &c->tty);
1119 /* ENXIO means: process has no controlling TTY */
1121 c->mask |= SD_BUS_CREDS_TTY;
1123 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1126 c->mask |= SD_BUS_CREDS_TTY;
1129 /* In case only the exe path was to be read we cannot
1130 * distinguish the case where the exe path was unreadable
1131 * because the process was a kernel thread, or when the
1132 * process didn't exist at all. Hence, let's do a final check,
1134 if (!pid_is_alive(pid))
1137 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1140 c->augmented = missing & c->mask;
1145 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1146 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1152 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1153 /* There's already all data we need, or augmentation
1154 * wasn't turned on. */
1156 *ret = sd_bus_creds_ref(c);
1160 n = bus_creds_new();
1164 /* Copy the original data over */
1166 if (c->mask & mask & SD_BUS_CREDS_PID) {
1168 n->mask |= SD_BUS_CREDS_PID;
1171 if (c->mask & mask & SD_BUS_CREDS_TID) {
1173 n->mask |= SD_BUS_CREDS_TID;
1176 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1178 n->mask |= SD_BUS_CREDS_PPID;
1181 if (c->mask & mask & SD_BUS_CREDS_UID) {
1183 n->mask |= SD_BUS_CREDS_UID;
1186 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1188 n->mask |= SD_BUS_CREDS_EUID;
1191 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1193 n->mask |= SD_BUS_CREDS_SUID;
1196 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1197 n->fsuid = c->fsuid;
1198 n->mask |= SD_BUS_CREDS_FSUID;
1201 if (c->mask & mask & SD_BUS_CREDS_GID) {
1203 n->mask |= SD_BUS_CREDS_GID;
1206 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1208 n->mask |= SD_BUS_CREDS_EGID;
1211 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1213 n->mask |= SD_BUS_CREDS_SGID;
1216 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1217 n->fsgid = c->fsgid;
1218 n->mask |= SD_BUS_CREDS_FSGID;
1221 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1222 if (c->supplementary_gids) {
1223 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1224 if (!n->supplementary_gids)
1226 n->n_supplementary_gids = c->n_supplementary_gids;
1228 n->supplementary_gids = NULL;
1229 n->n_supplementary_gids = 0;
1232 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1235 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1238 n->comm = strdup(c->comm);
1242 n->mask |= SD_BUS_CREDS_COMM;
1245 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1246 assert(c->tid_comm);
1248 n->tid_comm = strdup(c->tid_comm);
1252 n->mask |= SD_BUS_CREDS_TID_COMM;
1255 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1257 n->exe = strdup(c->exe);
1263 n->mask |= SD_BUS_CREDS_EXE;
1266 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1268 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1272 n->cmdline_size = c->cmdline_size;
1275 n->cmdline_size = 0;
1278 n->mask |= SD_BUS_CREDS_CMDLINE;
1281 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)) {
1284 n->cgroup = strdup(c->cgroup);
1288 n->cgroup_root = strdup(c->cgroup_root);
1289 if (!n->cgroup_root)
1292 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);
1295 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1296 assert(c->capability);
1298 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1302 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);
1305 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1308 n->label = strdup(c->label);
1311 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1314 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1315 n->audit_session_id = c->audit_session_id;
1316 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1318 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1319 n->audit_login_uid = c->audit_login_uid;
1320 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1323 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1325 n->tty = strdup(c->tty);
1330 n->mask |= SD_BUS_CREDS_TTY;
1333 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1334 assert(c->unique_name);
1336 n->unique_name = strdup(c->unique_name);
1337 if (!n->unique_name)
1339 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1342 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1343 if (strv_isempty(c->well_known_names))
1344 n->well_known_names = NULL;
1346 n->well_known_names = strv_copy(c->well_known_names);
1347 if (!n->well_known_names)
1350 n->well_known_names_driver = c->well_known_names_driver;
1351 n->well_known_names_local = c->well_known_names_local;
1352 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1355 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1356 assert(c->description);
1357 n->description = strdup(c->description);
1358 if (!n->description)
1360 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1363 n->augmented = c->augmented & n->mask;
1367 r = bus_creds_add_more(n, mask, 0, 0);