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