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