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