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