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