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/>.
22 #include <linux/capability.h>
25 #include "alloc-util.h"
26 #include "audit-util.h"
27 #include "bus-creds.h"
28 #include "bus-label.h"
29 #include "bus-message.h"
31 #include "capability-util.h"
32 #include "cgroup-util.h"
35 #include "formats-util.h"
36 #include "hexdecoct.h"
37 #include "parse-util.h"
38 #include "process-util.h"
39 #include "string-util.h"
41 #include "terminal-util.h"
42 #include "user-util.h"
46 CAP_OFFSET_INHERITABLE
= 0,
47 CAP_OFFSET_PERMITTED
= 1,
48 CAP_OFFSET_EFFECTIVE
= 2,
49 CAP_OFFSET_BOUNDING
= 3
52 void bus_creds_done(sd_bus_creds
*c
) {
55 /* For internal bus cred structures that are allocated by
63 free(c
->unescaped_description
);
64 free(c
->supplementary_gids
);
67 free(c
->well_known_names
); /* note that this is an strv, but
68 * we only free the array, not the
69 * strings the array points to. The
70 * full strv we only free if
71 * c->allocated is set, see
74 strv_free(c
->cmdline_array
);
77 _public_ sd_bus_creds
*sd_bus_creds_ref(sd_bus_creds
*c
) {
88 /* If this is an embedded creds structure, then
89 * forward ref counting to the message */
90 m
= container_of(c
, sd_bus_message
, creds
);
91 sd_bus_message_ref(m
);
97 _public_ sd_bus_creds
*sd_bus_creds_unref(sd_bus_creds
*c
) {
103 assert(c
->n_ref
> 0);
114 free(c
->unique_name
);
115 free(c
->cgroup_root
);
116 free(c
->description
);
118 c
->supplementary_gids
= mfree(c
->supplementary_gids
);
120 c
->well_known_names
= strv_free(c
->well_known_names
);
129 m
= container_of(c
, sd_bus_message
, creds
);
130 sd_bus_message_unref(m
);
137 _public_
uint64_t sd_bus_creds_get_mask(const sd_bus_creds
*c
) {
143 _public_
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds
*c
) {
149 sd_bus_creds
* bus_creds_new(void) {
152 c
= new0(sd_bus_creds
, 1);
161 _public_
int sd_bus_creds_new_from_pid(sd_bus_creds
**ret
, pid_t pid
, uint64_t mask
) {
165 assert_return(pid
>= 0, -EINVAL
);
166 assert_return(mask
<= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
167 assert_return(ret
, -EINVAL
);
176 r
= bus_creds_add_more(c
, mask
| SD_BUS_CREDS_AUGMENT
, pid
, 0);
178 sd_bus_creds_unref(c
);
182 /* Check if the process existed at all, in case we haven't
183 * figured that out already */
184 if (!pid_is_alive(pid
)) {
185 sd_bus_creds_unref(c
);
193 _public_
int sd_bus_creds_get_uid(sd_bus_creds
*c
, uid_t
*uid
) {
194 assert_return(c
, -EINVAL
);
195 assert_return(uid
, -EINVAL
);
197 if (!(c
->mask
& SD_BUS_CREDS_UID
))
204 _public_
int sd_bus_creds_get_euid(sd_bus_creds
*c
, uid_t
*euid
) {
205 assert_return(c
, -EINVAL
);
206 assert_return(euid
, -EINVAL
);
208 if (!(c
->mask
& SD_BUS_CREDS_EUID
))
215 _public_
int sd_bus_creds_get_suid(sd_bus_creds
*c
, uid_t
*suid
) {
216 assert_return(c
, -EINVAL
);
217 assert_return(suid
, -EINVAL
);
219 if (!(c
->mask
& SD_BUS_CREDS_SUID
))
227 _public_
int sd_bus_creds_get_fsuid(sd_bus_creds
*c
, uid_t
*fsuid
) {
228 assert_return(c
, -EINVAL
);
229 assert_return(fsuid
, -EINVAL
);
231 if (!(c
->mask
& SD_BUS_CREDS_FSUID
))
238 _public_
int sd_bus_creds_get_gid(sd_bus_creds
*c
, gid_t
*gid
) {
239 assert_return(c
, -EINVAL
);
240 assert_return(gid
, -EINVAL
);
242 if (!(c
->mask
& SD_BUS_CREDS_GID
))
249 _public_
int sd_bus_creds_get_egid(sd_bus_creds
*c
, gid_t
*egid
) {
250 assert_return(c
, -EINVAL
);
251 assert_return(egid
, -EINVAL
);
253 if (!(c
->mask
& SD_BUS_CREDS_EGID
))
260 _public_
int sd_bus_creds_get_sgid(sd_bus_creds
*c
, gid_t
*sgid
) {
261 assert_return(c
, -EINVAL
);
262 assert_return(sgid
, -EINVAL
);
264 if (!(c
->mask
& SD_BUS_CREDS_SGID
))
271 _public_
int sd_bus_creds_get_fsgid(sd_bus_creds
*c
, gid_t
*fsgid
) {
272 assert_return(c
, -EINVAL
);
273 assert_return(fsgid
, -EINVAL
);
275 if (!(c
->mask
& SD_BUS_CREDS_FSGID
))
282 _public_
int sd_bus_creds_get_supplementary_gids(sd_bus_creds
*c
, const gid_t
**gids
) {
283 assert_return(c
, -EINVAL
);
284 assert_return(gids
, -EINVAL
);
286 if (!(c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
))
289 *gids
= c
->supplementary_gids
;
290 return (int) c
->n_supplementary_gids
;
293 _public_
int sd_bus_creds_get_pid(sd_bus_creds
*c
, pid_t
*pid
) {
294 assert_return(c
, -EINVAL
);
295 assert_return(pid
, -EINVAL
);
297 if (!(c
->mask
& SD_BUS_CREDS_PID
))
305 _public_
int sd_bus_creds_get_ppid(sd_bus_creds
*c
, pid_t
*ppid
) {
306 assert_return(c
, -EINVAL
);
307 assert_return(ppid
, -EINVAL
);
309 if (!(c
->mask
& SD_BUS_CREDS_PPID
))
312 /* PID 1 has no parent process. Let's distinguish the case of
313 * not knowing and not having a parent process by the returned
322 _public_
int sd_bus_creds_get_tid(sd_bus_creds
*c
, pid_t
*tid
) {
323 assert_return(c
, -EINVAL
);
324 assert_return(tid
, -EINVAL
);
326 if (!(c
->mask
& SD_BUS_CREDS_TID
))
334 _public_
int sd_bus_creds_get_selinux_context(sd_bus_creds
*c
, const char **ret
) {
335 assert_return(c
, -EINVAL
);
337 if (!(c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
))
345 _public_
int sd_bus_creds_get_comm(sd_bus_creds
*c
, const char **ret
) {
346 assert_return(c
, -EINVAL
);
347 assert_return(ret
, -EINVAL
);
349 if (!(c
->mask
& SD_BUS_CREDS_COMM
))
357 _public_
int sd_bus_creds_get_tid_comm(sd_bus_creds
*c
, const char **ret
) {
358 assert_return(c
, -EINVAL
);
359 assert_return(ret
, -EINVAL
);
361 if (!(c
->mask
& SD_BUS_CREDS_TID_COMM
))
369 _public_
int sd_bus_creds_get_exe(sd_bus_creds
*c
, const char **ret
) {
370 assert_return(c
, -EINVAL
);
371 assert_return(ret
, -EINVAL
);
373 if (!(c
->mask
& SD_BUS_CREDS_EXE
))
383 _public_
int sd_bus_creds_get_cgroup(sd_bus_creds
*c
, const char **ret
) {
384 assert_return(c
, -EINVAL
);
385 assert_return(ret
, -EINVAL
);
387 if (!(c
->mask
& SD_BUS_CREDS_CGROUP
))
395 _public_
int sd_bus_creds_get_unit(sd_bus_creds
*c
, const char **ret
) {
398 assert_return(c
, -EINVAL
);
399 assert_return(ret
, -EINVAL
);
401 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
409 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
413 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
422 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
425 assert_return(c
, -EINVAL
);
426 assert_return(ret
, -EINVAL
);
428 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
436 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
440 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
449 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
452 assert_return(c
, -EINVAL
);
453 assert_return(ret
, -EINVAL
);
455 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
463 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
467 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
476 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
479 assert_return(c
, -EINVAL
);
480 assert_return(ret
, -EINVAL
);
482 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
487 if (!c
->user_slice
) {
490 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
494 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
499 *ret
= c
->user_slice
;
503 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
506 assert_return(c
, -EINVAL
);
507 assert_return(ret
, -EINVAL
);
509 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
517 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
521 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
530 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
534 assert_return(c
, -EINVAL
);
535 assert_return(uid
, -EINVAL
);
537 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
542 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
546 return cg_path_get_owner_uid(shifted
, uid
);
549 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
550 assert_return(c
, -EINVAL
);
552 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
558 if (!c
->cmdline_array
) {
559 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
560 if (!c
->cmdline_array
)
564 *cmdline
= c
->cmdline_array
;
568 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
569 assert_return(c
, -EINVAL
);
570 assert_return(sessionid
, -EINVAL
);
572 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
575 if (c
->audit_session_id
== AUDIT_SESSION_INVALID
)
578 *sessionid
= c
->audit_session_id
;
582 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
583 assert_return(c
, -EINVAL
);
584 assert_return(uid
, -EINVAL
);
586 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
589 if (c
->audit_login_uid
== UID_INVALID
)
592 *uid
= c
->audit_login_uid
;
596 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
597 assert_return(c
, -EINVAL
);
598 assert_return(ret
, -EINVAL
);
600 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
610 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
611 assert_return(c
, -EINVAL
);
612 assert_return(unique_name
, -EINVAL
);
614 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
617 *unique_name
= c
->unique_name
;
621 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
622 assert_return(c
, -EINVAL
);
623 assert_return(well_known_names
, -EINVAL
);
625 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
628 /* As a special hack we return the bus driver as well-known
629 * names list when this is requested. */
630 if (c
->well_known_names_driver
) {
631 static const char* const wkn
[] = {
632 "org.freedesktop.DBus",
636 *well_known_names
= (char**) wkn
;
640 if (c
->well_known_names_local
) {
641 static const char* const wkn
[] = {
642 "org.freedesktop.DBus.Local",
646 *well_known_names
= (char**) wkn
;
650 *well_known_names
= c
->well_known_names
;
654 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
655 assert_return(c
, -EINVAL
);
656 assert_return(ret
, -EINVAL
);
658 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
661 assert(c
->description
);
663 if (!c
->unescaped_description
) {
664 c
->unescaped_description
= bus_label_unescape(c
->description
);
665 if (!c
->unescaped_description
)
669 *ret
= c
->unescaped_description
;
673 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
677 assert(capability
>= 0);
678 assert(c
->capability
);
680 if ((unsigned) capability
> cap_last_cap())
683 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
685 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
688 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
689 assert_return(c
, -EINVAL
);
690 assert_return(capability
>= 0, -EINVAL
);
692 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
695 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
698 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
699 assert_return(c
, -EINVAL
);
700 assert_return(capability
>= 0, -EINVAL
);
702 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
705 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
708 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
709 assert_return(c
, -EINVAL
);
710 assert_return(capability
>= 0, -EINVAL
);
712 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
715 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
718 _public_
int sd_bus_creds_has_bounding_cap(sd_bus_creds
*c
, int capability
) {
719 assert_return(c
, -EINVAL
);
720 assert_return(capability
>= 0, -EINVAL
);
722 if (!(c
->mask
& SD_BUS_CREDS_BOUNDING_CAPS
))
725 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
728 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
735 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
736 p
+= strspn(p
, WHITESPACE
);
746 if (!c
->capability
) {
747 c
->capability
= new0(uint32_t, max
* 4);
752 for (i
= 0; i
< sz
; i
++) {
755 for (j
= 0; j
< 8; ++j
) {
765 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
771 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
776 assert(c
->allocated
);
778 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
781 /* Try to retrieve PID from creds if it wasn't passed to us */
784 c
->mask
|= SD_BUS_CREDS_PID
;
785 } else if (c
->mask
& SD_BUS_CREDS_PID
)
788 /* Without pid we cannot do much... */
791 /* Try to retrieve TID from creds if it wasn't passed to us */
792 if (tid
<= 0 && (c
->mask
& SD_BUS_CREDS_TID
))
795 /* Calculate what we shall and can add */
796 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
);
802 c
->mask
|= SD_BUS_CREDS_TID
;
805 if (missing
& (SD_BUS_CREDS_PPID
|
806 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
807 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
808 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
809 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
810 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
812 _cleanup_fclose_
FILE *f
= NULL
;
815 p
= procfs_file_alloca(pid
, "status");
821 else if (errno
!= EPERM
&& errno
!= EACCES
)
826 FOREACH_LINE(line
, f
, return -errno
) {
829 if (missing
& SD_BUS_CREDS_PPID
) {
830 p
= startswith(line
, "PPid:");
832 p
+= strspn(p
, WHITESPACE
);
834 /* Explicitly check for PPID 0 (which is the case for PID 1) */
835 if (!streq(p
, "0")) {
836 r
= parse_pid(p
, &c
->ppid
);
843 c
->mask
|= SD_BUS_CREDS_PPID
;
848 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
849 p
= startswith(line
, "Uid:");
851 unsigned long uid
, euid
, suid
, fsuid
;
853 p
+= strspn(p
, WHITESPACE
);
854 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
857 if (missing
& SD_BUS_CREDS_UID
)
858 c
->uid
= (uid_t
) uid
;
859 if (missing
& SD_BUS_CREDS_EUID
)
860 c
->euid
= (uid_t
) euid
;
861 if (missing
& SD_BUS_CREDS_SUID
)
862 c
->suid
= (uid_t
) suid
;
863 if (missing
& SD_BUS_CREDS_FSUID
)
864 c
->fsuid
= (uid_t
) fsuid
;
866 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
871 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
872 p
= startswith(line
, "Gid:");
874 unsigned long gid
, egid
, sgid
, fsgid
;
876 p
+= strspn(p
, WHITESPACE
);
877 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
880 if (missing
& SD_BUS_CREDS_GID
)
881 c
->gid
= (gid_t
) gid
;
882 if (missing
& SD_BUS_CREDS_EGID
)
883 c
->egid
= (gid_t
) egid
;
884 if (missing
& SD_BUS_CREDS_SGID
)
885 c
->sgid
= (gid_t
) sgid
;
886 if (missing
& SD_BUS_CREDS_FSGID
)
887 c
->fsgid
= (gid_t
) fsgid
;
889 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
894 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
895 p
= startswith(line
, "Groups:");
897 size_t allocated
= 0;
903 p
+= strspn(p
, WHITESPACE
);
907 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
910 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
913 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
917 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
922 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
923 p
= startswith(line
, "CapEff:");
925 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
929 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
934 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
935 p
= startswith(line
, "CapPrm:");
937 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
941 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
946 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
947 p
= startswith(line
, "CapInh:");
949 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
953 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
958 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
959 p
= startswith(line
, "CapBnd:");
961 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
965 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
973 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
976 p
= procfs_file_alloca(pid
, "attr/current");
977 r
= read_one_line_file(p
, &c
->label
);
979 if (r
!= -ENOENT
&& r
!= -EINVAL
&& r
!= -EPERM
&& r
!= -EACCES
)
982 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
985 if (missing
& SD_BUS_CREDS_COMM
) {
986 r
= get_process_comm(pid
, &c
->comm
);
988 if (r
!= -EPERM
&& r
!= -EACCES
)
991 c
->mask
|= SD_BUS_CREDS_COMM
;
994 if (missing
& SD_BUS_CREDS_EXE
) {
995 r
= get_process_exe(pid
, &c
->exe
);
997 /* Unfortunately we cannot really distinguish
998 * the case here where the process does not
999 * exist, and /proc/$PID/exe being unreadable
1000 * because $PID is a kernel thread. Hence,
1001 * assume it is a kernel thread, and rely on
1002 * that this case is caught with a later
1005 c
->mask
|= SD_BUS_CREDS_EXE
;
1007 if (r
!= -EPERM
&& r
!= -EACCES
)
1010 c
->mask
|= SD_BUS_CREDS_EXE
;
1013 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1016 p
= procfs_file_alloca(pid
, "cmdline");
1017 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1021 if (r
!= -EPERM
&& r
!= -EACCES
)
1024 if (c
->cmdline_size
== 0)
1025 c
->cmdline
= mfree(c
->cmdline
);
1027 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1031 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1032 _cleanup_free_
char *p
= NULL
;
1034 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1037 r
= read_one_line_file(p
, &c
->tid_comm
);
1041 if (r
!= -EPERM
&& r
!= -EACCES
)
1044 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1047 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
)) {
1050 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1052 if (r
!= -EPERM
&& r
!= -EACCES
)
1057 if (!c
->cgroup_root
) {
1058 r
= cg_get_root_path(&c
->cgroup_root
);
1064 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
);
1067 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1068 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1069 if (r
== -ENODATA
) {
1070 /* ENODATA means: no audit session id assigned */
1071 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1072 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1074 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1077 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1080 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1081 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1082 if (r
== -ENODATA
) {
1083 /* ENODATA means: no audit login uid assigned */
1084 c
->audit_login_uid
= UID_INVALID
;
1085 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1087 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1090 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1093 if (missing
& SD_BUS_CREDS_TTY
) {
1094 r
= get_ctty(pid
, NULL
, &c
->tty
);
1096 /* ENXIO means: process has no controlling TTY */
1098 c
->mask
|= SD_BUS_CREDS_TTY
;
1100 if (r
!= -EPERM
&& r
!= -EACCES
&& r
!= -ENOENT
)
1103 c
->mask
|= SD_BUS_CREDS_TTY
;
1106 /* In case only the exe path was to be read we cannot
1107 * distinguish the case where the exe path was unreadable
1108 * because the process was a kernel thread, or when the
1109 * process didn't exist at all. Hence, let's do a final check,
1111 if (!pid_is_alive(pid
))
1114 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1117 c
->augmented
= missing
& c
->mask
;
1122 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1123 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*n
= NULL
;
1129 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1130 /* There's already all data we need, or augmentation
1131 * wasn't turned on. */
1133 *ret
= sd_bus_creds_ref(c
);
1137 n
= bus_creds_new();
1141 /* Copy the original data over */
1143 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1145 n
->mask
|= SD_BUS_CREDS_PID
;
1148 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1150 n
->mask
|= SD_BUS_CREDS_TID
;
1153 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1155 n
->mask
|= SD_BUS_CREDS_PPID
;
1158 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1160 n
->mask
|= SD_BUS_CREDS_UID
;
1163 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1165 n
->mask
|= SD_BUS_CREDS_EUID
;
1168 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1170 n
->mask
|= SD_BUS_CREDS_SUID
;
1173 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1174 n
->fsuid
= c
->fsuid
;
1175 n
->mask
|= SD_BUS_CREDS_FSUID
;
1178 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1180 n
->mask
|= SD_BUS_CREDS_GID
;
1183 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1185 n
->mask
|= SD_BUS_CREDS_EGID
;
1188 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1190 n
->mask
|= SD_BUS_CREDS_SGID
;
1193 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1194 n
->fsgid
= c
->fsgid
;
1195 n
->mask
|= SD_BUS_CREDS_FSGID
;
1198 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1199 if (c
->supplementary_gids
) {
1200 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1201 if (!n
->supplementary_gids
)
1203 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1205 n
->supplementary_gids
= NULL
;
1206 n
->n_supplementary_gids
= 0;
1209 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1212 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1215 n
->comm
= strdup(c
->comm
);
1219 n
->mask
|= SD_BUS_CREDS_COMM
;
1222 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1223 assert(c
->tid_comm
);
1225 n
->tid_comm
= strdup(c
->tid_comm
);
1229 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1232 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1234 n
->exe
= strdup(c
->exe
);
1240 n
->mask
|= SD_BUS_CREDS_EXE
;
1243 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1245 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1249 n
->cmdline_size
= c
->cmdline_size
;
1252 n
->cmdline_size
= 0;
1255 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1258 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
)) {
1261 n
->cgroup
= strdup(c
->cgroup
);
1265 n
->cgroup_root
= strdup(c
->cgroup_root
);
1266 if (!n
->cgroup_root
)
1269 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
);
1272 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1273 assert(c
->capability
);
1275 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1279 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
);
1282 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1285 n
->label
= strdup(c
->label
);
1288 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1291 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1292 n
->audit_session_id
= c
->audit_session_id
;
1293 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1295 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1296 n
->audit_login_uid
= c
->audit_login_uid
;
1297 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1300 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1302 n
->tty
= strdup(c
->tty
);
1307 n
->mask
|= SD_BUS_CREDS_TTY
;
1310 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1311 assert(c
->unique_name
);
1313 n
->unique_name
= strdup(c
->unique_name
);
1314 if (!n
->unique_name
)
1316 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1319 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1320 if (strv_isempty(c
->well_known_names
))
1321 n
->well_known_names
= NULL
;
1323 n
->well_known_names
= strv_copy(c
->well_known_names
);
1324 if (!n
->well_known_names
)
1327 n
->well_known_names_driver
= c
->well_known_names_driver
;
1328 n
->well_known_names_local
= c
->well_known_names_local
;
1329 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1332 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1333 assert(c
->description
);
1334 n
->description
= strdup(c
->description
);
1335 if (!n
->description
)
1337 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1340 n
->augmented
= c
->augmented
& n
->mask
;
1344 r
= bus_creds_add_more(n
, mask
, 0, 0);