]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-creds.c
Merge pull request #8617 from keszybz/tmpfiles-relax
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-creds.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <linux/capability.h>
22 #include <stdlib.h>
23
24 #include "alloc-util.h"
25 #include "audit-util.h"
26 #include "bus-creds.h"
27 #include "bus-label.h"
28 #include "bus-message.h"
29 #include "bus-util.h"
30 #include "capability-util.h"
31 #include "cgroup-util.h"
32 #include "fd-util.h"
33 #include "fileio.h"
34 #include "format-util.h"
35 #include "hexdecoct.h"
36 #include "parse-util.h"
37 #include "process-util.h"
38 #include "string-util.h"
39 #include "strv.h"
40 #include "terminal-util.h"
41 #include "user-util.h"
42 #include "util.h"
43
44 enum {
45 CAP_OFFSET_INHERITABLE = 0,
46 CAP_OFFSET_PERMITTED = 1,
47 CAP_OFFSET_EFFECTIVE = 2,
48 CAP_OFFSET_BOUNDING = 3
49 };
50
51 void bus_creds_done(sd_bus_creds *c) {
52 assert(c);
53
54 /* For internal bus cred structures that are allocated by
55 * something else */
56
57 free(c->session);
58 free(c->unit);
59 free(c->user_unit);
60 free(c->slice);
61 free(c->user_slice);
62 free(c->unescaped_description);
63 free(c->supplementary_gids);
64 free(c->tty);
65
66 free(c->well_known_names); /* note that this is an strv, but
67 * we only free the array, not the
68 * strings the array points to. The
69 * full strv we only free if
70 * c->allocated is set, see
71 * below. */
72
73 strv_free(c->cmdline_array);
74 }
75
76 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
77
78 if (!c)
79 return NULL;
80
81 if (c->allocated) {
82 assert(c->n_ref > 0);
83 c->n_ref++;
84 } else {
85 sd_bus_message *m;
86
87 /* If this is an embedded creds structure, then
88 * forward ref counting to the message */
89 m = container_of(c, sd_bus_message, creds);
90 sd_bus_message_ref(m);
91 }
92
93 return c;
94 }
95
96 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
97
98 if (!c)
99 return NULL;
100
101 if (c->allocated) {
102 assert(c->n_ref > 0);
103 c->n_ref--;
104
105 if (c->n_ref == 0) {
106 free(c->comm);
107 free(c->tid_comm);
108 free(c->exe);
109 free(c->cmdline);
110 free(c->cgroup);
111 free(c->capability);
112 free(c->label);
113 free(c->unique_name);
114 free(c->cgroup_root);
115 free(c->description);
116
117 c->supplementary_gids = mfree(c->supplementary_gids);
118
119 c->well_known_names = strv_free(c->well_known_names);
120
121 bus_creds_done(c);
122
123 free(c);
124 }
125 } else {
126 sd_bus_message *m;
127
128 m = container_of(c, sd_bus_message, creds);
129 sd_bus_message_unref(m);
130 }
131
132
133 return NULL;
134 }
135
136 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
137 assert_return(c, 0);
138
139 return c->mask;
140 }
141
142 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
143 assert_return(c, 0);
144
145 return c->augmented;
146 }
147
148 sd_bus_creds* bus_creds_new(void) {
149 sd_bus_creds *c;
150
151 c = new0(sd_bus_creds, 1);
152 if (!c)
153 return NULL;
154
155 c->allocated = true;
156 c->n_ref = 1;
157 return c;
158 }
159
160 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
161 sd_bus_creds *c;
162 int r;
163
164 assert_return(pid >= 0, -EINVAL);
165 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
166 assert_return(ret, -EINVAL);
167
168 if (pid == 0)
169 pid = getpid_cached();
170
171 c = bus_creds_new();
172 if (!c)
173 return -ENOMEM;
174
175 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
176 if (r < 0) {
177 sd_bus_creds_unref(c);
178 return r;
179 }
180
181 /* Check if the process existed at all, in case we haven't
182 * figured that out already */
183 if (!pid_is_alive(pid)) {
184 sd_bus_creds_unref(c);
185 return -ESRCH;
186 }
187
188 *ret = c;
189 return 0;
190 }
191
192 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
193 assert_return(c, -EINVAL);
194 assert_return(uid, -EINVAL);
195
196 if (!(c->mask & SD_BUS_CREDS_UID))
197 return -ENODATA;
198
199 *uid = c->uid;
200 return 0;
201 }
202
203 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
204 assert_return(c, -EINVAL);
205 assert_return(euid, -EINVAL);
206
207 if (!(c->mask & SD_BUS_CREDS_EUID))
208 return -ENODATA;
209
210 *euid = c->euid;
211 return 0;
212 }
213
214 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
215 assert_return(c, -EINVAL);
216 assert_return(suid, -EINVAL);
217
218 if (!(c->mask & SD_BUS_CREDS_SUID))
219 return -ENODATA;
220
221 *suid = c->suid;
222 return 0;
223 }
224
225
226 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
227 assert_return(c, -EINVAL);
228 assert_return(fsuid, -EINVAL);
229
230 if (!(c->mask & SD_BUS_CREDS_FSUID))
231 return -ENODATA;
232
233 *fsuid = c->fsuid;
234 return 0;
235 }
236
237 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
238 assert_return(c, -EINVAL);
239 assert_return(gid, -EINVAL);
240
241 if (!(c->mask & SD_BUS_CREDS_GID))
242 return -ENODATA;
243
244 *gid = c->gid;
245 return 0;
246 }
247
248 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
249 assert_return(c, -EINVAL);
250 assert_return(egid, -EINVAL);
251
252 if (!(c->mask & SD_BUS_CREDS_EGID))
253 return -ENODATA;
254
255 *egid = c->egid;
256 return 0;
257 }
258
259 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
260 assert_return(c, -EINVAL);
261 assert_return(sgid, -EINVAL);
262
263 if (!(c->mask & SD_BUS_CREDS_SGID))
264 return -ENODATA;
265
266 *sgid = c->sgid;
267 return 0;
268 }
269
270 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
271 assert_return(c, -EINVAL);
272 assert_return(fsgid, -EINVAL);
273
274 if (!(c->mask & SD_BUS_CREDS_FSGID))
275 return -ENODATA;
276
277 *fsgid = c->fsgid;
278 return 0;
279 }
280
281 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
282 assert_return(c, -EINVAL);
283 assert_return(gids, -EINVAL);
284
285 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
286 return -ENODATA;
287
288 *gids = c->supplementary_gids;
289 return (int) c->n_supplementary_gids;
290 }
291
292 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
293 assert_return(c, -EINVAL);
294 assert_return(pid, -EINVAL);
295
296 if (!(c->mask & SD_BUS_CREDS_PID))
297 return -ENODATA;
298
299 assert(c->pid > 0);
300 *pid = c->pid;
301 return 0;
302 }
303
304 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
305 assert_return(c, -EINVAL);
306 assert_return(ppid, -EINVAL);
307
308 if (!(c->mask & SD_BUS_CREDS_PPID))
309 return -ENODATA;
310
311 /* PID 1 has no parent process. Let's distinguish the case of
312 * not knowing and not having a parent process by the returned
313 * error code. */
314 if (c->ppid == 0)
315 return -ENXIO;
316
317 *ppid = c->ppid;
318 return 0;
319 }
320
321 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
322 assert_return(c, -EINVAL);
323 assert_return(tid, -EINVAL);
324
325 if (!(c->mask & SD_BUS_CREDS_TID))
326 return -ENODATA;
327
328 assert(c->tid > 0);
329 *tid = c->tid;
330 return 0;
331 }
332
333 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
334 assert_return(c, -EINVAL);
335
336 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
337 return -ENODATA;
338
339 assert(c->label);
340 *ret = c->label;
341 return 0;
342 }
343
344 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
345 assert_return(c, -EINVAL);
346 assert_return(ret, -EINVAL);
347
348 if (!(c->mask & SD_BUS_CREDS_COMM))
349 return -ENODATA;
350
351 assert(c->comm);
352 *ret = c->comm;
353 return 0;
354 }
355
356 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
357 assert_return(c, -EINVAL);
358 assert_return(ret, -EINVAL);
359
360 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
361 return -ENODATA;
362
363 assert(c->tid_comm);
364 *ret = c->tid_comm;
365 return 0;
366 }
367
368 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
369 assert_return(c, -EINVAL);
370 assert_return(ret, -EINVAL);
371
372 if (!(c->mask & SD_BUS_CREDS_EXE))
373 return -ENODATA;
374
375 if (!c->exe)
376 return -ENXIO;
377
378 *ret = c->exe;
379 return 0;
380 }
381
382 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
383 assert_return(c, -EINVAL);
384 assert_return(ret, -EINVAL);
385
386 if (!(c->mask & SD_BUS_CREDS_CGROUP))
387 return -ENODATA;
388
389 assert(c->cgroup);
390 *ret = c->cgroup;
391 return 0;
392 }
393
394 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
395 int r;
396
397 assert_return(c, -EINVAL);
398 assert_return(ret, -EINVAL);
399
400 if (!(c->mask & SD_BUS_CREDS_UNIT))
401 return -ENODATA;
402
403 assert(c->cgroup);
404
405 if (!c->unit) {
406 const char *shifted;
407
408 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
409 if (r < 0)
410 return r;
411
412 r = cg_path_get_unit(shifted, (char**) &c->unit);
413 if (r < 0)
414 return r;
415 }
416
417 *ret = c->unit;
418 return 0;
419 }
420
421 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
422 int r;
423
424 assert_return(c, -EINVAL);
425 assert_return(ret, -EINVAL);
426
427 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
428 return -ENODATA;
429
430 assert(c->cgroup);
431
432 if (!c->user_unit) {
433 const char *shifted;
434
435 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
436 if (r < 0)
437 return r;
438
439 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
440 if (r < 0)
441 return r;
442 }
443
444 *ret = c->user_unit;
445 return 0;
446 }
447
448 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
449 int r;
450
451 assert_return(c, -EINVAL);
452 assert_return(ret, -EINVAL);
453
454 if (!(c->mask & SD_BUS_CREDS_SLICE))
455 return -ENODATA;
456
457 assert(c->cgroup);
458
459 if (!c->slice) {
460 const char *shifted;
461
462 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
463 if (r < 0)
464 return r;
465
466 r = cg_path_get_slice(shifted, (char**) &c->slice);
467 if (r < 0)
468 return r;
469 }
470
471 *ret = c->slice;
472 return 0;
473 }
474
475 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
476 int r;
477
478 assert_return(c, -EINVAL);
479 assert_return(ret, -EINVAL);
480
481 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
482 return -ENODATA;
483
484 assert(c->cgroup);
485
486 if (!c->user_slice) {
487 const char *shifted;
488
489 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
490 if (r < 0)
491 return r;
492
493 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
494 if (r < 0)
495 return r;
496 }
497
498 *ret = c->user_slice;
499 return 0;
500 }
501
502 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
503 int r;
504
505 assert_return(c, -EINVAL);
506 assert_return(ret, -EINVAL);
507
508 if (!(c->mask & SD_BUS_CREDS_SESSION))
509 return -ENODATA;
510
511 assert(c->cgroup);
512
513 if (!c->session) {
514 const char *shifted;
515
516 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
517 if (r < 0)
518 return r;
519
520 r = cg_path_get_session(shifted, (char**) &c->session);
521 if (r < 0)
522 return r;
523 }
524
525 *ret = c->session;
526 return 0;
527 }
528
529 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
530 const char *shifted;
531 int r;
532
533 assert_return(c, -EINVAL);
534 assert_return(uid, -EINVAL);
535
536 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
537 return -ENODATA;
538
539 assert(c->cgroup);
540
541 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
542 if (r < 0)
543 return r;
544
545 return cg_path_get_owner_uid(shifted, uid);
546 }
547
548 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
549 assert_return(c, -EINVAL);
550
551 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
552 return -ENODATA;
553
554 if (!c->cmdline)
555 return -ENXIO;
556
557 if (!c->cmdline_array) {
558 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
559 if (!c->cmdline_array)
560 return -ENOMEM;
561 }
562
563 *cmdline = c->cmdline_array;
564 return 0;
565 }
566
567 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
568 assert_return(c, -EINVAL);
569 assert_return(sessionid, -EINVAL);
570
571 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
572 return -ENODATA;
573
574 if (!audit_session_is_valid(c->audit_session_id))
575 return -ENXIO;
576
577 *sessionid = c->audit_session_id;
578 return 0;
579 }
580
581 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
582 assert_return(c, -EINVAL);
583 assert_return(uid, -EINVAL);
584
585 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
586 return -ENODATA;
587
588 if (!uid_is_valid(c->audit_login_uid))
589 return -ENXIO;
590
591 *uid = c->audit_login_uid;
592 return 0;
593 }
594
595 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
596 assert_return(c, -EINVAL);
597 assert_return(ret, -EINVAL);
598
599 if (!(c->mask & SD_BUS_CREDS_TTY))
600 return -ENODATA;
601
602 if (!c->tty)
603 return -ENXIO;
604
605 *ret = c->tty;
606 return 0;
607 }
608
609 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
610 assert_return(c, -EINVAL);
611 assert_return(unique_name, -EINVAL);
612
613 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
614 return -ENODATA;
615
616 *unique_name = c->unique_name;
617 return 0;
618 }
619
620 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
621 assert_return(c, -EINVAL);
622 assert_return(well_known_names, -EINVAL);
623
624 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
625 return -ENODATA;
626
627 /* As a special hack we return the bus driver as well-known
628 * names list when this is requested. */
629 if (c->well_known_names_driver) {
630 static const char* const wkn[] = {
631 "org.freedesktop.DBus",
632 NULL
633 };
634
635 *well_known_names = (char**) wkn;
636 return 0;
637 }
638
639 if (c->well_known_names_local) {
640 static const char* const wkn[] = {
641 "org.freedesktop.DBus.Local",
642 NULL
643 };
644
645 *well_known_names = (char**) wkn;
646 return 0;
647 }
648
649 *well_known_names = c->well_known_names;
650 return 0;
651 }
652
653 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
654 assert_return(c, -EINVAL);
655 assert_return(ret, -EINVAL);
656
657 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
658 return -ENODATA;
659
660 assert(c->description);
661
662 if (!c->unescaped_description) {
663 c->unescaped_description = bus_label_unescape(c->description);
664 if (!c->unescaped_description)
665 return -ENOMEM;
666 }
667
668 *ret = c->unescaped_description;
669 return 0;
670 }
671
672 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
673 size_t sz;
674
675 assert(c);
676 assert(capability >= 0);
677 assert(c->capability);
678
679 if ((unsigned) capability > cap_last_cap())
680 return 0;
681
682 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
683
684 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
685 }
686
687 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
688 assert_return(c, -EINVAL);
689 assert_return(capability >= 0, -EINVAL);
690
691 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
692 return -ENODATA;
693
694 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
695 }
696
697 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
698 assert_return(c, -EINVAL);
699 assert_return(capability >= 0, -EINVAL);
700
701 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
702 return -ENODATA;
703
704 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
705 }
706
707 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
708 assert_return(c, -EINVAL);
709 assert_return(capability >= 0, -EINVAL);
710
711 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
712 return -ENODATA;
713
714 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
715 }
716
717 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
718 assert_return(c, -EINVAL);
719 assert_return(capability >= 0, -EINVAL);
720
721 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
722 return -ENODATA;
723
724 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
725 }
726
727 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
728 size_t sz, max;
729 unsigned i, j;
730
731 assert(c);
732 assert(p);
733
734 max = DIV_ROUND_UP(cap_last_cap(), 32U);
735 p += strspn(p, WHITESPACE);
736
737 sz = strlen(p);
738 if (sz % 8 != 0)
739 return -EINVAL;
740
741 sz /= 8;
742 if (sz > max)
743 return -EINVAL;
744
745 if (!c->capability) {
746 c->capability = new0(uint32_t, max * 4);
747 if (!c->capability)
748 return -ENOMEM;
749 }
750
751 for (i = 0; i < sz; i ++) {
752 uint32_t v = 0;
753
754 for (j = 0; j < 8; ++j) {
755 int t;
756
757 t = unhexchar(*p++);
758 if (t < 0)
759 return -EINVAL;
760
761 v = (v << 4) | t;
762 }
763
764 c->capability[offset * max + (sz - i - 1)] = v;
765 }
766
767 return 0;
768 }
769
770 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
771 uint64_t missing;
772 int r;
773
774 assert(c);
775 assert(c->allocated);
776
777 if (!(mask & SD_BUS_CREDS_AUGMENT))
778 return 0;
779
780 /* Try to retrieve PID from creds if it wasn't passed to us */
781 if (pid > 0) {
782 c->pid = pid;
783 c->mask |= SD_BUS_CREDS_PID;
784 } else if (c->mask & SD_BUS_CREDS_PID)
785 pid = c->pid;
786 else
787 /* Without pid we cannot do much... */
788 return 0;
789
790 /* Try to retrieve TID from creds if it wasn't passed to us */
791 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
792 tid = c->tid;
793
794 /* Calculate what we shall and can add */
795 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);
796 if (missing == 0)
797 return 0;
798
799 if (tid > 0) {
800 c->tid = tid;
801 c->mask |= SD_BUS_CREDS_TID;
802 }
803
804 if (missing & (SD_BUS_CREDS_PPID |
805 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
806 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
807 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
808 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
809 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
810
811 _cleanup_fclose_ FILE *f = NULL;
812 const char *p;
813
814 p = procfs_file_alloca(pid, "status");
815
816 f = fopen(p, "re");
817 if (!f) {
818 if (errno == ENOENT)
819 return -ESRCH;
820 else if (!IN_SET(errno, EPERM, EACCES))
821 return -errno;
822 } else {
823 char line[LINE_MAX];
824
825 FOREACH_LINE(line, f, return -errno) {
826 truncate_nl(line);
827
828 if (missing & SD_BUS_CREDS_PPID) {
829 p = startswith(line, "PPid:");
830 if (p) {
831 p += strspn(p, WHITESPACE);
832
833 /* Explicitly check for PPID 0 (which is the case for PID 1) */
834 if (!streq(p, "0")) {
835 r = parse_pid(p, &c->ppid);
836 if (r < 0)
837 return r;
838
839 } else
840 c->ppid = 0;
841
842 c->mask |= SD_BUS_CREDS_PPID;
843 continue;
844 }
845 }
846
847 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
848 p = startswith(line, "Uid:");
849 if (p) {
850 unsigned long uid, euid, suid, fsuid;
851
852 p += strspn(p, WHITESPACE);
853 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
854 return -EIO;
855
856 if (missing & SD_BUS_CREDS_UID)
857 c->uid = (uid_t) uid;
858 if (missing & SD_BUS_CREDS_EUID)
859 c->euid = (uid_t) euid;
860 if (missing & SD_BUS_CREDS_SUID)
861 c->suid = (uid_t) suid;
862 if (missing & SD_BUS_CREDS_FSUID)
863 c->fsuid = (uid_t) fsuid;
864
865 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
866 continue;
867 }
868 }
869
870 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
871 p = startswith(line, "Gid:");
872 if (p) {
873 unsigned long gid, egid, sgid, fsgid;
874
875 p += strspn(p, WHITESPACE);
876 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
877 return -EIO;
878
879 if (missing & SD_BUS_CREDS_GID)
880 c->gid = (gid_t) gid;
881 if (missing & SD_BUS_CREDS_EGID)
882 c->egid = (gid_t) egid;
883 if (missing & SD_BUS_CREDS_SGID)
884 c->sgid = (gid_t) sgid;
885 if (missing & SD_BUS_CREDS_FSGID)
886 c->fsgid = (gid_t) fsgid;
887
888 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
889 continue;
890 }
891 }
892
893 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
894 p = startswith(line, "Groups:");
895 if (p) {
896 size_t allocated = 0;
897
898 for (;;) {
899 unsigned long g;
900 int n = 0;
901
902 p += strspn(p, WHITESPACE);
903 if (*p == 0)
904 break;
905
906 if (sscanf(p, "%lu%n", &g, &n) != 1)
907 return -EIO;
908
909 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
910 return -ENOMEM;
911
912 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
913 p += n;
914 }
915
916 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
917 continue;
918 }
919 }
920
921 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
922 p = startswith(line, "CapEff:");
923 if (p) {
924 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
925 if (r < 0)
926 return r;
927
928 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
929 continue;
930 }
931 }
932
933 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
934 p = startswith(line, "CapPrm:");
935 if (p) {
936 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
937 if (r < 0)
938 return r;
939
940 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
941 continue;
942 }
943 }
944
945 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
946 p = startswith(line, "CapInh:");
947 if (p) {
948 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
949 if (r < 0)
950 return r;
951
952 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
953 continue;
954 }
955 }
956
957 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
958 p = startswith(line, "CapBnd:");
959 if (p) {
960 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
961 if (r < 0)
962 return r;
963
964 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
965 continue;
966 }
967 }
968 }
969 }
970 }
971
972 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
973 const char *p;
974
975 p = procfs_file_alloca(pid, "attr/current");
976 r = read_one_line_file(p, &c->label);
977 if (r < 0) {
978 if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
979 return r;
980 } else
981 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
982 }
983
984 if (missing & SD_BUS_CREDS_COMM) {
985 r = get_process_comm(pid, &c->comm);
986 if (r < 0) {
987 if (!IN_SET(r, -EPERM, -EACCES))
988 return r;
989 } else
990 c->mask |= SD_BUS_CREDS_COMM;
991 }
992
993 if (missing & SD_BUS_CREDS_EXE) {
994 r = get_process_exe(pid, &c->exe);
995 if (r == -ESRCH) {
996 /* Unfortunately we cannot really distinguish
997 * the case here where the process does not
998 * exist, and /proc/$PID/exe being unreadable
999 * because $PID is a kernel thread. Hence,
1000 * assume it is a kernel thread, and rely on
1001 * that this case is caught with a later
1002 * call. */
1003 c->exe = NULL;
1004 c->mask |= SD_BUS_CREDS_EXE;
1005 } else if (r < 0) {
1006 if (!IN_SET(r, -EPERM, -EACCES))
1007 return r;
1008 } else
1009 c->mask |= SD_BUS_CREDS_EXE;
1010 }
1011
1012 if (missing & SD_BUS_CREDS_CMDLINE) {
1013 const char *p;
1014
1015 p = procfs_file_alloca(pid, "cmdline");
1016 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1017 if (r == -ENOENT)
1018 return -ESRCH;
1019 if (r < 0) {
1020 if (!IN_SET(r, -EPERM, -EACCES))
1021 return r;
1022 } else {
1023 if (c->cmdline_size == 0)
1024 c->cmdline = mfree(c->cmdline);
1025
1026 c->mask |= SD_BUS_CREDS_CMDLINE;
1027 }
1028 }
1029
1030 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1031 _cleanup_free_ char *p = NULL;
1032
1033 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1034 return -ENOMEM;
1035
1036 r = read_one_line_file(p, &c->tid_comm);
1037 if (r == -ENOENT)
1038 return -ESRCH;
1039 if (r < 0) {
1040 if (!IN_SET(r, -EPERM, -EACCES))
1041 return r;
1042 } else
1043 c->mask |= SD_BUS_CREDS_TID_COMM;
1044 }
1045
1046 if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
1047
1048 if (!c->cgroup) {
1049 r = cg_pid_get_path(NULL, pid, &c->cgroup);
1050 if (r < 0) {
1051 if (!IN_SET(r, -EPERM, -EACCES))
1052 return r;
1053 }
1054 }
1055
1056 if (!c->cgroup_root) {
1057 r = cg_get_root_path(&c->cgroup_root);
1058 if (r < 0)
1059 return r;
1060 }
1061
1062 if (c->cgroup)
1063 c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
1064 }
1065
1066 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1067 r = audit_session_from_pid(pid, &c->audit_session_id);
1068 if (r == -ENODATA) {
1069 /* ENODATA means: no audit session id assigned */
1070 c->audit_session_id = AUDIT_SESSION_INVALID;
1071 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1072 } else if (r < 0) {
1073 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
1074 return r;
1075 } else
1076 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1077 }
1078
1079 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1080 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1081 if (r == -ENODATA) {
1082 /* ENODATA means: no audit login uid assigned */
1083 c->audit_login_uid = UID_INVALID;
1084 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1085 } else if (r < 0) {
1086 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
1087 return r;
1088 } else
1089 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1090 }
1091
1092 if (missing & SD_BUS_CREDS_TTY) {
1093 r = get_ctty(pid, NULL, &c->tty);
1094 if (r == -ENXIO) {
1095 /* ENXIO means: process has no controlling TTY */
1096 c->tty = NULL;
1097 c->mask |= SD_BUS_CREDS_TTY;
1098 } else if (r < 0) {
1099 if (!IN_SET(r, -EPERM, -EACCES, -ENOENT))
1100 return r;
1101 } else
1102 c->mask |= SD_BUS_CREDS_TTY;
1103 }
1104
1105 /* In case only the exe path was to be read we cannot
1106 * distinguish the case where the exe path was unreadable
1107 * because the process was a kernel thread, or when the
1108 * process didn't exist at all. Hence, let's do a final check,
1109 * to be sure. */
1110 if (!pid_is_alive(pid))
1111 return -ESRCH;
1112
1113 if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1114 return -ESRCH;
1115
1116 c->augmented = missing & c->mask;
1117
1118 return 0;
1119 }
1120
1121 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1122 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
1123 int r;
1124
1125 assert(c);
1126 assert(ret);
1127
1128 if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1129 /* There's already all data we need, or augmentation
1130 * wasn't turned on. */
1131
1132 *ret = sd_bus_creds_ref(c);
1133 return 0;
1134 }
1135
1136 n = bus_creds_new();
1137 if (!n)
1138 return -ENOMEM;
1139
1140 /* Copy the original data over */
1141
1142 if (c->mask & mask & SD_BUS_CREDS_PID) {
1143 n->pid = c->pid;
1144 n->mask |= SD_BUS_CREDS_PID;
1145 }
1146
1147 if (c->mask & mask & SD_BUS_CREDS_TID) {
1148 n->tid = c->tid;
1149 n->mask |= SD_BUS_CREDS_TID;
1150 }
1151
1152 if (c->mask & mask & SD_BUS_CREDS_PPID) {
1153 n->ppid = c->ppid;
1154 n->mask |= SD_BUS_CREDS_PPID;
1155 }
1156
1157 if (c->mask & mask & SD_BUS_CREDS_UID) {
1158 n->uid = c->uid;
1159 n->mask |= SD_BUS_CREDS_UID;
1160 }
1161
1162 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1163 n->euid = c->euid;
1164 n->mask |= SD_BUS_CREDS_EUID;
1165 }
1166
1167 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1168 n->suid = c->suid;
1169 n->mask |= SD_BUS_CREDS_SUID;
1170 }
1171
1172 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1173 n->fsuid = c->fsuid;
1174 n->mask |= SD_BUS_CREDS_FSUID;
1175 }
1176
1177 if (c->mask & mask & SD_BUS_CREDS_GID) {
1178 n->gid = c->gid;
1179 n->mask |= SD_BUS_CREDS_GID;
1180 }
1181
1182 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1183 n->egid = c->egid;
1184 n->mask |= SD_BUS_CREDS_EGID;
1185 }
1186
1187 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1188 n->sgid = c->sgid;
1189 n->mask |= SD_BUS_CREDS_SGID;
1190 }
1191
1192 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1193 n->fsgid = c->fsgid;
1194 n->mask |= SD_BUS_CREDS_FSGID;
1195 }
1196
1197 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1198 if (c->supplementary_gids) {
1199 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1200 if (!n->supplementary_gids)
1201 return -ENOMEM;
1202 n->n_supplementary_gids = c->n_supplementary_gids;
1203 } else {
1204 n->supplementary_gids = NULL;
1205 n->n_supplementary_gids = 0;
1206 }
1207
1208 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1209 }
1210
1211 if (c->mask & mask & SD_BUS_CREDS_COMM) {
1212 assert(c->comm);
1213
1214 n->comm = strdup(c->comm);
1215 if (!n->comm)
1216 return -ENOMEM;
1217
1218 n->mask |= SD_BUS_CREDS_COMM;
1219 }
1220
1221 if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1222 assert(c->tid_comm);
1223
1224 n->tid_comm = strdup(c->tid_comm);
1225 if (!n->tid_comm)
1226 return -ENOMEM;
1227
1228 n->mask |= SD_BUS_CREDS_TID_COMM;
1229 }
1230
1231 if (c->mask & mask & SD_BUS_CREDS_EXE) {
1232 if (c->exe) {
1233 n->exe = strdup(c->exe);
1234 if (!n->exe)
1235 return -ENOMEM;
1236 } else
1237 n->exe = NULL;
1238
1239 n->mask |= SD_BUS_CREDS_EXE;
1240 }
1241
1242 if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1243 if (c->cmdline) {
1244 n->cmdline = memdup(c->cmdline, c->cmdline_size);
1245 if (!n->cmdline)
1246 return -ENOMEM;
1247
1248 n->cmdline_size = c->cmdline_size;
1249 } else {
1250 n->cmdline = NULL;
1251 n->cmdline_size = 0;
1252 }
1253
1254 n->mask |= SD_BUS_CREDS_CMDLINE;
1255 }
1256
1257 if (c->mask & mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) {
1258 assert(c->cgroup);
1259
1260 n->cgroup = strdup(c->cgroup);
1261 if (!n->cgroup)
1262 return -ENOMEM;
1263
1264 n->cgroup_root = strdup(c->cgroup_root);
1265 if (!n->cgroup_root)
1266 return -ENOMEM;
1267
1268 n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID);
1269 }
1270
1271 if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1272 assert(c->capability);
1273
1274 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1275 if (!n->capability)
1276 return -ENOMEM;
1277
1278 n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS);
1279 }
1280
1281 if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1282 assert(c->label);
1283
1284 n->label = strdup(c->label);
1285 if (!n->label)
1286 return -ENOMEM;
1287 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1288 }
1289
1290 if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1291 n->audit_session_id = c->audit_session_id;
1292 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1293 }
1294 if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1295 n->audit_login_uid = c->audit_login_uid;
1296 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1297 }
1298
1299 if (c->mask & mask & SD_BUS_CREDS_TTY) {
1300 if (c->tty) {
1301 n->tty = strdup(c->tty);
1302 if (!n->tty)
1303 return -ENOMEM;
1304 } else
1305 n->tty = NULL;
1306 n->mask |= SD_BUS_CREDS_TTY;
1307 }
1308
1309 if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1310 assert(c->unique_name);
1311
1312 n->unique_name = strdup(c->unique_name);
1313 if (!n->unique_name)
1314 return -ENOMEM;
1315 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1316 }
1317
1318 if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1319 if (strv_isempty(c->well_known_names))
1320 n->well_known_names = NULL;
1321 else {
1322 n->well_known_names = strv_copy(c->well_known_names);
1323 if (!n->well_known_names)
1324 return -ENOMEM;
1325 }
1326 n->well_known_names_driver = c->well_known_names_driver;
1327 n->well_known_names_local = c->well_known_names_local;
1328 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1329 }
1330
1331 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1332 assert(c->description);
1333 n->description = strdup(c->description);
1334 if (!n->description)
1335 return -ENOMEM;
1336 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1337 }
1338
1339 n->augmented = c->augmented & n->mask;
1340
1341 /* Get more data */
1342
1343 r = bus_creds_add_more(n, mask, 0, 0);
1344 if (r < 0)
1345 return r;
1346
1347 *ret = TAKE_PTR(n);
1348
1349 return 0;
1350 }