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