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 c->supplementary_gids = mfree(c->supplementary_gids);
112 strv_free(c->well_known_names);
113 c->well_known_names = NULL;
122 m = container_of(c, sd_bus_message, creds);
123 sd_bus_message_unref(m);
130 /// UNNEEDED by elogind
132 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
139 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
145 sd_bus_creds* bus_creds_new(void) {
148 c = new0(sd_bus_creds, 1);
157 /// UNNEEDED by elogind
159 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
163 assert_return(pid >= 0, -EINVAL);
164 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
165 assert_return(ret, -EINVAL);
174 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
176 sd_bus_creds_unref(c);
180 /* Check if the process existed at all, in case we haven't
181 * figured that out already */
182 if (!pid_is_alive(pid)) {
183 sd_bus_creds_unref(c);
192 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
193 assert_return(c, -EINVAL);
194 assert_return(uid, -EINVAL);
196 if (!(c->mask & SD_BUS_CREDS_UID))
203 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
204 assert_return(c, -EINVAL);
205 assert_return(euid, -EINVAL);
207 if (!(c->mask & SD_BUS_CREDS_EUID))
214 /// UNNEEDED by elogind
216 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
217 assert_return(c, -EINVAL);
218 assert_return(suid, -EINVAL);
220 if (!(c->mask & SD_BUS_CREDS_SUID))
228 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
229 assert_return(c, -EINVAL);
230 assert_return(fsuid, -EINVAL);
232 if (!(c->mask & SD_BUS_CREDS_FSUID))
239 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
240 assert_return(c, -EINVAL);
241 assert_return(gid, -EINVAL);
243 if (!(c->mask & SD_BUS_CREDS_GID))
251 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
252 assert_return(c, -EINVAL);
253 assert_return(egid, -EINVAL);
255 if (!(c->mask & SD_BUS_CREDS_EGID))
262 /// UNNEEDED by elogind
264 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
265 assert_return(c, -EINVAL);
266 assert_return(sgid, -EINVAL);
268 if (!(c->mask & SD_BUS_CREDS_SGID))
275 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
276 assert_return(c, -EINVAL);
277 assert_return(fsgid, -EINVAL);
279 if (!(c->mask & SD_BUS_CREDS_FSGID))
286 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
287 assert_return(c, -EINVAL);
288 assert_return(gids, -EINVAL);
290 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
293 *gids = c->supplementary_gids;
294 return (int) c->n_supplementary_gids;
298 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
299 assert_return(c, -EINVAL);
300 assert_return(pid, -EINVAL);
302 if (!(c->mask & SD_BUS_CREDS_PID))
310 /// 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 /// UNNEEDED by elogind
355 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
356 assert_return(c, -EINVAL);
357 assert_return(ret, -EINVAL);
359 if (!(c->mask & SD_BUS_CREDS_COMM))
367 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
368 assert_return(c, -EINVAL);
369 assert_return(ret, -EINVAL);
371 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
379 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
380 assert_return(c, -EINVAL);
381 assert_return(ret, -EINVAL);
383 if (!(c->mask & SD_BUS_CREDS_EXE))
393 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
394 assert_return(c, -EINVAL);
395 assert_return(ret, -EINVAL);
397 if (!(c->mask & SD_BUS_CREDS_CGROUP))
405 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
408 assert_return(c, -EINVAL);
409 assert_return(ret, -EINVAL);
411 if (!(c->mask & SD_BUS_CREDS_UNIT))
419 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
423 r = cg_path_get_unit(shifted, (char**) &c->unit);
432 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
435 assert_return(c, -EINVAL);
436 assert_return(ret, -EINVAL);
438 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
446 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
450 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
459 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
462 assert_return(c, -EINVAL);
463 assert_return(ret, -EINVAL);
465 if (!(c->mask & SD_BUS_CREDS_SLICE))
473 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
477 r = cg_path_get_slice(shifted, (char**) &c->slice);
486 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
489 assert_return(c, -EINVAL);
490 assert_return(ret, -EINVAL);
492 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
497 if (!c->user_slice) {
500 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
504 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
509 *ret = c->user_slice;
514 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
517 assert_return(c, -EINVAL);
518 assert_return(ret, -EINVAL);
520 if (!(c->mask & SD_BUS_CREDS_SESSION))
528 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
529 c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
530 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
534 log_debug_elogind("Shifted: \"%s\"", shifted);
535 r = cg_path_get_session(shifted, (char**) &c->session);
544 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
548 assert_return(c, -EINVAL);
549 assert_return(uid, -EINVAL);
551 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
556 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
560 /// 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 /// UNNEEDED by elogind
632 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
633 assert_return(c, -EINVAL);
634 assert_return(unique_name, -EINVAL);
636 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
639 *unique_name = c->unique_name;
643 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
644 assert_return(c, -EINVAL);
645 assert_return(well_known_names, -EINVAL);
647 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
650 /* As a special hack we return the bus driver as well-known
651 * names list when this is requested. */
652 if (c->well_known_names_driver) {
653 static const char* const wkn[] = {
654 "org.freedesktop.DBus",
658 *well_known_names = (char**) wkn;
662 if (c->well_known_names_local) {
663 static const char* const wkn[] = {
664 "org.freedesktop.DBus.Local",
668 *well_known_names = (char**) wkn;
672 *well_known_names = c->well_known_names;
676 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
677 assert_return(c, -EINVAL);
678 assert_return(ret, -EINVAL);
680 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
683 assert(c->description);
685 if (!c->unescaped_description) {
686 c->unescaped_description = bus_label_unescape(c->description);
687 if (!c->unescaped_description)
691 *ret = c->unescaped_description;
696 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
700 assert(capability >= 0);
701 assert(c->capability);
703 if ((unsigned) capability > cap_last_cap())
706 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
708 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
711 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
712 assert_return(c, -EINVAL);
713 assert_return(capability >= 0, -EINVAL);
715 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
718 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
721 /// UNNEEDED by elogind
723 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
724 assert_return(c, -EINVAL);
725 assert_return(capability >= 0, -EINVAL);
727 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
730 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
733 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
734 assert_return(c, -EINVAL);
735 assert_return(capability >= 0, -EINVAL);
737 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
740 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
743 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
744 assert_return(c, -EINVAL);
745 assert_return(capability >= 0, -EINVAL);
747 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
750 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
754 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
761 max = DIV_ROUND_UP(cap_last_cap(), 32U);
762 p += strspn(p, WHITESPACE);
772 if (!c->capability) {
773 c->capability = new0(uint32_t, max * 4);
778 for (i = 0; i < sz; i ++) {
781 for (j = 0; j < 8; ++j) {
791 c->capability[offset * max + (sz - i - 1)] = v;
797 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
802 assert(c->allocated);
804 if (!(mask & SD_BUS_CREDS_AUGMENT))
807 /* Try to retrieve PID from creds if it wasn't passed to us */
810 c->mask |= SD_BUS_CREDS_PID;
811 } else if (c->mask & SD_BUS_CREDS_PID)
814 /* Without pid we cannot do much... */
817 /* Try to retrieve TID from creds if it wasn't passed to us */
818 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
821 /* Calculate what we shall and can add */
822 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);
828 c->mask |= SD_BUS_CREDS_TID;
831 if (missing & (SD_BUS_CREDS_PPID |
832 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
833 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
834 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
835 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
836 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
838 _cleanup_fclose_ FILE *f = NULL;
841 p = procfs_file_alloca(pid, "status");
847 else if (errno != EPERM && errno != EACCES)
852 FOREACH_LINE(line, f, return -errno) {
855 if (missing & SD_BUS_CREDS_PPID) {
856 p = startswith(line, "PPid:");
858 p += strspn(p, WHITESPACE);
860 /* Explicitly check for PPID 0 (which is the case for PID 1) */
861 if (!streq(p, "0")) {
862 r = parse_pid(p, &c->ppid);
869 c->mask |= SD_BUS_CREDS_PPID;
874 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
875 p = startswith(line, "Uid:");
877 unsigned long uid, euid, suid, fsuid;
879 p += strspn(p, WHITESPACE);
880 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
883 if (missing & SD_BUS_CREDS_UID)
884 c->uid = (uid_t) uid;
885 if (missing & SD_BUS_CREDS_EUID)
886 c->euid = (uid_t) euid;
887 if (missing & SD_BUS_CREDS_SUID)
888 c->suid = (uid_t) suid;
889 if (missing & SD_BUS_CREDS_FSUID)
890 c->fsuid = (uid_t) fsuid;
892 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
897 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
898 p = startswith(line, "Gid:");
900 unsigned long gid, egid, sgid, fsgid;
902 p += strspn(p, WHITESPACE);
903 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
906 if (missing & SD_BUS_CREDS_GID)
907 c->gid = (gid_t) gid;
908 if (missing & SD_BUS_CREDS_EGID)
909 c->egid = (gid_t) egid;
910 if (missing & SD_BUS_CREDS_SGID)
911 c->sgid = (gid_t) sgid;
912 if (missing & SD_BUS_CREDS_FSGID)
913 c->fsgid = (gid_t) fsgid;
915 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
920 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
921 p = startswith(line, "Groups:");
923 size_t allocated = 0;
929 p += strspn(p, WHITESPACE);
933 if (sscanf(p, "%lu%n", &g, &n) != 1)
936 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
939 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
943 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
948 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
949 p = startswith(line, "CapEff:");
951 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
955 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
960 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
961 p = startswith(line, "CapPrm:");
963 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
967 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
972 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
973 p = startswith(line, "CapInh:");
975 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
979 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
984 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
985 p = startswith(line, "CapBnd:");
987 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
991 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
999 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1002 p = procfs_file_alloca(pid, "attr/current");
1003 r = read_one_line_file(p, &c->label);
1005 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1008 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1011 if (missing & SD_BUS_CREDS_COMM) {
1012 r = get_process_comm(pid, &c->comm);
1014 if (r != -EPERM && r != -EACCES)
1017 c->mask |= SD_BUS_CREDS_COMM;
1020 if (missing & SD_BUS_CREDS_EXE) {
1021 r = get_process_exe(pid, &c->exe);
1023 /* Unfortunately we cannot really distinguish
1024 * the case here where the process does not
1025 * exist, and /proc/$PID/exe being unreadable
1026 * because $PID is a kernel thread. Hence,
1027 * assume it is a kernel thread, and rely on
1028 * that this case is caught with a later
1031 c->mask |= SD_BUS_CREDS_EXE;
1033 if (r != -EPERM && r != -EACCES)
1036 c->mask |= SD_BUS_CREDS_EXE;
1039 if (missing & SD_BUS_CREDS_CMDLINE) {
1042 p = procfs_file_alloca(pid, "cmdline");
1043 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1047 if (r != -EPERM && r != -EACCES)
1050 if (c->cmdline_size == 0) {
1051 c->cmdline = mfree(c->cmdline);
1054 c->mask |= SD_BUS_CREDS_CMDLINE;
1058 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1059 _cleanup_free_ char *p = NULL;
1061 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1064 r = read_one_line_file(p, &c->tid_comm);
1068 if (r != -EPERM && r != -EACCES)
1071 c->mask |= SD_BUS_CREDS_TID_COMM;
1074 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)) {
1077 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1079 if (r != -EPERM && r != -EACCES)
1084 if (!c->cgroup_root) {
1085 r = cg_get_root_path(&c->cgroup_root);
1091 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);
1094 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1095 r = audit_session_from_pid(pid, &c->audit_session_id);
1096 if (r == -ENODATA) {
1097 /* ENODATA means: no audit session id assigned */
1098 c->audit_session_id = AUDIT_SESSION_INVALID;
1099 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1101 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1104 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1107 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1108 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1109 if (r == -ENODATA) {
1110 /* ENODATA means: no audit login uid assigned */
1111 c->audit_login_uid = UID_INVALID;
1112 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1114 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1117 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1120 if (missing & SD_BUS_CREDS_TTY) {
1121 r = get_ctty(pid, NULL, &c->tty);
1123 /* ENXIO means: process has no controlling TTY */
1125 c->mask |= SD_BUS_CREDS_TTY;
1127 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1130 c->mask |= SD_BUS_CREDS_TTY;
1133 /* In case only the exe path was to be read we cannot
1134 * distinguish the case where the exe path was unreadable
1135 * because the process was a kernel thread, or when the
1136 * process didn't exist at all. Hence, let's do a final check,
1138 if (!pid_is_alive(pid))
1141 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1144 c->augmented = missing & c->mask;
1149 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1150 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1156 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1157 /* There's already all data we need, or augmentation
1158 * wasn't turned on. */
1160 *ret = sd_bus_creds_ref(c);
1164 n = bus_creds_new();
1168 /* Copy the original data over */
1170 if (c->mask & mask & SD_BUS_CREDS_PID) {
1172 n->mask |= SD_BUS_CREDS_PID;
1175 if (c->mask & mask & SD_BUS_CREDS_TID) {
1177 n->mask |= SD_BUS_CREDS_TID;
1180 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1182 n->mask |= SD_BUS_CREDS_PPID;
1185 if (c->mask & mask & SD_BUS_CREDS_UID) {
1187 n->mask |= SD_BUS_CREDS_UID;
1190 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1192 n->mask |= SD_BUS_CREDS_EUID;
1195 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1197 n->mask |= SD_BUS_CREDS_SUID;
1200 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1201 n->fsuid = c->fsuid;
1202 n->mask |= SD_BUS_CREDS_FSUID;
1205 if (c->mask & mask & SD_BUS_CREDS_GID) {
1207 n->mask |= SD_BUS_CREDS_GID;
1210 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1212 n->mask |= SD_BUS_CREDS_EGID;
1215 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1217 n->mask |= SD_BUS_CREDS_SGID;
1220 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1221 n->fsgid = c->fsgid;
1222 n->mask |= SD_BUS_CREDS_FSGID;
1225 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1226 if (c->supplementary_gids) {
1227 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1228 if (!n->supplementary_gids)
1230 n->n_supplementary_gids = c->n_supplementary_gids;
1232 n->supplementary_gids = NULL;
1233 n->n_supplementary_gids = 0;
1236 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1239 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1242 n->comm = strdup(c->comm);
1246 n->mask |= SD_BUS_CREDS_COMM;
1249 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1250 assert(c->tid_comm);
1252 n->tid_comm = strdup(c->tid_comm);
1256 n->mask |= SD_BUS_CREDS_TID_COMM;
1259 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1261 n->exe = strdup(c->exe);
1267 n->mask |= SD_BUS_CREDS_EXE;
1270 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1272 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1276 n->cmdline_size = c->cmdline_size;
1279 n->cmdline_size = 0;
1282 n->mask |= SD_BUS_CREDS_CMDLINE;
1285 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)) {
1288 n->cgroup = strdup(c->cgroup);
1292 n->cgroup_root = strdup(c->cgroup_root);
1293 if (!n->cgroup_root)
1296 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);
1299 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1300 assert(c->capability);
1302 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1306 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);
1309 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1312 n->label = strdup(c->label);
1315 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1318 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1319 n->audit_session_id = c->audit_session_id;
1320 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1322 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1323 n->audit_login_uid = c->audit_login_uid;
1324 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1327 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1329 n->tty = strdup(c->tty);
1334 n->mask |= SD_BUS_CREDS_TTY;
1337 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1338 assert(c->unique_name);
1340 n->unique_name = strdup(c->unique_name);
1341 if (!n->unique_name)
1343 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1346 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1347 if (strv_isempty(c->well_known_names))
1348 n->well_known_names = NULL;
1350 n->well_known_names = strv_copy(c->well_known_names);
1351 if (!n->well_known_names)
1354 n->well_known_names_driver = c->well_known_names_driver;
1355 n->well_known_names_local = c->well_known_names_local;
1356 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1359 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1360 assert(c->description);
1361 n->description = strdup(c->description);
1362 if (!n->description)
1364 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1367 n->augmented = c->augmented & n->mask;
1371 r = bus_creds_add_more(n, mask, 0, 0);