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