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