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