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 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
137 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
143 sd_bus_creds* bus_creds_new(void) {
146 c = new0(sd_bus_creds, 1);
155 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
159 assert_return(pid >= 0, -EINVAL);
160 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
161 assert_return(ret, -EINVAL);
170 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
172 sd_bus_creds_unref(c);
176 /* Check if the process existed at all, in case we haven't
177 * figured that out already */
178 if (!pid_is_alive(pid)) {
179 sd_bus_creds_unref(c);
187 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
188 assert_return(c, -EINVAL);
189 assert_return(uid, -EINVAL);
191 if (!(c->mask & SD_BUS_CREDS_UID))
198 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
199 assert_return(c, -EINVAL);
200 assert_return(euid, -EINVAL);
202 if (!(c->mask & SD_BUS_CREDS_EUID))
209 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
210 assert_return(c, -EINVAL);
211 assert_return(suid, -EINVAL);
213 if (!(c->mask & SD_BUS_CREDS_SUID))
221 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
222 assert_return(c, -EINVAL);
223 assert_return(fsuid, -EINVAL);
225 if (!(c->mask & SD_BUS_CREDS_FSUID))
232 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
233 assert_return(c, -EINVAL);
234 assert_return(gid, -EINVAL);
236 if (!(c->mask & SD_BUS_CREDS_GID))
243 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
244 assert_return(c, -EINVAL);
245 assert_return(egid, -EINVAL);
247 if (!(c->mask & SD_BUS_CREDS_EGID))
254 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
255 assert_return(c, -EINVAL);
256 assert_return(sgid, -EINVAL);
258 if (!(c->mask & SD_BUS_CREDS_SGID))
265 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
266 assert_return(c, -EINVAL);
267 assert_return(fsgid, -EINVAL);
269 if (!(c->mask & SD_BUS_CREDS_FSGID))
276 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
277 assert_return(c, -EINVAL);
278 assert_return(gids, -EINVAL);
280 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
283 *gids = c->supplementary_gids;
284 return (int) c->n_supplementary_gids;
287 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
288 assert_return(c, -EINVAL);
289 assert_return(pid, -EINVAL);
291 if (!(c->mask & SD_BUS_CREDS_PID))
299 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
300 assert_return(c, -EINVAL);
301 assert_return(ppid, -EINVAL);
303 if (!(c->mask & SD_BUS_CREDS_PPID))
306 /* PID 1 has no parent process. Let's distuingish the case of
307 * not knowing and not having a parent process by the returned
316 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
317 assert_return(c, -EINVAL);
318 assert_return(tid, -EINVAL);
320 if (!(c->mask & SD_BUS_CREDS_TID))
328 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
329 assert_return(c, -EINVAL);
331 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
339 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
340 assert_return(c, -EINVAL);
341 assert_return(ret, -EINVAL);
343 if (!(c->mask & SD_BUS_CREDS_COMM))
351 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
352 assert_return(c, -EINVAL);
353 assert_return(ret, -EINVAL);
355 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
363 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
364 assert_return(c, -EINVAL);
365 assert_return(ret, -EINVAL);
367 if (!(c->mask & SD_BUS_CREDS_EXE))
377 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
378 assert_return(c, -EINVAL);
379 assert_return(ret, -EINVAL);
381 if (!(c->mask & SD_BUS_CREDS_CGROUP))
389 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
390 assert_return(c, -EINVAL);
391 assert_return(ret, -EINVAL);
393 if (!(c->mask & SD_BUS_CREDS_UNIT))
405 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
406 assert_return(c, -EINVAL);
407 assert_return(ret, -EINVAL);
409 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
421 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
422 assert_return(c, -EINVAL);
423 assert_return(ret, -EINVAL);
425 if (!(c->mask & SD_BUS_CREDS_SLICE))
437 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
440 assert_return(c, -EINVAL);
441 assert_return(ret, -EINVAL);
443 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
448 if (!c->user_slice) {
451 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
455 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
460 *ret = c->user_slice;
464 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
467 assert_return(c, -EINVAL);
468 assert_return(ret, -EINVAL);
470 if (!(c->mask & SD_BUS_CREDS_SESSION))
478 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
482 r = cg_path_get_session(shifted, (char**) &c->session);
491 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
495 assert_return(c, -EINVAL);
496 assert_return(uid, -EINVAL);
498 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
503 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
510 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
511 assert_return(c, -EINVAL);
513 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
519 if (!c->cmdline_array) {
520 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
521 if (!c->cmdline_array)
525 *cmdline = c->cmdline_array;
529 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
530 assert_return(c, -EINVAL);
531 assert_return(sessionid, -EINVAL);
533 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
536 if (c->audit_session_id == AUDIT_SESSION_INVALID)
539 *sessionid = c->audit_session_id;
543 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
544 assert_return(c, -EINVAL);
545 assert_return(uid, -EINVAL);
547 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
550 if (c->audit_login_uid == UID_INVALID)
553 *uid = c->audit_login_uid;
557 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
558 assert_return(c, -EINVAL);
559 assert_return(ret, -EINVAL);
561 if (!(c->mask & SD_BUS_CREDS_TTY))
571 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
572 assert_return(c, -EINVAL);
573 assert_return(unique_name, -EINVAL);
575 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
578 *unique_name = c->unique_name;
582 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
583 assert_return(c, -EINVAL);
584 assert_return(well_known_names, -EINVAL);
586 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
589 /* As a special hack we return the bus driver as well-known
590 * names list when this is requested. */
591 if (c->well_known_names_driver) {
592 static const char* const wkn[] = {
593 "org.freedesktop.DBus",
597 *well_known_names = (char**) wkn;
601 if (c->well_known_names_local) {
602 static const char* const wkn[] = {
603 "org.freedesktop.DBus.Local",
607 *well_known_names = (char**) wkn;
611 *well_known_names = c->well_known_names;
615 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
616 assert_return(c, -EINVAL);
617 assert_return(ret, -EINVAL);
619 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
622 assert(c->description);
624 if (!c->unescaped_description) {
625 c->unescaped_description = bus_label_unescape(c->description);
626 if (!c->unescaped_description)
630 *ret = c->unescaped_description;
634 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
638 assert(capability >= 0);
639 assert(c->capability);
641 if ((unsigned) capability > cap_last_cap())
644 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
646 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
649 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
650 assert_return(c, -EINVAL);
651 assert_return(capability >= 0, -EINVAL);
653 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
656 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
659 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
660 assert_return(c, -EINVAL);
661 assert_return(capability >= 0, -EINVAL);
663 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
666 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
669 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
670 assert_return(c, -EINVAL);
671 assert_return(capability >= 0, -EINVAL);
673 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
676 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
679 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
680 assert_return(c, -EINVAL);
681 assert_return(capability >= 0, -EINVAL);
683 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
686 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
689 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
696 max = DIV_ROUND_UP(cap_last_cap(), 32U);
697 p += strspn(p, WHITESPACE);
707 if (!c->capability) {
708 c->capability = new0(uint32_t, max * 4);
713 for (i = 0; i < sz; i ++) {
716 for (j = 0; j < 8; ++j) {
726 c->capability[offset * max + (sz - i - 1)] = v;
732 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
737 assert(c->allocated);
739 if (!(mask & SD_BUS_CREDS_AUGMENT))
742 /* Try to retrieve PID from creds if it wasn't passed to us */
743 if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID))
746 /* Without pid we cannot do much... */
750 /* Try to retrieve TID from creds if it wasn't passed to us */
751 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
754 /* Calculate what we shall and can add */
755 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);
760 c->mask |= SD_BUS_CREDS_PID;
764 c->mask |= SD_BUS_CREDS_TID;
767 if (missing & (SD_BUS_CREDS_PPID |
768 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
769 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
770 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
771 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
772 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
774 _cleanup_fclose_ FILE *f = NULL;
777 p = procfs_file_alloca(pid, "status");
783 else if (errno != EPERM && errno != EACCES)
788 FOREACH_LINE(line, f, return -errno) {
791 if (missing & SD_BUS_CREDS_PPID) {
792 p = startswith(line, "PPid:");
794 p += strspn(p, WHITESPACE);
796 /* Explicitly check for PPID 0 (which is the case for PID 1) */
797 if (!streq(p, "0")) {
798 r = parse_pid(p, &c->ppid);
805 c->mask |= SD_BUS_CREDS_PPID;
810 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
811 p = startswith(line, "Uid:");
813 unsigned long uid, euid, suid, fsuid;
815 p += strspn(p, WHITESPACE);
816 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
819 if (missing & SD_BUS_CREDS_UID)
820 c->uid = (uid_t) uid;
821 if (missing & SD_BUS_CREDS_EUID)
822 c->euid = (uid_t) euid;
823 if (missing & SD_BUS_CREDS_SUID)
824 c->suid = (uid_t) suid;
825 if (missing & SD_BUS_CREDS_FSUID)
826 c->fsuid = (uid_t) fsuid;
828 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
833 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
834 p = startswith(line, "Gid:");
836 unsigned long gid, egid, sgid, fsgid;
838 p += strspn(p, WHITESPACE);
839 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
842 if (missing & SD_BUS_CREDS_GID)
843 c->gid = (gid_t) gid;
844 if (missing & SD_BUS_CREDS_EGID)
845 c->egid = (gid_t) egid;
846 if (missing & SD_BUS_CREDS_SGID)
847 c->sgid = (gid_t) sgid;
848 if (missing & SD_BUS_CREDS_FSGID)
849 c->fsgid = (gid_t) fsgid;
851 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
856 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
857 p = startswith(line, "Groups:");
859 size_t allocated = 0;
865 p += strspn(p, WHITESPACE);
869 if (sscanf(p, "%lu%n", &g, &n) != 1)
872 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
875 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
879 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
884 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
885 p = startswith(line, "CapEff:");
887 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
891 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
896 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
897 p = startswith(line, "CapPrm:");
899 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
903 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
908 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
909 p = startswith(line, "CapInh:");
911 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
915 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
920 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
921 p = startswith(line, "CapBnd:");
923 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
927 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
935 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
938 p = procfs_file_alloca(pid, "attr/current");
939 r = read_one_line_file(p, &c->label);
941 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
944 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
947 if (missing & SD_BUS_CREDS_COMM) {
948 r = get_process_comm(pid, &c->comm);
950 if (r != -EPERM && r != -EACCES)
953 c->mask |= SD_BUS_CREDS_COMM;
956 if (missing & SD_BUS_CREDS_EXE) {
957 r = get_process_exe(pid, &c->exe);
959 /* Unfortunately we cannot really distuingish
960 * the case here where the process does not
961 * exist, and /proc/$PID/exe being unreadable
962 * because $PID is a kernel thread. Hence,
963 * assume it is a kernel thread, and rely on
964 * that this case is caught with a later
967 c->mask |= SD_BUS_CREDS_EXE;
969 if (r != -EPERM && r != -EACCES)
972 c->mask |= SD_BUS_CREDS_EXE;
975 if (missing & SD_BUS_CREDS_CMDLINE) {
978 p = procfs_file_alloca(pid, "cmdline");
979 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
983 if (r != -EPERM && r != -EACCES)
986 if (c->cmdline_size == 0) {
991 c->mask |= SD_BUS_CREDS_CMDLINE;
995 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
996 _cleanup_free_ char *p = NULL;
998 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1001 r = read_one_line_file(p, &c->tid_comm);
1005 if (r != -EPERM && r != -EACCES)
1008 c->mask |= SD_BUS_CREDS_TID_COMM;
1011 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)) {
1014 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1016 if (r != -EPERM && r != -EACCES)
1021 if (!c->cgroup_root) {
1022 r = cg_get_root_path(&c->cgroup_root);
1028 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);
1031 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1032 r = audit_session_from_pid(pid, &c->audit_session_id);
1034 /* ENXIO means: no audit session id assigned */
1035 c->audit_session_id = AUDIT_SESSION_INVALID;
1036 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1038 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1041 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1044 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1045 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1047 /* ENXIO means: no audit login uid assigned */
1048 c->audit_login_uid = UID_INVALID;
1049 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1051 if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1054 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1057 if (missing & SD_BUS_CREDS_TTY) {
1058 r = get_ctty(pid, NULL, &c->tty);
1060 /* ENXIO means: process has no controlling TTY */
1062 c->mask |= SD_BUS_CREDS_TTY;
1064 if (r != -EPERM && r != -EACCES && r != -ENOENT)
1067 c->mask |= SD_BUS_CREDS_TTY;
1070 /* In case only the exe path was to be read we cannot
1071 * distuingish the case where the exe path was unreadable
1072 * because the process was a kernel thread, or when the
1073 * process didn't exist at all. Hence, let's do a final check,
1075 if (!pid_is_alive(pid))
1078 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1081 c->augmented = missing & c->mask;
1086 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1087 _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1093 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1094 /* There's already all data we need, or augmentation
1095 * wasn't turned on. */
1097 *ret = sd_bus_creds_ref(c);
1101 n = bus_creds_new();
1105 /* Copy the original data over */
1107 if (c->mask & mask & SD_BUS_CREDS_PID) {
1109 n->mask |= SD_BUS_CREDS_PID;
1112 if (c->mask & mask & SD_BUS_CREDS_TID) {
1114 n->mask |= SD_BUS_CREDS_TID;
1117 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1119 n->mask |= SD_BUS_CREDS_PPID;
1122 if (c->mask & mask & SD_BUS_CREDS_UID) {
1124 n->mask |= SD_BUS_CREDS_UID;
1127 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1129 n->mask |= SD_BUS_CREDS_EUID;
1132 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1134 n->mask |= SD_BUS_CREDS_SUID;
1137 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1138 n->fsuid = c->fsuid;
1139 n->mask |= SD_BUS_CREDS_FSUID;
1142 if (c->mask & mask & SD_BUS_CREDS_GID) {
1144 n->mask |= SD_BUS_CREDS_GID;
1147 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1149 n->mask |= SD_BUS_CREDS_EGID;
1152 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1154 n->mask |= SD_BUS_CREDS_SGID;
1157 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1158 n->fsgid = c->fsgid;
1159 n->mask |= SD_BUS_CREDS_FSGID;
1162 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1163 if (c->supplementary_gids) {
1164 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1165 if (!n->supplementary_gids)
1167 n->n_supplementary_gids = c->n_supplementary_gids;
1169 n->supplementary_gids = NULL;
1170 n->n_supplementary_gids = 0;
1173 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1176 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1179 n->comm = strdup(c->comm);
1183 n->mask |= SD_BUS_CREDS_COMM;
1186 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1187 assert(c->tid_comm);
1189 n->tid_comm = strdup(c->tid_comm);
1193 n->mask |= SD_BUS_CREDS_TID_COMM;
1196 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1198 n->exe = strdup(c->exe);
1204 n->mask |= SD_BUS_CREDS_EXE;
1207 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1209 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1213 n->cmdline_size = c->cmdline_size;
1216 n->cmdline_size = 0;
1219 n->mask |= SD_BUS_CREDS_CMDLINE;
1222 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)) {
1225 n->cgroup = strdup(c->cgroup);
1229 n->cgroup_root = strdup(c->cgroup_root);
1230 if (!n->cgroup_root)
1233 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);
1236 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1237 assert(c->capability);
1239 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1243 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);
1246 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1249 n->label = strdup(c->label);
1252 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1255 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1256 n->audit_session_id = c->audit_session_id;
1257 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1259 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1260 n->audit_login_uid = c->audit_login_uid;
1261 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1264 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1266 n->tty = strdup(c->tty);
1271 n->mask |= SD_BUS_CREDS_TTY;
1274 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1275 assert(c->unique_name);
1277 n->unique_name = strdup(c->unique_name);
1278 if (!n->unique_name)
1280 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1283 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1284 if (strv_isempty(c->well_known_names))
1285 n->well_known_names = NULL;
1287 n->well_known_names = strv_copy(c->well_known_names);
1288 if (!n->well_known_names)
1291 n->well_known_names_driver = c->well_known_names_driver;
1292 n->well_known_names_local = c->well_known_names_local;
1293 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1296 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1297 assert(c->description);
1298 n->description = strdup(c->description);
1299 if (!n->description)
1301 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1304 n->augmented = c->augmented & n->mask;
1308 r = bus_creds_add_more(n, mask, 0, 0);