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