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