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