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
) {
78 assert_return(c
, NULL
);
86 /* If this is an embedded creds structure, then
87 * forward ref counting to the message */
88 m
= container_of(c
, sd_bus_message
, creds
);
89 sd_bus_message_ref(m
);
95 _public_ sd_bus_creds
*sd_bus_creds_unref(sd_bus_creds
*c
) {
101 assert(c
->n_ref
> 0);
112 free(c
->unique_name
);
113 free(c
->cgroup_root
);
114 free(c
->description
);
116 c
->supplementary_gids
= mfree(c
->supplementary_gids
);
118 c
->well_known_names
= strv_free(c
->well_known_names
);
127 m
= container_of(c
, sd_bus_message
, creds
);
128 sd_bus_message_unref(m
);
135 _public_
uint64_t sd_bus_creds_get_mask(const sd_bus_creds
*c
) {
141 _public_
uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds
*c
) {
147 sd_bus_creds
* bus_creds_new(void) {
150 c
= new0(sd_bus_creds
, 1);
159 _public_
int sd_bus_creds_new_from_pid(sd_bus_creds
**ret
, pid_t pid
, uint64_t mask
) {
163 assert_return(pid
>= 0, -EINVAL
);
164 assert_return(mask
<= _SD_BUS_CREDS_ALL
, -EOPNOTSUPP
);
165 assert_return(ret
, -EINVAL
);
174 r
= bus_creds_add_more(c
, mask
| SD_BUS_CREDS_AUGMENT
, pid
, 0);
176 sd_bus_creds_unref(c
);
180 /* Check if the process existed at all, in case we haven't
181 * figured that out already */
182 if (!pid_is_alive(pid
)) {
183 sd_bus_creds_unref(c
);
191 _public_
int sd_bus_creds_get_uid(sd_bus_creds
*c
, uid_t
*uid
) {
192 assert_return(c
, -EINVAL
);
193 assert_return(uid
, -EINVAL
);
195 if (!(c
->mask
& SD_BUS_CREDS_UID
))
202 _public_
int sd_bus_creds_get_euid(sd_bus_creds
*c
, uid_t
*euid
) {
203 assert_return(c
, -EINVAL
);
204 assert_return(euid
, -EINVAL
);
206 if (!(c
->mask
& SD_BUS_CREDS_EUID
))
213 _public_
int sd_bus_creds_get_suid(sd_bus_creds
*c
, uid_t
*suid
) {
214 assert_return(c
, -EINVAL
);
215 assert_return(suid
, -EINVAL
);
217 if (!(c
->mask
& SD_BUS_CREDS_SUID
))
225 _public_
int sd_bus_creds_get_fsuid(sd_bus_creds
*c
, uid_t
*fsuid
) {
226 assert_return(c
, -EINVAL
);
227 assert_return(fsuid
, -EINVAL
);
229 if (!(c
->mask
& SD_BUS_CREDS_FSUID
))
236 _public_
int sd_bus_creds_get_gid(sd_bus_creds
*c
, gid_t
*gid
) {
237 assert_return(c
, -EINVAL
);
238 assert_return(gid
, -EINVAL
);
240 if (!(c
->mask
& SD_BUS_CREDS_GID
))
247 _public_
int sd_bus_creds_get_egid(sd_bus_creds
*c
, gid_t
*egid
) {
248 assert_return(c
, -EINVAL
);
249 assert_return(egid
, -EINVAL
);
251 if (!(c
->mask
& SD_BUS_CREDS_EGID
))
258 _public_
int sd_bus_creds_get_sgid(sd_bus_creds
*c
, gid_t
*sgid
) {
259 assert_return(c
, -EINVAL
);
260 assert_return(sgid
, -EINVAL
);
262 if (!(c
->mask
& SD_BUS_CREDS_SGID
))
269 _public_
int sd_bus_creds_get_fsgid(sd_bus_creds
*c
, gid_t
*fsgid
) {
270 assert_return(c
, -EINVAL
);
271 assert_return(fsgid
, -EINVAL
);
273 if (!(c
->mask
& SD_BUS_CREDS_FSGID
))
280 _public_
int sd_bus_creds_get_supplementary_gids(sd_bus_creds
*c
, const gid_t
**gids
) {
281 assert_return(c
, -EINVAL
);
282 assert_return(gids
, -EINVAL
);
284 if (!(c
->mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
))
287 *gids
= c
->supplementary_gids
;
288 return (int) c
->n_supplementary_gids
;
291 _public_
int sd_bus_creds_get_pid(sd_bus_creds
*c
, pid_t
*pid
) {
292 assert_return(c
, -EINVAL
);
293 assert_return(pid
, -EINVAL
);
295 if (!(c
->mask
& SD_BUS_CREDS_PID
))
303 _public_
int sd_bus_creds_get_ppid(sd_bus_creds
*c
, pid_t
*ppid
) {
304 assert_return(c
, -EINVAL
);
305 assert_return(ppid
, -EINVAL
);
307 if (!(c
->mask
& SD_BUS_CREDS_PPID
))
310 /* PID 1 has no parent process. Let's distinguish the case of
311 * not knowing and not having a parent process by the returned
320 _public_
int sd_bus_creds_get_tid(sd_bus_creds
*c
, pid_t
*tid
) {
321 assert_return(c
, -EINVAL
);
322 assert_return(tid
, -EINVAL
);
324 if (!(c
->mask
& SD_BUS_CREDS_TID
))
332 _public_
int sd_bus_creds_get_selinux_context(sd_bus_creds
*c
, const char **ret
) {
333 assert_return(c
, -EINVAL
);
335 if (!(c
->mask
& SD_BUS_CREDS_SELINUX_CONTEXT
))
343 _public_
int sd_bus_creds_get_comm(sd_bus_creds
*c
, const char **ret
) {
344 assert_return(c
, -EINVAL
);
345 assert_return(ret
, -EINVAL
);
347 if (!(c
->mask
& SD_BUS_CREDS_COMM
))
355 _public_
int sd_bus_creds_get_tid_comm(sd_bus_creds
*c
, const char **ret
) {
356 assert_return(c
, -EINVAL
);
357 assert_return(ret
, -EINVAL
);
359 if (!(c
->mask
& SD_BUS_CREDS_TID_COMM
))
367 _public_
int sd_bus_creds_get_exe(sd_bus_creds
*c
, const char **ret
) {
368 assert_return(c
, -EINVAL
);
369 assert_return(ret
, -EINVAL
);
371 if (!(c
->mask
& SD_BUS_CREDS_EXE
))
381 _public_
int sd_bus_creds_get_cgroup(sd_bus_creds
*c
, const char **ret
) {
382 assert_return(c
, -EINVAL
);
383 assert_return(ret
, -EINVAL
);
385 if (!(c
->mask
& SD_BUS_CREDS_CGROUP
))
393 _public_
int sd_bus_creds_get_unit(sd_bus_creds
*c
, const char **ret
) {
396 assert_return(c
, -EINVAL
);
397 assert_return(ret
, -EINVAL
);
399 if (!(c
->mask
& SD_BUS_CREDS_UNIT
))
407 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
411 r
= cg_path_get_unit(shifted
, (char**) &c
->unit
);
420 _public_
int sd_bus_creds_get_user_unit(sd_bus_creds
*c
, const char **ret
) {
423 assert_return(c
, -EINVAL
);
424 assert_return(ret
, -EINVAL
);
426 if (!(c
->mask
& SD_BUS_CREDS_USER_UNIT
))
434 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
438 r
= cg_path_get_user_unit(shifted
, (char**) &c
->user_unit
);
447 _public_
int sd_bus_creds_get_slice(sd_bus_creds
*c
, const char **ret
) {
450 assert_return(c
, -EINVAL
);
451 assert_return(ret
, -EINVAL
);
453 if (!(c
->mask
& SD_BUS_CREDS_SLICE
))
461 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
465 r
= cg_path_get_slice(shifted
, (char**) &c
->slice
);
474 _public_
int sd_bus_creds_get_user_slice(sd_bus_creds
*c
, const char **ret
) {
477 assert_return(c
, -EINVAL
);
478 assert_return(ret
, -EINVAL
);
480 if (!(c
->mask
& SD_BUS_CREDS_USER_SLICE
))
485 if (!c
->user_slice
) {
488 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
492 r
= cg_path_get_user_slice(shifted
, (char**) &c
->user_slice
);
497 *ret
= c
->user_slice
;
501 _public_
int sd_bus_creds_get_session(sd_bus_creds
*c
, const char **ret
) {
504 assert_return(c
, -EINVAL
);
505 assert_return(ret
, -EINVAL
);
507 if (!(c
->mask
& SD_BUS_CREDS_SESSION
))
515 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
519 r
= cg_path_get_session(shifted
, (char**) &c
->session
);
528 _public_
int sd_bus_creds_get_owner_uid(sd_bus_creds
*c
, uid_t
*uid
) {
532 assert_return(c
, -EINVAL
);
533 assert_return(uid
, -EINVAL
);
535 if (!(c
->mask
& SD_BUS_CREDS_OWNER_UID
))
540 r
= cg_shift_path(c
->cgroup
, c
->cgroup_root
, &shifted
);
544 return cg_path_get_owner_uid(shifted
, uid
);
547 _public_
int sd_bus_creds_get_cmdline(sd_bus_creds
*c
, char ***cmdline
) {
548 assert_return(c
, -EINVAL
);
550 if (!(c
->mask
& SD_BUS_CREDS_CMDLINE
))
556 if (!c
->cmdline_array
) {
557 c
->cmdline_array
= strv_parse_nulstr(c
->cmdline
, c
->cmdline_size
);
558 if (!c
->cmdline_array
)
562 *cmdline
= c
->cmdline_array
;
566 _public_
int sd_bus_creds_get_audit_session_id(sd_bus_creds
*c
, uint32_t *sessionid
) {
567 assert_return(c
, -EINVAL
);
568 assert_return(sessionid
, -EINVAL
);
570 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
))
573 if (c
->audit_session_id
== AUDIT_SESSION_INVALID
)
576 *sessionid
= c
->audit_session_id
;
580 _public_
int sd_bus_creds_get_audit_login_uid(sd_bus_creds
*c
, uid_t
*uid
) {
581 assert_return(c
, -EINVAL
);
582 assert_return(uid
, -EINVAL
);
584 if (!(c
->mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
))
587 if (c
->audit_login_uid
== UID_INVALID
)
590 *uid
= c
->audit_login_uid
;
594 _public_
int sd_bus_creds_get_tty(sd_bus_creds
*c
, const char **ret
) {
595 assert_return(c
, -EINVAL
);
596 assert_return(ret
, -EINVAL
);
598 if (!(c
->mask
& SD_BUS_CREDS_TTY
))
608 _public_
int sd_bus_creds_get_unique_name(sd_bus_creds
*c
, const char **unique_name
) {
609 assert_return(c
, -EINVAL
);
610 assert_return(unique_name
, -EINVAL
);
612 if (!(c
->mask
& SD_BUS_CREDS_UNIQUE_NAME
))
615 *unique_name
= c
->unique_name
;
619 _public_
int sd_bus_creds_get_well_known_names(sd_bus_creds
*c
, char ***well_known_names
) {
620 assert_return(c
, -EINVAL
);
621 assert_return(well_known_names
, -EINVAL
);
623 if (!(c
->mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
))
626 /* As a special hack we return the bus driver as well-known
627 * names list when this is requested. */
628 if (c
->well_known_names_driver
) {
629 static const char* const wkn
[] = {
630 "org.freedesktop.DBus",
634 *well_known_names
= (char**) wkn
;
638 if (c
->well_known_names_local
) {
639 static const char* const wkn
[] = {
640 "org.freedesktop.DBus.Local",
644 *well_known_names
= (char**) wkn
;
648 *well_known_names
= c
->well_known_names
;
652 _public_
int sd_bus_creds_get_description(sd_bus_creds
*c
, const char **ret
) {
653 assert_return(c
, -EINVAL
);
654 assert_return(ret
, -EINVAL
);
656 if (!(c
->mask
& SD_BUS_CREDS_DESCRIPTION
))
659 assert(c
->description
);
661 if (!c
->unescaped_description
) {
662 c
->unescaped_description
= bus_label_unescape(c
->description
);
663 if (!c
->unescaped_description
)
667 *ret
= c
->unescaped_description
;
671 static int has_cap(sd_bus_creds
*c
, unsigned offset
, int capability
) {
675 assert(capability
>= 0);
676 assert(c
->capability
);
678 if ((unsigned) capability
> cap_last_cap())
681 sz
= DIV_ROUND_UP(cap_last_cap(), 32U);
683 return !!(c
->capability
[offset
* sz
+ CAP_TO_INDEX(capability
)] & CAP_TO_MASK(capability
));
686 _public_
int sd_bus_creds_has_effective_cap(sd_bus_creds
*c
, int capability
) {
687 assert_return(c
, -EINVAL
);
688 assert_return(capability
>= 0, -EINVAL
);
690 if (!(c
->mask
& SD_BUS_CREDS_EFFECTIVE_CAPS
))
693 return has_cap(c
, CAP_OFFSET_EFFECTIVE
, capability
);
696 _public_
int sd_bus_creds_has_permitted_cap(sd_bus_creds
*c
, int capability
) {
697 assert_return(c
, -EINVAL
);
698 assert_return(capability
>= 0, -EINVAL
);
700 if (!(c
->mask
& SD_BUS_CREDS_PERMITTED_CAPS
))
703 return has_cap(c
, CAP_OFFSET_PERMITTED
, capability
);
706 _public_
int sd_bus_creds_has_inheritable_cap(sd_bus_creds
*c
, int capability
) {
707 assert_return(c
, -EINVAL
);
708 assert_return(capability
>= 0, -EINVAL
);
710 if (!(c
->mask
& SD_BUS_CREDS_INHERITABLE_CAPS
))
713 return has_cap(c
, CAP_OFFSET_INHERITABLE
, capability
);
716 _public_
int sd_bus_creds_has_bounding_cap(sd_bus_creds
*c
, int capability
) {
717 assert_return(c
, -EINVAL
);
718 assert_return(capability
>= 0, -EINVAL
);
720 if (!(c
->mask
& SD_BUS_CREDS_BOUNDING_CAPS
))
723 return has_cap(c
, CAP_OFFSET_BOUNDING
, capability
);
726 static int parse_caps(sd_bus_creds
*c
, unsigned offset
, const char *p
) {
733 max
= DIV_ROUND_UP(cap_last_cap(), 32U);
734 p
+= strspn(p
, WHITESPACE
);
744 if (!c
->capability
) {
745 c
->capability
= new0(uint32_t, max
* 4);
750 for (i
= 0; i
< sz
; i
++) {
753 for (j
= 0; j
< 8; ++j
) {
763 c
->capability
[offset
* max
+ (sz
- i
- 1)] = v
;
769 int bus_creds_add_more(sd_bus_creds
*c
, uint64_t mask
, pid_t pid
, pid_t tid
) {
774 assert(c
->allocated
);
776 if (!(mask
& SD_BUS_CREDS_AUGMENT
))
779 /* Try to retrieve PID from creds if it wasn't passed to us */
782 c
->mask
|= SD_BUS_CREDS_PID
;
783 } else if (c
->mask
& SD_BUS_CREDS_PID
)
786 /* Without pid we cannot do much... */
789 /* Try to retrieve TID from creds if it wasn't passed to us */
790 if (tid
<= 0 && (c
->mask
& SD_BUS_CREDS_TID
))
793 /* Calculate what we shall and can add */
794 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
);
800 c
->mask
|= SD_BUS_CREDS_TID
;
803 if (missing
& (SD_BUS_CREDS_PPID
|
804 SD_BUS_CREDS_UID
| SD_BUS_CREDS_EUID
| SD_BUS_CREDS_SUID
| SD_BUS_CREDS_FSUID
|
805 SD_BUS_CREDS_GID
| SD_BUS_CREDS_EGID
| SD_BUS_CREDS_SGID
| SD_BUS_CREDS_FSGID
|
806 SD_BUS_CREDS_SUPPLEMENTARY_GIDS
|
807 SD_BUS_CREDS_EFFECTIVE_CAPS
| SD_BUS_CREDS_INHERITABLE_CAPS
|
808 SD_BUS_CREDS_PERMITTED_CAPS
| SD_BUS_CREDS_BOUNDING_CAPS
)) {
810 _cleanup_fclose_
FILE *f
= NULL
;
813 p
= procfs_file_alloca(pid
, "status");
819 else if (errno
!= EPERM
&& errno
!= EACCES
)
824 FOREACH_LINE(line
, f
, return -errno
) {
827 if (missing
& SD_BUS_CREDS_PPID
) {
828 p
= startswith(line
, "PPid:");
830 p
+= strspn(p
, WHITESPACE
);
832 /* Explicitly check for PPID 0 (which is the case for PID 1) */
833 if (!streq(p
, "0")) {
834 r
= parse_pid(p
, &c
->ppid
);
841 c
->mask
|= SD_BUS_CREDS_PPID
;
846 if (missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
)) {
847 p
= startswith(line
, "Uid:");
849 unsigned long uid
, euid
, suid
, fsuid
;
851 p
+= strspn(p
, WHITESPACE
);
852 if (sscanf(p
, "%lu %lu %lu %lu", &uid
, &euid
, &suid
, &fsuid
) != 4)
855 if (missing
& SD_BUS_CREDS_UID
)
856 c
->uid
= (uid_t
) uid
;
857 if (missing
& SD_BUS_CREDS_EUID
)
858 c
->euid
= (uid_t
) euid
;
859 if (missing
& SD_BUS_CREDS_SUID
)
860 c
->suid
= (uid_t
) suid
;
861 if (missing
& SD_BUS_CREDS_FSUID
)
862 c
->fsuid
= (uid_t
) fsuid
;
864 c
->mask
|= missing
& (SD_BUS_CREDS_UID
|SD_BUS_CREDS_EUID
|SD_BUS_CREDS_SUID
|SD_BUS_CREDS_FSUID
);
869 if (missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
)) {
870 p
= startswith(line
, "Gid:");
872 unsigned long gid
, egid
, sgid
, fsgid
;
874 p
+= strspn(p
, WHITESPACE
);
875 if (sscanf(p
, "%lu %lu %lu %lu", &gid
, &egid
, &sgid
, &fsgid
) != 4)
878 if (missing
& SD_BUS_CREDS_GID
)
879 c
->gid
= (gid_t
) gid
;
880 if (missing
& SD_BUS_CREDS_EGID
)
881 c
->egid
= (gid_t
) egid
;
882 if (missing
& SD_BUS_CREDS_SGID
)
883 c
->sgid
= (gid_t
) sgid
;
884 if (missing
& SD_BUS_CREDS_FSGID
)
885 c
->fsgid
= (gid_t
) fsgid
;
887 c
->mask
|= missing
& (SD_BUS_CREDS_GID
|SD_BUS_CREDS_EGID
|SD_BUS_CREDS_SGID
|SD_BUS_CREDS_FSGID
);
892 if (missing
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
893 p
= startswith(line
, "Groups:");
895 size_t allocated
= 0;
901 p
+= strspn(p
, WHITESPACE
);
905 if (sscanf(p
, "%lu%n", &g
, &n
) != 1)
908 if (!GREEDY_REALLOC(c
->supplementary_gids
, allocated
, c
->n_supplementary_gids
+1))
911 c
->supplementary_gids
[c
->n_supplementary_gids
++] = (gid_t
) g
;
915 c
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
920 if (missing
& SD_BUS_CREDS_EFFECTIVE_CAPS
) {
921 p
= startswith(line
, "CapEff:");
923 r
= parse_caps(c
, CAP_OFFSET_EFFECTIVE
, p
);
927 c
->mask
|= SD_BUS_CREDS_EFFECTIVE_CAPS
;
932 if (missing
& SD_BUS_CREDS_PERMITTED_CAPS
) {
933 p
= startswith(line
, "CapPrm:");
935 r
= parse_caps(c
, CAP_OFFSET_PERMITTED
, p
);
939 c
->mask
|= SD_BUS_CREDS_PERMITTED_CAPS
;
944 if (missing
& SD_BUS_CREDS_INHERITABLE_CAPS
) {
945 p
= startswith(line
, "CapInh:");
947 r
= parse_caps(c
, CAP_OFFSET_INHERITABLE
, p
);
951 c
->mask
|= SD_BUS_CREDS_INHERITABLE_CAPS
;
956 if (missing
& SD_BUS_CREDS_BOUNDING_CAPS
) {
957 p
= startswith(line
, "CapBnd:");
959 r
= parse_caps(c
, CAP_OFFSET_BOUNDING
, p
);
963 c
->mask
|= SD_BUS_CREDS_BOUNDING_CAPS
;
971 if (missing
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
974 p
= procfs_file_alloca(pid
, "attr/current");
975 r
= read_one_line_file(p
, &c
->label
);
977 if (r
!= -ENOENT
&& r
!= -EINVAL
&& r
!= -EPERM
&& r
!= -EACCES
)
980 c
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
983 if (missing
& SD_BUS_CREDS_COMM
) {
984 r
= get_process_comm(pid
, &c
->comm
);
986 if (r
!= -EPERM
&& r
!= -EACCES
)
989 c
->mask
|= SD_BUS_CREDS_COMM
;
992 if (missing
& SD_BUS_CREDS_EXE
) {
993 r
= get_process_exe(pid
, &c
->exe
);
995 /* Unfortunately we cannot really distinguish
996 * the case here where the process does not
997 * exist, and /proc/$PID/exe being unreadable
998 * because $PID is a kernel thread. Hence,
999 * assume it is a kernel thread, and rely on
1000 * that this case is caught with a later
1003 c
->mask
|= SD_BUS_CREDS_EXE
;
1005 if (r
!= -EPERM
&& r
!= -EACCES
)
1008 c
->mask
|= SD_BUS_CREDS_EXE
;
1011 if (missing
& SD_BUS_CREDS_CMDLINE
) {
1014 p
= procfs_file_alloca(pid
, "cmdline");
1015 r
= read_full_file(p
, &c
->cmdline
, &c
->cmdline_size
);
1019 if (r
!= -EPERM
&& r
!= -EACCES
)
1022 if (c
->cmdline_size
== 0)
1023 c
->cmdline
= mfree(c
->cmdline
);
1025 c
->mask
|= SD_BUS_CREDS_CMDLINE
;
1029 if (tid
> 0 && (missing
& SD_BUS_CREDS_TID_COMM
)) {
1030 _cleanup_free_
char *p
= NULL
;
1032 if (asprintf(&p
, "/proc/"PID_FMT
"/task/"PID_FMT
"/comm", pid
, tid
) < 0)
1035 r
= read_one_line_file(p
, &c
->tid_comm
);
1039 if (r
!= -EPERM
&& r
!= -EACCES
)
1042 c
->mask
|= SD_BUS_CREDS_TID_COMM
;
1045 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
)) {
1048 r
= cg_pid_get_path(NULL
, pid
, &c
->cgroup
);
1050 if (r
!= -EPERM
&& r
!= -EACCES
)
1055 if (!c
->cgroup_root
) {
1056 r
= cg_get_root_path(&c
->cgroup_root
);
1062 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
);
1065 if (missing
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1066 r
= audit_session_from_pid(pid
, &c
->audit_session_id
);
1067 if (r
== -ENODATA
) {
1068 /* ENODATA means: no audit session id assigned */
1069 c
->audit_session_id
= AUDIT_SESSION_INVALID
;
1070 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1072 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1075 c
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1078 if (missing
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1079 r
= audit_loginuid_from_pid(pid
, &c
->audit_login_uid
);
1080 if (r
== -ENODATA
) {
1081 /* ENODATA means: no audit login uid assigned */
1082 c
->audit_login_uid
= UID_INVALID
;
1083 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1085 if (r
!= -EOPNOTSUPP
&& r
!= -ENOENT
&& r
!= -EPERM
&& r
!= -EACCES
)
1088 c
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1091 if (missing
& SD_BUS_CREDS_TTY
) {
1092 r
= get_ctty(pid
, NULL
, &c
->tty
);
1094 /* ENXIO means: process has no controlling TTY */
1096 c
->mask
|= SD_BUS_CREDS_TTY
;
1098 if (r
!= -EPERM
&& r
!= -EACCES
&& r
!= -ENOENT
)
1101 c
->mask
|= SD_BUS_CREDS_TTY
;
1104 /* In case only the exe path was to be read we cannot
1105 * distinguish the case where the exe path was unreadable
1106 * because the process was a kernel thread, or when the
1107 * process didn't exist at all. Hence, let's do a final check,
1109 if (!pid_is_alive(pid
))
1112 if (tid
> 0 && tid
!= pid
&& !pid_is_unwaited(tid
))
1115 c
->augmented
= missing
& c
->mask
;
1120 int bus_creds_extend_by_pid(sd_bus_creds
*c
, uint64_t mask
, sd_bus_creds
**ret
) {
1121 _cleanup_bus_creds_unref_ sd_bus_creds
*n
= NULL
;
1127 if ((mask
& ~c
->mask
) == 0 || (!(mask
& SD_BUS_CREDS_AUGMENT
))) {
1128 /* There's already all data we need, or augmentation
1129 * wasn't turned on. */
1131 *ret
= sd_bus_creds_ref(c
);
1135 n
= bus_creds_new();
1139 /* Copy the original data over */
1141 if (c
->mask
& mask
& SD_BUS_CREDS_PID
) {
1143 n
->mask
|= SD_BUS_CREDS_PID
;
1146 if (c
->mask
& mask
& SD_BUS_CREDS_TID
) {
1148 n
->mask
|= SD_BUS_CREDS_TID
;
1151 if (c
->mask
& mask
& SD_BUS_CREDS_PPID
) {
1153 n
->mask
|= SD_BUS_CREDS_PPID
;
1156 if (c
->mask
& mask
& SD_BUS_CREDS_UID
) {
1158 n
->mask
|= SD_BUS_CREDS_UID
;
1161 if (c
->mask
& mask
& SD_BUS_CREDS_EUID
) {
1163 n
->mask
|= SD_BUS_CREDS_EUID
;
1166 if (c
->mask
& mask
& SD_BUS_CREDS_SUID
) {
1168 n
->mask
|= SD_BUS_CREDS_SUID
;
1171 if (c
->mask
& mask
& SD_BUS_CREDS_FSUID
) {
1172 n
->fsuid
= c
->fsuid
;
1173 n
->mask
|= SD_BUS_CREDS_FSUID
;
1176 if (c
->mask
& mask
& SD_BUS_CREDS_GID
) {
1178 n
->mask
|= SD_BUS_CREDS_GID
;
1181 if (c
->mask
& mask
& SD_BUS_CREDS_EGID
) {
1183 n
->mask
|= SD_BUS_CREDS_EGID
;
1186 if (c
->mask
& mask
& SD_BUS_CREDS_SGID
) {
1188 n
->mask
|= SD_BUS_CREDS_SGID
;
1191 if (c
->mask
& mask
& SD_BUS_CREDS_FSGID
) {
1192 n
->fsgid
= c
->fsgid
;
1193 n
->mask
|= SD_BUS_CREDS_FSGID
;
1196 if (c
->mask
& mask
& SD_BUS_CREDS_SUPPLEMENTARY_GIDS
) {
1197 if (c
->supplementary_gids
) {
1198 n
->supplementary_gids
= newdup(gid_t
, c
->supplementary_gids
, c
->n_supplementary_gids
);
1199 if (!n
->supplementary_gids
)
1201 n
->n_supplementary_gids
= c
->n_supplementary_gids
;
1203 n
->supplementary_gids
= NULL
;
1204 n
->n_supplementary_gids
= 0;
1207 n
->mask
|= SD_BUS_CREDS_SUPPLEMENTARY_GIDS
;
1210 if (c
->mask
& mask
& SD_BUS_CREDS_COMM
) {
1213 n
->comm
= strdup(c
->comm
);
1217 n
->mask
|= SD_BUS_CREDS_COMM
;
1220 if (c
->mask
& mask
& SD_BUS_CREDS_TID_COMM
) {
1221 assert(c
->tid_comm
);
1223 n
->tid_comm
= strdup(c
->tid_comm
);
1227 n
->mask
|= SD_BUS_CREDS_TID_COMM
;
1230 if (c
->mask
& mask
& SD_BUS_CREDS_EXE
) {
1232 n
->exe
= strdup(c
->exe
);
1238 n
->mask
|= SD_BUS_CREDS_EXE
;
1241 if (c
->mask
& mask
& SD_BUS_CREDS_CMDLINE
) {
1243 n
->cmdline
= memdup(c
->cmdline
, c
->cmdline_size
);
1247 n
->cmdline_size
= c
->cmdline_size
;
1250 n
->cmdline_size
= 0;
1253 n
->mask
|= SD_BUS_CREDS_CMDLINE
;
1256 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
)) {
1259 n
->cgroup
= strdup(c
->cgroup
);
1263 n
->cgroup_root
= strdup(c
->cgroup_root
);
1264 if (!n
->cgroup_root
)
1267 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
);
1270 if (c
->mask
& mask
& (SD_BUS_CREDS_EFFECTIVE_CAPS
|SD_BUS_CREDS_PERMITTED_CAPS
|SD_BUS_CREDS_INHERITABLE_CAPS
|SD_BUS_CREDS_BOUNDING_CAPS
)) {
1271 assert(c
->capability
);
1273 n
->capability
= memdup(c
->capability
, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1277 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
);
1280 if (c
->mask
& mask
& SD_BUS_CREDS_SELINUX_CONTEXT
) {
1283 n
->label
= strdup(c
->label
);
1286 n
->mask
|= SD_BUS_CREDS_SELINUX_CONTEXT
;
1289 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_SESSION_ID
) {
1290 n
->audit_session_id
= c
->audit_session_id
;
1291 n
->mask
|= SD_BUS_CREDS_AUDIT_SESSION_ID
;
1293 if (c
->mask
& mask
& SD_BUS_CREDS_AUDIT_LOGIN_UID
) {
1294 n
->audit_login_uid
= c
->audit_login_uid
;
1295 n
->mask
|= SD_BUS_CREDS_AUDIT_LOGIN_UID
;
1298 if (c
->mask
& mask
& SD_BUS_CREDS_TTY
) {
1300 n
->tty
= strdup(c
->tty
);
1305 n
->mask
|= SD_BUS_CREDS_TTY
;
1308 if (c
->mask
& mask
& SD_BUS_CREDS_UNIQUE_NAME
) {
1309 assert(c
->unique_name
);
1311 n
->unique_name
= strdup(c
->unique_name
);
1312 if (!n
->unique_name
)
1314 n
->mask
|= SD_BUS_CREDS_UNIQUE_NAME
;
1317 if (c
->mask
& mask
& SD_BUS_CREDS_WELL_KNOWN_NAMES
) {
1318 if (strv_isempty(c
->well_known_names
))
1319 n
->well_known_names
= NULL
;
1321 n
->well_known_names
= strv_copy(c
->well_known_names
);
1322 if (!n
->well_known_names
)
1325 n
->well_known_names_driver
= c
->well_known_names_driver
;
1326 n
->well_known_names_local
= c
->well_known_names_local
;
1327 n
->mask
|= SD_BUS_CREDS_WELL_KNOWN_NAMES
;
1330 if (c
->mask
& mask
& SD_BUS_CREDS_DESCRIPTION
) {
1331 assert(c
->description
);
1332 n
->description
= strdup(c
->description
);
1333 if (!n
->description
)
1335 n
->mask
|= SD_BUS_CREDS_DESCRIPTION
;
1338 n
->augmented
= c
->augmented
& n
->mask
;
1342 r
= bus_creds_add_more(n
, mask
, 0, 0);