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