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