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