chiark / gitweb /
Unifiy free() usage
[elogind.git] / src / libelogind / 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 #include <linux/capability.h>
24
25 #include "util.h"
26 #include "formats-util.h"
27 #include "process-util.h"
28 #include "terminal-util.h"
29 #include "capability.h"
30 #include "cgroup-util.h"
31 #include "fileio.h"
32 #include "audit.h"
33 #include "bus-message.h"
34 #include "bus-util.h"
35 #include "strv.h"
36 #include "bus-creds.h"
37 #include "bus-label.h"
38
39 enum {
40         CAP_OFFSET_INHERITABLE = 0,
41         CAP_OFFSET_PERMITTED = 1,
42         CAP_OFFSET_EFFECTIVE = 2,
43         CAP_OFFSET_BOUNDING = 3
44 };
45
46 void bus_creds_done(sd_bus_creds *c) {
47         assert(c);
48
49         /* For internal bus cred structures that are allocated by
50          * something else */
51
52         free(c->session);
53         free(c->unit);
54         free(c->user_unit);
55         free(c->slice);
56         free(c->user_slice);
57         free(c->unescaped_description);
58         free(c->supplementary_gids);
59         free(c->tty);
60
61         free(c->well_known_names); /* note that this is an strv, but
62                                     * we only free the array, not the
63                                     * strings the array points to. The
64                                     * full strv we only free if
65                                     * c->allocated is set, see
66                                     * below. */
67
68         strv_free(c->cmdline_array);
69 }
70
71 _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
72         assert_return(c, NULL);
73
74         if (c->allocated) {
75                 assert(c->n_ref > 0);
76                 c->n_ref++;
77         } else {
78                 sd_bus_message *m;
79
80                 /* If this is an embedded creds structure, then
81                  * forward ref counting to the message */
82                 m = container_of(c, sd_bus_message, creds);
83                 sd_bus_message_ref(m);
84         }
85
86         return c;
87 }
88
89 _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
90
91         if (!c)
92                 return NULL;
93
94         if (c->allocated) {
95                 assert(c->n_ref > 0);
96                 c->n_ref--;
97
98                 if (c->n_ref == 0) {
99                         free(c->comm);
100                         free(c->tid_comm);
101                         free(c->exe);
102                         free(c->cmdline);
103                         free(c->cgroup);
104                         free(c->capability);
105                         free(c->label);
106                         free(c->unique_name);
107                         free(c->cgroup_root);
108                         free(c->description);
109
110                         c->supplementary_gids = mfree(c->supplementary_gids);
111
112                         strv_free(c->well_known_names);
113                         c->well_known_names = NULL;
114
115                         bus_creds_done(c);
116
117                         free(c);
118                 }
119         } else {
120                 sd_bus_message *m;
121
122                 m = container_of(c, sd_bus_message, creds);
123                 sd_bus_message_unref(m);
124         }
125
126
127         return NULL;
128 }
129
130 /// UNNEEDED by elogind
131 #if 0
132 _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
133         assert_return(c, 0);
134
135         return c->mask;
136 }
137 #endif // 0
138
139 _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
140         assert_return(c, 0);
141
142         return c->augmented;
143 }
144
145 sd_bus_creds* bus_creds_new(void) {
146         sd_bus_creds *c;
147
148         c = new0(sd_bus_creds, 1);
149         if (!c)
150                 return NULL;
151
152         c->allocated = true;
153         c->n_ref = 1;
154         return c;
155 }
156
157 /// UNNEEDED by elogind
158 #if 0
159 _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
160         sd_bus_creds *c;
161         int r;
162
163         assert_return(pid >= 0, -EINVAL);
164         assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
165         assert_return(ret, -EINVAL);
166
167         if (pid == 0)
168                 pid = getpid();
169
170         c = bus_creds_new();
171         if (!c)
172                 return -ENOMEM;
173
174         r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
175         if (r < 0) {
176                 sd_bus_creds_unref(c);
177                 return r;
178         }
179
180         /* Check if the process existed at all, in case we haven't
181          * figured that out already */
182         if (!pid_is_alive(pid)) {
183                 sd_bus_creds_unref(c);
184                 return -ESRCH;
185         }
186
187         *ret = c;
188         return 0;
189 }
190 #endif // 0
191
192 _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
193         assert_return(c, -EINVAL);
194         assert_return(uid, -EINVAL);
195
196         if (!(c->mask & SD_BUS_CREDS_UID))
197                 return -ENODATA;
198
199         *uid = c->uid;
200         return 0;
201 }
202
203 _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
204         assert_return(c, -EINVAL);
205         assert_return(euid, -EINVAL);
206
207         if (!(c->mask & SD_BUS_CREDS_EUID))
208                 return -ENODATA;
209
210         *euid = c->euid;
211         return 0;
212 }
213
214 /// UNNEEDED by elogind
215 #if 0
216 _public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
217         assert_return(c, -EINVAL);
218         assert_return(suid, -EINVAL);
219
220         if (!(c->mask & SD_BUS_CREDS_SUID))
221                 return -ENODATA;
222
223         *suid = c->suid;
224         return 0;
225 }
226
227
228 _public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
229         assert_return(c, -EINVAL);
230         assert_return(fsuid, -EINVAL);
231
232         if (!(c->mask & SD_BUS_CREDS_FSUID))
233                 return -ENODATA;
234
235         *fsuid = c->fsuid;
236         return 0;
237 }
238
239 _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
240         assert_return(c, -EINVAL);
241         assert_return(gid, -EINVAL);
242
243         if (!(c->mask & SD_BUS_CREDS_GID))
244                 return -ENODATA;
245
246         *gid = c->gid;
247         return 0;
248 }
249 #endif // 0
250
251 _public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
252         assert_return(c, -EINVAL);
253         assert_return(egid, -EINVAL);
254
255         if (!(c->mask & SD_BUS_CREDS_EGID))
256                 return -ENODATA;
257
258         *egid = c->egid;
259         return 0;
260 }
261
262 /// UNNEEDED by elogind
263 #if 0
264 _public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
265         assert_return(c, -EINVAL);
266         assert_return(sgid, -EINVAL);
267
268         if (!(c->mask & SD_BUS_CREDS_SGID))
269                 return -ENODATA;
270
271         *sgid = c->sgid;
272         return 0;
273 }
274
275 _public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
276         assert_return(c, -EINVAL);
277         assert_return(fsgid, -EINVAL);
278
279         if (!(c->mask & SD_BUS_CREDS_FSGID))
280                 return -ENODATA;
281
282         *fsgid = c->fsgid;
283         return 0;
284 }
285
286 _public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
287         assert_return(c, -EINVAL);
288         assert_return(gids, -EINVAL);
289
290         if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
291                 return -ENODATA;
292
293         *gids = c->supplementary_gids;
294         return (int) c->n_supplementary_gids;
295 }
296 #endif // 0
297
298 _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
299         assert_return(c, -EINVAL);
300         assert_return(pid, -EINVAL);
301
302         if (!(c->mask & SD_BUS_CREDS_PID))
303                 return -ENODATA;
304
305         assert(c->pid > 0);
306         *pid = c->pid;
307         return 0;
308 }
309
310 /// UNNEEDED by elogind
311 #if 0
312 _public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
313         assert_return(c, -EINVAL);
314         assert_return(ppid, -EINVAL);
315
316         if (!(c->mask & SD_BUS_CREDS_PPID))
317                 return -ENODATA;
318
319         /* PID 1 has no parent process. Let's distinguish the case of
320          * not knowing and not having a parent process by the returned
321          * error code. */
322         if (c->ppid == 0)
323                 return -ENXIO;
324
325         *ppid = c->ppid;
326         return 0;
327 }
328 #endif // 0
329
330 _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
331         assert_return(c, -EINVAL);
332         assert_return(tid, -EINVAL);
333
334         if (!(c->mask & SD_BUS_CREDS_TID))
335                 return -ENODATA;
336
337         assert(c->tid > 0);
338         *tid = c->tid;
339         return 0;
340 }
341
342 _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
343         assert_return(c, -EINVAL);
344
345         if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
346                 return -ENODATA;
347
348         assert(c->label);
349         *ret = c->label;
350         return 0;
351 }
352
353 /// UNNEEDED by elogind
354 #if 0
355 _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
356         assert_return(c, -EINVAL);
357         assert_return(ret, -EINVAL);
358
359         if (!(c->mask & SD_BUS_CREDS_COMM))
360                 return -ENODATA;
361
362         assert(c->comm);
363         *ret = c->comm;
364         return 0;
365 }
366
367 _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
368         assert_return(c, -EINVAL);
369         assert_return(ret, -EINVAL);
370
371         if (!(c->mask & SD_BUS_CREDS_TID_COMM))
372                 return -ENODATA;
373
374         assert(c->tid_comm);
375         *ret = c->tid_comm;
376         return 0;
377 }
378
379 _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
380         assert_return(c, -EINVAL);
381         assert_return(ret, -EINVAL);
382
383         if (!(c->mask & SD_BUS_CREDS_EXE))
384                 return -ENODATA;
385
386         if (!c->exe)
387                 return -ENXIO;
388
389         *ret = c->exe;
390         return 0;
391 }
392
393 _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
394         assert_return(c, -EINVAL);
395         assert_return(ret, -EINVAL);
396
397         if (!(c->mask & SD_BUS_CREDS_CGROUP))
398                 return -ENODATA;
399
400         assert(c->cgroup);
401         *ret = c->cgroup;
402         return 0;
403 }
404
405 _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
406         int r;
407
408         assert_return(c, -EINVAL);
409         assert_return(ret, -EINVAL);
410
411         if (!(c->mask & SD_BUS_CREDS_UNIT))
412                 return -ENODATA;
413
414         assert(c->cgroup);
415
416         if (!c->unit) {
417                 const char *shifted;
418
419                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
420                 if (r < 0)
421                         return r;
422
423                 r = cg_path_get_unit(shifted, (char**) &c->unit);
424                 if (r < 0)
425                         return r;
426         }
427
428         *ret = c->unit;
429         return 0;
430 }
431
432 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
433         int r;
434
435         assert_return(c, -EINVAL);
436         assert_return(ret, -EINVAL);
437
438         if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
439                 return -ENODATA;
440
441         assert(c->cgroup);
442
443         if (!c->user_unit) {
444                 const char *shifted;
445
446                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
447                 if (r < 0)
448                         return r;
449
450                 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
451                 if (r < 0)
452                         return r;
453         }
454
455         *ret = c->user_unit;
456         return 0;
457 }
458
459 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
460         int r;
461
462         assert_return(c, -EINVAL);
463         assert_return(ret, -EINVAL);
464
465         if (!(c->mask & SD_BUS_CREDS_SLICE))
466                 return -ENODATA;
467
468         assert(c->cgroup);
469
470         if (!c->slice) {
471                 const char *shifted;
472
473                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
474                 if (r < 0)
475                         return r;
476
477                 r = cg_path_get_slice(shifted, (char**) &c->slice);
478                 if (r < 0)
479                         return r;
480         }
481
482         *ret = c->slice;
483         return 0;
484 }
485
486 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
487         int r;
488
489         assert_return(c, -EINVAL);
490         assert_return(ret, -EINVAL);
491
492         if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
493                 return -ENODATA;
494
495         assert(c->cgroup);
496
497         if (!c->user_slice) {
498                 const char *shifted;
499
500                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
501                 if (r < 0)
502                         return r;
503
504                 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
505                 if (r < 0)
506                         return r;
507         }
508
509         *ret = c->user_slice;
510         return 0;
511 }
512 #endif // 0
513
514 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
515         int r;
516
517         assert_return(c, -EINVAL);
518         assert_return(ret, -EINVAL);
519
520         if (!(c->mask & SD_BUS_CREDS_SESSION))
521                 return -ENODATA;
522
523         assert(c->cgroup);
524
525         if (!c->session) {
526                 const char *shifted;
527
528                 log_debug_elogind("Shifting cgroup \"%s\", root \"%s\"",
529                                   c->cgroup, c->cgroup_root ? c->cgroup_root : "NULL");
530                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
531                 if (r < 0)
532                         return r;
533
534                 log_debug_elogind("Shifted: \"%s\"", shifted);
535                 r = cg_path_get_session(shifted, (char**) &c->session);
536                 if (r < 0)
537                         return r;
538         }
539
540         *ret = c->session;
541         return 0;
542 }
543
544 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
545         const char *shifted;
546         int r;
547
548         assert_return(c, -EINVAL);
549         assert_return(uid, -EINVAL);
550
551         if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
552                 return -ENODATA;
553
554         assert(c->cgroup);
555
556         r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
557         if (r < 0)
558                 return r;
559
560 /// elogind does not support systemd slices
561 #if 0
562         return cg_path_get_owner_uid(shifted, uid);
563 #else
564         *uid = c->uid;
565         return 0;
566 #endif // 0
567 }
568
569 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
570         assert_return(c, -EINVAL);
571
572         if (!(c->mask & SD_BUS_CREDS_CMDLINE))
573                 return -ENODATA;
574
575         if (!c->cmdline)
576                 return -ENXIO;
577
578         if (!c->cmdline_array) {
579                 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
580                 if (!c->cmdline_array)
581                         return -ENOMEM;
582         }
583
584         *cmdline = c->cmdline_array;
585         return 0;
586 }
587
588 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
589         assert_return(c, -EINVAL);
590         assert_return(sessionid, -EINVAL);
591
592         if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
593                 return -ENODATA;
594
595         if (c->audit_session_id == AUDIT_SESSION_INVALID)
596                 return -ENXIO;
597
598         *sessionid = c->audit_session_id;
599         return 0;
600 }
601
602 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
603         assert_return(c, -EINVAL);
604         assert_return(uid, -EINVAL);
605
606         if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
607                 return -ENODATA;
608
609         if (c->audit_login_uid == UID_INVALID)
610                 return -ENXIO;
611
612         *uid = c->audit_login_uid;
613         return 0;
614 }
615
616 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
617         assert_return(c, -EINVAL);
618         assert_return(ret, -EINVAL);
619
620         if (!(c->mask & SD_BUS_CREDS_TTY))
621                 return -ENODATA;
622
623         if (!c->tty)
624                 return -ENXIO;
625
626         *ret = c->tty;
627         return 0;
628 }
629
630 /// UNNEEDED by elogind
631 #if 0
632 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
633         assert_return(c, -EINVAL);
634         assert_return(unique_name, -EINVAL);
635
636         if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
637                 return -ENODATA;
638
639         *unique_name = c->unique_name;
640         return 0;
641 }
642
643 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
644         assert_return(c, -EINVAL);
645         assert_return(well_known_names, -EINVAL);
646
647         if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
648                 return -ENODATA;
649
650         /* As a special hack we return the bus driver as well-known
651          * names list when this is requested. */
652         if (c->well_known_names_driver) {
653                 static const char* const wkn[] = {
654                         "org.freedesktop.DBus",
655                         NULL
656                 };
657
658                 *well_known_names = (char**) wkn;
659                 return 0;
660         }
661
662         if (c->well_known_names_local) {
663                 static const char* const wkn[] = {
664                         "org.freedesktop.DBus.Local",
665                         NULL
666                 };
667
668                 *well_known_names = (char**) wkn;
669                 return 0;
670         }
671
672         *well_known_names = c->well_known_names;
673         return 0;
674 }
675
676 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
677         assert_return(c, -EINVAL);
678         assert_return(ret, -EINVAL);
679
680         if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
681                 return -ENODATA;
682
683         assert(c->description);
684
685         if (!c->unescaped_description) {
686                 c->unescaped_description = bus_label_unescape(c->description);
687                 if (!c->unescaped_description)
688                         return -ENOMEM;
689         }
690
691         *ret = c->unescaped_description;
692         return 0;
693 }
694 #endif // 0
695
696 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
697         size_t sz;
698
699         assert(c);
700         assert(capability >= 0);
701         assert(c->capability);
702
703         if ((unsigned) capability > cap_last_cap())
704                 return 0;
705
706         sz = DIV_ROUND_UP(cap_last_cap(), 32U);
707
708         return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
709 }
710
711 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
712         assert_return(c, -EINVAL);
713         assert_return(capability >= 0, -EINVAL);
714
715         if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
716                 return -ENODATA;
717
718         return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
719 }
720
721 /// UNNEEDED by elogind
722 #if 0
723 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
724         assert_return(c, -EINVAL);
725         assert_return(capability >= 0, -EINVAL);
726
727         if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
728                 return -ENODATA;
729
730         return has_cap(c, CAP_OFFSET_PERMITTED, capability);
731 }
732
733 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
734         assert_return(c, -EINVAL);
735         assert_return(capability >= 0, -EINVAL);
736
737         if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
738                 return -ENODATA;
739
740         return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
741 }
742
743 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
744         assert_return(c, -EINVAL);
745         assert_return(capability >= 0, -EINVAL);
746
747         if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
748                 return -ENODATA;
749
750         return has_cap(c, CAP_OFFSET_BOUNDING, capability);
751 }
752 #endif // 0
753
754 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
755         size_t sz, max;
756         unsigned i, j;
757
758         assert(c);
759         assert(p);
760
761         max = DIV_ROUND_UP(cap_last_cap(), 32U);
762         p += strspn(p, WHITESPACE);
763
764         sz = strlen(p);
765         if (sz % 8 != 0)
766                 return -EINVAL;
767
768         sz /= 8;
769         if (sz > max)
770                 return -EINVAL;
771
772         if (!c->capability) {
773                 c->capability = new0(uint32_t, max * 4);
774                 if (!c->capability)
775                         return -ENOMEM;
776         }
777
778         for (i = 0; i < sz; i ++) {
779                 uint32_t v = 0;
780
781                 for (j = 0; j < 8; ++j) {
782                         int t;
783
784                         t = unhexchar(*p++);
785                         if (t < 0)
786                                 return -EINVAL;
787
788                         v = (v << 4) | t;
789                 }
790
791                 c->capability[offset * max + (sz - i - 1)] = v;
792         }
793
794         return 0;
795 }
796
797 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
798         uint64_t missing;
799         int r;
800
801         assert(c);
802         assert(c->allocated);
803
804         if (!(mask & SD_BUS_CREDS_AUGMENT))
805                 return 0;
806
807         /* Try to retrieve PID from creds if it wasn't passed to us */
808         if (pid > 0) {
809                 c->pid = pid;
810                 c->mask |= SD_BUS_CREDS_PID;
811         } else if (c->mask & SD_BUS_CREDS_PID)
812                 pid = c->pid;
813         else
814                 /* Without pid we cannot do much... */
815                 return 0;
816
817         /* Try to retrieve TID from creds if it wasn't passed to us */
818         if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
819                 tid = c->tid;
820
821         /* Calculate what we shall and can add */
822         missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT);
823         if (missing == 0)
824                 return 0;
825
826         if (tid > 0) {
827                 c->tid = tid;
828                 c->mask |= SD_BUS_CREDS_TID;
829         }
830
831         if (missing & (SD_BUS_CREDS_PPID |
832                        SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
833                        SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
834                        SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
835                        SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
836                        SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
837
838                 _cleanup_fclose_ FILE *f = NULL;
839                 const char *p;
840
841                 p = procfs_file_alloca(pid, "status");
842
843                 f = fopen(p, "re");
844                 if (!f) {
845                         if (errno == ENOENT)
846                                 return -ESRCH;
847                         else if (errno != EPERM && errno != EACCES)
848                                 return -errno;
849                 } else {
850                         char line[LINE_MAX];
851
852                         FOREACH_LINE(line, f, return -errno) {
853                                 truncate_nl(line);
854
855                                 if (missing & SD_BUS_CREDS_PPID) {
856                                         p = startswith(line, "PPid:");
857                                         if (p) {
858                                                 p += strspn(p, WHITESPACE);
859
860                                                 /* Explicitly check for PPID 0 (which is the case for PID 1) */
861                                                 if (!streq(p, "0")) {
862                                                         r = parse_pid(p, &c->ppid);
863                                                         if (r < 0)
864                                                                 return r;
865
866                                                 } else
867                                                         c->ppid = 0;
868
869                                                 c->mask |= SD_BUS_CREDS_PPID;
870                                                 continue;
871                                         }
872                                 }
873
874                                 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
875                                         p = startswith(line, "Uid:");
876                                         if (p) {
877                                                 unsigned long uid, euid, suid, fsuid;
878
879                                                 p += strspn(p, WHITESPACE);
880                                                 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
881                                                         return -EIO;
882
883                                                 if (missing & SD_BUS_CREDS_UID)
884                                                         c->uid = (uid_t) uid;
885                                                 if (missing & SD_BUS_CREDS_EUID)
886                                                         c->euid = (uid_t) euid;
887                                                 if (missing & SD_BUS_CREDS_SUID)
888                                                         c->suid = (uid_t) suid;
889                                                 if (missing & SD_BUS_CREDS_FSUID)
890                                                         c->fsuid = (uid_t) fsuid;
891
892                                                 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
893                                                 continue;
894                                         }
895                                 }
896
897                                 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
898                                         p = startswith(line, "Gid:");
899                                         if (p) {
900                                                 unsigned long gid, egid, sgid, fsgid;
901
902                                                 p += strspn(p, WHITESPACE);
903                                                 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
904                                                         return -EIO;
905
906                                                 if (missing & SD_BUS_CREDS_GID)
907                                                         c->gid = (gid_t) gid;
908                                                 if (missing & SD_BUS_CREDS_EGID)
909                                                         c->egid = (gid_t) egid;
910                                                 if (missing & SD_BUS_CREDS_SGID)
911                                                         c->sgid = (gid_t) sgid;
912                                                 if (missing & SD_BUS_CREDS_FSGID)
913                                                         c->fsgid = (gid_t) fsgid;
914
915                                                 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
916                                                 continue;
917                                         }
918                                 }
919
920                                 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
921                                         p = startswith(line, "Groups:");
922                                         if (p) {
923                                                 size_t allocated = 0;
924
925                                                 for (;;) {
926                                                         unsigned long g;
927                                                         int n = 0;
928
929                                                         p += strspn(p, WHITESPACE);
930                                                         if (*p == 0)
931                                                                 break;
932
933                                                         if (sscanf(p, "%lu%n", &g, &n) != 1)
934                                                                 return -EIO;
935
936                                                         if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
937                                                                 return -ENOMEM;
938
939                                                         c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
940                                                         p += n;
941                                                 }
942
943                                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
944                                                 continue;
945                                         }
946                                 }
947
948                                 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
949                                         p = startswith(line, "CapEff:");
950                                         if (p) {
951                                                 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
952                                                 if (r < 0)
953                                                         return r;
954
955                                                 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
956                                                 continue;
957                                         }
958                                 }
959
960                                 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
961                                         p = startswith(line, "CapPrm:");
962                                         if (p) {
963                                                 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
964                                                 if (r < 0)
965                                                         return r;
966
967                                                 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
968                                                 continue;
969                                         }
970                                 }
971
972                                 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
973                                         p = startswith(line, "CapInh:");
974                                         if (p) {
975                                                 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
976                                                 if (r < 0)
977                                                         return r;
978
979                                                 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
980                                                 continue;
981                                         }
982                                 }
983
984                                 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
985                                         p = startswith(line, "CapBnd:");
986                                         if (p) {
987                                                 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
988                                                 if (r < 0)
989                                                         return r;
990
991                                                 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
992                                                 continue;
993                                         }
994                                 }
995                         }
996                 }
997         }
998
999         if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1000                 const char *p;
1001
1002                 p = procfs_file_alloca(pid, "attr/current");
1003                 r = read_one_line_file(p, &c->label);
1004                 if (r < 0) {
1005                         if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
1006                                 return r;
1007                 } else
1008                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1009         }
1010
1011         if (missing & SD_BUS_CREDS_COMM) {
1012                 r = get_process_comm(pid, &c->comm);
1013                 if (r < 0) {
1014                         if (r != -EPERM && r != -EACCES)
1015                                 return r;
1016                 } else
1017                         c->mask |= SD_BUS_CREDS_COMM;
1018         }
1019
1020         if (missing & SD_BUS_CREDS_EXE) {
1021                 r = get_process_exe(pid, &c->exe);
1022                 if (r == -ESRCH) {
1023                         /* Unfortunately we cannot really distinguish
1024                          * the case here where the process does not
1025                          * exist, and /proc/$PID/exe being unreadable
1026                          * because $PID is a kernel thread. Hence,
1027                          * assume it is a kernel thread, and rely on
1028                          * that this case is caught with a later
1029                          * call. */
1030                         c->exe = NULL;
1031                         c->mask |= SD_BUS_CREDS_EXE;
1032                 } else if (r < 0) {
1033                         if (r != -EPERM && r != -EACCES)
1034                                 return r;
1035                 } else
1036                         c->mask |= SD_BUS_CREDS_EXE;
1037         }
1038
1039         if (missing & SD_BUS_CREDS_CMDLINE) {
1040                 const char *p;
1041
1042                 p = procfs_file_alloca(pid, "cmdline");
1043                 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1044                 if (r == -ENOENT)
1045                         return -ESRCH;
1046                 if (r < 0) {
1047                         if (r != -EPERM && r != -EACCES)
1048                                 return r;
1049                 } else {
1050                         if (c->cmdline_size == 0) {
1051                                 c->cmdline = mfree(c->cmdline);
1052                         }
1053
1054                         c->mask |= SD_BUS_CREDS_CMDLINE;
1055                 }
1056         }
1057
1058         if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1059                 _cleanup_free_ char *p = NULL;
1060
1061                 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1062                         return -ENOMEM;
1063
1064                 r = read_one_line_file(p, &c->tid_comm);
1065                 if (r == -ENOENT)
1066                         return -ESRCH;
1067                 if (r < 0) {
1068                         if (r != -EPERM && r != -EACCES)
1069                                 return r;
1070                 } else
1071                         c->mask |= SD_BUS_CREDS_TID_COMM;
1072         }
1073
1074         if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
1075
1076                 if (!c->cgroup) {
1077                         r = cg_pid_get_path(NULL, pid, &c->cgroup);
1078                         if (r < 0) {
1079                                 if (r != -EPERM && r != -EACCES)
1080                                         return r;
1081                         }
1082                 }
1083
1084                 if (!c->cgroup_root) {
1085                         r = cg_get_root_path(&c->cgroup_root);
1086                         if (r < 0)
1087                                 return r;
1088                 }
1089
1090                 if (c->cgroup)
1091                         c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
1092         }
1093
1094         if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1095                 r = audit_session_from_pid(pid, &c->audit_session_id);
1096                 if (r == -ENODATA) {
1097                         /* ENODATA means: no audit session id assigned */
1098                         c->audit_session_id = AUDIT_SESSION_INVALID;
1099                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1100                 } else if (r < 0) {
1101                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1102                                 return r;
1103                 } else
1104                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1105         }
1106
1107         if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1108                 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1109                 if (r == -ENODATA) {
1110                         /* ENODATA means: no audit login uid assigned */
1111                         c->audit_login_uid = UID_INVALID;
1112                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1113                 } else if (r < 0) {
1114                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1115                                 return r;
1116                 } else
1117                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1118         }
1119
1120         if (missing & SD_BUS_CREDS_TTY) {
1121                 r = get_ctty(pid, NULL, &c->tty);
1122                 if (r == -ENXIO) {
1123                         /* ENXIO means: process has no controlling TTY */
1124                         c->tty = NULL;
1125                         c->mask |= SD_BUS_CREDS_TTY;
1126                 } else if (r < 0) {
1127                         if (r != -EPERM && r != -EACCES && r != -ENOENT)
1128                                 return r;
1129                 } else
1130                         c->mask |= SD_BUS_CREDS_TTY;
1131         }
1132
1133         /* In case only the exe path was to be read we cannot
1134          * distinguish the case where the exe path was unreadable
1135          * because the process was a kernel thread, or when the
1136          * process didn't exist at all. Hence, let's do a final check,
1137          * to be sure. */
1138         if (!pid_is_alive(pid))
1139                 return -ESRCH;
1140
1141         if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1142                 return -ESRCH;
1143
1144         c->augmented = missing & c->mask;
1145
1146         return 0;
1147 }
1148
1149 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1150         _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1151         int r;
1152
1153         assert(c);
1154         assert(ret);
1155
1156         if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1157                 /* There's already all data we need, or augmentation
1158                  * wasn't turned on. */
1159
1160                 *ret = sd_bus_creds_ref(c);
1161                 return 0;
1162         }
1163
1164         n = bus_creds_new();
1165         if (!n)
1166                 return -ENOMEM;
1167
1168         /* Copy the original data over */
1169
1170         if (c->mask & mask & SD_BUS_CREDS_PID) {
1171                 n->pid = c->pid;
1172                 n->mask |= SD_BUS_CREDS_PID;
1173         }
1174
1175         if (c->mask & mask & SD_BUS_CREDS_TID) {
1176                 n->tid = c->tid;
1177                 n->mask |= SD_BUS_CREDS_TID;
1178         }
1179
1180         if (c->mask & mask & SD_BUS_CREDS_PPID) {
1181                 n->ppid = c->ppid;
1182                 n->mask |= SD_BUS_CREDS_PPID;
1183         }
1184
1185         if (c->mask & mask & SD_BUS_CREDS_UID) {
1186                 n->uid = c->uid;
1187                 n->mask |= SD_BUS_CREDS_UID;
1188         }
1189
1190         if (c->mask & mask & SD_BUS_CREDS_EUID) {
1191                 n->euid = c->euid;
1192                 n->mask |= SD_BUS_CREDS_EUID;
1193         }
1194
1195         if (c->mask & mask & SD_BUS_CREDS_SUID) {
1196                 n->suid = c->suid;
1197                 n->mask |= SD_BUS_CREDS_SUID;
1198         }
1199
1200         if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1201                 n->fsuid = c->fsuid;
1202                 n->mask |= SD_BUS_CREDS_FSUID;
1203         }
1204
1205         if (c->mask & mask & SD_BUS_CREDS_GID) {
1206                 n->gid = c->gid;
1207                 n->mask |= SD_BUS_CREDS_GID;
1208         }
1209
1210         if (c->mask & mask & SD_BUS_CREDS_EGID) {
1211                 n->egid = c->egid;
1212                 n->mask |= SD_BUS_CREDS_EGID;
1213         }
1214
1215         if (c->mask & mask & SD_BUS_CREDS_SGID) {
1216                 n->sgid = c->sgid;
1217                 n->mask |= SD_BUS_CREDS_SGID;
1218         }
1219
1220         if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1221                 n->fsgid = c->fsgid;
1222                 n->mask |= SD_BUS_CREDS_FSGID;
1223         }
1224
1225         if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1226                 if (c->supplementary_gids) {
1227                         n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1228                         if (!n->supplementary_gids)
1229                                 return -ENOMEM;
1230                         n->n_supplementary_gids = c->n_supplementary_gids;
1231                 } else {
1232                         n->supplementary_gids = NULL;
1233                         n->n_supplementary_gids = 0;
1234                 }
1235
1236                 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1237         }
1238
1239         if (c->mask & mask & SD_BUS_CREDS_COMM) {
1240                 assert(c->comm);
1241
1242                 n->comm = strdup(c->comm);
1243                 if (!n->comm)
1244                         return -ENOMEM;
1245
1246                 n->mask |= SD_BUS_CREDS_COMM;
1247         }
1248
1249         if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1250                 assert(c->tid_comm);
1251
1252                 n->tid_comm = strdup(c->tid_comm);
1253                 if (!n->tid_comm)
1254                         return -ENOMEM;
1255
1256                 n->mask |= SD_BUS_CREDS_TID_COMM;
1257         }
1258
1259         if (c->mask & mask & SD_BUS_CREDS_EXE) {
1260                 if (c->exe) {
1261                         n->exe = strdup(c->exe);
1262                         if (!n->exe)
1263                                 return -ENOMEM;
1264                 } else
1265                         n->exe = NULL;
1266
1267                 n->mask |= SD_BUS_CREDS_EXE;
1268         }
1269
1270         if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1271                 if (c->cmdline) {
1272                         n->cmdline = memdup(c->cmdline, c->cmdline_size);
1273                         if (!n->cmdline)
1274                                 return -ENOMEM;
1275
1276                         n->cmdline_size = c->cmdline_size;
1277                 } else {
1278                         n->cmdline = NULL;
1279                         n->cmdline_size = 0;
1280                 }
1281
1282                 n->mask |= SD_BUS_CREDS_CMDLINE;
1283         }
1284
1285         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_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) {
1286                 assert(c->cgroup);
1287
1288                 n->cgroup = strdup(c->cgroup);
1289                 if (!n->cgroup)
1290                         return -ENOMEM;
1291
1292                 n->cgroup_root = strdup(c->cgroup_root);
1293                 if (!n->cgroup_root)
1294                         return -ENOMEM;
1295
1296                 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_USER_SLICE|SD_BUS_CREDS_OWNER_UID);
1297         }
1298
1299         if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1300                 assert(c->capability);
1301
1302                 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1303                 if (!n->capability)
1304                         return -ENOMEM;
1305
1306                 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);
1307         }
1308
1309         if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1310                 assert(c->label);
1311
1312                 n->label = strdup(c->label);
1313                 if (!n->label)
1314                         return -ENOMEM;
1315                 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1316         }
1317
1318         if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1319                 n->audit_session_id = c->audit_session_id;
1320                 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1321         }
1322         if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1323                 n->audit_login_uid = c->audit_login_uid;
1324                 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1325         }
1326
1327         if (c->mask & mask & SD_BUS_CREDS_TTY) {
1328                 if (c->tty) {
1329                         n->tty = strdup(c->tty);
1330                         if (!n->tty)
1331                                 return -ENOMEM;
1332                 } else
1333                         n->tty = NULL;
1334                 n->mask |= SD_BUS_CREDS_TTY;
1335         }
1336
1337         if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1338                 assert(c->unique_name);
1339
1340                 n->unique_name = strdup(c->unique_name);
1341                 if (!n->unique_name)
1342                         return -ENOMEM;
1343                 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1344         }
1345
1346         if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1347                 if (strv_isempty(c->well_known_names))
1348                         n->well_known_names = NULL;
1349                 else {
1350                         n->well_known_names = strv_copy(c->well_known_names);
1351                         if (!n->well_known_names)
1352                                 return -ENOMEM;
1353                 }
1354                 n->well_known_names_driver = c->well_known_names_driver;
1355                 n->well_known_names_local = c->well_known_names_local;
1356                 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1357         }
1358
1359         if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1360                 assert(c->description);
1361                 n->description = strdup(c->description);
1362                 if (!n->description)
1363                         return -ENOMEM;
1364                 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1365         }
1366
1367         n->augmented = c->augmented & n->mask;
1368
1369         /* Get more data */
1370
1371         r = bus_creds_add_more(n, mask, 0, 0);
1372         if (r < 0)
1373                 return r;
1374
1375         *ret = n;
1376         n = NULL;
1377         return 0;
1378 }