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