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