1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
8 #include <linux/capability.h>
11 #include "alloc-util.h"
12 #include "audit-util.h"
13 #include "bus-creds.h"
14 #include "bus-label.h"
15 #include "bus-message.h"
17 #include "capability-util.h"
18 #include "cgroup-util.h"
21 #include "format-util.h"
22 #include "hexdecoct.h"
23 #include "parse-util.h"
24 #include "process-util.h"
25 #include "string-util.h"
27 #include "terminal-util.h"
28 #include "user-util.h"
32 CAP_OFFSET_INHERITABLE
= 0,
33 CAP_OFFSET_PERMITTED
= 1,
34 CAP_OFFSET_EFFECTIVE
= 2,
35 CAP_OFFSET_BOUNDING
= 3
38 void bus_creds_done(sd_bus_creds
*c
) {
41 /* For internal bus cred structures that are allocated by
49 free(c
->unescaped_description
);
50 free(c
->supplementary_gids
);
53 free(c
->well_known_names
); /* note that this is an strv, but
54 * we only free the array, not the
55 * strings the array points to. The
56 * full strv we only free if
57 * c->allocated is set, see
60 strv_free(c
->cmdline_array
);
63 _public_ sd_bus_creds
*sd_bus_creds_ref(sd_bus_creds
*c
) {
74 /* If this is an embedded creds structure, then
75 * forward ref counting to the message */
76 m
= container_of(c
, sd_bus_message
, creds
);
77 sd_bus_message_ref(m
);
83 _public_ sd_bus_creds
*sd_bus_creds_unref(sd_bus_creds
*c
) {
100 free(c
->unique_name
);
101 free(c
->cgroup_root
);
102 free(c
->description
);
104 c
->supplementary_gids
= mfree(c
->supplementary_gids
);
106 c
->well_known_names
= strv_free(c
->well_known_names
);
115 m
= container_of(c
, sd_bus_message
, creds
);
116 sd_bus_message_unref(m
);
123 _public_
uint64_t sd_bus_creds_get_mask(const sd_bus_creds
*c
) {
129 _public_
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds
*c
) {
135 sd_bus_creds
* bus_creds_new(void) {
138 c
= new0(sd_bus_creds
, 1);
147 _public_
int sd_bus_creds_new_from_pid(sd_bus_creds
**ret
, pid_t pid
, uint64_t mask
) {
151 assert_return(pid
>= 0, -EINVAL
);
152 assert_return(mask
<= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
153 assert_return(ret
, -EINVAL
);
156 pid
= getpid_cached();
162 r
= bus_creds_add_more(c
, mask
| SD_BUS_CREDS_AUGMENT
, pid
, 0);
164 sd_bus_creds_unref(c
);
168 /* Check if the process existed at all, in case we haven't
169 * figured that out already */
170 if (!pid_is_alive(pid
)) {
171 sd_bus_creds_unref(c
);
179 _public_
int sd_bus_creds_get_uid(sd_bus_creds
*c
, uid_t
*uid
) {
180 assert_return(c
, -EINVAL
);
181 assert_return(uid
, -EINVAL
);
183 if (!(c
->mask
& SD_BUS_CREDS_UID
))
190 _public_
int sd_bus_creds_get_euid(sd_bus_creds
*c
, uid_t
*euid
) {
191 assert_return(c
, -EINVAL
);
192 assert_return(euid
, -EINVAL
);
194 if (!(c
->mask
& SD_BUS_CREDS_EUID
))
201 _public_
int sd_bus_creds_get_suid(sd_bus_creds
*c
, uid_t
*suid
) {
202 assert_return(c
, -EINVAL
);
203 assert_return(suid
, -EINVAL
);
205 if (!(c
->mask
& SD_BUS_CREDS_SUID
))
213 _public_
int sd_bus_creds_get_fsuid(sd_bus_creds
*c
, uid_t
*fsuid
) {
214 assert_return(c
, -EINVAL
);
215 assert_return(fsuid
, -EINVAL
);
217 if (!(c
->mask
& SD_BUS_CREDS_FSUID
))
224 _public_
int sd_bus_creds_get_gid(sd_bus_creds
*c
, gid_t
*gid
) {
225 assert_return(c
, -EINVAL
);
226 assert_return(gid
, -EINVAL
);
228 if (!(c
->mask
& SD_BUS_CREDS_GID
))
235 _public_
int sd_bus_creds_get_egid(sd_bus_creds
*c
, gid_t
*egid
) {
236 assert_return(c
, -EINVAL
);
237 assert_return(egid
, -EINVAL
);
239 if (!(c
->mask
& SD_BUS_CREDS_EGID
))
246 _public_
int sd_bus_creds_get_sgid(sd_bus_creds
*c
, gid_t
*sgid
) {
247 assert_return(c
, -EINVAL
);
248 assert_return(sgid
, -EINVAL
);
250 if (!(c
->mask
& SD_BUS_CREDS_SGID
))
257 _public_
int sd_bus_creds_get_fsgid(sd_bus_creds
*c
, gid_t
*fsgid
) {
258 assert_return(c
, -EINVAL
);
259 assert_return(fsgid
, -EINVAL
);
261 if (!(c
->mask
& SD_BUS_CREDS_FSGID
))
268 _public_
int sd_bus_creds_get_supplementary_gids(sd_bus_creds
*c
, const gid_t
**gids
) {
269 assert_return(c
, -EINVAL
);
270 assert_return(gids
, -EINVAL
);
272 if (!(c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
))
275 *gids
= c
->supplementary_gids
;
276 return (int) c
->n_supplementary_gids
;
279 _public_
int sd_bus_creds_get_pid(sd_bus_creds
*c
, pid_t
*pid
) {
280 assert_return(c
, -EINVAL
);
281 assert_return(pid
, -EINVAL
);
283 if (!(c
->mask
& SD_BUS_CREDS_PID
))
291 _public_
int sd_bus_creds_get_ppid(sd_bus_creds
*c
, pid_t
*ppid
) {
292 assert_return(c
, -EINVAL
);
293 assert_return(ppid
, -EINVAL
);
295 if (!(c
->mask
& SD_BUS_CREDS_PPID
))
298 /* PID 1 has no parent process. Let's distinguish the case of
299 * not knowing and not having a parent process by the returned
308 _public_
int sd_bus_creds_get_tid(sd_bus_creds
*c
, pid_t
*tid
) {
309 assert_return(c
, -EINVAL
);
310 assert_return(tid
, -EINVAL
);
312 if (!(c
->mask
& SD_BUS_CREDS_TID
))
320 _public_
int sd_bus_creds_get_selinux_context(sd_bus_creds
*c
, const char **ret
) {
321 assert_return(c
, -EINVAL
);
323 if (!(c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
))
331 _public_
int sd_bus_creds_get_comm(sd_bus_creds
*c
, const char **ret
) {
332 assert_return(c
, -EINVAL
);
333 assert_return(ret
, -EINVAL
);
335 if (!(c
->mask
& SD_BUS_CREDS_COMM
))
343 _public_
int sd_bus_creds_get_tid_comm(sd_bus_creds
*c
, const char **ret
) {
344 assert_return(c
, -EINVAL
);
345 assert_return(ret
, -EINVAL
);
347 if (!(c
->mask
& SD_BUS_CREDS_TID_COMM
))
355 _public_
int sd_bus_creds_get_exe(sd_bus_creds
*c
, const char **ret
) {
356 assert_return(c
, -EINVAL
);
357 assert_return(ret
, -EINVAL
);
359 if (!(c
->mask
& SD_BUS_CREDS_EXE
))
369 _public_
int sd_bus_creds_get_cgroup(sd_bus_creds
*c
, const char **ret
) {
370 assert_return(c
, -EINVAL
);
371 assert_return(ret
, -EINVAL
);
373 if (!(c
->mask
& SD_BUS_CREDS_CGROUP
))
381 _public_
int sd_bus_creds_get_unit(sd_bus_creds
*c
, const char **ret
) {
384 assert_return(c
, -EINVAL
);
385 assert_return(ret
, -EINVAL
);
387 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
395 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
399 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
408 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
411 assert_return(c
, -EINVAL
);
412 assert_return(ret
, -EINVAL
);
414 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
422 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
426 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
435 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
438 assert_return(c
, -EINVAL
);
439 assert_return(ret
, -EINVAL
);
441 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
449 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
453 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
462 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
465 assert_return(c
, -EINVAL
);
466 assert_return(ret
, -EINVAL
);
468 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
473 if (!c
->user_slice
) {
476 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
480 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
485 *ret
= c
->user_slice
;
489 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
492 assert_return(c
, -EINVAL
);
493 assert_return(ret
, -EINVAL
);
495 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
503 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
507 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
516 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
520 assert_return(c
, -EINVAL
);
521 assert_return(uid
, -EINVAL
);
523 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
528 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
532 return cg_path_get_owner_uid(shifted
, uid
);
535 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
536 assert_return(c
, -EINVAL
);
538 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
544 if (!c
->cmdline_array
) {
545 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
546 if (!c
->cmdline_array
)
550 *cmdline
= c
->cmdline_array
;
554 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
555 assert_return(c
, -EINVAL
);
556 assert_return(sessionid
, -EINVAL
);
558 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
561 if (!audit_session_is_valid(c
->audit_session_id
))
564 *sessionid
= c
->audit_session_id
;
568 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
569 assert_return(c
, -EINVAL
);
570 assert_return(uid
, -EINVAL
);
572 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
575 if (!uid_is_valid(c
->audit_login_uid
))
578 *uid
= c
->audit_login_uid
;
582 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
583 assert_return(c
, -EINVAL
);
584 assert_return(ret
, -EINVAL
);
586 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
596 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
597 assert_return(c
, -EINVAL
);
598 assert_return(unique_name
, -EINVAL
);
600 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
603 *unique_name
= c
->unique_name
;
607 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
608 assert_return(c
, -EINVAL
);
609 assert_return(well_known_names
, -EINVAL
);
611 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
614 /* As a special hack we return the bus driver as well-known
615 * names list when this is requested. */
616 if (c
->well_known_names_driver
) {
617 static const char* const wkn
[] = {
618 "org.freedesktop.DBus",
622 *well_known_names
= (char**) wkn
;
626 if (c
->well_known_names_local
) {
627 static const char* const wkn
[] = {
628 "org.freedesktop.DBus.Local",
632 *well_known_names
= (char**) wkn
;
636 *well_known_names
= c
->well_known_names
;
640 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
641 assert_return(c
, -EINVAL
);
642 assert_return(ret
, -EINVAL
);
644 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
647 assert(c
->description
);
649 if (!c
->unescaped_description
) {
650 c
->unescaped_description
= bus_label_unescape(c
->description
);
651 if (!c
->unescaped_description
)
655 *ret
= c
->unescaped_description
;
659 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
663 assert(capability
>= 0);
664 assert(c
->capability
);
666 if ((unsigned) capability
> cap_last_cap())
669 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
671 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
674 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
675 assert_return(c
, -EINVAL
);
676 assert_return(capability
>= 0, -EINVAL
);
678 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
681 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
684 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
685 assert_return(c
, -EINVAL
);
686 assert_return(capability
>= 0, -EINVAL
);
688 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
691 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
694 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
695 assert_return(c
, -EINVAL
);
696 assert_return(capability
>= 0, -EINVAL
);
698 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
701 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
704 _public_
int sd_bus_creds_has_bounding_cap(sd_bus_creds
*c
, int capability
) {
705 assert_return(c
, -EINVAL
);
706 assert_return(capability
>= 0, -EINVAL
);
708 if (!(c
->mask
& SD_BUS_CREDS_BOUNDING_CAPS
))
711 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
714 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
721 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
722 p
+= strspn(p
, WHITESPACE
);
732 if (!c
->capability
) {
733 c
->capability
= new0(uint32_t, max
* 4);
738 for (i
= 0; i
< sz
; i
++) {
741 for (j
= 0; j
< 8; ++j
) {
751 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
757 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
762 assert(c
->allocated
);
764 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
767 /* Try to retrieve PID from creds if it wasn't passed to us */
770 c
->mask
|= SD_BUS_CREDS_PID
;
771 } else if (c
->mask
& SD_BUS_CREDS_PID
)
774 /* Without pid we cannot do much... */
777 /* Try to retrieve TID from creds if it wasn't passed to us */
778 if (tid
<= 0 && (c
->mask
& SD_BUS_CREDS_TID
))
781 /* Calculate what we shall and can add */
782 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
);
788 c
->mask
|= SD_BUS_CREDS_TID
;
791 if (missing
& (SD_BUS_CREDS_PPID
|
792 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
793 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
794 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
795 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
796 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
798 _cleanup_fclose_
FILE *f
= NULL
;
801 p
= procfs_file_alloca(pid
, "status");
807 else if (!IN_SET(errno
, EPERM
, EACCES
))
812 FOREACH_LINE(line
, f
, return -errno
) {
815 if (missing
& SD_BUS_CREDS_PPID
) {
816 p
= startswith(line
, "PPid:");
818 p
+= strspn(p
, WHITESPACE
);
820 /* Explicitly check for PPID 0 (which is the case for PID 1) */
821 if (!streq(p
, "0")) {
822 r
= parse_pid(p
, &c
->ppid
);
829 c
->mask
|= SD_BUS_CREDS_PPID
;
834 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
835 p
= startswith(line
, "Uid:");
837 unsigned long uid
, euid
, suid
, fsuid
;
839 p
+= strspn(p
, WHITESPACE
);
840 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
843 if (missing
& SD_BUS_CREDS_UID
)
844 c
->uid
= (uid_t
) uid
;
845 if (missing
& SD_BUS_CREDS_EUID
)
846 c
->euid
= (uid_t
) euid
;
847 if (missing
& SD_BUS_CREDS_SUID
)
848 c
->suid
= (uid_t
) suid
;
849 if (missing
& SD_BUS_CREDS_FSUID
)
850 c
->fsuid
= (uid_t
) fsuid
;
852 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
857 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
858 p
= startswith(line
, "Gid:");
860 unsigned long gid
, egid
, sgid
, fsgid
;
862 p
+= strspn(p
, WHITESPACE
);
863 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
866 if (missing
& SD_BUS_CREDS_GID
)
867 c
->gid
= (gid_t
) gid
;
868 if (missing
& SD_BUS_CREDS_EGID
)
869 c
->egid
= (gid_t
) egid
;
870 if (missing
& SD_BUS_CREDS_SGID
)
871 c
->sgid
= (gid_t
) sgid
;
872 if (missing
& SD_BUS_CREDS_FSGID
)
873 c
->fsgid
= (gid_t
) fsgid
;
875 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
880 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
881 p
= startswith(line
, "Groups:");
883 size_t allocated
= 0;
889 p
+= strspn(p
, WHITESPACE
);
893 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
896 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
899 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
903 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
908 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
909 p
= startswith(line
, "CapEff:");
911 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
915 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
920 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
921 p
= startswith(line
, "CapPrm:");
923 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
927 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
932 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
933 p
= startswith(line
, "CapInh:");
935 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
939 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
944 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
945 p
= startswith(line
, "CapBnd:");
947 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
951 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
959 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
962 p
= procfs_file_alloca(pid
, "attr/current");
963 r
= read_one_line_file(p
, &c
->label
);
965 if (!IN_SET(r
, -ENOENT
, -EINVAL
, -EPERM
, -EACCES
))
968 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
971 if (missing
& SD_BUS_CREDS_COMM
) {
972 r
= get_process_comm(pid
, &c
->comm
);
974 if (!IN_SET(r
, -EPERM
, -EACCES
))
977 c
->mask
|= SD_BUS_CREDS_COMM
;
980 if (missing
& SD_BUS_CREDS_EXE
) {
981 r
= get_process_exe(pid
, &c
->exe
);
983 /* Unfortunately we cannot really distinguish
984 * the case here where the process does not
985 * exist, and /proc/$PID/exe being unreadable
986 * because $PID is a kernel thread. Hence,
987 * assume it is a kernel thread, and rely on
988 * that this case is caught with a later
991 c
->mask
|= SD_BUS_CREDS_EXE
;
993 if (!IN_SET(r
, -EPERM
, -EACCES
))
996 c
->mask
|= SD_BUS_CREDS_EXE
;
999 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1002 p
= procfs_file_alloca(pid
, "cmdline");
1003 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1007 if (!IN_SET(r
, -EPERM
, -EACCES
))
1010 if (c
->cmdline_size
== 0)
1011 c
->cmdline
= mfree(c
->cmdline
);
1013 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1017 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1018 _cleanup_free_
char *p
= NULL
;
1020 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1023 r
= read_one_line_file(p
, &c
->tid_comm
);
1027 if (!IN_SET(r
, -EPERM
, -EACCES
))
1030 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1033 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
)) {
1036 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1038 if (!IN_SET(r
, -EPERM
, -EACCES
))
1043 if (!c
->cgroup_root
) {
1044 r
= cg_get_root_path(&c
->cgroup_root
);
1050 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
);
1053 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1054 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1055 if (r
== -ENODATA
) {
1056 /* ENODATA means: no audit session id assigned */
1057 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1058 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1060 if (!IN_SET(r
, -EOPNOTSUPP
, -ENOENT
, -EPERM
, -EACCES
))
1063 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1066 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1067 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1068 if (r
== -ENODATA
) {
1069 /* ENODATA means: no audit login uid assigned */
1070 c
->audit_login_uid
= UID_INVALID
;
1071 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1073 if (!IN_SET(r
, -EOPNOTSUPP
, -ENOENT
, -EPERM
, -EACCES
))
1076 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1079 if (missing
& SD_BUS_CREDS_TTY
) {
1080 r
= get_ctty(pid
, NULL
, &c
->tty
);
1082 /* ENXIO means: process has no controlling TTY */
1084 c
->mask
|= SD_BUS_CREDS_TTY
;
1086 if (!IN_SET(r
, -EPERM
, -EACCES
, -ENOENT
))
1089 c
->mask
|= SD_BUS_CREDS_TTY
;
1092 /* In case only the exe path was to be read we cannot
1093 * distinguish the case where the exe path was unreadable
1094 * because the process was a kernel thread, or when the
1095 * process didn't exist at all. Hence, let's do a final check,
1097 if (!pid_is_alive(pid
))
1100 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1103 c
->augmented
= missing
& c
->mask
;
1108 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1109 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*n
= NULL
;
1115 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1116 /* There's already all data we need, or augmentation
1117 * wasn't turned on. */
1119 *ret
= sd_bus_creds_ref(c
);
1123 n
= bus_creds_new();
1127 /* Copy the original data over */
1129 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1131 n
->mask
|= SD_BUS_CREDS_PID
;
1134 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1136 n
->mask
|= SD_BUS_CREDS_TID
;
1139 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1141 n
->mask
|= SD_BUS_CREDS_PPID
;
1144 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1146 n
->mask
|= SD_BUS_CREDS_UID
;
1149 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1151 n
->mask
|= SD_BUS_CREDS_EUID
;
1154 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1156 n
->mask
|= SD_BUS_CREDS_SUID
;
1159 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1160 n
->fsuid
= c
->fsuid
;
1161 n
->mask
|= SD_BUS_CREDS_FSUID
;
1164 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1166 n
->mask
|= SD_BUS_CREDS_GID
;
1169 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1171 n
->mask
|= SD_BUS_CREDS_EGID
;
1174 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1176 n
->mask
|= SD_BUS_CREDS_SGID
;
1179 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1180 n
->fsgid
= c
->fsgid
;
1181 n
->mask
|= SD_BUS_CREDS_FSGID
;
1184 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1185 if (c
->supplementary_gids
) {
1186 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1187 if (!n
->supplementary_gids
)
1189 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1191 n
->supplementary_gids
= NULL
;
1192 n
->n_supplementary_gids
= 0;
1195 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1198 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1201 n
->comm
= strdup(c
->comm
);
1205 n
->mask
|= SD_BUS_CREDS_COMM
;
1208 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1209 assert(c
->tid_comm
);
1211 n
->tid_comm
= strdup(c
->tid_comm
);
1215 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1218 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1220 n
->exe
= strdup(c
->exe
);
1226 n
->mask
|= SD_BUS_CREDS_EXE
;
1229 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1231 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1235 n
->cmdline_size
= c
->cmdline_size
;
1238 n
->cmdline_size
= 0;
1241 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1244 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
)) {
1247 n
->cgroup
= strdup(c
->cgroup
);
1251 n
->cgroup_root
= strdup(c
->cgroup_root
);
1252 if (!n
->cgroup_root
)
1255 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
);
1258 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1259 assert(c
->capability
);
1261 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1265 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
);
1268 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1271 n
->label
= strdup(c
->label
);
1274 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1277 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1278 n
->audit_session_id
= c
->audit_session_id
;
1279 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1281 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1282 n
->audit_login_uid
= c
->audit_login_uid
;
1283 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1286 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1288 n
->tty
= strdup(c
->tty
);
1293 n
->mask
|= SD_BUS_CREDS_TTY
;
1296 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1297 assert(c
->unique_name
);
1299 n
->unique_name
= strdup(c
->unique_name
);
1300 if (!n
->unique_name
)
1302 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1305 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1306 if (strv_isempty(c
->well_known_names
))
1307 n
->well_known_names
= NULL
;
1309 n
->well_known_names
= strv_copy(c
->well_known_names
);
1310 if (!n
->well_known_names
)
1313 n
->well_known_names_driver
= c
->well_known_names_driver
;
1314 n
->well_known_names_local
= c
->well_known_names_local
;
1315 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1318 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1319 assert(c
->description
);
1320 n
->description
= strdup(c
->description
);
1321 if (!n
->description
)
1323 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1326 n
->augmented
= c
->augmented
& n
->mask
;
1330 r
= bus_creds_add_more(n
, mask
, 0, 0);