]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-creds.c
sd-bus: when copying creds objects, make sure we copy even the implicit well known...
[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_public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
235 assert_return(c, -EINVAL);
236 assert_return(egid, -EINVAL);
237
238 if (!(c->mask & SD_BUS_CREDS_EGID))
239 return -ENODATA;
240
241 *egid = c->egid;
242 return 0;
243}
244
245_public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
246 assert_return(c, -EINVAL);
247 assert_return(sgid, -EINVAL);
248
249 if (!(c->mask & SD_BUS_CREDS_SGID))
250 return -ENODATA;
251
252 *sgid = c->sgid;
253 return 0;
254}
255
705a415f
LP
256_public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
257 assert_return(c, -EINVAL);
258 assert_return(fsgid, -EINVAL);
259
260 if (!(c->mask & SD_BUS_CREDS_FSGID))
261 return -ENODATA;
262
263 *fsgid = c->fsgid;
264 return 0;
265}
266
02581590
LP
267_public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
268 assert_return(c, -EINVAL);
269 assert_return(gids, -EINVAL);
270
271 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
272 return -ENODATA;
273
274 *gids = c->supplementary_gids;
275 return (int) c->n_supplementary_gids;
276}
277
5b12334d
LP
278_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
279 assert_return(c, -EINVAL);
280 assert_return(pid, -EINVAL);
6a4abbc8
LP
281
282 if (!(c->mask & SD_BUS_CREDS_PID))
283 return -ENODATA;
5b12334d
LP
284
285 assert(c->pid > 0);
286 *pid = c->pid;
287 return 0;
288}
289
290_public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
291 assert_return(c, -EINVAL);
292 assert_return(tid, -EINVAL);
6a4abbc8
LP
293
294 if (!(c->mask & SD_BUS_CREDS_TID))
295 return -ENODATA;
5b12334d
LP
296
297 assert(c->tid > 0);
298 *tid = c->tid;
299 return 0;
300}
301
5b12334d
LP
302_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
303 assert_return(c, -EINVAL);
6a4abbc8
LP
304
305 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
306 return -ENODATA;
5b12334d
LP
307
308 assert(c->label);
309 *ret = c->label;
310 return 0;
311}
312
313_public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
314 assert_return(c, -EINVAL);
315 assert_return(ret, -EINVAL);
6a4abbc8
LP
316
317 if (!(c->mask & SD_BUS_CREDS_COMM))
318 return -ENODATA;
5b12334d
LP
319
320 assert(c->comm);
321 *ret = c->comm;
322 return 0;
323}
324
325_public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
326 assert_return(c, -EINVAL);
327 assert_return(ret, -EINVAL);
6a4abbc8
LP
328
329 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
330 return -ENODATA;
5b12334d
LP
331
332 assert(c->tid_comm);
333 *ret = c->tid_comm;
334 return 0;
335}
336
337_public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
338 assert_return(c, -EINVAL);
339 assert_return(ret, -EINVAL);
6a4abbc8
LP
340
341 if (!(c->mask & SD_BUS_CREDS_EXE))
342 return -ENODATA;
5b12334d
LP
343
344 assert(c->exe);
345 *ret = c->exe;
346 return 0;
347}
348
349_public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
350 assert_return(c, -EINVAL);
351 assert_return(ret, -EINVAL);
6a4abbc8
LP
352
353 if (!(c->mask & SD_BUS_CREDS_CGROUP))
354 return -ENODATA;
5b12334d
LP
355
356 assert(c->cgroup);
357 *ret = c->cgroup;
358 return 0;
359}
360
361_public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
362 int r;
363
364 assert_return(c, -EINVAL);
365 assert_return(ret, -EINVAL);
6a4abbc8
LP
366
367 if (!(c->mask & SD_BUS_CREDS_UNIT))
368 return -ENODATA;
5b12334d
LP
369
370 assert(c->cgroup);
371
372 if (!c->unit) {
751bc6ac
LP
373 const char *shifted;
374
375 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
376 if (r < 0)
377 return r;
378
379 r = cg_path_get_unit(shifted, (char**) &c->unit);
5b12334d
LP
380 if (r < 0)
381 return r;
382 }
383
384 *ret = c->unit;
385 return 0;
386}
387
388_public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
389 int r;
390
391 assert_return(c, -EINVAL);
392 assert_return(ret, -EINVAL);
6a4abbc8
LP
393
394 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
395 return -ENODATA;
5b12334d
LP
396
397 assert(c->cgroup);
398
399 if (!c->user_unit) {
751bc6ac
LP
400 const char *shifted;
401
402 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
403 if (r < 0)
404 return r;
405
406 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
5b12334d
LP
407 if (r < 0)
408 return r;
409 }
410
411 *ret = c->user_unit;
412 return 0;
413}
414
415_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
416 int r;
417
418 assert_return(c, -EINVAL);
419 assert_return(ret, -EINVAL);
6a4abbc8
LP
420
421 if (!(c->mask & SD_BUS_CREDS_SLICE))
422 return -ENODATA;
5b12334d
LP
423
424 assert(c->cgroup);
425
426 if (!c->slice) {
751bc6ac
LP
427 const char *shifted;
428
429 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
430 if (r < 0)
431 return r;
432
433 r = cg_path_get_slice(shifted, (char**) &c->slice);
5b12334d
LP
434 if (r < 0)
435 return r;
436 }
437
438 *ret = c->slice;
439 return 0;
440}
441
442_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
443 int r;
444
445 assert_return(c, -EINVAL);
446 assert_return(ret, -EINVAL);
6a4abbc8
LP
447
448 if (!(c->mask & SD_BUS_CREDS_SESSION))
449 return -ENODATA;
5b12334d
LP
450
451 assert(c->cgroup);
452
453 if (!c->session) {
751bc6ac
LP
454 const char *shifted;
455
456 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
457 if (r < 0)
458 return r;
459
460 r = cg_path_get_session(shifted, (char**) &c->session);
5b12334d
LP
461 if (r < 0)
462 return r;
463 }
464
465 *ret = c->session;
466 return 0;
467}
468
469_public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
751bc6ac
LP
470 const char *shifted;
471 int r;
472
5b12334d
LP
473 assert_return(c, -EINVAL);
474 assert_return(uid, -EINVAL);
6a4abbc8
LP
475
476 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
477 return -ENODATA;
5b12334d
LP
478
479 assert(c->cgroup);
480
751bc6ac
LP
481 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
482 if (r < 0)
483 return r;
484
485 return cg_path_get_owner_uid(shifted, uid);
5b12334d
LP
486}
487
488_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
5b12334d 489 assert_return(c, -EINVAL);
6a4abbc8
LP
490
491 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
492 return -ENODATA;
5b12334d 493
689bd78d 494 assert_return(c->cmdline, -ESRCH);
5b12334d
LP
495 assert(c->cmdline);
496
49b832c5
LP
497 if (!c->cmdline_array) {
498 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
499 if (!c->cmdline_array)
500 return -ENOMEM;
5b12334d
LP
501 }
502
5b12334d 503 *cmdline = c->cmdline_array;
5b12334d
LP
504 return 0;
505}
506
507_public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
508 assert_return(c, -EINVAL);
509 assert_return(sessionid, -EINVAL);
6a4abbc8
LP
510
511 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
512 return -ENODATA;
5b12334d
LP
513
514 *sessionid = c->audit_session_id;
515 return 0;
516}
517
518_public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
519 assert_return(c, -EINVAL);
520 assert_return(uid, -EINVAL);
6a4abbc8
LP
521
522 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
523 return -ENODATA;
5b12334d
LP
524
525 *uid = c->audit_login_uid;
526 return 0;
527}
528
49b832c5
LP
529_public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
530 assert_return(c, -EINVAL);
531 assert_return(unique_name, -EINVAL);
6a4abbc8
LP
532
533 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
534 return -ENODATA;
49b832c5
LP
535
536 *unique_name = c->unique_name;
537 return 0;
538}
539
540_public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
541 assert_return(c, -EINVAL);
542 assert_return(well_known_names, -EINVAL);
6a4abbc8
LP
543
544 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
545 return -ENODATA;
49b832c5 546
ac653862
LP
547 /* As a special hack we return the bus driver as well-known
548 * names list when this is requested. */
549 if (c->well_known_names_driver) {
550 static const char* const wkn[] = {
551 "org.freedesktop.DBus",
552 NULL
553 };
554
555 *well_known_names = (char**) wkn;
556 return 0;
557 }
558
fb6d9b77
LP
559 if (c->well_known_names_local) {
560 static const char* const wkn[] = {
561 "org.freedesktop.DBus.Local",
562 NULL
563 };
564
565 *well_known_names = (char**) wkn;
566 return 0;
567 }
568
65dae17a 569 *well_known_names = c->well_known_names;
49b832c5
LP
570 return 0;
571}
572
455971c1 573_public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
cccb0b2c
LP
574 assert_return(c, -EINVAL);
575 assert_return(ret, -EINVAL);
576
455971c1 577 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
cccb0b2c
LP
578 return -ENODATA;
579
455971c1 580 assert(c->description);
2578d51e 581
455971c1
LP
582 if (!c->unescaped_description) {
583 c->unescaped_description = bus_label_unescape(c->description);
584 if (!c->unescaped_description)
2578d51e
LP
585 return -ENOMEM;
586 }
587
455971c1 588 *ret = c->unescaped_description;
cccb0b2c
LP
589 return 0;
590}
591
5b12334d
LP
592static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
593 size_t sz;
594
595 assert(c);
34a5d5e5 596 assert(capability >= 0);
5b12334d
LP
597 assert(c->capability);
598
da634f97 599 if ((unsigned) capability > cap_last_cap())
5b12334d
LP
600 return 0;
601
da634f97
LP
602 sz = DIV_ROUND_UP(cap_last_cap(), 32U);
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
da634f97
LP
985 if (c->mask & mask & SD_BUS_CREDS_PID) {
986 n->pid = c->pid;
987 n->mask |= SD_BUS_CREDS_PID;
988 }
989
990 if (c->mask & mask & SD_BUS_CREDS_TID) {
991 n->tid = c->tid;
992 n->mask |= SD_BUS_CREDS_TID;
993 }
994
5b12334d
LP
995 if (c->mask & mask & SD_BUS_CREDS_UID) {
996 n->uid = c->uid;
997 n->mask |= SD_BUS_CREDS_UID;
998 }
999
705a415f
LP
1000 if (c->mask & mask & SD_BUS_CREDS_EUID) {
1001 n->euid = c->euid;
1002 n->mask |= SD_BUS_CREDS_EUID;
1003 }
1004
1005 if (c->mask & mask & SD_BUS_CREDS_SUID) {
1006 n->suid = c->suid;
1007 n->mask |= SD_BUS_CREDS_SUID;
1008 }
1009
1010 if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1011 n->fsuid = c->fsuid;
1012 n->mask |= SD_BUS_CREDS_FSUID;
1013 }
1014
5b12334d
LP
1015 if (c->mask & mask & SD_BUS_CREDS_GID) {
1016 n->gid = c->gid;
1017 n->mask |= SD_BUS_CREDS_GID;
1018 }
1019
705a415f
LP
1020 if (c->mask & mask & SD_BUS_CREDS_EGID) {
1021 n->egid = c->egid;
1022 n->mask |= SD_BUS_CREDS_EGID;
1023 }
1024
1025 if (c->mask & mask & SD_BUS_CREDS_SGID) {
1026 n->sgid = c->sgid;
1027 n->mask |= SD_BUS_CREDS_SGID;
1028 }
1029
1030 if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1031 n->fsgid = c->fsgid;
1032 n->mask |= SD_BUS_CREDS_FSGID;
1033 }
1034
02581590
LP
1035 if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1036 n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1037 if (!n->supplementary_gids)
1038 return -ENOMEM;
1039 n->n_supplementary_gids = c->n_supplementary_gids;
1040 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
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;
da634f97
LP
1123 n->well_known_names_driver = c->well_known_names_driver;
1124 n->well_known_names_local = c->well_known_names_local;
a6ede528
LP
1125 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1126 }
1127
1128 if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1129 n->description = strdup(c->description);
1130 if (!n->description)
1131 return -ENOMEM;
1132 n->mask |= SD_BUS_CREDS_DESCRIPTION;
49b832c5
LP
1133 }
1134
5b12334d
LP
1135 /* Get more data */
1136
1137 r = bus_creds_add_more(n, mask,
1138 c->mask & SD_BUS_CREDS_PID ? c->pid : 0,
1139 c->mask & SD_BUS_CREDS_TID ? c->tid : 0);
1140 if (r < 0)
1141 return r;
1142
1143 *ret = n;
1144 n = NULL;
1145 return 0;
1146}