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