chiark / gitweb /
Prep v220: Use new cgroups functions
[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         int r;
391
392         assert_return(c, -EINVAL);
393         assert_return(ret, -EINVAL);
394
395         if (!(c->mask & SD_BUS_CREDS_UNIT))
396                 return -ENODATA;
397
398         assert(c->cgroup);
399
400         if (!c->unit) {
401                 const char *shifted;
402
403                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
404                 if (r < 0)
405                         return r;
406
407                 r = cg_path_get_unit(shifted, (char**) &c->unit);
408                 if (r < 0)
409                         return r;
410         }
411
412         *ret = c->unit;
413         return 0;
414 }
415
416 _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
417         int r;
418
419         assert_return(c, -EINVAL);
420         assert_return(ret, -EINVAL);
421
422         if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
423                 return -ENODATA;
424
425         assert(c->cgroup);
426
427         if (!c->user_unit) {
428                 const char *shifted;
429
430                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
431                 if (r < 0)
432                         return r;
433
434                 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
435                 if (r < 0)
436                         return r;
437         }
438
439         *ret = c->user_unit;
440         return 0;
441 }
442
443 _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
444         int r;
445
446         assert_return(c, -EINVAL);
447         assert_return(ret, -EINVAL);
448
449         if (!(c->mask & SD_BUS_CREDS_SLICE))
450                 return -ENODATA;
451
452         assert(c->cgroup);
453
454         if (!c->slice) {
455                 const char *shifted;
456
457                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
458                 if (r < 0)
459                         return r;
460
461                 r = cg_path_get_slice(shifted, (char**) &c->slice);
462                 if (r < 0)
463                         return r;
464         }
465
466         *ret = c->slice;
467         return 0;
468 }
469
470 _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
471         int r;
472
473         assert_return(c, -EINVAL);
474         assert_return(ret, -EINVAL);
475
476         if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
477                 return -ENODATA;
478
479         assert(c->cgroup);
480
481         if (!c->user_slice) {
482                 const char *shifted;
483
484                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
485                 if (r < 0)
486                         return r;
487
488                 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
489                 if (r < 0)
490                         return r;
491         }
492
493         *ret = c->user_slice;
494         return 0;
495 }
496
497 _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
498         int r;
499
500         assert_return(c, -EINVAL);
501         assert_return(ret, -EINVAL);
502
503         if (!(c->mask & SD_BUS_CREDS_SESSION))
504                 return -ENODATA;
505
506         assert(c->cgroup);
507
508         if (!c->session) {
509                 const char *shifted;
510
511                 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
512                 if (r < 0)
513                         return r;
514
515                 r = cg_path_get_session(shifted, (char**) &c->session);
516                 if (r < 0)
517                         return r;
518         }
519
520         *ret = c->session;
521         return 0;
522 }
523
524 _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
525         const char *shifted;
526         int r;
527
528         assert_return(c, -EINVAL);
529         assert_return(uid, -EINVAL);
530
531         if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
532                 return -ENODATA;
533
534         assert(c->cgroup);
535
536         r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
537         if (r < 0)
538                 return r;
539
540         return cg_path_get_owner_uid(shifted, uid);
541 }
542
543 _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
544         assert_return(c, -EINVAL);
545
546         if (!(c->mask & SD_BUS_CREDS_CMDLINE))
547                 return -ENODATA;
548
549         if (!c->cmdline)
550                 return -ENXIO;
551
552         if (!c->cmdline_array) {
553                 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
554                 if (!c->cmdline_array)
555                         return -ENOMEM;
556         }
557
558         *cmdline = c->cmdline_array;
559         return 0;
560 }
561
562 _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
563         assert_return(c, -EINVAL);
564         assert_return(sessionid, -EINVAL);
565
566         if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
567                 return -ENODATA;
568
569         if (c->audit_session_id == AUDIT_SESSION_INVALID)
570                 return -ENXIO;
571
572         *sessionid = c->audit_session_id;
573         return 0;
574 }
575
576 _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
577         assert_return(c, -EINVAL);
578         assert_return(uid, -EINVAL);
579
580         if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
581                 return -ENODATA;
582
583         if (c->audit_login_uid == UID_INVALID)
584                 return -ENXIO;
585
586         *uid = c->audit_login_uid;
587         return 0;
588 }
589
590 _public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
591         assert_return(c, -EINVAL);
592         assert_return(ret, -EINVAL);
593
594         if (!(c->mask & SD_BUS_CREDS_TTY))
595                 return -ENODATA;
596
597         if (!c->tty)
598                 return -ENXIO;
599
600         *ret = c->tty;
601         return 0;
602 }
603
604 _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
605         assert_return(c, -EINVAL);
606         assert_return(unique_name, -EINVAL);
607
608         if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
609                 return -ENODATA;
610
611         *unique_name = c->unique_name;
612         return 0;
613 }
614
615 _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
616         assert_return(c, -EINVAL);
617         assert_return(well_known_names, -EINVAL);
618
619         if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
620                 return -ENODATA;
621
622         /* As a special hack we return the bus driver as well-known
623          * names list when this is requested. */
624         if (c->well_known_names_driver) {
625                 static const char* const wkn[] = {
626                         "org.freedesktop.DBus",
627                         NULL
628                 };
629
630                 *well_known_names = (char**) wkn;
631                 return 0;
632         }
633
634         if (c->well_known_names_local) {
635                 static const char* const wkn[] = {
636                         "org.freedesktop.DBus.Local",
637                         NULL
638                 };
639
640                 *well_known_names = (char**) wkn;
641                 return 0;
642         }
643
644         *well_known_names = c->well_known_names;
645         return 0;
646 }
647
648 _public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
649         assert_return(c, -EINVAL);
650         assert_return(ret, -EINVAL);
651
652         if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
653                 return -ENODATA;
654
655         assert(c->description);
656
657         if (!c->unescaped_description) {
658                 c->unescaped_description = bus_label_unescape(c->description);
659                 if (!c->unescaped_description)
660                         return -ENOMEM;
661         }
662
663         *ret = c->unescaped_description;
664         return 0;
665 }
666
667 static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
668         size_t sz;
669
670         assert(c);
671         assert(capability >= 0);
672         assert(c->capability);
673
674         if ((unsigned) capability > cap_last_cap())
675                 return 0;
676
677         sz = DIV_ROUND_UP(cap_last_cap(), 32U);
678
679         return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
680 }
681
682 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
683         assert_return(c, -EINVAL);
684         assert_return(capability >= 0, -EINVAL);
685
686         if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
687                 return -ENODATA;
688
689         return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
690 }
691
692 _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
693         assert_return(c, -EINVAL);
694         assert_return(capability >= 0, -EINVAL);
695
696         if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
697                 return -ENODATA;
698
699         return has_cap(c, CAP_OFFSET_PERMITTED, capability);
700 }
701
702 _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
703         assert_return(c, -EINVAL);
704         assert_return(capability >= 0, -EINVAL);
705
706         if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
707                 return -ENODATA;
708
709         return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
710 }
711
712 _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
713         assert_return(c, -EINVAL);
714         assert_return(capability >= 0, -EINVAL);
715
716         if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
717                 return -ENODATA;
718
719         return has_cap(c, CAP_OFFSET_BOUNDING, capability);
720 }
721
722 static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
723         size_t sz, max;
724         unsigned i, j;
725
726         assert(c);
727         assert(p);
728
729         max = DIV_ROUND_UP(cap_last_cap(), 32U);
730         p += strspn(p, WHITESPACE);
731
732         sz = strlen(p);
733         if (sz % 8 != 0)
734                 return -EINVAL;
735
736         sz /= 8;
737         if (sz > max)
738                 return -EINVAL;
739
740         if (!c->capability) {
741                 c->capability = new0(uint32_t, max * 4);
742                 if (!c->capability)
743                         return -ENOMEM;
744         }
745
746         for (i = 0; i < sz; i ++) {
747                 uint32_t v = 0;
748
749                 for (j = 0; j < 8; ++j) {
750                         int t;
751
752                         t = unhexchar(*p++);
753                         if (t < 0)
754                                 return -EINVAL;
755
756                         v = (v << 4) | t;
757                 }
758
759                 c->capability[offset * max + (sz - i - 1)] = v;
760         }
761
762         return 0;
763 }
764
765 int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
766         uint64_t missing;
767         int r;
768
769         assert(c);
770         assert(c->allocated);
771
772         if (!(mask & SD_BUS_CREDS_AUGMENT))
773                 return 0;
774
775         /* Try to retrieve PID from creds if it wasn't passed to us */
776         if (pid > 0) {
777                 c->pid = pid;
778                 c->mask |= SD_BUS_CREDS_PID;
779         } else if (c->mask & SD_BUS_CREDS_PID)
780                 pid = c->pid;
781         else
782                 /* Without pid we cannot do much... */
783                 return 0;
784
785         /* Try to retrieve TID from creds if it wasn't passed to us */
786         if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
787                 tid = c->tid;
788
789         /* Calculate what we shall and can add */
790         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);
791         if (missing == 0)
792                 return 0;
793
794         if (tid > 0) {
795                 c->tid = tid;
796                 c->mask |= SD_BUS_CREDS_TID;
797         }
798
799         if (missing & (SD_BUS_CREDS_PPID |
800                        SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
801                        SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
802                        SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
803                        SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
804                        SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
805
806                 _cleanup_fclose_ FILE *f = NULL;
807                 const char *p;
808
809                 p = procfs_file_alloca(pid, "status");
810
811                 f = fopen(p, "re");
812                 if (!f) {
813                         if (errno == ENOENT)
814                                 return -ESRCH;
815                         else if (errno != EPERM && errno != EACCES)
816                                 return -errno;
817                 } else {
818                         char line[LINE_MAX];
819
820                         FOREACH_LINE(line, f, return -errno) {
821                                 truncate_nl(line);
822
823                                 if (missing & SD_BUS_CREDS_PPID) {
824                                         p = startswith(line, "PPid:");
825                                         if (p) {
826                                                 p += strspn(p, WHITESPACE);
827
828                                                 /* Explicitly check for PPID 0 (which is the case for PID 1) */
829                                                 if (!streq(p, "0")) {
830                                                         r = parse_pid(p, &c->ppid);
831                                                         if (r < 0)
832                                                                 return r;
833
834                                                 } else
835                                                         c->ppid = 0;
836
837                                                 c->mask |= SD_BUS_CREDS_PPID;
838                                                 continue;
839                                         }
840                                 }
841
842                                 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
843                                         p = startswith(line, "Uid:");
844                                         if (p) {
845                                                 unsigned long uid, euid, suid, fsuid;
846
847                                                 p += strspn(p, WHITESPACE);
848                                                 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
849                                                         return -EIO;
850
851                                                 if (missing & SD_BUS_CREDS_UID)
852                                                         c->uid = (uid_t) uid;
853                                                 if (missing & SD_BUS_CREDS_EUID)
854                                                         c->euid = (uid_t) euid;
855                                                 if (missing & SD_BUS_CREDS_SUID)
856                                                         c->suid = (uid_t) suid;
857                                                 if (missing & SD_BUS_CREDS_FSUID)
858                                                         c->fsuid = (uid_t) fsuid;
859
860                                                 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
861                                                 continue;
862                                         }
863                                 }
864
865                                 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
866                                         p = startswith(line, "Gid:");
867                                         if (p) {
868                                                 unsigned long gid, egid, sgid, fsgid;
869
870                                                 p += strspn(p, WHITESPACE);
871                                                 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
872                                                         return -EIO;
873
874                                                 if (missing & SD_BUS_CREDS_GID)
875                                                         c->gid = (gid_t) gid;
876                                                 if (missing & SD_BUS_CREDS_EGID)
877                                                         c->egid = (gid_t) egid;
878                                                 if (missing & SD_BUS_CREDS_SGID)
879                                                         c->sgid = (gid_t) sgid;
880                                                 if (missing & SD_BUS_CREDS_FSGID)
881                                                         c->fsgid = (gid_t) fsgid;
882
883                                                 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
884                                                 continue;
885                                         }
886                                 }
887
888                                 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
889                                         p = startswith(line, "Groups:");
890                                         if (p) {
891                                                 size_t allocated = 0;
892
893                                                 for (;;) {
894                                                         unsigned long g;
895                                                         int n = 0;
896
897                                                         p += strspn(p, WHITESPACE);
898                                                         if (*p == 0)
899                                                                 break;
900
901                                                         if (sscanf(p, "%lu%n", &g, &n) != 1)
902                                                                 return -EIO;
903
904                                                         if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
905                                                                 return -ENOMEM;
906
907                                                         c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
908                                                         p += n;
909                                                 }
910
911                                                 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
912                                                 continue;
913                                         }
914                                 }
915
916                                 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
917                                         p = startswith(line, "CapEff:");
918                                         if (p) {
919                                                 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
920                                                 if (r < 0)
921                                                         return r;
922
923                                                 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
924                                                 continue;
925                                         }
926                                 }
927
928                                 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
929                                         p = startswith(line, "CapPrm:");
930                                         if (p) {
931                                                 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
932                                                 if (r < 0)
933                                                         return r;
934
935                                                 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
936                                                 continue;
937                                         }
938                                 }
939
940                                 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
941                                         p = startswith(line, "CapInh:");
942                                         if (p) {
943                                                 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
944                                                 if (r < 0)
945                                                         return r;
946
947                                                 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
948                                                 continue;
949                                         }
950                                 }
951
952                                 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
953                                         p = startswith(line, "CapBnd:");
954                                         if (p) {
955                                                 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
956                                                 if (r < 0)
957                                                         return r;
958
959                                                 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
960                                                 continue;
961                                         }
962                                 }
963                         }
964                 }
965         }
966
967         if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
968                 const char *p;
969
970                 p = procfs_file_alloca(pid, "attr/current");
971                 r = read_one_line_file(p, &c->label);
972                 if (r < 0) {
973                         if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
974                                 return r;
975                 } else
976                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
977         }
978
979         if (missing & SD_BUS_CREDS_COMM) {
980                 r = get_process_comm(pid, &c->comm);
981                 if (r < 0) {
982                         if (r != -EPERM && r != -EACCES)
983                                 return r;
984                 } else
985                         c->mask |= SD_BUS_CREDS_COMM;
986         }
987
988         if (missing & SD_BUS_CREDS_EXE) {
989                 r = get_process_exe(pid, &c->exe);
990                 if (r == -ESRCH) {
991                         /* Unfortunately we cannot really distinguish
992                          * the case here where the process does not
993                          * exist, and /proc/$PID/exe being unreadable
994                          * because $PID is a kernel thread. Hence,
995                          * assume it is a kernel thread, and rely on
996                          * that this case is caught with a later
997                          * call. */
998                         c->exe = NULL;
999                         c->mask |= SD_BUS_CREDS_EXE;
1000                 } else if (r < 0) {
1001                         if (r != -EPERM && r != -EACCES)
1002                                 return r;
1003                 } else
1004                         c->mask |= SD_BUS_CREDS_EXE;
1005         }
1006
1007         if (missing & SD_BUS_CREDS_CMDLINE) {
1008                 const char *p;
1009
1010                 p = procfs_file_alloca(pid, "cmdline");
1011                 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1012                 if (r == -ENOENT)
1013                         return -ESRCH;
1014                 if (r < 0) {
1015                         if (r != -EPERM && r != -EACCES)
1016                                 return r;
1017                 } else {
1018                         if (c->cmdline_size == 0) {
1019                                 free(c->cmdline);
1020                                 c->cmdline = NULL;
1021                         }
1022
1023                         c->mask |= SD_BUS_CREDS_CMDLINE;
1024                 }
1025         }
1026
1027         if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1028                 _cleanup_free_ char *p = NULL;
1029
1030                 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
1031                         return -ENOMEM;
1032
1033                 r = read_one_line_file(p, &c->tid_comm);
1034                 if (r == -ENOENT)
1035                         return -ESRCH;
1036                 if (r < 0) {
1037                         if (r != -EPERM && r != -EACCES)
1038                                 return r;
1039                 } else
1040                         c->mask |= SD_BUS_CREDS_TID_COMM;
1041         }
1042
1043         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)) {
1044
1045                 if (!c->cgroup) {
1046                         r = cg_pid_get_path(NULL, pid, &c->cgroup);
1047                         if (r < 0) {
1048                                 if (r != -EPERM && r != -EACCES)
1049                                         return r;
1050                         }
1051                 }
1052
1053                 if (!c->cgroup_root) {
1054                         r = cg_get_root_path(&c->cgroup_root);
1055                         if (r < 0)
1056                                 return r;
1057                 }
1058
1059                 if (c->cgroup)
1060                         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);
1061         }
1062
1063         if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1064                 r = audit_session_from_pid(pid, &c->audit_session_id);
1065                 if (r == -ENXIO) {
1066                         /* ENXIO means: no audit session id assigned */
1067                         c->audit_session_id = AUDIT_SESSION_INVALID;
1068                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1069                 } else if (r < 0) {
1070                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1071                                 return r;
1072                 } else
1073                         c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1074         }
1075
1076         if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1077                 r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1078                 if (r == -ENXIO) {
1079                         /* ENXIO means: no audit login uid assigned */
1080                         c->audit_login_uid = UID_INVALID;
1081                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1082                 } else if (r < 0) {
1083                         if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
1084                                 return r;
1085                 } else
1086                         c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1087         }
1088
1089         if (missing & SD_BUS_CREDS_TTY) {
1090                 r = get_ctty(pid, NULL, &c->tty);
1091                 if (r == -ENXIO) {
1092                         /* ENXIO means: process has no controlling TTY */
1093                         c->tty = NULL;
1094                         c->mask |= SD_BUS_CREDS_TTY;
1095                 } else if (r < 0) {
1096                         if (r != -EPERM && r != -EACCES && r != -ENOENT)
1097                                 return r;
1098                 } else
1099                         c->mask |= SD_BUS_CREDS_TTY;
1100         }
1101
1102         /* In case only the exe path was to be read we cannot
1103          * distinguish the case where the exe path was unreadable
1104          * because the process was a kernel thread, or when the
1105          * process didn't exist at all. Hence, let's do a final check,
1106          * to be sure. */
1107         if (!pid_is_alive(pid))
1108                 return -ESRCH;
1109
1110         if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
1111                 return -ESRCH;
1112
1113         c->augmented = missing & c->mask;
1114
1115         return 0;
1116 }
1117
1118 int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
1119         _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL;
1120         int r;
1121
1122         assert(c);
1123         assert(ret);
1124
1125         if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
1126                 /* There's already all data we need, or augmentation
1127                  * wasn't turned on. */
1128
1129                 *ret = sd_bus_creds_ref(c);
1130                 return 0;
1131         }
1132
1133         n = bus_creds_new();
1134         if (!n)
1135                 return -ENOMEM;
1136
1137         /* Copy the original data over */
1138
1139         if (c->mask & mask & SD_BUS_CREDS_PID) {
1140                 n->pid = c->pid;
1141                 n->mask |= SD_BUS_CREDS_PID;
1142         }
1143
1144         if (c->mask & mask & SD_BUS_CREDS_TID) {
1145                 n->tid = c->tid;
1146                 n->mask |= SD_BUS_CREDS_TID;
1147         }
1148
1149         if (c->mask & mask & SD_BUS_CREDS_PPID) {
1150                 n->ppid = c->ppid;
1151                 n->mask |= SD_BUS_CREDS_PPID;
1152         }
1153
1154         if (c->mask & mask & SD_BUS_CREDS_UID) {
1155                 n->uid = c->uid;
1156                 n->mask |= SD_BUS_CREDS_UID;
1157         }
1158
1159         if (c->mask & mask & SD_BUS_CREDS_EUID) {
1160                 n->euid = c->euid;
1161                 n->mask |= SD_BUS_CREDS_EUID;
1162         }
1163
1164         if (c->mask & mask & SD_BUS_CREDS_SUID) {
1165                 n->suid = c->suid;
1166                 n->mask |= SD_BUS_CREDS_SUID;
1167         }
1168
1169         if (c->mask & mask & SD_BUS_CREDS_FSUID) {
1170                 n->fsuid = c->fsuid;
1171                 n->mask |= SD_BUS_CREDS_FSUID;
1172         }
1173
1174         if (c->mask & mask & SD_BUS_CREDS_GID) {
1175                 n->gid = c->gid;
1176                 n->mask |= SD_BUS_CREDS_GID;
1177         }
1178
1179         if (c->mask & mask & SD_BUS_CREDS_EGID) {
1180                 n->egid = c->egid;
1181                 n->mask |= SD_BUS_CREDS_EGID;
1182         }
1183
1184         if (c->mask & mask & SD_BUS_CREDS_SGID) {
1185                 n->sgid = c->sgid;
1186                 n->mask |= SD_BUS_CREDS_SGID;
1187         }
1188
1189         if (c->mask & mask & SD_BUS_CREDS_FSGID) {
1190                 n->fsgid = c->fsgid;
1191                 n->mask |= SD_BUS_CREDS_FSGID;
1192         }
1193
1194         if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
1195                 if (c->supplementary_gids) {
1196                         n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
1197                         if (!n->supplementary_gids)
1198                                 return -ENOMEM;
1199                         n->n_supplementary_gids = c->n_supplementary_gids;
1200                 } else {
1201                         n->supplementary_gids = NULL;
1202                         n->n_supplementary_gids = 0;
1203                 }
1204
1205                 n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
1206         }
1207
1208         if (c->mask & mask & SD_BUS_CREDS_COMM) {
1209                 assert(c->comm);
1210
1211                 n->comm = strdup(c->comm);
1212                 if (!n->comm)
1213                         return -ENOMEM;
1214
1215                 n->mask |= SD_BUS_CREDS_COMM;
1216         }
1217
1218         if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
1219                 assert(c->tid_comm);
1220
1221                 n->tid_comm = strdup(c->tid_comm);
1222                 if (!n->tid_comm)
1223                         return -ENOMEM;
1224
1225                 n->mask |= SD_BUS_CREDS_TID_COMM;
1226         }
1227
1228         if (c->mask & mask & SD_BUS_CREDS_EXE) {
1229                 if (c->exe) {
1230                         n->exe = strdup(c->exe);
1231                         if (!n->exe)
1232                                 return -ENOMEM;
1233                 } else
1234                         n->exe = NULL;
1235
1236                 n->mask |= SD_BUS_CREDS_EXE;
1237         }
1238
1239         if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
1240                 if (c->cmdline) {
1241                         n->cmdline = memdup(c->cmdline, c->cmdline_size);
1242                         if (!n->cmdline)
1243                                 return -ENOMEM;
1244
1245                         n->cmdline_size = c->cmdline_size;
1246                 } else {
1247                         n->cmdline = NULL;
1248                         n->cmdline_size = 0;
1249                 }
1250
1251                 n->mask |= SD_BUS_CREDS_CMDLINE;
1252         }
1253
1254         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)) {
1255                 assert(c->cgroup);
1256
1257                 n->cgroup = strdup(c->cgroup);
1258                 if (!n->cgroup)
1259                         return -ENOMEM;
1260
1261                 n->cgroup_root = strdup(c->cgroup_root);
1262                 if (!n->cgroup_root)
1263                         return -ENOMEM;
1264
1265                 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);
1266         }
1267
1268         if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
1269                 assert(c->capability);
1270
1271                 n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
1272                 if (!n->capability)
1273                         return -ENOMEM;
1274
1275                 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);
1276         }
1277
1278         if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
1279                 assert(c->label);
1280
1281                 n->label = strdup(c->label);
1282                 if (!n->label)
1283                         return -ENOMEM;
1284                 n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1285         }
1286
1287         if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1288                 n->audit_session_id = c->audit_session_id;
1289                 n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1290         }
1291         if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1292                 n->audit_login_uid = c->audit_login_uid;
1293                 n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1294         }
1295
1296         if (c->mask & mask & SD_BUS_CREDS_TTY) {
1297                 if (c->tty) {
1298                         n->tty = strdup(c->tty);
1299                         if (!n->tty)
1300                                 return -ENOMEM;
1301                 } else
1302                         n->tty = NULL;
1303                 n->mask |= SD_BUS_CREDS_TTY;
1304         }
1305
1306         if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
1307                 assert(c->unique_name);
1308
1309                 n->unique_name = strdup(c->unique_name);
1310                 if (!n->unique_name)
1311                         return -ENOMEM;
1312                 n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
1313         }
1314
1315         if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
1316                 if (strv_isempty(c->well_known_names))
1317                         n->well_known_names = NULL;
1318                 else {
1319                         n->well_known_names = strv_copy(c->well_known_names);
1320                         if (!n->well_known_names)
1321                                 return -ENOMEM;
1322                 }
1323                 n->well_known_names_driver = c->well_known_names_driver;
1324                 n->well_known_names_local = c->well_known_names_local;
1325                 n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
1326         }
1327
1328         if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
1329                 assert(c->description);
1330                 n->description = strdup(c->description);
1331                 if (!n->description)
1332                         return -ENOMEM;
1333                 n->mask |= SD_BUS_CREDS_DESCRIPTION;
1334         }
1335
1336         n->augmented = c->augmented & n->mask;
1337
1338         /* Get more data */
1339
1340         r = bus_creds_add_more(n, mask, 0, 0);
1341         if (r < 0)
1342                 return r;
1343
1344         *ret = n;
1345         n = NULL;
1346         return 0;
1347 }