1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/capability.h>
24 #include "alloc-util.h"
25 #include "audit-util.h"
26 #include "bus-creds.h"
27 #include "bus-label.h"
28 #include "bus-message.h"
30 #include "capability-util.h"
31 #include "cgroup-util.h"
34 #include "format-util.h"
35 #include "hexdecoct.h"
36 #include "parse-util.h"
37 #include "process-util.h"
38 #include "string-util.h"
40 #include "terminal-util.h"
41 #include "user-util.h"
45 CAP_OFFSET_INHERITABLE
= 0,
46 CAP_OFFSET_PERMITTED
= 1,
47 CAP_OFFSET_EFFECTIVE
= 2,
48 CAP_OFFSET_BOUNDING
= 3
51 void bus_creds_done(sd_bus_creds
*c
) {
54 /* For internal bus cred structures that are allocated by
62 free(c
->unescaped_description
);
63 free(c
->supplementary_gids
);
66 free(c
->well_known_names
); /* note that this is an strv, but
67 * we only free the array, not the
68 * strings the array points to. The
69 * full strv we only free if
70 * c->allocated is set, see
73 strv_free(c
->cmdline_array
);
76 _public_ sd_bus_creds
*sd_bus_creds_ref(sd_bus_creds
*c
) {
87 /* If this is an embedded creds structure, then
88 * forward ref counting to the message */
89 m
= container_of(c
, sd_bus_message
, creds
);
90 sd_bus_message_ref(m
);
96 _public_ sd_bus_creds
*sd_bus_creds_unref(sd_bus_creds
*c
) {
102 assert(c
->n_ref
> 0);
113 free(c
->unique_name
);
114 free(c
->cgroup_root
);
115 free(c
->description
);
117 c
->supplementary_gids
= mfree(c
->supplementary_gids
);
119 c
->well_known_names
= strv_free(c
->well_known_names
);
128 m
= container_of(c
, sd_bus_message
, creds
);
129 sd_bus_message_unref(m
);
136 _public_
uint64_t sd_bus_creds_get_mask(const sd_bus_creds
*c
) {
142 _public_
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds
*c
) {
148 sd_bus_creds
* bus_creds_new(void) {
151 c
= new0(sd_bus_creds
, 1);
160 _public_
int sd_bus_creds_new_from_pid(sd_bus_creds
**ret
, pid_t pid
, uint64_t mask
) {
164 assert_return(pid
>= 0, -EINVAL
);
165 assert_return(mask
<= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
166 assert_return(ret
, -EINVAL
);
169 pid
= getpid_cached();
175 r
= bus_creds_add_more(c
, mask
| SD_BUS_CREDS_AUGMENT
, pid
, 0);
177 sd_bus_creds_unref(c
);
181 /* Check if the process existed at all, in case we haven't
182 * figured that out already */
183 if (!pid_is_alive(pid
)) {
184 sd_bus_creds_unref(c
);
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 _public_
int sd_bus_creds_get_suid(sd_bus_creds
*c
, uid_t
*suid
) {
215 assert_return(c
, -EINVAL
);
216 assert_return(suid
, -EINVAL
);
218 if (!(c
->mask
& SD_BUS_CREDS_SUID
))
226 _public_
int sd_bus_creds_get_fsuid(sd_bus_creds
*c
, uid_t
*fsuid
) {
227 assert_return(c
, -EINVAL
);
228 assert_return(fsuid
, -EINVAL
);
230 if (!(c
->mask
& SD_BUS_CREDS_FSUID
))
237 _public_
int sd_bus_creds_get_gid(sd_bus_creds
*c
, gid_t
*gid
) {
238 assert_return(c
, -EINVAL
);
239 assert_return(gid
, -EINVAL
);
241 if (!(c
->mask
& SD_BUS_CREDS_GID
))
248 _public_
int sd_bus_creds_get_egid(sd_bus_creds
*c
, gid_t
*egid
) {
249 assert_return(c
, -EINVAL
);
250 assert_return(egid
, -EINVAL
);
252 if (!(c
->mask
& SD_BUS_CREDS_EGID
))
259 _public_
int sd_bus_creds_get_sgid(sd_bus_creds
*c
, gid_t
*sgid
) {
260 assert_return(c
, -EINVAL
);
261 assert_return(sgid
, -EINVAL
);
263 if (!(c
->mask
& SD_BUS_CREDS_SGID
))
270 _public_
int sd_bus_creds_get_fsgid(sd_bus_creds
*c
, gid_t
*fsgid
) {
271 assert_return(c
, -EINVAL
);
272 assert_return(fsgid
, -EINVAL
);
274 if (!(c
->mask
& SD_BUS_CREDS_FSGID
))
281 _public_
int sd_bus_creds_get_supplementary_gids(sd_bus_creds
*c
, const gid_t
**gids
) {
282 assert_return(c
, -EINVAL
);
283 assert_return(gids
, -EINVAL
);
285 if (!(c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
))
288 *gids
= c
->supplementary_gids
;
289 return (int) c
->n_supplementary_gids
;
292 _public_
int sd_bus_creds_get_pid(sd_bus_creds
*c
, pid_t
*pid
) {
293 assert_return(c
, -EINVAL
);
294 assert_return(pid
, -EINVAL
);
296 if (!(c
->mask
& SD_BUS_CREDS_PID
))
304 _public_
int sd_bus_creds_get_ppid(sd_bus_creds
*c
, pid_t
*ppid
) {
305 assert_return(c
, -EINVAL
);
306 assert_return(ppid
, -EINVAL
);
308 if (!(c
->mask
& SD_BUS_CREDS_PPID
))
311 /* PID 1 has no parent process. Let's distinguish the case of
312 * not knowing and not having a parent process by the returned
321 _public_
int sd_bus_creds_get_tid(sd_bus_creds
*c
, pid_t
*tid
) {
322 assert_return(c
, -EINVAL
);
323 assert_return(tid
, -EINVAL
);
325 if (!(c
->mask
& SD_BUS_CREDS_TID
))
333 _public_
int sd_bus_creds_get_selinux_context(sd_bus_creds
*c
, const char **ret
) {
334 assert_return(c
, -EINVAL
);
336 if (!(c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
))
344 _public_
int sd_bus_creds_get_comm(sd_bus_creds
*c
, const char **ret
) {
345 assert_return(c
, -EINVAL
);
346 assert_return(ret
, -EINVAL
);
348 if (!(c
->mask
& SD_BUS_CREDS_COMM
))
356 _public_
int sd_bus_creds_get_tid_comm(sd_bus_creds
*c
, const char **ret
) {
357 assert_return(c
, -EINVAL
);
358 assert_return(ret
, -EINVAL
);
360 if (!(c
->mask
& SD_BUS_CREDS_TID_COMM
))
368 _public_
int sd_bus_creds_get_exe(sd_bus_creds
*c
, const char **ret
) {
369 assert_return(c
, -EINVAL
);
370 assert_return(ret
, -EINVAL
);
372 if (!(c
->mask
& SD_BUS_CREDS_EXE
))
382 _public_
int sd_bus_creds_get_cgroup(sd_bus_creds
*c
, const char **ret
) {
383 assert_return(c
, -EINVAL
);
384 assert_return(ret
, -EINVAL
);
386 if (!(c
->mask
& SD_BUS_CREDS_CGROUP
))
394 _public_
int sd_bus_creds_get_unit(sd_bus_creds
*c
, const char **ret
) {
397 assert_return(c
, -EINVAL
);
398 assert_return(ret
, -EINVAL
);
400 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
408 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
412 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
421 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
424 assert_return(c
, -EINVAL
);
425 assert_return(ret
, -EINVAL
);
427 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
435 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
439 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
448 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
451 assert_return(c
, -EINVAL
);
452 assert_return(ret
, -EINVAL
);
454 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
462 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
466 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
475 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
478 assert_return(c
, -EINVAL
);
479 assert_return(ret
, -EINVAL
);
481 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
486 if (!c
->user_slice
) {
489 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
493 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
498 *ret
= c
->user_slice
;
502 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
505 assert_return(c
, -EINVAL
);
506 assert_return(ret
, -EINVAL
);
508 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
516 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
520 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
529 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
533 assert_return(c
, -EINVAL
);
534 assert_return(uid
, -EINVAL
);
536 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
541 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
545 return cg_path_get_owner_uid(shifted
, uid
);
548 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
549 assert_return(c
, -EINVAL
);
551 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
557 if (!c
->cmdline_array
) {
558 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
559 if (!c
->cmdline_array
)
563 *cmdline
= c
->cmdline_array
;
567 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
568 assert_return(c
, -EINVAL
);
569 assert_return(sessionid
, -EINVAL
);
571 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
574 if (!audit_session_is_valid(c
->audit_session_id
))
577 *sessionid
= c
->audit_session_id
;
581 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
582 assert_return(c
, -EINVAL
);
583 assert_return(uid
, -EINVAL
);
585 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
588 if (!uid_is_valid(c
->audit_login_uid
))
591 *uid
= c
->audit_login_uid
;
595 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
596 assert_return(c
, -EINVAL
);
597 assert_return(ret
, -EINVAL
);
599 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
609 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
610 assert_return(c
, -EINVAL
);
611 assert_return(unique_name
, -EINVAL
);
613 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
616 *unique_name
= c
->unique_name
;
620 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
621 assert_return(c
, -EINVAL
);
622 assert_return(well_known_names
, -EINVAL
);
624 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
627 /* As a special hack we return the bus driver as well-known
628 * names list when this is requested. */
629 if (c
->well_known_names_driver
) {
630 static const char* const wkn
[] = {
631 "org.freedesktop.DBus",
635 *well_known_names
= (char**) wkn
;
639 if (c
->well_known_names_local
) {
640 static const char* const wkn
[] = {
641 "org.freedesktop.DBus.Local",
645 *well_known_names
= (char**) wkn
;
649 *well_known_names
= c
->well_known_names
;
653 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
654 assert_return(c
, -EINVAL
);
655 assert_return(ret
, -EINVAL
);
657 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
660 assert(c
->description
);
662 if (!c
->unescaped_description
) {
663 c
->unescaped_description
= bus_label_unescape(c
->description
);
664 if (!c
->unescaped_description
)
668 *ret
= c
->unescaped_description
;
672 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
676 assert(capability
>= 0);
677 assert(c
->capability
);
679 if ((unsigned) capability
> cap_last_cap())
682 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
684 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
687 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
688 assert_return(c
, -EINVAL
);
689 assert_return(capability
>= 0, -EINVAL
);
691 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
694 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
697 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
698 assert_return(c
, -EINVAL
);
699 assert_return(capability
>= 0, -EINVAL
);
701 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
704 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
707 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
708 assert_return(c
, -EINVAL
);
709 assert_return(capability
>= 0, -EINVAL
);
711 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
714 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
717 _public_
int sd_bus_creds_has_bounding_cap(sd_bus_creds
*c
, int capability
) {
718 assert_return(c
, -EINVAL
);
719 assert_return(capability
>= 0, -EINVAL
);
721 if (!(c
->mask
& SD_BUS_CREDS_BOUNDING_CAPS
))
724 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
727 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
734 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
735 p
+= strspn(p
, WHITESPACE
);
745 if (!c
->capability
) {
746 c
->capability
= new0(uint32_t, max
* 4);
751 for (i
= 0; i
< sz
; i
++) {
754 for (j
= 0; j
< 8; ++j
) {
764 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
770 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
775 assert(c
->allocated
);
777 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
780 /* Try to retrieve PID from creds if it wasn't passed to us */
783 c
->mask
|= SD_BUS_CREDS_PID
;
784 } else if (c
->mask
& SD_BUS_CREDS_PID
)
787 /* Without pid we cannot do much... */
790 /* Try to retrieve TID from creds if it wasn't passed to us */
791 if (tid
<= 0 && (c
->mask
& SD_BUS_CREDS_TID
))
794 /* Calculate what we shall and can add */
795 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
);
801 c
->mask
|= SD_BUS_CREDS_TID
;
804 if (missing
& (SD_BUS_CREDS_PPID
|
805 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
806 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
807 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
808 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
809 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
811 _cleanup_fclose_
FILE *f
= NULL
;
814 p
= procfs_file_alloca(pid
, "status");
820 else if (!IN_SET(errno
, EPERM
, EACCES
))
825 FOREACH_LINE(line
, f
, return -errno
) {
828 if (missing
& SD_BUS_CREDS_PPID
) {
829 p
= startswith(line
, "PPid:");
831 p
+= strspn(p
, WHITESPACE
);
833 /* Explicitly check for PPID 0 (which is the case for PID 1) */
834 if (!streq(p
, "0")) {
835 r
= parse_pid(p
, &c
->ppid
);
842 c
->mask
|= SD_BUS_CREDS_PPID
;
847 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
848 p
= startswith(line
, "Uid:");
850 unsigned long uid
, euid
, suid
, fsuid
;
852 p
+= strspn(p
, WHITESPACE
);
853 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
856 if (missing
& SD_BUS_CREDS_UID
)
857 c
->uid
= (uid_t
) uid
;
858 if (missing
& SD_BUS_CREDS_EUID
)
859 c
->euid
= (uid_t
) euid
;
860 if (missing
& SD_BUS_CREDS_SUID
)
861 c
->suid
= (uid_t
) suid
;
862 if (missing
& SD_BUS_CREDS_FSUID
)
863 c
->fsuid
= (uid_t
) fsuid
;
865 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
870 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
871 p
= startswith(line
, "Gid:");
873 unsigned long gid
, egid
, sgid
, fsgid
;
875 p
+= strspn(p
, WHITESPACE
);
876 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
879 if (missing
& SD_BUS_CREDS_GID
)
880 c
->gid
= (gid_t
) gid
;
881 if (missing
& SD_BUS_CREDS_EGID
)
882 c
->egid
= (gid_t
) egid
;
883 if (missing
& SD_BUS_CREDS_SGID
)
884 c
->sgid
= (gid_t
) sgid
;
885 if (missing
& SD_BUS_CREDS_FSGID
)
886 c
->fsgid
= (gid_t
) fsgid
;
888 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
893 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
894 p
= startswith(line
, "Groups:");
896 size_t allocated
= 0;
902 p
+= strspn(p
, WHITESPACE
);
906 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
909 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
912 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
916 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
921 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
922 p
= startswith(line
, "CapEff:");
924 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
928 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
933 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
934 p
= startswith(line
, "CapPrm:");
936 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
940 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
945 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
946 p
= startswith(line
, "CapInh:");
948 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
952 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
957 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
958 p
= startswith(line
, "CapBnd:");
960 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
964 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
972 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
975 p
= procfs_file_alloca(pid
, "attr/current");
976 r
= read_one_line_file(p
, &c
->label
);
978 if (!IN_SET(r
, -ENOENT
, -EINVAL
, -EPERM
, -EACCES
))
981 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
984 if (missing
& SD_BUS_CREDS_COMM
) {
985 r
= get_process_comm(pid
, &c
->comm
);
987 if (!IN_SET(r
, -EPERM
, -EACCES
))
990 c
->mask
|= SD_BUS_CREDS_COMM
;
993 if (missing
& SD_BUS_CREDS_EXE
) {
994 r
= get_process_exe(pid
, &c
->exe
);
996 /* Unfortunately we cannot really distinguish
997 * the case here where the process does not
998 * exist, and /proc/$PID/exe being unreadable
999 * because $PID is a kernel thread. Hence,
1000 * assume it is a kernel thread, and rely on
1001 * that this case is caught with a later
1004 c
->mask
|= SD_BUS_CREDS_EXE
;
1006 if (!IN_SET(r
, -EPERM
, -EACCES
))
1009 c
->mask
|= SD_BUS_CREDS_EXE
;
1012 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1015 p
= procfs_file_alloca(pid
, "cmdline");
1016 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1020 if (!IN_SET(r
, -EPERM
, -EACCES
))
1023 if (c
->cmdline_size
== 0)
1024 c
->cmdline
= mfree(c
->cmdline
);
1026 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1030 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1031 _cleanup_free_
char *p
= NULL
;
1033 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1036 r
= read_one_line_file(p
, &c
->tid_comm
);
1040 if (!IN_SET(r
, -EPERM
, -EACCES
))
1043 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1046 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
)) {
1049 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1051 if (!IN_SET(r
, -EPERM
, -EACCES
))
1056 if (!c
->cgroup_root
) {
1057 r
= cg_get_root_path(&c
->cgroup_root
);
1063 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
);
1066 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1067 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1068 if (r
== -ENODATA
) {
1069 /* ENODATA means: no audit session id assigned */
1070 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1071 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1073 if (!IN_SET(r
, -EOPNOTSUPP
, -ENOENT
, -EPERM
, -EACCES
))
1076 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1079 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1080 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1081 if (r
== -ENODATA
) {
1082 /* ENODATA means: no audit login uid assigned */
1083 c
->audit_login_uid
= UID_INVALID
;
1084 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1086 if (!IN_SET(r
, -EOPNOTSUPP
, -ENOENT
, -EPERM
, -EACCES
))
1089 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1092 if (missing
& SD_BUS_CREDS_TTY
) {
1093 r
= get_ctty(pid
, NULL
, &c
->tty
);
1095 /* ENXIO means: process has no controlling TTY */
1097 c
->mask
|= SD_BUS_CREDS_TTY
;
1099 if (!IN_SET(r
, -EPERM
, -EACCES
, -ENOENT
))
1102 c
->mask
|= SD_BUS_CREDS_TTY
;
1105 /* In case only the exe path was to be read we cannot
1106 * distinguish the case where the exe path was unreadable
1107 * because the process was a kernel thread, or when the
1108 * process didn't exist at all. Hence, let's do a final check,
1110 if (!pid_is_alive(pid
))
1113 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1116 c
->augmented
= missing
& c
->mask
;
1121 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1122 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*n
= NULL
;
1128 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1129 /* There's already all data we need, or augmentation
1130 * wasn't turned on. */
1132 *ret
= sd_bus_creds_ref(c
);
1136 n
= bus_creds_new();
1140 /* Copy the original data over */
1142 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1144 n
->mask
|= SD_BUS_CREDS_PID
;
1147 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1149 n
->mask
|= SD_BUS_CREDS_TID
;
1152 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1154 n
->mask
|= SD_BUS_CREDS_PPID
;
1157 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1159 n
->mask
|= SD_BUS_CREDS_UID
;
1162 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1164 n
->mask
|= SD_BUS_CREDS_EUID
;
1167 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1169 n
->mask
|= SD_BUS_CREDS_SUID
;
1172 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1173 n
->fsuid
= c
->fsuid
;
1174 n
->mask
|= SD_BUS_CREDS_FSUID
;
1177 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1179 n
->mask
|= SD_BUS_CREDS_GID
;
1182 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1184 n
->mask
|= SD_BUS_CREDS_EGID
;
1187 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1189 n
->mask
|= SD_BUS_CREDS_SGID
;
1192 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1193 n
->fsgid
= c
->fsgid
;
1194 n
->mask
|= SD_BUS_CREDS_FSGID
;
1197 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1198 if (c
->supplementary_gids
) {
1199 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1200 if (!n
->supplementary_gids
)
1202 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1204 n
->supplementary_gids
= NULL
;
1205 n
->n_supplementary_gids
= 0;
1208 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1211 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1214 n
->comm
= strdup(c
->comm
);
1218 n
->mask
|= SD_BUS_CREDS_COMM
;
1221 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1222 assert(c
->tid_comm
);
1224 n
->tid_comm
= strdup(c
->tid_comm
);
1228 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1231 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1233 n
->exe
= strdup(c
->exe
);
1239 n
->mask
|= SD_BUS_CREDS_EXE
;
1242 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1244 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1248 n
->cmdline_size
= c
->cmdline_size
;
1251 n
->cmdline_size
= 0;
1254 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1257 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
)) {
1260 n
->cgroup
= strdup(c
->cgroup
);
1264 n
->cgroup_root
= strdup(c
->cgroup_root
);
1265 if (!n
->cgroup_root
)
1268 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
);
1271 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1272 assert(c
->capability
);
1274 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1278 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
);
1281 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1284 n
->label
= strdup(c
->label
);
1287 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1290 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1291 n
->audit_session_id
= c
->audit_session_id
;
1292 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1294 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1295 n
->audit_login_uid
= c
->audit_login_uid
;
1296 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1299 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1301 n
->tty
= strdup(c
->tty
);
1306 n
->mask
|= SD_BUS_CREDS_TTY
;
1309 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1310 assert(c
->unique_name
);
1312 n
->unique_name
= strdup(c
->unique_name
);
1313 if (!n
->unique_name
)
1315 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1318 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1319 if (strv_isempty(c
->well_known_names
))
1320 n
->well_known_names
= NULL
;
1322 n
->well_known_names
= strv_copy(c
->well_known_names
);
1323 if (!n
->well_known_names
)
1326 n
->well_known_names_driver
= c
->well_known_names_driver
;
1327 n
->well_known_names_local
= c
->well_known_names_local
;
1328 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1331 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1332 assert(c
->description
);
1333 n
->description
= strdup(c
->description
);
1334 if (!n
->description
)
1336 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1339 n
->augmented
= c
->augmented
& n
->mask
;
1343 r
= bus_creds_add_more(n
, mask
, 0, 0);