chiark / gitweb /
sd-bus: don't leak kdbus notifications
[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 distinguish 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) {
744                 c->pid = pid;
745                 c->mask |= SD_BUS_CREDS_PID;
746         } else if (c->mask & SD_BUS_CREDS_PID)
747                 pid = c->pid;
748         else
749                 /* Without pid we cannot do much... */
750                 return 0;
751
752         /* Try to retrieve TID from creds if it wasn't passed to us */
753         if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
754                 tid = c->tid;
755
756         /* Calculate what we shall and can add */
757         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);
758         if (missing == 0)
759                 return 0;
760
761         if (tid > 0) {
762                 c->tid = tid;
763                 c->mask |= SD_BUS_CREDS_TID;
764         }
765
766         if (missing & (SD_BUS_CREDS_PPID |
767                        SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
768                        SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
769                        SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
770                        SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
771                        SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
772
773                 _cleanup_fclose_ FILE *f = NULL;
774                 const char *p;
775
776                 p = procfs_file_alloca(pid, "status");
777
778                 f = fopen(p, "re");
779                 if (!f) {
780                         if (errno == ENOENT)
781                                 return -ESRCH;
782                         else if (errno != EPERM && errno != EACCES)
783                                 return -errno;
784                 } else {
785                         char line[LINE_MAX];
786
787                         FOREACH_LINE(line, f, return -errno) {
788                                 truncate_nl(line);
789
790                                 if (missing & SD_BUS_CREDS_PPID) {
791                                         p = startswith(line, "PPid:");
792                                         if (p) {
793                                                 p += strspn(p, WHITESPACE);
794
795                                                 /* Explicitly check for PPID 0 (which is the case for PID 1) */
796                                                 if (!streq(p, "0")) {
797                                                         r = parse_pid(p, &c->ppid);
798                                                         if (r < 0)
799                                                                 return r;
800
801                                                 } else
802                                                         c->ppid = 0;
803
804                                                 c->mask |= SD_BUS_CREDS_PPID;
805                                                 continue;
806                                         }
807                                 }
808
809                                 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
810                                         p = startswith(line, "Uid:");
811                                         if (p) {
812                                                 unsigned long uid, euid, suid, fsuid;
813
814                                                 p += strspn(p, WHITESPACE);
815                                                 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
816                                                         return -EIO;
817
818                                                 if (missing & SD_BUS_CREDS_UID)
819                                                         c->uid = (uid_t) uid;
820                                                 if (missing & SD_BUS_CREDS_EUID)
821                                                         c->euid = (uid_t) euid;
822                                                 if (missing & SD_BUS_CREDS_SUID)
823                                                         c->suid = (uid_t) suid;
824                                                 if (missing & SD_BUS_CREDS_FSUID)
825                                                         c->fsuid = (uid_t) fsuid;
826
827                                                 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
828                                                 continue;
829                                         }
830                                 }
831
832                                 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
833                                         p = startswith(line, "Gid:");
834                                         if (p) {
835                                                 unsigned long gid, egid, sgid, fsgid;
836
837                                                 p += strspn(p, WHITESPACE);
838                                                 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
839                                                         return -EIO;
840
841                                                 if (missing & SD_BUS_CREDS_GID)
842                                                         c->gid = (gid_t) gid;
843                                                 if (missing & SD_BUS_CREDS_EGID)
844                                                         c->egid = (gid_t) egid;
845                                                 if (missing & SD_BUS_CREDS_SGID)
846                                                         c->sgid = (gid_t) sgid;
847                                                 if (missing & SD_BUS_CREDS_FSGID)
848                                                         c->fsgid = (gid_t) fsgid;
849
850                                                 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
851                                                 continue;
852                                         }
853                                 }
854
855                                 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
856                                         p = startswith(line, "Groups:");
857                                         if (p) {
858                                                 size_t allocated = 0;
859
860                                                 for (;;) {
861                                                         unsigned long g;
862                                                         int n = 0;
863
864                                                         p += strspn(p, WHITESPACE);
865                                                         if (*p == 0)
866                                                                 break;
867
868                                                         if (sscanf(p, "%lu%n", &g, &n) != 1)
869                                                                 return -EIO;
870
871                                                         if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
872                                                                 return -ENOMEM;
873
874                                                         c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
875                                                         p += n;
876                                                 }
877
878                                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
879                                                 continue;
880                                         }
881                                 }
882
883                                 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
884                                         p = startswith(line, "CapEff:");
885                                         if (p) {
886                                                 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
887                                                 if (r < 0)
888                                                         return r;
889
890                                                 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
891                                                 continue;
892                                         }
893                                 }
894
895                                 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
896                                         p = startswith(line, "CapPrm:");
897                                         if (p) {
898                                                 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
899                                                 if (r < 0)
900                                                         return r;
901
902                                                 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
903                                                 continue;
904                                         }
905                                 }
906
907                                 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
908                                         p = startswith(line, "CapInh:");
909                                         if (p) {
910                                                 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
911                                                 if (r < 0)
912                                                         return r;
913
914                                                 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
915                                                 continue;
916                                         }
917                                 }
918
919                                 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
920                                         p = startswith(line, "CapBnd:");
921                                         if (p) {
922                                                 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
923                                                 if (r < 0)
924                                                         return r;
925
926                                                 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
927                                                 continue;
928                                         }
929                                 }
930                         }
931                 }
932         }
933
934         if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
935                 const char *p;
936
937                 p = procfs_file_alloca(pid, "attr/current");
938                 r = read_one_line_file(p, &c->label);
939                 if (r < 0) {
940                         if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
941                                 return r;
942                 } else
943                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
944         }
945
946         if (missing & SD_BUS_CREDS_COMM) {
947                 r = get_process_comm(pid, &c->comm);
948                 if (r < 0) {
949                         if (r != -EPERM && r != -EACCES)
950                                 return r;
951                 } else
952                         c->mask |= SD_BUS_CREDS_COMM;
953         }
954
955         if (missing & SD_BUS_CREDS_EXE) {
956                 r = get_process_exe(pid, &c->exe);
957                 if (r == -ESRCH) {
958                         /* Unfortunately we cannot really distinguish
959                          * the case here where the process does not
960                          * exist, and /proc/$PID/exe being unreadable
961                          * because $PID is a kernel thread. Hence,
962                          * assume it is a kernel thread, and rely on
963                          * that this case is caught with a later
964                          * call. */
965                         c->exe = NULL;
966                         c->mask |= SD_BUS_CREDS_EXE;
967                 } else if (r < 0) {
968                         if (r != -EPERM && r != -EACCES)
969                                 return r;
970                 } else
971                         c->mask |= SD_BUS_CREDS_EXE;
972         }
973
974         if (missing & SD_BUS_CREDS_CMDLINE) {
975                 const char *p;
976
977                 p = procfs_file_alloca(pid, "cmdline");
978                 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
979                 if (r == -ENOENT)
980                         return -ESRCH;
981                 if (r < 0) {
982                         if (r != -EPERM && r != -EACCES)
983                                 return r;
984                 } else {
985                         if (c->cmdline_size == 0) {
986                                 free(c->cmdline);
987                                 c->cmdline = NULL;
988                         }
989
990                         c->mask |= SD_BUS_CREDS_CMDLINE;
991                 }
992         }
993
994         if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
995                 _cleanup_free_ char *p = NULL;
996
997                 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
998                         return -ENOMEM;
999
1000                 r = read_one_line_file(p, &c->tid_comm);
1001                 if (r == -ENOENT)
1002                         return -ESRCH;
1003                 if (r < 0) {
1004                         if (r != -EPERM && r != -EACCES)
1005                                 return r;
1006                 } else
1007                         c->mask |= SD_BUS_CREDS_TID_COMM;
1008         }
1009
1010         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)) {
1011
1012                 if (!c->cgroup) {
1013                         r = cg_pid_get_path(NULL, pid, &c->cgroup);
1014                         if (r < 0) {
1015                                 if (r != -EPERM && r != -EACCES)
1016                                         return r;
1017                         }
1018                 }
1019
1020                 if (!c->cgroup_root) {
1021                         r = cg_get_root_path(&c->cgroup_root);
1022                         if (r < 0)
1023                                 return r;
1024                 }
1025
1026                 if (c->cgroup)
1027                         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);
1028         }
1029
1030         if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1031                 r = audit_session_from_pid(pid, &c->audit_session_id);
1032                 if (r == -ENXIO) {
1033                         /* ENXIO means: no audit session id assigned */
1034                         c->audit_session_id = AUDIT_SESSION_INVALID;
1035                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1036                 } else if (r < 0) {
1037                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1038                                 return r;
1039                 } else
1040                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1041         }
1042
1043         if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1044                 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1045                 if (r == -ENXIO) {
1046                         /* ENXIO means: no audit login uid assigned */
1047                         c->audit_login_uid = UID_INVALID;
1048                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1049                 } else if (r < 0) {
1050                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1051                                 return r;
1052                 } else
1053                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1054         }
1055
1056         if (missing & SD_BUS_CREDS_TTY) {
1057                 r = get_ctty(pid, NULL, &c->tty);
1058                 if (r == -ENXIO) {
1059                         /* ENXIO means: process has no controlling TTY */
1060                         c->tty = NULL;
1061                         c->mask |= SD_BUS_CREDS_TTY;
1062                 } else if (r < 0) {
1063                         if (r != -EPERM && r != -EACCES && r != -ENOENT)
1064                                 return r;
1065                 } else
1066                         c->mask |= SD_BUS_CREDS_TTY;
1067         }
1068
1069         /* In case only the exe path was to be read we cannot
1070          * distinguish the case where the exe path was unreadable
1071          * because the process was a kernel thread, or when the
1072          * process didn't exist at all. Hence, let's do a final check,
1073          * to be sure. */
1074         if (!pid_is_alive(pid))
1075                 return -ESRCH;
1076
1077         if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1078                 return -ESRCH;
1079
1080         c->augmented = missing & c->mask;
1081
1082         return 0;
1083 }
1084
1085 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1086         _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1087         int r;
1088
1089         assert(c);
1090         assert(ret);
1091
1092         if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1093                 /* There's already all data we need, or augmentation
1094                  * wasn't turned on. */
1095
1096                 *ret = sd_bus_creds_ref(c);
1097                 return 0;
1098         }
1099
1100         n = bus_creds_new();
1101         if (!n)
1102                 return -ENOMEM;
1103
1104         /* Copy the original data over */
1105
1106         if (c->mask & mask & SD_BUS_CREDS_PID) {
1107                 n->pid = c->pid;
1108                 n->mask |= SD_BUS_CREDS_PID;
1109         }
1110
1111         if (c->mask & mask & SD_BUS_CREDS_TID) {
1112                 n->tid = c->tid;
1113                 n->mask |= SD_BUS_CREDS_TID;
1114         }
1115
1116         if (c->mask & mask & SD_BUS_CREDS_PPID) {
1117                 n->ppid = c->ppid;
1118                 n->mask |= SD_BUS_CREDS_PPID;
1119         }
1120
1121         if (c->mask & mask & SD_BUS_CREDS_UID) {
1122                 n->uid = c->uid;
1123                 n->mask |= SD_BUS_CREDS_UID;
1124         }
1125
1126         if (c->mask & mask & SD_BUS_CREDS_EUID) {
1127                 n->euid = c->euid;
1128                 n->mask |= SD_BUS_CREDS_EUID;
1129         }
1130
1131         if (c->mask & mask & SD_BUS_CREDS_SUID) {
1132                 n->suid = c->suid;
1133                 n->mask |= SD_BUS_CREDS_SUID;
1134         }
1135
1136         if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1137                 n->fsuid = c->fsuid;
1138                 n->mask |= SD_BUS_CREDS_FSUID;
1139         }
1140
1141         if (c->mask & mask & SD_BUS_CREDS_GID) {
1142                 n->gid = c->gid;
1143                 n->mask |= SD_BUS_CREDS_GID;
1144         }
1145
1146         if (c->mask & mask & SD_BUS_CREDS_EGID) {
1147                 n->egid = c->egid;
1148                 n->mask |= SD_BUS_CREDS_EGID;
1149         }
1150
1151         if (c->mask & mask & SD_BUS_CREDS_SGID) {
1152                 n->sgid = c->sgid;
1153                 n->mask |= SD_BUS_CREDS_SGID;
1154         }
1155
1156         if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1157                 n->fsgid = c->fsgid;
1158                 n->mask |= SD_BUS_CREDS_FSGID;
1159         }
1160
1161         if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1162                 if (c->supplementary_gids) {
1163                         n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1164                         if (!n->supplementary_gids)
1165                                 return -ENOMEM;
1166                         n->n_supplementary_gids = c->n_supplementary_gids;
1167                 } else {
1168                         n->supplementary_gids = NULL;
1169                         n->n_supplementary_gids = 0;
1170                 }
1171
1172                 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1173         }
1174
1175         if (c->mask & mask & SD_BUS_CREDS_COMM) {
1176                 assert(c->comm);
1177
1178                 n->comm = strdup(c->comm);
1179                 if (!n->comm)
1180                         return -ENOMEM;
1181
1182                 n->mask |= SD_BUS_CREDS_COMM;
1183         }
1184
1185         if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1186                 assert(c->tid_comm);
1187
1188                 n->tid_comm = strdup(c->tid_comm);
1189                 if (!n->tid_comm)
1190                         return -ENOMEM;
1191
1192                 n->mask |= SD_BUS_CREDS_TID_COMM;
1193         }
1194
1195         if (c->mask & mask & SD_BUS_CREDS_EXE) {
1196                 if (c->exe) {
1197                         n->exe = strdup(c->exe);
1198                         if (!n->exe)
1199                                 return -ENOMEM;
1200                 } else
1201                         n->exe = NULL;
1202
1203                 n->mask |= SD_BUS_CREDS_EXE;
1204         }
1205
1206         if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1207                 if (c->cmdline) {
1208                         n->cmdline = memdup(c->cmdline, c->cmdline_size);
1209                         if (!n->cmdline)
1210                                 return -ENOMEM;
1211
1212                         n->cmdline_size = c->cmdline_size;
1213                 } else {
1214                         n->cmdline = NULL;
1215                         n->cmdline_size = 0;
1216                 }
1217
1218                 n->mask |= SD_BUS_CREDS_CMDLINE;
1219         }
1220
1221         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)) {
1222                 assert(c->cgroup);
1223
1224                 n->cgroup = strdup(c->cgroup);
1225                 if (!n->cgroup)
1226                         return -ENOMEM;
1227
1228                 n->cgroup_root = strdup(c->cgroup_root);
1229                 if (!n->cgroup_root)
1230                         return -ENOMEM;
1231
1232                 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);
1233         }
1234
1235         if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1236                 assert(c->capability);
1237
1238                 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1239                 if (!n->capability)
1240                         return -ENOMEM;
1241
1242                 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);
1243         }
1244
1245         if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1246                 assert(c->label);
1247
1248                 n->label = strdup(c->label);
1249                 if (!n->label)
1250                         return -ENOMEM;
1251                 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1252         }
1253
1254         if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1255                 n->audit_session_id = c->audit_session_id;
1256                 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1257         }
1258         if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1259                 n->audit_login_uid = c->audit_login_uid;
1260                 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1261         }
1262
1263         if (c->mask & mask & SD_BUS_CREDS_TTY) {
1264                 if (c->tty) {
1265                         n->tty = strdup(c->tty);
1266                         if (!n->tty)
1267                                 return -ENOMEM;
1268                 } else
1269                         n->tty = NULL;
1270                 n->mask |= SD_BUS_CREDS_TTY;
1271         }
1272
1273         if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1274                 assert(c->unique_name);
1275
1276                 n->unique_name = strdup(c->unique_name);
1277                 if (!n->unique_name)
1278                         return -ENOMEM;
1279                 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1280         }
1281
1282         if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1283                 if (strv_isempty(c->well_known_names))
1284                         n->well_known_names = NULL;
1285                 else {
1286                         n->well_known_names = strv_copy(c->well_known_names);
1287                         if (!n->well_known_names)
1288                                 return -ENOMEM;
1289                 }
1290                 n->well_known_names_driver = c->well_known_names_driver;
1291                 n->well_known_names_local = c->well_known_names_local;
1292                 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1293         }
1294
1295         if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1296                 assert(c->description);
1297                 n->description = strdup(c->description);
1298                 if (!n->description)
1299                         return -ENOMEM;
1300                 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1301         }
1302
1303         n->augmented = c->augmented & n->mask;
1304
1305         /* Get more data */
1306
1307         r = bus_creds_add_more(n, mask, 0, 0);
1308         if (r < 0)
1309                 return r;
1310
1311         *ret = n;
1312         n = NULL;
1313         return 0;
1314 }