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