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