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