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 _public_
uint64_t sd_bus_creds_get_mask(const sd_bus_creds
*c
) {
136 _public_
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds
*c
) {
142 sd_bus_creds
* bus_creds_new(void) {
145 c
= new0(sd_bus_creds
, 1);
154 _public_
int sd_bus_creds_new_from_pid(sd_bus_creds
**ret
, pid_t pid
, uint64_t mask
) {
158 assert_return(pid
>= 0, -EINVAL
);
159 assert_return(mask
<= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
160 assert_return(ret
, -EINVAL
);
169 r
= bus_creds_add_more(c
, mask
| SD_BUS_CREDS_AUGMENT
, pid
, 0);
171 sd_bus_creds_unref(c
);
175 /* Check if the process existed at all, in case we haven't
176 * figured that out already */
177 if (!pid_is_alive(pid
)) {
178 sd_bus_creds_unref(c
);
186 _public_
int sd_bus_creds_get_uid(sd_bus_creds
*c
, uid_t
*uid
) {
187 assert_return(c
, -EINVAL
);
188 assert_return(uid
, -EINVAL
);
190 if (!(c
->mask
& SD_BUS_CREDS_UID
))
197 _public_
int sd_bus_creds_get_euid(sd_bus_creds
*c
, uid_t
*euid
) {
198 assert_return(c
, -EINVAL
);
199 assert_return(euid
, -EINVAL
);
201 if (!(c
->mask
& SD_BUS_CREDS_EUID
))
208 _public_
int sd_bus_creds_get_suid(sd_bus_creds
*c
, uid_t
*suid
) {
209 assert_return(c
, -EINVAL
);
210 assert_return(suid
, -EINVAL
);
212 if (!(c
->mask
& SD_BUS_CREDS_SUID
))
220 _public_
int sd_bus_creds_get_fsuid(sd_bus_creds
*c
, uid_t
*fsuid
) {
221 assert_return(c
, -EINVAL
);
222 assert_return(fsuid
, -EINVAL
);
224 if (!(c
->mask
& SD_BUS_CREDS_FSUID
))
231 _public_
int sd_bus_creds_get_gid(sd_bus_creds
*c
, gid_t
*gid
) {
232 assert_return(c
, -EINVAL
);
233 assert_return(gid
, -EINVAL
);
235 if (!(c
->mask
& SD_BUS_CREDS_GID
))
242 _public_
int sd_bus_creds_get_egid(sd_bus_creds
*c
, gid_t
*egid
) {
243 assert_return(c
, -EINVAL
);
244 assert_return(egid
, -EINVAL
);
246 if (!(c
->mask
& SD_BUS_CREDS_EGID
))
253 _public_
int sd_bus_creds_get_sgid(sd_bus_creds
*c
, gid_t
*sgid
) {
254 assert_return(c
, -EINVAL
);
255 assert_return(sgid
, -EINVAL
);
257 if (!(c
->mask
& SD_BUS_CREDS_SGID
))
264 _public_
int sd_bus_creds_get_fsgid(sd_bus_creds
*c
, gid_t
*fsgid
) {
265 assert_return(c
, -EINVAL
);
266 assert_return(fsgid
, -EINVAL
);
268 if (!(c
->mask
& SD_BUS_CREDS_FSGID
))
275 _public_
int sd_bus_creds_get_supplementary_gids(sd_bus_creds
*c
, const gid_t
**gids
) {
276 assert_return(c
, -EINVAL
);
277 assert_return(gids
, -EINVAL
);
279 if (!(c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
))
282 *gids
= c
->supplementary_gids
;
283 return (int) c
->n_supplementary_gids
;
286 _public_
int sd_bus_creds_get_pid(sd_bus_creds
*c
, pid_t
*pid
) {
287 assert_return(c
, -EINVAL
);
288 assert_return(pid
, -EINVAL
);
290 if (!(c
->mask
& SD_BUS_CREDS_PID
))
298 _public_
int sd_bus_creds_get_ppid(sd_bus_creds
*c
, pid_t
*ppid
) {
299 assert_return(c
, -EINVAL
);
300 assert_return(ppid
, -EINVAL
);
302 if (!(c
->mask
& SD_BUS_CREDS_PPID
))
305 /* PID 1 has no parent process. Let's distinguish the case of
306 * not knowing and not having a parent process by the returned
315 _public_
int sd_bus_creds_get_tid(sd_bus_creds
*c
, pid_t
*tid
) {
316 assert_return(c
, -EINVAL
);
317 assert_return(tid
, -EINVAL
);
319 if (!(c
->mask
& SD_BUS_CREDS_TID
))
327 _public_
int sd_bus_creds_get_selinux_context(sd_bus_creds
*c
, const char **ret
) {
328 assert_return(c
, -EINVAL
);
330 if (!(c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
))
338 _public_
int sd_bus_creds_get_comm(sd_bus_creds
*c
, const char **ret
) {
339 assert_return(c
, -EINVAL
);
340 assert_return(ret
, -EINVAL
);
342 if (!(c
->mask
& SD_BUS_CREDS_COMM
))
350 _public_
int sd_bus_creds_get_tid_comm(sd_bus_creds
*c
, const char **ret
) {
351 assert_return(c
, -EINVAL
);
352 assert_return(ret
, -EINVAL
);
354 if (!(c
->mask
& SD_BUS_CREDS_TID_COMM
))
362 _public_
int sd_bus_creds_get_exe(sd_bus_creds
*c
, const char **ret
) {
363 assert_return(c
, -EINVAL
);
364 assert_return(ret
, -EINVAL
);
366 if (!(c
->mask
& SD_BUS_CREDS_EXE
))
376 _public_
int sd_bus_creds_get_cgroup(sd_bus_creds
*c
, const char **ret
) {
377 assert_return(c
, -EINVAL
);
378 assert_return(ret
, -EINVAL
);
380 if (!(c
->mask
& SD_BUS_CREDS_CGROUP
))
388 _public_
int sd_bus_creds_get_unit(sd_bus_creds
*c
, const char **ret
) {
391 assert_return(c
, -EINVAL
);
392 assert_return(ret
, -EINVAL
);
394 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
402 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
406 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
415 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
418 assert_return(c
, -EINVAL
);
419 assert_return(ret
, -EINVAL
);
421 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
429 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
433 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
442 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
445 assert_return(c
, -EINVAL
);
446 assert_return(ret
, -EINVAL
);
448 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
456 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
460 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
469 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
472 assert_return(c
, -EINVAL
);
473 assert_return(ret
, -EINVAL
);
475 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
480 if (!c
->user_slice
) {
483 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
487 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
492 *ret
= c
->user_slice
;
496 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
499 assert_return(c
, -EINVAL
);
500 assert_return(ret
, -EINVAL
);
502 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
510 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
514 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
523 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
527 assert_return(c
, -EINVAL
);
528 assert_return(uid
, -EINVAL
);
530 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
535 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
539 return cg_path_get_owner_uid(shifted
, uid
);
542 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
543 assert_return(c
, -EINVAL
);
545 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
551 if (!c
->cmdline_array
) {
552 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
553 if (!c
->cmdline_array
)
557 *cmdline
= c
->cmdline_array
;
561 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
562 assert_return(c
, -EINVAL
);
563 assert_return(sessionid
, -EINVAL
);
565 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
568 if (c
->audit_session_id
== AUDIT_SESSION_INVALID
)
571 *sessionid
= c
->audit_session_id
;
575 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
576 assert_return(c
, -EINVAL
);
577 assert_return(uid
, -EINVAL
);
579 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
582 if (c
->audit_login_uid
== UID_INVALID
)
585 *uid
= c
->audit_login_uid
;
589 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
590 assert_return(c
, -EINVAL
);
591 assert_return(ret
, -EINVAL
);
593 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
603 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
604 assert_return(c
, -EINVAL
);
605 assert_return(unique_name
, -EINVAL
);
607 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
610 *unique_name
= c
->unique_name
;
614 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
615 assert_return(c
, -EINVAL
);
616 assert_return(well_known_names
, -EINVAL
);
618 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
621 /* As a special hack we return the bus driver as well-known
622 * names list when this is requested. */
623 if (c
->well_known_names_driver
) {
624 static const char* const wkn
[] = {
625 "org.freedesktop.DBus",
629 *well_known_names
= (char**) wkn
;
633 if (c
->well_known_names_local
) {
634 static const char* const wkn
[] = {
635 "org.freedesktop.DBus.Local",
639 *well_known_names
= (char**) wkn
;
643 *well_known_names
= c
->well_known_names
;
647 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
648 assert_return(c
, -EINVAL
);
649 assert_return(ret
, -EINVAL
);
651 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
654 assert(c
->description
);
656 if (!c
->unescaped_description
) {
657 c
->unescaped_description
= bus_label_unescape(c
->description
);
658 if (!c
->unescaped_description
)
662 *ret
= c
->unescaped_description
;
666 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
670 assert(capability
>= 0);
671 assert(c
->capability
);
673 if ((unsigned) capability
> cap_last_cap())
676 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
678 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
681 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
682 assert_return(c
, -EINVAL
);
683 assert_return(capability
>= 0, -EINVAL
);
685 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
688 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
691 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
692 assert_return(c
, -EINVAL
);
693 assert_return(capability
>= 0, -EINVAL
);
695 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
698 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
701 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
702 assert_return(c
, -EINVAL
);
703 assert_return(capability
>= 0, -EINVAL
);
705 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
708 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
711 _public_
int sd_bus_creds_has_bounding_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_BOUNDING_CAPS
))
718 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
721 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
728 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
729 p
+= strspn(p
, WHITESPACE
);
739 if (!c
->capability
) {
740 c
->capability
= new0(uint32_t, max
* 4);
745 for (i
= 0; i
< sz
; i
++) {
748 for (j
= 0; j
< 8; ++j
) {
758 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
764 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
769 assert(c
->allocated
);
771 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
774 /* Try to retrieve PID from creds if it wasn't passed to us */
777 c
->mask
|= SD_BUS_CREDS_PID
;
778 } else if (c
->mask
& SD_BUS_CREDS_PID
)
781 /* Without pid we cannot do much... */
784 /* Try to retrieve TID from creds if it wasn't passed to us */
785 if (tid
<= 0 && (c
->mask
& SD_BUS_CREDS_TID
))
788 /* Calculate what we shall and can add */
789 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
);
795 c
->mask
|= SD_BUS_CREDS_TID
;
798 if (missing
& (SD_BUS_CREDS_PPID
|
799 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
800 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
801 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
802 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
803 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
805 _cleanup_fclose_
FILE *f
= NULL
;
808 p
= procfs_file_alloca(pid
, "status");
814 else if (errno
!= EPERM
&& errno
!= EACCES
)
819 FOREACH_LINE(line
, f
, return -errno
) {
822 if (missing
& SD_BUS_CREDS_PPID
) {
823 p
= startswith(line
, "PPid:");
825 p
+= strspn(p
, WHITESPACE
);
827 /* Explicitly check for PPID 0 (which is the case for PID 1) */
828 if (!streq(p
, "0")) {
829 r
= parse_pid(p
, &c
->ppid
);
836 c
->mask
|= SD_BUS_CREDS_PPID
;
841 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
842 p
= startswith(line
, "Uid:");
844 unsigned long uid
, euid
, suid
, fsuid
;
846 p
+= strspn(p
, WHITESPACE
);
847 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
850 if (missing
& SD_BUS_CREDS_UID
)
851 c
->uid
= (uid_t
) uid
;
852 if (missing
& SD_BUS_CREDS_EUID
)
853 c
->euid
= (uid_t
) euid
;
854 if (missing
& SD_BUS_CREDS_SUID
)
855 c
->suid
= (uid_t
) suid
;
856 if (missing
& SD_BUS_CREDS_FSUID
)
857 c
->fsuid
= (uid_t
) fsuid
;
859 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
864 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
865 p
= startswith(line
, "Gid:");
867 unsigned long gid
, egid
, sgid
, fsgid
;
869 p
+= strspn(p
, WHITESPACE
);
870 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
873 if (missing
& SD_BUS_CREDS_GID
)
874 c
->gid
= (gid_t
) gid
;
875 if (missing
& SD_BUS_CREDS_EGID
)
876 c
->egid
= (gid_t
) egid
;
877 if (missing
& SD_BUS_CREDS_SGID
)
878 c
->sgid
= (gid_t
) sgid
;
879 if (missing
& SD_BUS_CREDS_FSGID
)
880 c
->fsgid
= (gid_t
) fsgid
;
882 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
887 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
888 p
= startswith(line
, "Groups:");
890 size_t allocated
= 0;
896 p
+= strspn(p
, WHITESPACE
);
900 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
903 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
906 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
910 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
915 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
916 p
= startswith(line
, "CapEff:");
918 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
922 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
927 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
928 p
= startswith(line
, "CapPrm:");
930 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
934 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
939 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
940 p
= startswith(line
, "CapInh:");
942 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
946 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
951 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
952 p
= startswith(line
, "CapBnd:");
954 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
958 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
966 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
969 p
= procfs_file_alloca(pid
, "attr/current");
970 r
= read_one_line_file(p
, &c
->label
);
972 if (r
!= -ENOENT
&& r
!= -EINVAL
&& r
!= -EPERM
&& r
!= -EACCES
)
975 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
978 if (missing
& SD_BUS_CREDS_COMM
) {
979 r
= get_process_comm(pid
, &c
->comm
);
981 if (r
!= -EPERM
&& r
!= -EACCES
)
984 c
->mask
|= SD_BUS_CREDS_COMM
;
987 if (missing
& SD_BUS_CREDS_EXE
) {
988 r
= get_process_exe(pid
, &c
->exe
);
990 /* Unfortunately we cannot really distinguish
991 * the case here where the process does not
992 * exist, and /proc/$PID/exe being unreadable
993 * because $PID is a kernel thread. Hence,
994 * assume it is a kernel thread, and rely on
995 * that this case is caught with a later
998 c
->mask
|= SD_BUS_CREDS_EXE
;
1000 if (r
!= -EPERM
&& r
!= -EACCES
)
1003 c
->mask
|= SD_BUS_CREDS_EXE
;
1006 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1009 p
= procfs_file_alloca(pid
, "cmdline");
1010 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1014 if (r
!= -EPERM
&& r
!= -EACCES
)
1017 if (c
->cmdline_size
== 0) {
1018 c
->cmdline
= mfree(c
->cmdline
);
1021 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1025 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1026 _cleanup_free_
char *p
= NULL
;
1028 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1031 r
= read_one_line_file(p
, &c
->tid_comm
);
1035 if (r
!= -EPERM
&& r
!= -EACCES
)
1038 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1041 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
)) {
1044 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1046 if (r
!= -EPERM
&& r
!= -EACCES
)
1051 if (!c
->cgroup_root
) {
1052 r
= cg_get_root_path(&c
->cgroup_root
);
1058 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
);
1061 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1062 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1063 if (r
== -ENODATA
) {
1064 /* ENODATA means: no audit session id assigned */
1065 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1066 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1068 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1071 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1074 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1075 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1076 if (r
== -ENODATA
) {
1077 /* ENODATA means: no audit login uid assigned */
1078 c
->audit_login_uid
= UID_INVALID
;
1079 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1081 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1084 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1087 if (missing
& SD_BUS_CREDS_TTY
) {
1088 r
= get_ctty(pid
, NULL
, &c
->tty
);
1090 /* ENXIO means: process has no controlling TTY */
1092 c
->mask
|= SD_BUS_CREDS_TTY
;
1094 if (r
!= -EPERM
&& r
!= -EACCES
&& r
!= -ENOENT
)
1097 c
->mask
|= SD_BUS_CREDS_TTY
;
1100 /* In case only the exe path was to be read we cannot
1101 * distinguish the case where the exe path was unreadable
1102 * because the process was a kernel thread, or when the
1103 * process didn't exist at all. Hence, let's do a final check,
1105 if (!pid_is_alive(pid
))
1108 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1111 c
->augmented
= missing
& c
->mask
;
1116 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1117 _cleanup_bus_creds_unref_ sd_bus_creds
*n
= NULL
;
1123 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1124 /* There's already all data we need, or augmentation
1125 * wasn't turned on. */
1127 *ret
= sd_bus_creds_ref(c
);
1131 n
= bus_creds_new();
1135 /* Copy the original data over */
1137 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1139 n
->mask
|= SD_BUS_CREDS_PID
;
1142 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1144 n
->mask
|= SD_BUS_CREDS_TID
;
1147 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1149 n
->mask
|= SD_BUS_CREDS_PPID
;
1152 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1154 n
->mask
|= SD_BUS_CREDS_UID
;
1157 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1159 n
->mask
|= SD_BUS_CREDS_EUID
;
1162 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1164 n
->mask
|= SD_BUS_CREDS_SUID
;
1167 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1168 n
->fsuid
= c
->fsuid
;
1169 n
->mask
|= SD_BUS_CREDS_FSUID
;
1172 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1174 n
->mask
|= SD_BUS_CREDS_GID
;
1177 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1179 n
->mask
|= SD_BUS_CREDS_EGID
;
1182 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1184 n
->mask
|= SD_BUS_CREDS_SGID
;
1187 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1188 n
->fsgid
= c
->fsgid
;
1189 n
->mask
|= SD_BUS_CREDS_FSGID
;
1192 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1193 if (c
->supplementary_gids
) {
1194 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1195 if (!n
->supplementary_gids
)
1197 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1199 n
->supplementary_gids
= NULL
;
1200 n
->n_supplementary_gids
= 0;
1203 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1206 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1209 n
->comm
= strdup(c
->comm
);
1213 n
->mask
|= SD_BUS_CREDS_COMM
;
1216 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1217 assert(c
->tid_comm
);
1219 n
->tid_comm
= strdup(c
->tid_comm
);
1223 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1226 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1228 n
->exe
= strdup(c
->exe
);
1234 n
->mask
|= SD_BUS_CREDS_EXE
;
1237 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1239 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1243 n
->cmdline_size
= c
->cmdline_size
;
1246 n
->cmdline_size
= 0;
1249 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1252 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
)) {
1255 n
->cgroup
= strdup(c
->cgroup
);
1259 n
->cgroup_root
= strdup(c
->cgroup_root
);
1260 if (!n
->cgroup_root
)
1263 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
);
1266 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1267 assert(c
->capability
);
1269 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1273 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
);
1276 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1279 n
->label
= strdup(c
->label
);
1282 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1285 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1286 n
->audit_session_id
= c
->audit_session_id
;
1287 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1289 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1290 n
->audit_login_uid
= c
->audit_login_uid
;
1291 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1294 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1296 n
->tty
= strdup(c
->tty
);
1301 n
->mask
|= SD_BUS_CREDS_TTY
;
1304 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1305 assert(c
->unique_name
);
1307 n
->unique_name
= strdup(c
->unique_name
);
1308 if (!n
->unique_name
)
1310 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1313 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1314 if (strv_isempty(c
->well_known_names
))
1315 n
->well_known_names
= NULL
;
1317 n
->well_known_names
= strv_copy(c
->well_known_names
);
1318 if (!n
->well_known_names
)
1321 n
->well_known_names_driver
= c
->well_known_names_driver
;
1322 n
->well_known_names_local
= c
->well_known_names_local
;
1323 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1326 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1327 assert(c
->description
);
1328 n
->description
= strdup(c
->description
);
1329 if (!n
->description
)
1331 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1334 n
->augmented
= c
->augmented
& n
->mask
;
1338 r
= bus_creds_add_more(n
, mask
, 0, 0);