2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/capability.h>
23 #include "alloc-util.h"
24 #include "audit-util.h"
25 #include "bus-creds.h"
26 #include "bus-label.h"
27 #include "bus-message.h"
29 #include "capability-util.h"
30 #include "cgroup-util.h"
33 #include "formats-util.h"
34 #include "hexdecoct.h"
35 #include "parse-util.h"
36 #include "process-util.h"
37 #include "string-util.h"
39 #include "terminal-util.h"
40 #include "user-util.h"
44 CAP_OFFSET_INHERITABLE
= 0,
45 CAP_OFFSET_PERMITTED
= 1,
46 CAP_OFFSET_EFFECTIVE
= 2,
47 CAP_OFFSET_BOUNDING
= 3
50 void bus_creds_done(sd_bus_creds
*c
) {
53 /* For internal bus cred structures that are allocated by
61 free(c
->unescaped_description
);
62 free(c
->supplementary_gids
);
65 free(c
->well_known_names
); /* note that this is an strv, but
66 * we only free the array, not the
67 * strings the array points to. The
68 * full strv we only free if
69 * c->allocated is set, see
72 strv_free(c
->cmdline_array
);
75 _public_ sd_bus_creds
*sd_bus_creds_ref(sd_bus_creds
*c
) {
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_(sd_bus_creds_unrefp
) 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);