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