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 distinguish 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
) {
392 assert_return(c
, -EINVAL
);
393 assert_return(ret
, -EINVAL
);
395 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
403 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
407 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
416 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
419 assert_return(c
, -EINVAL
);
420 assert_return(ret
, -EINVAL
);
422 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
430 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
434 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
443 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
446 assert_return(c
, -EINVAL
);
447 assert_return(ret
, -EINVAL
);
449 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
457 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
461 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
470 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
473 assert_return(c
, -EINVAL
);
474 assert_return(ret
, -EINVAL
);
476 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
481 if (!c
->user_slice
) {
484 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
488 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
493 *ret
= c
->user_slice
;
497 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
500 assert_return(c
, -EINVAL
);
501 assert_return(ret
, -EINVAL
);
503 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
511 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
515 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
524 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
528 assert_return(c
, -EINVAL
);
529 assert_return(uid
, -EINVAL
);
531 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
536 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
540 return cg_path_get_owner_uid(shifted
, uid
);
543 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
544 assert_return(c
, -EINVAL
);
546 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
552 if (!c
->cmdline_array
) {
553 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
554 if (!c
->cmdline_array
)
558 *cmdline
= c
->cmdline_array
;
562 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
563 assert_return(c
, -EINVAL
);
564 assert_return(sessionid
, -EINVAL
);
566 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
569 if (c
->audit_session_id
== AUDIT_SESSION_INVALID
)
572 *sessionid
= c
->audit_session_id
;
576 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
577 assert_return(c
, -EINVAL
);
578 assert_return(uid
, -EINVAL
);
580 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
583 if (c
->audit_login_uid
== UID_INVALID
)
586 *uid
= c
->audit_login_uid
;
590 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
591 assert_return(c
, -EINVAL
);
592 assert_return(ret
, -EINVAL
);
594 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
604 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
605 assert_return(c
, -EINVAL
);
606 assert_return(unique_name
, -EINVAL
);
608 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
611 *unique_name
= c
->unique_name
;
615 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
616 assert_return(c
, -EINVAL
);
617 assert_return(well_known_names
, -EINVAL
);
619 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
622 /* As a special hack we return the bus driver as well-known
623 * names list when this is requested. */
624 if (c
->well_known_names_driver
) {
625 static const char* const wkn
[] = {
626 "org.freedesktop.DBus",
630 *well_known_names
= (char**) wkn
;
634 if (c
->well_known_names_local
) {
635 static const char* const wkn
[] = {
636 "org.freedesktop.DBus.Local",
640 *well_known_names
= (char**) wkn
;
644 *well_known_names
= c
->well_known_names
;
648 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
649 assert_return(c
, -EINVAL
);
650 assert_return(ret
, -EINVAL
);
652 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
655 assert(c
->description
);
657 if (!c
->unescaped_description
) {
658 c
->unescaped_description
= bus_label_unescape(c
->description
);
659 if (!c
->unescaped_description
)
663 *ret
= c
->unescaped_description
;
667 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
671 assert(capability
>= 0);
672 assert(c
->capability
);
674 if ((unsigned) capability
> cap_last_cap())
677 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
679 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
682 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
683 assert_return(c
, -EINVAL
);
684 assert_return(capability
>= 0, -EINVAL
);
686 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
689 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
692 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
693 assert_return(c
, -EINVAL
);
694 assert_return(capability
>= 0, -EINVAL
);
696 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
699 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
702 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
703 assert_return(c
, -EINVAL
);
704 assert_return(capability
>= 0, -EINVAL
);
706 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
709 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
712 _public_
int sd_bus_creds_has_bounding_cap(sd_bus_creds
*c
, int capability
) {
713 assert_return(c
, -EINVAL
);
714 assert_return(capability
>= 0, -EINVAL
);
716 if (!(c
->mask
& SD_BUS_CREDS_BOUNDING_CAPS
))
719 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
722 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
729 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
730 p
+= strspn(p
, WHITESPACE
);
740 if (!c
->capability
) {
741 c
->capability
= new0(uint32_t, max
* 4);
746 for (i
= 0; i
< sz
; i
++) {
749 for (j
= 0; j
< 8; ++j
) {
759 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
765 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
770 assert(c
->allocated
);
772 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
775 /* Try to retrieve PID from creds if it wasn't passed to us */
776 if (pid
<= 0 && (c
->mask
& SD_BUS_CREDS_PID
))
779 /* Without pid we cannot do much... */
783 /* Try to retrieve TID from creds if it wasn't passed to us */
784 if (tid
<= 0 && (c
->mask
& SD_BUS_CREDS_TID
))
787 /* Calculate what we shall and can add */
788 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
);
793 c
->mask
|= SD_BUS_CREDS_PID
;
797 c
->mask
|= SD_BUS_CREDS_TID
;
800 if (missing
& (SD_BUS_CREDS_PPID
|
801 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
802 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
803 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
804 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
805 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
807 _cleanup_fclose_
FILE *f
= NULL
;
810 p
= procfs_file_alloca(pid
, "status");
816 else if (errno
!= EPERM
&& errno
!= EACCES
)
821 FOREACH_LINE(line
, f
, return -errno
) {
824 if (missing
& SD_BUS_CREDS_PPID
) {
825 p
= startswith(line
, "PPid:");
827 p
+= strspn(p
, WHITESPACE
);
829 /* Explicitly check for PPID 0 (which is the case for PID 1) */
830 if (!streq(p
, "0")) {
831 r
= parse_pid(p
, &c
->ppid
);
838 c
->mask
|= SD_BUS_CREDS_PPID
;
843 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
844 p
= startswith(line
, "Uid:");
846 unsigned long uid
, euid
, suid
, fsuid
;
848 p
+= strspn(p
, WHITESPACE
);
849 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
852 if (missing
& SD_BUS_CREDS_UID
)
853 c
->uid
= (uid_t
) uid
;
854 if (missing
& SD_BUS_CREDS_EUID
)
855 c
->euid
= (uid_t
) euid
;
856 if (missing
& SD_BUS_CREDS_SUID
)
857 c
->suid
= (uid_t
) suid
;
858 if (missing
& SD_BUS_CREDS_FSUID
)
859 c
->fsuid
= (uid_t
) fsuid
;
861 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
866 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
867 p
= startswith(line
, "Gid:");
869 unsigned long gid
, egid
, sgid
, fsgid
;
871 p
+= strspn(p
, WHITESPACE
);
872 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
875 if (missing
& SD_BUS_CREDS_GID
)
876 c
->gid
= (gid_t
) gid
;
877 if (missing
& SD_BUS_CREDS_EGID
)
878 c
->egid
= (gid_t
) egid
;
879 if (missing
& SD_BUS_CREDS_SGID
)
880 c
->sgid
= (gid_t
) sgid
;
881 if (missing
& SD_BUS_CREDS_FSGID
)
882 c
->fsgid
= (gid_t
) fsgid
;
884 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
889 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
890 p
= startswith(line
, "Groups:");
892 size_t allocated
= 0;
898 p
+= strspn(p
, WHITESPACE
);
902 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
905 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
908 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
912 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
917 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
918 p
= startswith(line
, "CapEff:");
920 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
924 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
929 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
930 p
= startswith(line
, "CapPrm:");
932 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
936 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
941 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
942 p
= startswith(line
, "CapInh:");
944 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
948 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
953 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
954 p
= startswith(line
, "CapBnd:");
956 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
960 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
968 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
971 p
= procfs_file_alloca(pid
, "attr/current");
972 r
= read_one_line_file(p
, &c
->label
);
974 if (r
!= -ENOENT
&& r
!= -EINVAL
&& r
!= -EPERM
&& r
!= -EACCES
)
977 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
980 if (missing
& SD_BUS_CREDS_COMM
) {
981 r
= get_process_comm(pid
, &c
->comm
);
983 if (r
!= -EPERM
&& r
!= -EACCES
)
986 c
->mask
|= SD_BUS_CREDS_COMM
;
989 if (missing
& SD_BUS_CREDS_EXE
) {
990 r
= get_process_exe(pid
, &c
->exe
);
992 /* Unfortunately we cannot really distinguish
993 * the case here where the process does not
994 * exist, and /proc/$PID/exe being unreadable
995 * because $PID is a kernel thread. Hence,
996 * assume it is a kernel thread, and rely on
997 * that this case is caught with a later
1000 c
->mask
|= SD_BUS_CREDS_EXE
;
1002 if (r
!= -EPERM
&& r
!= -EACCES
)
1005 c
->mask
|= SD_BUS_CREDS_EXE
;
1008 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1011 p
= procfs_file_alloca(pid
, "cmdline");
1012 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1016 if (r
!= -EPERM
&& r
!= -EACCES
)
1019 if (c
->cmdline_size
== 0) {
1024 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1028 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1029 _cleanup_free_
char *p
= NULL
;
1031 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1034 r
= read_one_line_file(p
, &c
->tid_comm
);
1038 if (r
!= -EPERM
&& r
!= -EACCES
)
1041 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1044 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
)) {
1047 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1049 if (r
!= -EPERM
&& r
!= -EACCES
)
1054 if (!c
->cgroup_root
) {
1055 r
= cg_get_root_path(&c
->cgroup_root
);
1061 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
);
1064 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1065 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1067 /* ENXIO means: no audit session id assigned */
1068 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1069 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1071 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1074 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1077 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1078 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1080 /* ENXIO means: no audit login uid assigned */
1081 c
->audit_login_uid
= UID_INVALID
;
1082 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1084 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1087 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1090 if (missing
& SD_BUS_CREDS_TTY
) {
1091 r
= get_ctty(pid
, NULL
, &c
->tty
);
1093 /* ENXIO means: process has no controlling TTY */
1095 c
->mask
|= SD_BUS_CREDS_TTY
;
1097 if (r
!= -EPERM
&& r
!= -EACCES
&& r
!= -ENOENT
)
1100 c
->mask
|= SD_BUS_CREDS_TTY
;
1103 /* In case only the exe path was to be read we cannot
1104 * distinguish the case where the exe path was unreadable
1105 * because the process was a kernel thread, or when the
1106 * process didn't exist at all. Hence, let's do a final check,
1108 if (!pid_is_alive(pid
))
1111 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1114 c
->augmented
= missing
& c
->mask
;
1119 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1120 _cleanup_bus_creds_unref_ sd_bus_creds
*n
= NULL
;
1126 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1127 /* There's already all data we need, or augmentation
1128 * wasn't turned on. */
1130 *ret
= sd_bus_creds_ref(c
);
1134 n
= bus_creds_new();
1138 /* Copy the original data over */
1140 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1142 n
->mask
|= SD_BUS_CREDS_PID
;
1145 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1147 n
->mask
|= SD_BUS_CREDS_TID
;
1150 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1152 n
->mask
|= SD_BUS_CREDS_PPID
;
1155 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1157 n
->mask
|= SD_BUS_CREDS_UID
;
1160 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1162 n
->mask
|= SD_BUS_CREDS_EUID
;
1165 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1167 n
->mask
|= SD_BUS_CREDS_SUID
;
1170 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1171 n
->fsuid
= c
->fsuid
;
1172 n
->mask
|= SD_BUS_CREDS_FSUID
;
1175 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1177 n
->mask
|= SD_BUS_CREDS_GID
;
1180 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1182 n
->mask
|= SD_BUS_CREDS_EGID
;
1185 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1187 n
->mask
|= SD_BUS_CREDS_SGID
;
1190 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1191 n
->fsgid
= c
->fsgid
;
1192 n
->mask
|= SD_BUS_CREDS_FSGID
;
1195 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1196 if (c
->supplementary_gids
) {
1197 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1198 if (!n
->supplementary_gids
)
1200 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1202 n
->supplementary_gids
= NULL
;
1203 n
->n_supplementary_gids
= 0;
1206 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1209 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1212 n
->comm
= strdup(c
->comm
);
1216 n
->mask
|= SD_BUS_CREDS_COMM
;
1219 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1220 assert(c
->tid_comm
);
1222 n
->tid_comm
= strdup(c
->tid_comm
);
1226 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1229 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1231 n
->exe
= strdup(c
->exe
);
1237 n
->mask
|= SD_BUS_CREDS_EXE
;
1240 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1242 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1246 n
->cmdline_size
= c
->cmdline_size
;
1249 n
->cmdline_size
= 0;
1252 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1255 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
)) {
1258 n
->cgroup
= strdup(c
->cgroup
);
1262 n
->cgroup_root
= strdup(c
->cgroup_root
);
1263 if (!n
->cgroup_root
)
1266 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
);
1269 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1270 assert(c
->capability
);
1272 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1276 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
);
1279 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1282 n
->label
= strdup(c
->label
);
1285 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1288 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1289 n
->audit_session_id
= c
->audit_session_id
;
1290 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1292 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1293 n
->audit_login_uid
= c
->audit_login_uid
;
1294 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1297 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1299 n
->tty
= strdup(c
->tty
);
1304 n
->mask
|= SD_BUS_CREDS_TTY
;
1307 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1308 assert(c
->unique_name
);
1310 n
->unique_name
= strdup(c
->unique_name
);
1311 if (!n
->unique_name
)
1313 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1316 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1317 if (strv_isempty(c
->well_known_names
))
1318 n
->well_known_names
= NULL
;
1320 n
->well_known_names
= strv_copy(c
->well_known_names
);
1321 if (!n
->well_known_names
)
1324 n
->well_known_names_driver
= c
->well_known_names_driver
;
1325 n
->well_known_names_local
= c
->well_known_names_local
;
1326 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1329 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1330 assert(c
->description
);
1331 n
->description
= strdup(c
->description
);
1332 if (!n
->description
)
1334 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1337 n
->augmented
= c
->augmented
& n
->mask
;
1341 r
= bus_creds_add_more(n
, mask
, 0, 0);