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 c
->well_known_names
= strv_free(c
->well_known_names
);
121 m
= container_of(c
, sd_bus_message
, creds
);
122 sd_bus_message_unref(m
);
129 _public_
uint64_t sd_bus_creds_get_mask(const sd_bus_creds
*c
) {
135 _public_
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds
*c
) {
141 sd_bus_creds
* bus_creds_new(void) {
144 c
= new0(sd_bus_creds
, 1);
153 _public_
int sd_bus_creds_new_from_pid(sd_bus_creds
**ret
, pid_t pid
, uint64_t mask
) {
157 assert_return(pid
>= 0, -EINVAL
);
158 assert_return(mask
<= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
159 assert_return(ret
, -EINVAL
);
168 r
= bus_creds_add_more(c
, mask
| SD_BUS_CREDS_AUGMENT
, pid
, 0);
170 sd_bus_creds_unref(c
);
174 /* Check if the process existed at all, in case we haven't
175 * figured that out already */
176 if (!pid_is_alive(pid
)) {
177 sd_bus_creds_unref(c
);
185 _public_
int sd_bus_creds_get_uid(sd_bus_creds
*c
, uid_t
*uid
) {
186 assert_return(c
, -EINVAL
);
187 assert_return(uid
, -EINVAL
);
189 if (!(c
->mask
& SD_BUS_CREDS_UID
))
196 _public_
int sd_bus_creds_get_euid(sd_bus_creds
*c
, uid_t
*euid
) {
197 assert_return(c
, -EINVAL
);
198 assert_return(euid
, -EINVAL
);
200 if (!(c
->mask
& SD_BUS_CREDS_EUID
))
207 _public_
int sd_bus_creds_get_suid(sd_bus_creds
*c
, uid_t
*suid
) {
208 assert_return(c
, -EINVAL
);
209 assert_return(suid
, -EINVAL
);
211 if (!(c
->mask
& SD_BUS_CREDS_SUID
))
219 _public_
int sd_bus_creds_get_fsuid(sd_bus_creds
*c
, uid_t
*fsuid
) {
220 assert_return(c
, -EINVAL
);
221 assert_return(fsuid
, -EINVAL
);
223 if (!(c
->mask
& SD_BUS_CREDS_FSUID
))
230 _public_
int sd_bus_creds_get_gid(sd_bus_creds
*c
, gid_t
*gid
) {
231 assert_return(c
, -EINVAL
);
232 assert_return(gid
, -EINVAL
);
234 if (!(c
->mask
& SD_BUS_CREDS_GID
))
241 _public_
int sd_bus_creds_get_egid(sd_bus_creds
*c
, gid_t
*egid
) {
242 assert_return(c
, -EINVAL
);
243 assert_return(egid
, -EINVAL
);
245 if (!(c
->mask
& SD_BUS_CREDS_EGID
))
252 _public_
int sd_bus_creds_get_sgid(sd_bus_creds
*c
, gid_t
*sgid
) {
253 assert_return(c
, -EINVAL
);
254 assert_return(sgid
, -EINVAL
);
256 if (!(c
->mask
& SD_BUS_CREDS_SGID
))
263 _public_
int sd_bus_creds_get_fsgid(sd_bus_creds
*c
, gid_t
*fsgid
) {
264 assert_return(c
, -EINVAL
);
265 assert_return(fsgid
, -EINVAL
);
267 if (!(c
->mask
& SD_BUS_CREDS_FSGID
))
274 _public_
int sd_bus_creds_get_supplementary_gids(sd_bus_creds
*c
, const gid_t
**gids
) {
275 assert_return(c
, -EINVAL
);
276 assert_return(gids
, -EINVAL
);
278 if (!(c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
))
281 *gids
= c
->supplementary_gids
;
282 return (int) c
->n_supplementary_gids
;
285 _public_
int sd_bus_creds_get_pid(sd_bus_creds
*c
, pid_t
*pid
) {
286 assert_return(c
, -EINVAL
);
287 assert_return(pid
, -EINVAL
);
289 if (!(c
->mask
& SD_BUS_CREDS_PID
))
297 _public_
int sd_bus_creds_get_ppid(sd_bus_creds
*c
, pid_t
*ppid
) {
298 assert_return(c
, -EINVAL
);
299 assert_return(ppid
, -EINVAL
);
301 if (!(c
->mask
& SD_BUS_CREDS_PPID
))
304 /* PID 1 has no parent process. Let's distinguish the case of
305 * not knowing and not having a parent process by the returned
314 _public_
int sd_bus_creds_get_tid(sd_bus_creds
*c
, pid_t
*tid
) {
315 assert_return(c
, -EINVAL
);
316 assert_return(tid
, -EINVAL
);
318 if (!(c
->mask
& SD_BUS_CREDS_TID
))
326 _public_
int sd_bus_creds_get_selinux_context(sd_bus_creds
*c
, const char **ret
) {
327 assert_return(c
, -EINVAL
);
329 if (!(c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
))
337 _public_
int sd_bus_creds_get_comm(sd_bus_creds
*c
, const char **ret
) {
338 assert_return(c
, -EINVAL
);
339 assert_return(ret
, -EINVAL
);
341 if (!(c
->mask
& SD_BUS_CREDS_COMM
))
349 _public_
int sd_bus_creds_get_tid_comm(sd_bus_creds
*c
, const char **ret
) {
350 assert_return(c
, -EINVAL
);
351 assert_return(ret
, -EINVAL
);
353 if (!(c
->mask
& SD_BUS_CREDS_TID_COMM
))
361 _public_
int sd_bus_creds_get_exe(sd_bus_creds
*c
, const char **ret
) {
362 assert_return(c
, -EINVAL
);
363 assert_return(ret
, -EINVAL
);
365 if (!(c
->mask
& SD_BUS_CREDS_EXE
))
375 _public_
int sd_bus_creds_get_cgroup(sd_bus_creds
*c
, const char **ret
) {
376 assert_return(c
, -EINVAL
);
377 assert_return(ret
, -EINVAL
);
379 if (!(c
->mask
& SD_BUS_CREDS_CGROUP
))
387 _public_
int sd_bus_creds_get_unit(sd_bus_creds
*c
, const char **ret
) {
390 assert_return(c
, -EINVAL
);
391 assert_return(ret
, -EINVAL
);
393 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
401 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
405 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
414 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
417 assert_return(c
, -EINVAL
);
418 assert_return(ret
, -EINVAL
);
420 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
428 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
432 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
441 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
444 assert_return(c
, -EINVAL
);
445 assert_return(ret
, -EINVAL
);
447 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
455 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
459 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
468 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
471 assert_return(c
, -EINVAL
);
472 assert_return(ret
, -EINVAL
);
474 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
479 if (!c
->user_slice
) {
482 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
486 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
491 *ret
= c
->user_slice
;
495 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
498 assert_return(c
, -EINVAL
);
499 assert_return(ret
, -EINVAL
);
501 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
509 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
513 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
522 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
526 assert_return(c
, -EINVAL
);
527 assert_return(uid
, -EINVAL
);
529 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
534 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
538 return cg_path_get_owner_uid(shifted
, uid
);
541 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
542 assert_return(c
, -EINVAL
);
544 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
550 if (!c
->cmdline_array
) {
551 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
552 if (!c
->cmdline_array
)
556 *cmdline
= c
->cmdline_array
;
560 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
561 assert_return(c
, -EINVAL
);
562 assert_return(sessionid
, -EINVAL
);
564 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
567 if (c
->audit_session_id
== AUDIT_SESSION_INVALID
)
570 *sessionid
= c
->audit_session_id
;
574 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
575 assert_return(c
, -EINVAL
);
576 assert_return(uid
, -EINVAL
);
578 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
581 if (c
->audit_login_uid
== UID_INVALID
)
584 *uid
= c
->audit_login_uid
;
588 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
589 assert_return(c
, -EINVAL
);
590 assert_return(ret
, -EINVAL
);
592 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
602 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
603 assert_return(c
, -EINVAL
);
604 assert_return(unique_name
, -EINVAL
);
606 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
609 *unique_name
= c
->unique_name
;
613 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
614 assert_return(c
, -EINVAL
);
615 assert_return(well_known_names
, -EINVAL
);
617 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
620 /* As a special hack we return the bus driver as well-known
621 * names list when this is requested. */
622 if (c
->well_known_names_driver
) {
623 static const char* const wkn
[] = {
624 "org.freedesktop.DBus",
628 *well_known_names
= (char**) wkn
;
632 if (c
->well_known_names_local
) {
633 static const char* const wkn
[] = {
634 "org.freedesktop.DBus.Local",
638 *well_known_names
= (char**) wkn
;
642 *well_known_names
= c
->well_known_names
;
646 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
647 assert_return(c
, -EINVAL
);
648 assert_return(ret
, -EINVAL
);
650 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
653 assert(c
->description
);
655 if (!c
->unescaped_description
) {
656 c
->unescaped_description
= bus_label_unescape(c
->description
);
657 if (!c
->unescaped_description
)
661 *ret
= c
->unescaped_description
;
665 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
669 assert(capability
>= 0);
670 assert(c
->capability
);
672 if ((unsigned) capability
> cap_last_cap())
675 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
677 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
680 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
681 assert_return(c
, -EINVAL
);
682 assert_return(capability
>= 0, -EINVAL
);
684 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
687 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
690 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
691 assert_return(c
, -EINVAL
);
692 assert_return(capability
>= 0, -EINVAL
);
694 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
697 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
700 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
701 assert_return(c
, -EINVAL
);
702 assert_return(capability
>= 0, -EINVAL
);
704 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
707 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
710 _public_
int sd_bus_creds_has_bounding_cap(sd_bus_creds
*c
, int capability
) {
711 assert_return(c
, -EINVAL
);
712 assert_return(capability
>= 0, -EINVAL
);
714 if (!(c
->mask
& SD_BUS_CREDS_BOUNDING_CAPS
))
717 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
720 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
727 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
728 p
+= strspn(p
, WHITESPACE
);
738 if (!c
->capability
) {
739 c
->capability
= new0(uint32_t, max
* 4);
744 for (i
= 0; i
< sz
; i
++) {
747 for (j
= 0; j
< 8; ++j
) {
757 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
763 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
768 assert(c
->allocated
);
770 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
773 /* Try to retrieve PID from creds if it wasn't passed to us */
776 c
->mask
|= SD_BUS_CREDS_PID
;
777 } else if (c
->mask
& SD_BUS_CREDS_PID
)
780 /* 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
);
794 c
->mask
|= SD_BUS_CREDS_TID
;
797 if (missing
& (SD_BUS_CREDS_PPID
|
798 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
799 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
800 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
801 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
802 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
804 _cleanup_fclose_
FILE *f
= NULL
;
807 p
= procfs_file_alloca(pid
, "status");
813 else if (errno
!= EPERM
&& errno
!= EACCES
)
818 FOREACH_LINE(line
, f
, return -errno
) {
821 if (missing
& SD_BUS_CREDS_PPID
) {
822 p
= startswith(line
, "PPid:");
824 p
+= strspn(p
, WHITESPACE
);
826 /* Explicitly check for PPID 0 (which is the case for PID 1) */
827 if (!streq(p
, "0")) {
828 r
= parse_pid(p
, &c
->ppid
);
835 c
->mask
|= SD_BUS_CREDS_PPID
;
840 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
841 p
= startswith(line
, "Uid:");
843 unsigned long uid
, euid
, suid
, fsuid
;
845 p
+= strspn(p
, WHITESPACE
);
846 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
849 if (missing
& SD_BUS_CREDS_UID
)
850 c
->uid
= (uid_t
) uid
;
851 if (missing
& SD_BUS_CREDS_EUID
)
852 c
->euid
= (uid_t
) euid
;
853 if (missing
& SD_BUS_CREDS_SUID
)
854 c
->suid
= (uid_t
) suid
;
855 if (missing
& SD_BUS_CREDS_FSUID
)
856 c
->fsuid
= (uid_t
) fsuid
;
858 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
863 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
864 p
= startswith(line
, "Gid:");
866 unsigned long gid
, egid
, sgid
, fsgid
;
868 p
+= strspn(p
, WHITESPACE
);
869 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
872 if (missing
& SD_BUS_CREDS_GID
)
873 c
->gid
= (gid_t
) gid
;
874 if (missing
& SD_BUS_CREDS_EGID
)
875 c
->egid
= (gid_t
) egid
;
876 if (missing
& SD_BUS_CREDS_SGID
)
877 c
->sgid
= (gid_t
) sgid
;
878 if (missing
& SD_BUS_CREDS_FSGID
)
879 c
->fsgid
= (gid_t
) fsgid
;
881 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
886 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
887 p
= startswith(line
, "Groups:");
889 size_t allocated
= 0;
895 p
+= strspn(p
, WHITESPACE
);
899 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
902 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
905 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
909 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
914 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
915 p
= startswith(line
, "CapEff:");
917 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
921 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
926 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
927 p
= startswith(line
, "CapPrm:");
929 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
933 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
938 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
939 p
= startswith(line
, "CapInh:");
941 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
945 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
950 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
951 p
= startswith(line
, "CapBnd:");
953 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
957 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
965 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
968 p
= procfs_file_alloca(pid
, "attr/current");
969 r
= read_one_line_file(p
, &c
->label
);
971 if (r
!= -ENOENT
&& r
!= -EINVAL
&& r
!= -EPERM
&& r
!= -EACCES
)
974 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
977 if (missing
& SD_BUS_CREDS_COMM
) {
978 r
= get_process_comm(pid
, &c
->comm
);
980 if (r
!= -EPERM
&& r
!= -EACCES
)
983 c
->mask
|= SD_BUS_CREDS_COMM
;
986 if (missing
& SD_BUS_CREDS_EXE
) {
987 r
= get_process_exe(pid
, &c
->exe
);
989 /* Unfortunately we cannot really distinguish
990 * the case here where the process does not
991 * exist, and /proc/$PID/exe being unreadable
992 * because $PID is a kernel thread. Hence,
993 * assume it is a kernel thread, and rely on
994 * that this case is caught with a later
997 c
->mask
|= SD_BUS_CREDS_EXE
;
999 if (r
!= -EPERM
&& r
!= -EACCES
)
1002 c
->mask
|= SD_BUS_CREDS_EXE
;
1005 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1008 p
= procfs_file_alloca(pid
, "cmdline");
1009 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1013 if (r
!= -EPERM
&& r
!= -EACCES
)
1016 if (c
->cmdline_size
== 0)
1017 c
->cmdline
= mfree(c
->cmdline
);
1019 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1023 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1024 _cleanup_free_
char *p
= NULL
;
1026 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1029 r
= read_one_line_file(p
, &c
->tid_comm
);
1033 if (r
!= -EPERM
&& r
!= -EACCES
)
1036 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1039 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
)) {
1042 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1044 if (r
!= -EPERM
&& r
!= -EACCES
)
1049 if (!c
->cgroup_root
) {
1050 r
= cg_get_root_path(&c
->cgroup_root
);
1056 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
);
1059 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1060 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1061 if (r
== -ENODATA
) {
1062 /* ENODATA means: no audit session id assigned */
1063 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1064 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1066 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1069 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1072 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1073 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1074 if (r
== -ENODATA
) {
1075 /* ENODATA means: no audit login uid assigned */
1076 c
->audit_login_uid
= UID_INVALID
;
1077 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1079 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1082 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1085 if (missing
& SD_BUS_CREDS_TTY
) {
1086 r
= get_ctty(pid
, NULL
, &c
->tty
);
1088 /* ENXIO means: process has no controlling TTY */
1090 c
->mask
|= SD_BUS_CREDS_TTY
;
1092 if (r
!= -EPERM
&& r
!= -EACCES
&& r
!= -ENOENT
)
1095 c
->mask
|= SD_BUS_CREDS_TTY
;
1098 /* In case only the exe path was to be read we cannot
1099 * distinguish the case where the exe path was unreadable
1100 * because the process was a kernel thread, or when the
1101 * process didn't exist at all. Hence, let's do a final check,
1103 if (!pid_is_alive(pid
))
1106 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1109 c
->augmented
= missing
& c
->mask
;
1114 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1115 _cleanup_bus_creds_unref_ sd_bus_creds
*n
= NULL
;
1121 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1122 /* There's already all data we need, or augmentation
1123 * wasn't turned on. */
1125 *ret
= sd_bus_creds_ref(c
);
1129 n
= bus_creds_new();
1133 /* Copy the original data over */
1135 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1137 n
->mask
|= SD_BUS_CREDS_PID
;
1140 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1142 n
->mask
|= SD_BUS_CREDS_TID
;
1145 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1147 n
->mask
|= SD_BUS_CREDS_PPID
;
1150 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1152 n
->mask
|= SD_BUS_CREDS_UID
;
1155 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1157 n
->mask
|= SD_BUS_CREDS_EUID
;
1160 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1162 n
->mask
|= SD_BUS_CREDS_SUID
;
1165 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1166 n
->fsuid
= c
->fsuid
;
1167 n
->mask
|= SD_BUS_CREDS_FSUID
;
1170 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1172 n
->mask
|= SD_BUS_CREDS_GID
;
1175 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1177 n
->mask
|= SD_BUS_CREDS_EGID
;
1180 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1182 n
->mask
|= SD_BUS_CREDS_SGID
;
1185 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1186 n
->fsgid
= c
->fsgid
;
1187 n
->mask
|= SD_BUS_CREDS_FSGID
;
1190 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1191 if (c
->supplementary_gids
) {
1192 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1193 if (!n
->supplementary_gids
)
1195 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1197 n
->supplementary_gids
= NULL
;
1198 n
->n_supplementary_gids
= 0;
1201 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1204 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1207 n
->comm
= strdup(c
->comm
);
1211 n
->mask
|= SD_BUS_CREDS_COMM
;
1214 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1215 assert(c
->tid_comm
);
1217 n
->tid_comm
= strdup(c
->tid_comm
);
1221 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1224 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1226 n
->exe
= strdup(c
->exe
);
1232 n
->mask
|= SD_BUS_CREDS_EXE
;
1235 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1237 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1241 n
->cmdline_size
= c
->cmdline_size
;
1244 n
->cmdline_size
= 0;
1247 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1250 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
)) {
1253 n
->cgroup
= strdup(c
->cgroup
);
1257 n
->cgroup_root
= strdup(c
->cgroup_root
);
1258 if (!n
->cgroup_root
)
1261 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
);
1264 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1265 assert(c
->capability
);
1267 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1271 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
);
1274 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1277 n
->label
= strdup(c
->label
);
1280 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1283 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1284 n
->audit_session_id
= c
->audit_session_id
;
1285 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1287 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1288 n
->audit_login_uid
= c
->audit_login_uid
;
1289 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1292 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1294 n
->tty
= strdup(c
->tty
);
1299 n
->mask
|= SD_BUS_CREDS_TTY
;
1302 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1303 assert(c
->unique_name
);
1305 n
->unique_name
= strdup(c
->unique_name
);
1306 if (!n
->unique_name
)
1308 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1311 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1312 if (strv_isempty(c
->well_known_names
))
1313 n
->well_known_names
= NULL
;
1315 n
->well_known_names
= strv_copy(c
->well_known_names
);
1316 if (!n
->well_known_names
)
1319 n
->well_known_names_driver
= c
->well_known_names_driver
;
1320 n
->well_known_names_local
= c
->well_known_names_local
;
1321 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1324 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1325 assert(c
->description
);
1326 n
->description
= strdup(c
->description
);
1327 if (!n
->description
)
1329 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1332 n
->augmented
= c
->augmented
& n
->mask
;
1336 r
= bus_creds_add_more(n
, mask
, 0, 0);