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