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