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