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