]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/bus-creds.c
Merge pull request #977 from richardmaw-codethink/machinectl-userns-login-v2
[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 <stdlib.h>
23 #include <linux/capability.h>
24
25 #include "util.h"
26 #include "formats-util.h"
27 #include "process-util.h"
28 #include "terminal-util.h"
29 #include "capability.h"
30 #include "cgroup-util.h"
31 #include "fileio.h"
32 #include "audit.h"
33 #include "bus-message.h"
34 #include "strv.h"
35 #include "bus-creds.h"
36 #include "bus-label.h"
37 #include "bus-internal.h"
38
39 enum {
40 CAP_OFFSET_INHERITABLE = 0,
41 CAP_OFFSET_PERMITTED = 1,
42 CAP_OFFSET_EFFECTIVE = 2,
43 CAP_OFFSET_BOUNDING = 3
44 };
45
46 void bus_creds_done(sd_bus_creds *c) {
47 assert(c);
48
49 /* For internal bus cred structures that are allocated by
50 * something else */
51
52 free(c->session);
53 free(c->unit);
54 free(c->user_unit);
55 free(c->slice);
56 free(c->user_slice);
57 free(c->unescaped_description);
58 free(c->supplementary_gids);
59 free(c->tty);
60
61 free(c->well_known_names); /* note that this is an strv, but
62 * we only free the array, not the
63 * strings the array points to. The
64 * full strv we only free if
65 * c->allocated is set, see
66 * below. */
67
68 strv_free(c->cmdline_array);
69 }
70
71 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
72 assert_return(c, NULL);
73
74 if (c->allocated) {
75 assert(c->n_ref > 0);
76 c->n_ref++;
77 } else {
78 sd_bus_message *m;
79
80 /* If this is an embedded creds structure, then
81 * forward ref counting to the message */
82 m = container_of(c, sd_bus_message, creds);
83 sd_bus_message_ref(m);
84 }
85
86 return c;
87 }
88
89 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
90
91 if (!c)
92 return NULL;
93
94 if (c->allocated) {
95 assert(c->n_ref > 0);
96 c->n_ref--;
97
98 if (c->n_ref == 0) {
99 free(c->comm);
100 free(c->tid_comm);
101 free(c->exe);
102 free(c->cmdline);
103 free(c->cgroup);
104 free(c->capability);
105 free(c->label);
106 free(c->unique_name);
107 free(c->cgroup_root);
108 free(c->description);
109
110 free(c->supplementary_gids);
111 c->supplementary_gids = NULL;
112
113 strv_free(c->well_known_names);
114 c->well_known_names = NULL;
115
116 bus_creds_done(c);
117
118 free(c);
119 }
120 } else {
121 sd_bus_message *m;
122
123 m = container_of(c, sd_bus_message, creds);
124 sd_bus_message_unref(m);
125 }
126
127
128 return NULL;
129 }
130
131 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
132 assert_return(c, 0);
133
134 return c->mask;
135 }
136
137 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
138 assert_return(c, 0);
139
140 return c->augmented;
141 }
142
143 sd_bus_creds* bus_creds_new(void) {
144 sd_bus_creds *c;
145
146 c = new0(sd_bus_creds, 1);
147 if (!c)
148 return NULL;
149
150 c->allocated = true;
151 c->n_ref = 1;
152 return c;
153 }
154
155 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
156 sd_bus_creds *c;
157 int r;
158
159 assert_return(pid >= 0, -EINVAL);
160 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
161 assert_return(ret, -EINVAL);
162
163 if (pid == 0)
164 pid = getpid();
165
166 c = bus_creds_new();
167 if (!c)
168 return -ENOMEM;
169
170 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
171 if (r < 0) {
172 sd_bus_creds_unref(c);
173 return r;
174 }
175
176 /* Check if the process existed at all, in case we haven't
177 * figured that out already */
178 if (!pid_is_alive(pid)) {
179 sd_bus_creds_unref(c);
180 return -ESRCH;
181 }
182
183 *ret = c;
184 return 0;
185 }
186
187 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
188 assert_return(c, -EINVAL);
189 assert_return(uid, -EINVAL);
190
191 if (!(c->mask & SD_BUS_CREDS_UID))
192 return -ENODATA;
193
194 *uid = c->uid;
195 return 0;
196 }
197
198 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
199 assert_return(c, -EINVAL);
200 assert_return(euid, -EINVAL);
201
202 if (!(c->mask & SD_BUS_CREDS_EUID))
203 return -ENODATA;
204
205 *euid = c->euid;
206 return 0;
207 }
208
209 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
210 assert_return(c, -EINVAL);
211 assert_return(suid, -EINVAL);
212
213 if (!(c->mask & SD_BUS_CREDS_SUID))
214 return -ENODATA;
215
216 *suid = c->suid;
217 return 0;
218 }
219
220
221 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
222 assert_return(c, -EINVAL);
223 assert_return(fsuid, -EINVAL);
224
225 if (!(c->mask & SD_BUS_CREDS_FSUID))
226 return -ENODATA;
227
228 *fsuid = c->fsuid;
229 return 0;
230 }
231
232 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
233 assert_return(c, -EINVAL);
234 assert_return(gid, -EINVAL);
235
236 if (!(c->mask & SD_BUS_CREDS_GID))
237 return -ENODATA;
238
239 *gid = c->gid;
240 return 0;
241 }
242
243 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
244 assert_return(c, -EINVAL);
245 assert_return(egid, -EINVAL);
246
247 if (!(c->mask & SD_BUS_CREDS_EGID))
248 return -ENODATA;
249
250 *egid = c->egid;
251 return 0;
252 }
253
254 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
255 assert_return(c, -EINVAL);
256 assert_return(sgid, -EINVAL);
257
258 if (!(c->mask & SD_BUS_CREDS_SGID))
259 return -ENODATA;
260
261 *sgid = c->sgid;
262 return 0;
263 }
264
265 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
266 assert_return(c, -EINVAL);
267 assert_return(fsgid, -EINVAL);
268
269 if (!(c->mask & SD_BUS_CREDS_FSGID))
270 return -ENODATA;
271
272 *fsgid = c->fsgid;
273 return 0;
274 }
275
276 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
277 assert_return(c, -EINVAL);
278 assert_return(gids, -EINVAL);
279
280 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
281 return -ENODATA;
282
283 *gids = c->supplementary_gids;
284 return (int) c->n_supplementary_gids;
285 }
286
287 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
288 assert_return(c, -EINVAL);
289 assert_return(pid, -EINVAL);
290
291 if (!(c->mask & SD_BUS_CREDS_PID))
292 return -ENODATA;
293
294 assert(c->pid > 0);
295 *pid = c->pid;
296 return 0;
297 }
298
299 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
300 assert_return(c, -EINVAL);
301 assert_return(ppid, -EINVAL);
302
303 if (!(c->mask & SD_BUS_CREDS_PPID))
304 return -ENODATA;
305
306 /* PID 1 has no parent process. Let's distinguish the case of
307 * not knowing and not having a parent process by the returned
308 * error code. */
309 if (c->ppid == 0)
310 return -ENXIO;
311
312 *ppid = c->ppid;
313 return 0;
314 }
315
316 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
317 assert_return(c, -EINVAL);
318 assert_return(tid, -EINVAL);
319
320 if (!(c->mask & SD_BUS_CREDS_TID))
321 return -ENODATA;
322
323 assert(c->tid > 0);
324 *tid = c->tid;
325 return 0;
326 }
327
328 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
329 assert_return(c, -EINVAL);
330
331 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
332 return -ENODATA;
333
334 assert(c->label);
335 *ret = c->label;
336 return 0;
337 }
338
339 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
340 assert_return(c, -EINVAL);
341 assert_return(ret, -EINVAL);
342
343 if (!(c->mask & SD_BUS_CREDS_COMM))
344 return -ENODATA;
345
346 assert(c->comm);
347 *ret = c->comm;
348 return 0;
349 }
350
351 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
352 assert_return(c, -EINVAL);
353 assert_return(ret, -EINVAL);
354
355 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
356 return -ENODATA;
357
358 assert(c->tid_comm);
359 *ret = c->tid_comm;
360 return 0;
361 }
362
363 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
364 assert_return(c, -EINVAL);
365 assert_return(ret, -EINVAL);
366
367 if (!(c->mask & SD_BUS_CREDS_EXE))
368 return -ENODATA;
369
370 if (!c->exe)
371 return -ENXIO;
372
373 *ret = c->exe;
374 return 0;
375 }
376
377 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
378 assert_return(c, -EINVAL);
379 assert_return(ret, -EINVAL);
380
381 if (!(c->mask & SD_BUS_CREDS_CGROUP))
382 return -ENODATA;
383
384 assert(c->cgroup);
385 *ret = c->cgroup;
386 return 0;
387 }
388
389 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
390 int r;
391
392 assert_return(c, -EINVAL);
393 assert_return(ret, -EINVAL);
394
395 if (!(c->mask & SD_BUS_CREDS_UNIT))
396 return -ENODATA;
397
398 assert(c->cgroup);
399
400 if (!c->unit) {
401 const char *shifted;
402
403 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
404 if (r < 0)
405 return r;
406
407 r = cg_path_get_unit(shifted, (char**) &c->unit);
408 if (r < 0)
409 return r;
410 }
411
412 *ret = c->unit;
413 return 0;
414 }
415
416 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
417 int r;
418
419 assert_return(c, -EINVAL);
420 assert_return(ret, -EINVAL);
421
422 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
423 return -ENODATA;
424
425 assert(c->cgroup);
426
427 if (!c->user_unit) {
428 const char *shifted;
429
430 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
431 if (r < 0)
432 return r;
433
434 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
435 if (r < 0)
436 return r;
437 }
438
439 *ret = c->user_unit;
440 return 0;
441 }
442
443 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
444 int r;
445
446 assert_return(c, -EINVAL);
447 assert_return(ret, -EINVAL);
448
449 if (!(c->mask & SD_BUS_CREDS_SLICE))
450 return -ENODATA;
451
452 assert(c->cgroup);
453
454 if (!c->slice) {
455 const char *shifted;
456
457 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
458 if (r < 0)
459 return r;
460
461 r = cg_path_get_slice(shifted, (char**) &c->slice);
462 if (r < 0)
463 return r;
464 }
465
466 *ret = c->slice;
467 return 0;
468 }
469
470 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
471 int r;
472
473 assert_return(c, -EINVAL);
474 assert_return(ret, -EINVAL);
475
476 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
477 return -ENODATA;
478
479 assert(c->cgroup);
480
481 if (!c->user_slice) {
482 const char *shifted;
483
484 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
485 if (r < 0)
486 return r;
487
488 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
489 if (r < 0)
490 return r;
491 }
492
493 *ret = c->user_slice;
494 return 0;
495 }
496
497 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
498 int r;
499
500 assert_return(c, -EINVAL);
501 assert_return(ret, -EINVAL);
502
503 if (!(c->mask & SD_BUS_CREDS_SESSION))
504 return -ENODATA;
505
506 assert(c->cgroup);
507
508 if (!c->session) {
509 const char *shifted;
510
511 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
512 if (r < 0)
513 return r;
514
515 r = cg_path_get_session(shifted, (char**) &c->session);
516 if (r < 0)
517 return r;
518 }
519
520 *ret = c->session;
521 return 0;
522 }
523
524 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
525 const char *shifted;
526 int r;
527
528 assert_return(c, -EINVAL);
529 assert_return(uid, -EINVAL);
530
531 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
532 return -ENODATA;
533
534 assert(c->cgroup);
535
536 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
537 if (r < 0)
538 return r;
539
540 return cg_path_get_owner_uid(shifted, uid);
541 }
542
543 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
544 assert_return(c, -EINVAL);
545
546 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
547 return -ENODATA;
548
549 if (!c->cmdline)
550 return -ENXIO;
551
552 if (!c->cmdline_array) {
553 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
554 if (!c->cmdline_array)
555 return -ENOMEM;
556 }
557
558 *cmdline = c->cmdline_array;
559 return 0;
560 }
561
562 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
563 assert_return(c, -EINVAL);
564 assert_return(sessionid, -EINVAL);
565
566 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
567 return -ENODATA;
568
569 if (c->audit_session_id == AUDIT_SESSION_INVALID)
570 return -ENXIO;
571
572 *sessionid = c->audit_session_id;
573 return 0;
574 }
575
576 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
577 assert_return(c, -EINVAL);
578 assert_return(uid, -EINVAL);
579
580 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
581 return -ENODATA;
582
583 if (c->audit_login_uid == UID_INVALID)
584 return -ENXIO;
585
586 *uid = c->audit_login_uid;
587 return 0;
588 }
589
590 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
591 assert_return(c, -EINVAL);
592 assert_return(ret, -EINVAL);
593
594 if (!(c->mask & SD_BUS_CREDS_TTY))
595 return -ENODATA;
596
597 if (!c->tty)
598 return -ENXIO;
599
600 *ret = c->tty;
601 return 0;
602 }
603
604 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
605 assert_return(c, -EINVAL);
606 assert_return(unique_name, -EINVAL);
607
608 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
609 return -ENODATA;
610
611 *unique_name = c->unique_name;
612 return 0;
613 }
614
615 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
616 assert_return(c, -EINVAL);
617 assert_return(well_known_names, -EINVAL);
618
619 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
620 return -ENODATA;
621
622 /* As a special hack we return the bus driver as well-known
623 * names list when this is requested. */
624 if (c->well_known_names_driver) {
625 static const char* const wkn[] = {
626 "org.freedesktop.DBus",
627 NULL
628 };
629
630 *well_known_names = (char**) wkn;
631 return 0;
632 }
633
634 if (c->well_known_names_local) {
635 static const char* const wkn[] = {
636 "org.freedesktop.DBus.Local",
637 NULL
638 };
639
640 *well_known_names = (char**) wkn;
641 return 0;
642 }
643
644 *well_known_names = c->well_known_names;
645 return 0;
646 }
647
648 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
649 assert_return(c, -EINVAL);
650 assert_return(ret, -EINVAL);
651
652 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
653 return -ENODATA;
654
655 assert(c->description);
656
657 if (!c->unescaped_description) {
658 c->unescaped_description = bus_label_unescape(c->description);
659 if (!c->unescaped_description)
660 return -ENOMEM;
661 }
662
663 *ret = c->unescaped_description;
664 return 0;
665 }
666
667 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
668 size_t sz;
669
670 assert(c);
671 assert(capability >= 0);
672 assert(c->capability);
673
674 if ((unsigned) capability > cap_last_cap())
675 return 0;
676
677 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
678
679 return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
680 }
681
682 _public_ int sd_bus_creds_has_effective_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_EFFECTIVE_CAPS))
687 return -ENODATA;
688
689 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
690 }
691
692 _public_ int sd_bus_creds_has_permitted_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_PERMITTED_CAPS))
697 return -ENODATA;
698
699 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
700 }
701
702 _public_ int sd_bus_creds_has_inheritable_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_INHERITABLE_CAPS))
707 return -ENODATA;
708
709 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
710 }
711
712 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
713 assert_return(c, -EINVAL);
714 assert_return(capability >= 0, -EINVAL);
715
716 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
717 return -ENODATA;
718
719 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
720 }
721
722 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
723 size_t sz, max;
724 unsigned i, j;
725
726 assert(c);
727 assert(p);
728
729 max = DIV_ROUND_UP(cap_last_cap(), 32U);
730 p += strspn(p, WHITESPACE);
731
732 sz = strlen(p);
733 if (sz % 8 != 0)
734 return -EINVAL;
735
736 sz /= 8;
737 if (sz > max)
738 return -EINVAL;
739
740 if (!c->capability) {
741 c->capability = new0(uint32_t, max * 4);
742 if (!c->capability)
743 return -ENOMEM;
744 }
745
746 for (i = 0; i < sz; i ++) {
747 uint32_t v = 0;
748
749 for (j = 0; j < 8; ++j) {
750 int t;
751
752 t = unhexchar(*p++);
753 if (t < 0)
754 return -EINVAL;
755
756 v = (v << 4) | t;
757 }
758
759 c->capability[offset * max + (sz - i - 1)] = v;
760 }
761
762 return 0;
763 }
764
765 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
766 uint64_t missing;
767 int r;
768
769 assert(c);
770 assert(c->allocated);
771
772 if (!(mask & SD_BUS_CREDS_AUGMENT))
773 return 0;
774
775 /* Try to retrieve PID from creds if it wasn't passed to us */
776 if (pid > 0) {
777 c->pid = pid;
778 c->mask |= SD_BUS_CREDS_PID;
779 } else if (c->mask & SD_BUS_CREDS_PID)
780 pid = c->pid;
781 else
782 /* Without pid we cannot do much... */
783 return 0;
784
785 /* Try to retrieve TID from creds if it wasn't passed to us */
786 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
787 tid = c->tid;
788
789 /* Calculate what we shall and can add */
790 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);
791 if (missing == 0)
792 return 0;
793
794 if (tid > 0) {
795 c->tid = tid;
796 c->mask |= SD_BUS_CREDS_TID;
797 }
798
799 if (missing & (SD_BUS_CREDS_PPID |
800 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
801 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
802 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
803 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
804 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
805
806 _cleanup_fclose_ FILE *f = NULL;
807 const char *p;
808
809 p = procfs_file_alloca(pid, "status");
810
811 f = fopen(p, "re");
812 if (!f) {
813 if (errno == ENOENT)
814 return -ESRCH;
815 else if (errno != EPERM && errno != EACCES)
816 return -errno;
817 } else {
818 char line[LINE_MAX];
819
820 FOREACH_LINE(line, f, return -errno) {
821 truncate_nl(line);
822
823 if (missing & SD_BUS_CREDS_PPID) {
824 p = startswith(line, "PPid:");
825 if (p) {
826 p += strspn(p, WHITESPACE);
827
828 /* Explicitly check for PPID 0 (which is the case for PID 1) */
829 if (!streq(p, "0")) {
830 r = parse_pid(p, &c->ppid);
831 if (r < 0)
832 return r;
833
834 } else
835 c->ppid = 0;
836
837 c->mask |= SD_BUS_CREDS_PPID;
838 continue;
839 }
840 }
841
842 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
843 p = startswith(line, "Uid:");
844 if (p) {
845 unsigned long uid, euid, suid, fsuid;
846
847 p += strspn(p, WHITESPACE);
848 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
849 return -EIO;
850
851 if (missing & SD_BUS_CREDS_UID)
852 c->uid = (uid_t) uid;
853 if (missing & SD_BUS_CREDS_EUID)
854 c->euid = (uid_t) euid;
855 if (missing & SD_BUS_CREDS_SUID)
856 c->suid = (uid_t) suid;
857 if (missing & SD_BUS_CREDS_FSUID)
858 c->fsuid = (uid_t) fsuid;
859
860 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
861 continue;
862 }
863 }
864
865 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
866 p = startswith(line, "Gid:");
867 if (p) {
868 unsigned long gid, egid, sgid, fsgid;
869
870 p += strspn(p, WHITESPACE);
871 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
872 return -EIO;
873
874 if (missing & SD_BUS_CREDS_GID)
875 c->gid = (gid_t) gid;
876 if (missing & SD_BUS_CREDS_EGID)
877 c->egid = (gid_t) egid;
878 if (missing & SD_BUS_CREDS_SGID)
879 c->sgid = (gid_t) sgid;
880 if (missing & SD_BUS_CREDS_FSGID)
881 c->fsgid = (gid_t) fsgid;
882
883 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
884 continue;
885 }
886 }
887
888 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
889 p = startswith(line, "Groups:");
890 if (p) {
891 size_t allocated = 0;
892
893 for (;;) {
894 unsigned long g;
895 int n = 0;
896
897 p += strspn(p, WHITESPACE);
898 if (*p == 0)
899 break;
900
901 if (sscanf(p, "%lu%n", &g, &n) != 1)
902 return -EIO;
903
904 if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
905 return -ENOMEM;
906
907 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
908 p += n;
909 }
910
911 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
912 continue;
913 }
914 }
915
916 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
917 p = startswith(line, "CapEff:");
918 if (p) {
919 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
920 if (r < 0)
921 return r;
922
923 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
924 continue;
925 }
926 }
927
928 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
929 p = startswith(line, "CapPrm:");
930 if (p) {
931 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
932 if (r < 0)
933 return r;
934
935 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
936 continue;
937 }
938 }
939
940 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
941 p = startswith(line, "CapInh:");
942 if (p) {
943 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
944 if (r < 0)
945 return r;
946
947 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
948 continue;
949 }
950 }
951
952 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
953 p = startswith(line, "CapBnd:");
954 if (p) {
955 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
956 if (r < 0)
957 return r;
958
959 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
960 continue;
961 }
962 }
963 }
964 }
965 }
966
967 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
968 const char *p;
969
970 p = procfs_file_alloca(pid, "attr/current");
971 r = read_one_line_file(p, &c->label);
972 if (r < 0) {
973 if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
974 return r;
975 } else
976 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
977 }
978
979 if (missing & SD_BUS_CREDS_COMM) {
980 r = get_process_comm(pid, &c->comm);
981 if (r < 0) {
982 if (r != -EPERM && r != -EACCES)
983 return r;
984 } else
985 c->mask |= SD_BUS_CREDS_COMM;
986 }
987
988 if (missing & SD_BUS_CREDS_EXE) {
989 r = get_process_exe(pid, &c->exe);
990 if (r == -ESRCH) {
991 /* Unfortunately we cannot really distinguish
992 * the case here where the process does not
993 * exist, and /proc/$PID/exe being unreadable
994 * because $PID is a kernel thread. Hence,
995 * assume it is a kernel thread, and rely on
996 * that this case is caught with a later
997 * call. */
998 c->exe = NULL;
999 c->mask |= SD_BUS_CREDS_EXE;
1000 } else if (r < 0) {
1001 if (r != -EPERM && r != -EACCES)
1002 return r;
1003 } else
1004 c->mask |= SD_BUS_CREDS_EXE;
1005 }
1006
1007 if (missing & SD_BUS_CREDS_CMDLINE) {
1008 const char *p;
1009
1010 p = procfs_file_alloca(pid, "cmdline");
1011 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1012 if (r == -ENOENT)
1013 return -ESRCH;
1014 if (r < 0) {
1015 if (r != -EPERM && r != -EACCES)
1016 return r;
1017 } else {
1018 if (c->cmdline_size == 0) {
1019 free(c->cmdline);
1020 c->cmdline = NULL;
1021 }
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 == -ENXIO) {
1066 /* ENXIO 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 == -ENXIO) {
1079 /* ENXIO 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 }