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