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