]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-creds.c
ssh-generator: generate /etc/issue.d/ with VSOCK ssh info data (#37819)
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-creds.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
5b12334d 2
7d9fcc2b 3#include <linux/capability.h>
5cdf13c7
DDM
4
5#include "sd-bus.h"
5b12334d 6
b5efdb8a 7#include "alloc-util.h"
430f0182 8#include "audit-util.h"
07630cea
LP
9#include "bus-creds.h"
10#include "bus-label.h"
5b12334d 11#include "bus-message.h"
430f0182 12#include "capability-util.h"
07630cea 13#include "cgroup-util.h"
065b4774 14#include "errno-util.h"
3ffd4af2 15#include "fd-util.h"
07630cea 16#include "fileio.h"
f97b34a6 17#include "format-util.h"
e4e73a63 18#include "hexdecoct.h"
08af3cc5 19#include "nulstr-util.h"
6bedfcbb 20#include "parse-util.h"
5cdf13c7 21#include "pidref.h"
07630cea
LP
22#include "process-util.h"
23#include "string-util.h"
49b832c5 24#include "strv.h"
07630cea 25#include "terminal-util.h"
ee104e11 26#include "user-util.h"
5b12334d
LP
27
28enum {
29 CAP_OFFSET_INHERITABLE = 0,
30 CAP_OFFSET_PERMITTED = 1,
31 CAP_OFFSET_EFFECTIVE = 2,
32 CAP_OFFSET_BOUNDING = 3
33};
34
35void bus_creds_done(sd_bus_creds *c) {
36 assert(c);
37
38 /* For internal bus cred structures that are allocated by
39 * something else */
40
41 free(c->session);
42 free(c->unit);
43 free(c->user_unit);
44 free(c->slice);
329ac4bc 45 free(c->user_slice);
455971c1 46 free(c->unescaped_description);
606303a9 47 free(c->supplementary_gids);
4761e880 48 free(c->tty);
5b12334d 49
50c45216
LP
50 free(c->well_known_names); /* note that this is an strv, but
51 * we only free the array, not the
52 * strings the array points to. The
53 * full strv we only free if
54 * c->allocated is set, see
55 * below. */
56
49b832c5 57 strv_free(c->cmdline_array);
71be6406
LP
58
59 safe_close(c->pidfd);
5b12334d
LP
60}
61
31a1e15c 62_public_ sd_bus_creds* sd_bus_creds_ref(sd_bus_creds *c) {
4afd3348
LP
63
64 if (!c)
65 return NULL;
5b12334d
LP
66
67 if (c->allocated) {
68 assert(c->n_ref > 0);
69 c->n_ref++;
70 } else {
71 sd_bus_message *m;
72
73 /* If this is an embedded creds structure, then
74 * forward ref counting to the message */
75 m = container_of(c, sd_bus_message, creds);
76 sd_bus_message_ref(m);
77 }
78
79 return c;
80}
81
31a1e15c 82_public_ sd_bus_creds* sd_bus_creds_unref(sd_bus_creds *c) {
5b1bc83f
LP
83
84 if (!c)
85 return NULL;
5b12334d
LP
86
87 if (c->allocated) {
88 assert(c->n_ref > 0);
89 c->n_ref--;
90
91 if (c->n_ref == 0) {
5b12334d
LP
92 free(c->comm);
93 free(c->tid_comm);
94 free(c->exe);
95 free(c->cmdline);
96 free(c->cgroup);
97 free(c->capability);
98 free(c->label);
49b832c5 99 free(c->unique_name);
751bc6ac 100 free(c->cgroup_root);
455971c1 101 free(c->description);
606303a9 102
a1e58e8e 103 c->supplementary_gids = mfree(c->supplementary_gids);
50c45216 104
6796073e 105 c->well_known_names = strv_free(c->well_known_names);
50c45216
LP
106
107 bus_creds_done(c);
108
5b12334d
LP
109 free(c);
110 }
111 } else {
112 sd_bus_message *m;
113
114 m = container_of(c, sd_bus_message, creds);
115 sd_bus_message_unref(m);
116 }
117
5b12334d
LP
118 return NULL;
119}
120
4cf8496d 121_public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
5b12334d
LP
122 assert_return(c, 0);
123
124 return c->mask;
125}
126
0f514420
LP
127_public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
128 assert_return(c, 0);
129
130 return c->augmented;
131}
132
5b12334d
LP
133sd_bus_creds* bus_creds_new(void) {
134 sd_bus_creds *c;
135
71be6406 136 c = new(sd_bus_creds, 1);
5b12334d
LP
137 if (!c)
138 return NULL;
139
71be6406
LP
140 *c = (sd_bus_creds) {
141 .allocated = true,
142 .n_ref = 1,
143 SD_BUS_CREDS_INIT_FIELDS,
144 };
145
5b12334d
LP
146 return c;
147}
148
71be6406 149static int bus_creds_new_from_pidref(sd_bus_creds **ret, PidRef *pidref, uint64_t mask) {
becdfcb9 150 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
5b12334d
LP
151 int r;
152
15411c0c 153 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
5b12334d
LP
154 assert_return(ret, -EINVAL);
155
5b12334d
LP
156 c = bus_creds_new();
157 if (!c)
158 return -ENOMEM;
159
71be6406 160 r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pidref, 0);
becdfcb9 161 if (r < 0)
5b12334d 162 return r;
5b12334d 163
71be6406 164 r = pidref_verify(pidref);
becdfcb9
LP
165 if (r < 0)
166 return r;
5b12334d 167
becdfcb9 168 *ret = TAKE_PTR(c);
5b12334d
LP
169 return 0;
170}
171
71be6406
LP
172_public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
173 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
174 int r;
175
176 assert_return(pid >= 0, -EINVAL);
177 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
178 assert_return(ret, -EINVAL);
179
180 r = pidref_set_pid(&pidref, pid);
181 if (r < 0)
182 return r;
183
184 return bus_creds_new_from_pidref(ret, &pidref, mask);
185}
186
187_public_ int sd_bus_creds_new_from_pidfd(sd_bus_creds **ret, int pidfd, uint64_t mask) {
188 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
189 int r;
190
191 assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
192 assert_return(ret, -EINVAL);
193 assert_return(pidfd >= 0, -EBADF);
194
195 r = pidref_set_pidfd(&pidref, pidfd);
196 if (r < 0)
197 return r;
198
199 return bus_creds_new_from_pidref(ret, &pidref, mask);
200}
201
31a1e15c 202_public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *ret) {
5b12334d 203 assert_return(c, -EINVAL);
31a1e15c 204 assert_return(ret, -EINVAL);
6a4abbc8
LP
205
206 if (!(c->mask & SD_BUS_CREDS_UID))
207 return -ENODATA;
5b12334d 208
31a1e15c 209 *ret = c->uid;
5b12334d
LP
210 return 0;
211}
212
31a1e15c 213_public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *ret) {
705a415f 214 assert_return(c, -EINVAL);
31a1e15c 215 assert_return(ret, -EINVAL);
705a415f
LP
216
217 if (!(c->mask & SD_BUS_CREDS_EUID))
218 return -ENODATA;
219
31a1e15c 220 *ret = c->euid;
705a415f
LP
221 return 0;
222}
223
31a1e15c 224_public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *ret) {
705a415f 225 assert_return(c, -EINVAL);
31a1e15c 226 assert_return(ret, -EINVAL);
705a415f
LP
227
228 if (!(c->mask & SD_BUS_CREDS_SUID))
229 return -ENODATA;
230
31a1e15c 231 *ret = c->suid;
705a415f
LP
232 return 0;
233}
234
31a1e15c 235_public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *ret) {
705a415f 236 assert_return(c, -EINVAL);
31a1e15c 237 assert_return(ret, -EINVAL);
705a415f
LP
238
239 if (!(c->mask & SD_BUS_CREDS_FSUID))
240 return -ENODATA;
241
31a1e15c 242 *ret = c->fsuid;
705a415f
LP
243 return 0;
244}
245
31a1e15c 246_public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *ret) {
5b12334d 247 assert_return(c, -EINVAL);
31a1e15c 248 assert_return(ret, -EINVAL);
6a4abbc8 249
1c021669 250 if (!(c->mask & SD_BUS_CREDS_GID))
6a4abbc8 251 return -ENODATA;
5b12334d 252
31a1e15c 253 *ret = c->gid;
5b12334d
LP
254 return 0;
255}
256
31a1e15c 257_public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *ret) {
705a415f 258 assert_return(c, -EINVAL);
31a1e15c 259 assert_return(ret, -EINVAL);
705a415f
LP
260
261 if (!(c->mask & SD_BUS_CREDS_EGID))
262 return -ENODATA;
263
31a1e15c 264 *ret = c->egid;
705a415f
LP
265 return 0;
266}
267
31a1e15c 268_public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *ret) {
705a415f 269 assert_return(c, -EINVAL);
31a1e15c 270 assert_return(ret, -EINVAL);
705a415f
LP
271
272 if (!(c->mask & SD_BUS_CREDS_SGID))
273 return -ENODATA;
274
31a1e15c 275 *ret = c->sgid;
705a415f
LP
276 return 0;
277}
278
31a1e15c 279_public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *ret) {
705a415f 280 assert_return(c, -EINVAL);
31a1e15c 281 assert_return(ret, -EINVAL);
705a415f
LP
282
283 if (!(c->mask & SD_BUS_CREDS_FSGID))
284 return -ENODATA;
285
31a1e15c 286 *ret = c->fsgid;
705a415f
LP
287 return 0;
288}
289
31a1e15c 290_public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **ret) {
02581590 291 assert_return(c, -EINVAL);
31a1e15c 292 assert_return(ret, -EINVAL);
02581590
LP
293
294 if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
295 return -ENODATA;
296
31a1e15c 297 *ret = c->supplementary_gids;
02581590
LP
298 return (int) c->n_supplementary_gids;
299}
300
31a1e15c 301_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *ret) {
5b12334d 302 assert_return(c, -EINVAL);
31a1e15c 303 assert_return(ret, -EINVAL);
6a4abbc8
LP
304
305 if (!(c->mask & SD_BUS_CREDS_PID))
306 return -ENODATA;
5b12334d
LP
307
308 assert(c->pid > 0);
31a1e15c 309 *ret = c->pid;
5b12334d
LP
310 return 0;
311}
312
31a1e15c 313_public_ int sd_bus_creds_get_pidfd_dup(sd_bus_creds *c, int *ret) {
71be6406
LP
314 _cleanup_close_ int copy = -EBADF;
315
316 assert_return(c, -EINVAL);
31a1e15c 317 assert_return(ret, -EINVAL);
71be6406
LP
318
319 if (!(c->mask & SD_BUS_CREDS_PIDFD))
320 return -ENODATA;
321
322 copy = fcntl(c->pidfd, F_DUPFD_CLOEXEC, 3);
323 if (copy < 0)
324 return -errno;
325
31a1e15c 326 *ret = TAKE_FD(copy);
71be6406
LP
327 return 0;
328}
329
31a1e15c 330_public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ret) {
1386e47d 331 assert_return(c, -EINVAL);
31a1e15c 332 assert_return(ret, -EINVAL);
1386e47d
LP
333
334 if (!(c->mask & SD_BUS_CREDS_PPID))
335 return -ENODATA;
336
45afd519 337 /* PID 1 has no parent process. Let's distinguish the case of
cfeaa44a
LP
338 * not knowing and not having a parent process by the returned
339 * error code. */
340 if (c->ppid == 0)
341 return -ENXIO;
342
31a1e15c 343 *ret = c->ppid;
1386e47d
LP
344 return 0;
345}
346
31a1e15c 347_public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *ret) {
5b12334d 348 assert_return(c, -EINVAL);
31a1e15c 349 assert_return(ret, -EINVAL);
6a4abbc8
LP
350
351 if (!(c->mask & SD_BUS_CREDS_TID))
352 return -ENODATA;
5b12334d
LP
353
354 assert(c->tid > 0);
31a1e15c 355 *ret = c->tid;
5b12334d
LP
356 return 0;
357}
358
5b12334d
LP
359_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
360 assert_return(c, -EINVAL);
6a4abbc8
LP
361
362 if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
363 return -ENODATA;
5b12334d
LP
364
365 assert(c->label);
366 *ret = c->label;
367 return 0;
368}
369
370_public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
371 assert_return(c, -EINVAL);
372 assert_return(ret, -EINVAL);
6a4abbc8
LP
373
374 if (!(c->mask & SD_BUS_CREDS_COMM))
375 return -ENODATA;
5b12334d
LP
376
377 assert(c->comm);
378 *ret = c->comm;
379 return 0;
380}
381
382_public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
383 assert_return(c, -EINVAL);
384 assert_return(ret, -EINVAL);
6a4abbc8
LP
385
386 if (!(c->mask & SD_BUS_CREDS_TID_COMM))
387 return -ENODATA;
5b12334d
LP
388
389 assert(c->tid_comm);
390 *ret = c->tid_comm;
391 return 0;
392}
393
394_public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
395 assert_return(c, -EINVAL);
396 assert_return(ret, -EINVAL);
6a4abbc8
LP
397
398 if (!(c->mask & SD_BUS_CREDS_EXE))
399 return -ENODATA;
5b12334d 400
cfeaa44a
LP
401 if (!c->exe)
402 return -ENXIO;
403
5b12334d
LP
404 *ret = c->exe;
405 return 0;
406}
407
408_public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
409 assert_return(c, -EINVAL);
410 assert_return(ret, -EINVAL);
6a4abbc8
LP
411
412 if (!(c->mask & SD_BUS_CREDS_CGROUP))
413 return -ENODATA;
5b12334d
LP
414
415 assert(c->cgroup);
416 *ret = c->cgroup;
417 return 0;
418}
419
420_public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
421 int r;
422
423 assert_return(c, -EINVAL);
424 assert_return(ret, -EINVAL);
6a4abbc8
LP
425
426 if (!(c->mask & SD_BUS_CREDS_UNIT))
427 return -ENODATA;
5b12334d
LP
428
429 assert(c->cgroup);
430
431 if (!c->unit) {
751bc6ac
LP
432 const char *shifted;
433
434 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
435 if (r < 0)
436 return r;
437
438 r = cg_path_get_unit(shifted, (char**) &c->unit);
5b12334d
LP
439 if (r < 0)
440 return r;
441 }
442
443 *ret = c->unit;
444 return 0;
445}
446
447_public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
448 int r;
449
450 assert_return(c, -EINVAL);
451 assert_return(ret, -EINVAL);
6a4abbc8
LP
452
453 if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
454 return -ENODATA;
5b12334d
LP
455
456 assert(c->cgroup);
457
458 if (!c->user_unit) {
751bc6ac
LP
459 const char *shifted;
460
461 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
462 if (r < 0)
463 return r;
464
465 r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
5b12334d
LP
466 if (r < 0)
467 return r;
468 }
469
470 *ret = c->user_unit;
471 return 0;
472}
473
474_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
475 int r;
476
477 assert_return(c, -EINVAL);
478 assert_return(ret, -EINVAL);
6a4abbc8
LP
479
480 if (!(c->mask & SD_BUS_CREDS_SLICE))
481 return -ENODATA;
5b12334d
LP
482
483 assert(c->cgroup);
484
485 if (!c->slice) {
751bc6ac
LP
486 const char *shifted;
487
488 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
489 if (r < 0)
490 return r;
491
492 r = cg_path_get_slice(shifted, (char**) &c->slice);
5b12334d
LP
493 if (r < 0)
494 return r;
495 }
496
497 *ret = c->slice;
498 return 0;
499}
500
329ac4bc
LP
501_public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
502 int r;
503
504 assert_return(c, -EINVAL);
505 assert_return(ret, -EINVAL);
506
507 if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
508 return -ENODATA;
509
510 assert(c->cgroup);
511
512 if (!c->user_slice) {
513 const char *shifted;
514
515 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
516 if (r < 0)
517 return r;
518
519 r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
520 if (r < 0)
521 return r;
522 }
523
524 *ret = c->user_slice;
525 return 0;
526}
527
5b12334d
LP
528_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
529 int r;
530
531 assert_return(c, -EINVAL);
532 assert_return(ret, -EINVAL);
6a4abbc8
LP
533
534 if (!(c->mask & SD_BUS_CREDS_SESSION))
535 return -ENODATA;
5b12334d
LP
536
537 assert(c->cgroup);
538
539 if (!c->session) {
751bc6ac
LP
540 const char *shifted;
541
542 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
543 if (r < 0)
544 return r;
545
546 r = cg_path_get_session(shifted, (char**) &c->session);
5b12334d
LP
547 if (r < 0)
548 return r;
549 }
550
551 *ret = c->session;
552 return 0;
553}
554
31a1e15c 555_public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *ret) {
751bc6ac
LP
556 const char *shifted;
557 int r;
558
5b12334d 559 assert_return(c, -EINVAL);
31a1e15c 560 assert_return(ret, -EINVAL);
6a4abbc8
LP
561
562 if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
563 return -ENODATA;
5b12334d
LP
564
565 assert(c->cgroup);
566
751bc6ac
LP
567 r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
568 if (r < 0)
569 return r;
570
31a1e15c 571 return cg_path_get_owner_uid(shifted, ret);
5b12334d
LP
572}
573
31a1e15c 574_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***ret) {
5b12334d 575 assert_return(c, -EINVAL);
31a1e15c 576 assert_return(ret, -EINVAL);
6a4abbc8
LP
577
578 if (!(c->mask & SD_BUS_CREDS_CMDLINE))
579 return -ENODATA;
5b12334d 580
cfeaa44a
LP
581 if (!c->cmdline)
582 return -ENXIO;
5b12334d 583
49b832c5
LP
584 if (!c->cmdline_array) {
585 c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
586 if (!c->cmdline_array)
587 return -ENOMEM;
5b12334d
LP
588 }
589
31a1e15c 590 *ret = c->cmdline_array;
5b12334d
LP
591 return 0;
592}
593
31a1e15c 594_public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *ret) {
5b12334d 595 assert_return(c, -EINVAL);
31a1e15c 596 assert_return(ret, -EINVAL);
6a4abbc8
LP
597
598 if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
599 return -ENODATA;
5b12334d 600
3a87a86e 601 if (!audit_session_is_valid(c->audit_session_id))
cfeaa44a
LP
602 return -ENXIO;
603
31a1e15c 604 *ret = c->audit_session_id;
5b12334d
LP
605 return 0;
606}
607
31a1e15c 608_public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *ret) {
5b12334d 609 assert_return(c, -EINVAL);
31a1e15c 610 assert_return(ret, -EINVAL);
6a4abbc8
LP
611
612 if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
613 return -ENODATA;
5b12334d 614
cad93f29 615 if (!uid_is_valid(c->audit_login_uid))
cfeaa44a
LP
616 return -ENXIO;
617
31a1e15c 618 *ret = c->audit_login_uid;
5b12334d
LP
619 return 0;
620}
621
4761e880
LP
622_public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
623 assert_return(c, -EINVAL);
624 assert_return(ret, -EINVAL);
625
626 if (!(c->mask & SD_BUS_CREDS_TTY))
627 return -ENODATA;
628
cfeaa44a
LP
629 if (!c->tty)
630 return -ENXIO;
631
4761e880
LP
632 *ret = c->tty;
633 return 0;
634}
635
31a1e15c 636_public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **ret) {
49b832c5 637 assert_return(c, -EINVAL);
31a1e15c 638 assert_return(ret, -EINVAL);
6a4abbc8
LP
639
640 if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
641 return -ENODATA;
49b832c5 642
31a1e15c 643 *ret = c->unique_name;
49b832c5
LP
644 return 0;
645}
646
31a1e15c 647_public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***ret) {
49b832c5 648 assert_return(c, -EINVAL);
31a1e15c 649 assert_return(ret, -EINVAL);
6a4abbc8
LP
650
651 if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
652 return -ENODATA;
49b832c5 653
ac653862
LP
654 /* As a special hack we return the bus driver as well-known
655 * names list when this is requested. */
656 if (c->well_known_names_driver) {
657 static const char* const wkn[] = {
658 "org.freedesktop.DBus",
659 NULL
660 };
661
31a1e15c 662 *ret = (char**) wkn;
ac653862
LP
663 return 0;
664 }
665
fb6d9b77
LP
666 if (c->well_known_names_local) {
667 static const char* const wkn[] = {
668 "org.freedesktop.DBus.Local",
669 NULL
670 };
671
31a1e15c 672 *ret = (char**) wkn;
fb6d9b77
LP
673 return 0;
674 }
675
31a1e15c 676 *ret = c->well_known_names;
49b832c5
LP
677 return 0;
678}
679
455971c1 680_public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
cccb0b2c
LP
681 assert_return(c, -EINVAL);
682 assert_return(ret, -EINVAL);
683
455971c1 684 if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
cccb0b2c
LP
685 return -ENODATA;
686
455971c1 687 assert(c->description);
2578d51e 688
455971c1
LP
689 if (!c->unescaped_description) {
690 c->unescaped_description = bus_label_unescape(c->description);
691 if (!c->unescaped_description)
2578d51e
LP
692 return -ENOMEM;
693 }
694
455971c1 695 *ret = c->unescaped_description;
cccb0b2c
LP
696 return 0;
697}
698
3cae6c21 699static int has_cap(sd_bus_creds *c, size_t offset, int capability) {
5b12334d
LP
700 size_t sz;
701
702 assert(c);
34a5d5e5 703 assert(capability >= 0);
5b12334d
LP
704 assert(c->capability);
705
864a25d9 706 unsigned lc = cap_last_cap();
92a40e20 707
864a25d9 708 if ((unsigned) capability > lc)
5b12334d
LP
709 return 0;
710
da890466
ZJS
711 /* If the last cap is 63, then there are 64 caps defined, and we need 2 entries à 32-bit hence. *
712 * If the last cap is 64, then there are 65 caps defined, and we need 3 entries à 32-bit hence. */
39720042 713 sz = DIV_ROUND_UP(lc+1, 32LU);
da634f97 714
5f00c568 715 return !!(c->capability[offset * sz + CAP_TO_INDEX((uint32_t) capability)] & CAP_TO_MASK_CORRECTED((uint32_t) capability));
5b12334d
LP
716}
717
718_public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
719 assert_return(c, -EINVAL);
720 assert_return(capability >= 0, -EINVAL);
6a4abbc8
LP
721
722 if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
723 return -ENODATA;
5b12334d
LP
724
725 return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
726}
727
728_public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
729 assert_return(c, -EINVAL);
730 assert_return(capability >= 0, -EINVAL);
6a4abbc8
LP
731
732 if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
733 return -ENODATA;
5b12334d
LP
734
735 return has_cap(c, CAP_OFFSET_PERMITTED, capability);
736}
737
738_public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
739 assert_return(c, -EINVAL);
740 assert_return(capability >= 0, -EINVAL);
6a4abbc8
LP
741
742 if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
743 return -ENODATA;
5b12334d
LP
744
745 return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
746}
747
748_public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
749 assert_return(c, -EINVAL);
750 assert_return(capability >= 0, -EINVAL);
6a4abbc8
LP
751
752 if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
753 return -ENODATA;
5b12334d
LP
754
755 return has_cap(c, CAP_OFFSET_BOUNDING, capability);
756}
757
758static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
34a5d5e5 759 size_t sz, max;
5b12334d
LP
760
761 assert(c);
762 assert(p);
763
39720042 764 max = DIV_ROUND_UP(cap_last_cap()+1, 32U);
5b12334d
LP
765
766 sz = strlen(p);
7d9fcc2b 767 if (sz % 8 != 0)
5b12334d
LP
768 return -EINVAL;
769
7d9fcc2b 770 sz /= 8;
34a5d5e5
DH
771 if (sz > max)
772 return -EINVAL;
773
5b12334d 774 if (!c->capability) {
7d9fcc2b 775 c->capability = new0(uint32_t, max * 4);
5b12334d
LP
776 if (!c->capability)
777 return -ENOMEM;
5b12334d
LP
778 }
779
2cdfe756 780 for (unsigned i = 0; i < sz; i++) {
7d9fcc2b 781 uint32_t v = 0;
5b12334d 782
2cdfe756 783 for (unsigned j = 0; j < 8; j++) {
7d9fcc2b 784 int t;
5b12334d 785
7d9fcc2b
DH
786 t = unhexchar(*p++);
787 if (t < 0)
788 return -EINVAL;
5b12334d 789
7d9fcc2b
DH
790 v = (v << 4) | t;
791 }
792
793 c->capability[offset * max + (sz - i - 1)] = v;
5b12334d
LP
794 }
795
796 return 0;
797}
798
71be6406
LP
799int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, PidRef *pidref, pid_t tid) {
800 _cleanup_(pidref_done) PidRef pidref_buf = PIDREF_NULL;
5b12334d
LP
801 uint64_t missing;
802 int r;
803
804 assert(c);
805 assert(c->allocated);
806
705a415f
LP
807 if (!(mask & SD_BUS_CREDS_AUGMENT))
808 return 0;
809
5b12334d 810 /* Try to retrieve PID from creds if it wasn't passed to us */
71be6406
LP
811 if (pidref_is_set(pidref)) {
812 if ((c->mask & SD_BUS_CREDS_PID) && c->pid != pidref->pid) /* Insist that things match if already set */
813 return -EBUSY;
814
815 c->pid = pidref->pid;
236f83af 816 c->mask |= SD_BUS_CREDS_PID;
71be6406
LP
817 } else if (c->mask & SD_BUS_CREDS_PIDFD) {
818 r = pidref_set_pidfd(&pidref_buf, c->pidfd);
819 if (r < 0)
820 return r;
821
822 pidref = &pidref_buf;
823
824 } else if (c->mask & SD_BUS_CREDS_PID) {
825 r = pidref_set_pid(&pidref_buf, c->pid);
826 if (r < 0)
827 return r;
828
829 pidref = &pidref_buf;
830 } else
236f83af 831 /* Without pid we cannot do much... */
5b12334d
LP
832 return 0;
833
0f514420
LP
834 /* Try to retrieve TID from creds if it wasn't passed to us */
835 if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
836 tid = c->tid;
837
838 /* Calculate what we shall and can add */
839 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);
840 if (missing == 0)
841 return 0;
842
705a415f
LP
843 if (tid > 0) {
844 c->tid = tid;
845 c->mask |= SD_BUS_CREDS_TID;
846 }
847
71be6406
LP
848 if ((missing & SD_BUS_CREDS_PIDFD) && pidref->fd >= 0) {
849 c->pidfd = fcntl(pidref->fd, F_DUPFD_CLOEXEC, 3);
850 if (c->pidfd < 0)
851 return -errno;
852
853 c->mask |= SD_BUS_CREDS_PIDFD;
854 }
855
1386e47d
LP
856 if (missing & (SD_BUS_CREDS_PPID |
857 SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
705a415f 858 SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
02581590 859 SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
5b12334d
LP
860 SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
861 SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
862
863 _cleanup_fclose_ FILE *f = NULL;
5b12334d
LP
864 const char *p;
865
71be6406 866 p = procfs_file_alloca(pidref->pid, "status");
5b12334d
LP
867
868 f = fopen(p, "re");
705a415f
LP
869 if (!f) {
870 if (errno == ENOENT)
871 return -ESRCH;
71be6406 872 if (!ERRNO_IS_PRIVILEGE(errno))
705a415f
LP
873 return -errno;
874 } else {
705a415f 875
8ae29228
LP
876 for (;;) {
877 _cleanup_free_ char *line = NULL;
878
879 r = read_line(f, LONG_LINE_MAX, &line);
880 if (r < 0)
881 return r;
882 if (r == 0)
883 break;
705a415f 884
1386e47d 885 if (missing & SD_BUS_CREDS_PPID) {
2cdfe756 886 p = first_word(line, "PPid:");
1386e47d 887 if (p) {
3a698817
LP
888 /* Explicitly check for PPID 0 (which is the case for PID 1) */
889 if (!streq(p, "0")) {
890 r = parse_pid(p, &c->ppid);
891 if (r < 0)
892 return r;
cfeaa44a
LP
893 } else
894 c->ppid = 0;
895
896 c->mask |= SD_BUS_CREDS_PPID;
1386e47d
LP
897 continue;
898 }
899 }
900
705a415f 901 if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
2cdfe756 902 p = first_word(line, "Uid:");
705a415f
LP
903 if (p) {
904 unsigned long uid, euid, suid, fsuid;
905
705a415f
LP
906 if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
907 return -EIO;
908
f887fa73
LP
909 if (missing & SD_BUS_CREDS_UID)
910 c->uid = (uid_t) uid;
911 if (missing & SD_BUS_CREDS_EUID)
912 c->euid = (uid_t) euid;
913 if (missing & SD_BUS_CREDS_SUID)
914 c->suid = (uid_t) suid;
915 if (missing & SD_BUS_CREDS_FSUID)
916 c->fsuid = (uid_t) fsuid;
917
705a415f
LP
918 c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
919 continue;
920 }
5b12334d 921 }
5b12334d 922
705a415f 923 if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
2cdfe756 924 p = first_word(line, "Gid:");
705a415f
LP
925 if (p) {
926 unsigned long gid, egid, sgid, fsgid;
927
705a415f
LP
928 if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
929 return -EIO;
930
f887fa73
LP
931 if (missing & SD_BUS_CREDS_GID)
932 c->gid = (gid_t) gid;
933 if (missing & SD_BUS_CREDS_EGID)
934 c->egid = (gid_t) egid;
935 if (missing & SD_BUS_CREDS_SGID)
936 c->sgid = (gid_t) sgid;
937 if (missing & SD_BUS_CREDS_FSGID)
938 c->fsgid = (gid_t) fsgid;
939
705a415f
LP
940 c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
941 continue;
942 }
5b12334d 943 }
5b12334d 944
02581590
LP
945 if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
946 p = startswith(line, "Groups:");
947 if (p) {
02581590
LP
948 for (;;) {
949 unsigned long g;
950 int n = 0;
951
2cdfe756 952 p = skip_leading_chars(p, /* bad = */ NULL);
02581590
LP
953 if (*p == 0)
954 break;
955
956 if (sscanf(p, "%lu%n", &g, &n) != 1)
957 return -EIO;
958
319a4f4b 959 if (!GREEDY_REALLOC(c->supplementary_gids, c->n_supplementary_gids+1))
02581590
LP
960 return -ENOMEM;
961
962 c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
963 p += n;
964 }
965
966 c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
967 continue;
968 }
969 }
970
705a415f 971 if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
2cdfe756 972 p = first_word(line, "CapEff:");
705a415f
LP
973 if (p) {
974 r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
975 if (r < 0)
976 return r;
5b12334d 977
705a415f
LP
978 c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
979 continue;
980 }
5b12334d 981 }
5b12334d 982
705a415f 983 if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
2cdfe756 984 p = first_word(line, "CapPrm:");
705a415f
LP
985 if (p) {
986 r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
987 if (r < 0)
988 return r;
5b12334d 989
705a415f
LP
990 c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
991 continue;
992 }
5b12334d 993 }
5b12334d 994
705a415f 995 if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
2cdfe756 996 p = first_word(line, "CapInh:");
705a415f
LP
997 if (p) {
998 r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
999 if (r < 0)
1000 return r;
5b12334d 1001
705a415f
LP
1002 c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
1003 continue;
1004 }
5b12334d 1005 }
5b12334d 1006
705a415f 1007 if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
2cdfe756 1008 p = first_word(line, "CapBnd:");
705a415f
LP
1009 if (p) {
1010 r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
1011 if (r < 0)
1012 return r;
5b12334d 1013
705a415f
LP
1014 c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
1015 continue;
1016 }
5b12334d
LP
1017 }
1018 }
1019 }
1020 }
1021
5b12334d
LP
1022 if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
1023 const char *p;
1024
71be6406 1025 p = procfs_file_alloca(pidref->pid, "attr/current");
5b12334d 1026 r = read_one_line_file(p, &c->label);
705a415f 1027 if (r < 0) {
945c2931 1028 if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
705a415f
LP
1029 return r;
1030 } else
5b12334d
LP
1031 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
1032 }
1033
1034 if (missing & SD_BUS_CREDS_COMM) {
71be6406 1035 r = pid_get_comm(pidref->pid, &c->comm);
705a415f 1036 if (r < 0) {
065b4774 1037 if (!ERRNO_IS_PRIVILEGE(r))
705a415f
LP
1038 return r;
1039 } else
1040 c->mask |= SD_BUS_CREDS_COMM;
5b12334d
LP
1041 }
1042
1043 if (missing & SD_BUS_CREDS_EXE) {
71be6406 1044 r = get_process_exe(pidref->pid, &c->exe);
cfeaa44a 1045 if (r == -ESRCH) {
45afd519 1046 /* Unfortunately we cannot really distinguish
cfeaa44a
LP
1047 * the case here where the process does not
1048 * exist, and /proc/$PID/exe being unreadable
1049 * because $PID is a kernel thread. Hence,
1050 * assume it is a kernel thread, and rely on
1051 * that this case is caught with a later
1052 * call. */
1053 c->exe = NULL;
1054 c->mask |= SD_BUS_CREDS_EXE;
1055 } else if (r < 0) {
065b4774 1056 if (!ERRNO_IS_PRIVILEGE(r))
705a415f
LP
1057 return r;
1058 } else
1059 c->mask |= SD_BUS_CREDS_EXE;
5b12334d
LP
1060 }
1061
1062 if (missing & SD_BUS_CREDS_CMDLINE) {
1063 const char *p;
1064
71be6406 1065 p = procfs_file_alloca(pidref->pid, "cmdline");
36b159ab 1066 r = read_full_file(p, &c->cmdline, &c->cmdline_size);
cfeaa44a
LP
1067 if (r == -ENOENT)
1068 return -ESRCH;
705a415f 1069 if (r < 0) {
065b4774 1070 if (!ERRNO_IS_PRIVILEGE(r))
705a415f
LP
1071 return r;
1072 } else {
ece174c5 1073 if (c->cmdline_size == 0)
a1e58e8e 1074 c->cmdline = mfree(c->cmdline);
cfeaa44a
LP
1075
1076 c->mask |= SD_BUS_CREDS_CMDLINE;
705a415f 1077 }
5b12334d
LP
1078 }
1079
1080 if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
1081 _cleanup_free_ char *p = NULL;
1082
71be6406 1083 if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pidref->pid, tid) < 0)
5b12334d
LP
1084 return -ENOMEM;
1085
1086 r = read_one_line_file(p, &c->tid_comm);
cfeaa44a
LP
1087 if (r == -ENOENT)
1088 return -ESRCH;
705a415f 1089 if (r < 0) {
065b4774 1090 if (!ERRNO_IS_PRIVILEGE(r))
705a415f
LP
1091 return r;
1092 } else
1093 c->mask |= SD_BUS_CREDS_TID_COMM;
5b12334d
LP
1094 }
1095
329ac4bc 1096 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)) {
5b12334d 1097
822d9b6e 1098 if (!c->cgroup) {
71be6406 1099 r = cg_pid_get_path(NULL, pidref->pid, &c->cgroup);
2cdfe756
MY
1100 if (r < 0 && !ERRNO_IS_NEG_PRIVILEGE(r))
1101 return r;
822d9b6e
LP
1102 }
1103
1104 if (!c->cgroup_root) {
705a415f
LP
1105 r = cg_get_root_path(&c->cgroup_root);
1106 if (r < 0)
1107 return r;
822d9b6e 1108 }
705a415f 1109
822d9b6e 1110 if (c->cgroup)
329ac4bc 1111 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);
5b12334d
LP
1112 }
1113
1114 if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
7e02ee98 1115 r = audit_session_from_pid(pidref, &c->audit_session_id);
d7e46e01
LP
1116 if (r == -ENODATA) {
1117 /* ENODATA means: no audit session id assigned */
cfeaa44a
LP
1118 c->audit_session_id = AUDIT_SESSION_INVALID;
1119 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1120 } else if (r < 0) {
945c2931 1121 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
705a415f
LP
1122 return r;
1123 } else
5b12334d
LP
1124 c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1125 }
1126
1127 if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
7e02ee98 1128 r = audit_loginuid_from_pid(pidref, &c->audit_login_uid);
d7e46e01
LP
1129 if (r == -ENODATA) {
1130 /* ENODATA means: no audit login uid assigned */
cfeaa44a
LP
1131 c->audit_login_uid = UID_INVALID;
1132 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1133 } else if (r < 0) {
945c2931 1134 if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
705a415f
LP
1135 return r;
1136 } else
5b12334d
LP
1137 c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1138 }
1139
4761e880 1140 if (missing & SD_BUS_CREDS_TTY) {
71be6406 1141 r = get_ctty(pidref->pid, NULL, &c->tty);
cfeaa44a
LP
1142 if (r == -ENXIO) {
1143 /* ENXIO means: process has no controlling TTY */
1144 c->tty = NULL;
1145 c->mask |= SD_BUS_CREDS_TTY;
1146 } else if (r < 0) {
945c2931 1147 if (!IN_SET(r, -EPERM, -EACCES, -ENOENT))
4761e880
LP
1148 return r;
1149 } else
1150 c->mask |= SD_BUS_CREDS_TTY;
1151 }
1152
71be6406 1153 r = pidref_verify(pidref);
becdfcb9
LP
1154 if (r < 0)
1155 return r;
cfeaa44a 1156
71be6406
LP
1157 /* Validate tid is still valid, too */
1158 if (tid > 0 && tid != pidref->pid && pid_is_unwaited(tid) == 0)
cfeaa44a
LP
1159 return -ESRCH;
1160
0f514420
LP
1161 c->augmented = missing & c->mask;
1162
5b12334d
LP
1163 return 0;
1164}