Branch data 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 : 1214 : void bus_creds_done(sd_bus_creds *c) {
34 [ - + ]: 1214 : assert(c);
35 : :
36 : : /* For internal bus cred structures that are allocated by
37 : : * something else */
38 : :
39 : 1214 : free(c->session);
40 : 1214 : free(c->unit);
41 : 1214 : free(c->user_unit);
42 : 1214 : free(c->slice);
43 : 1214 : free(c->user_slice);
44 : 1214 : free(c->unescaped_description);
45 : 1214 : free(c->supplementary_gids);
46 : 1214 : free(c->tty);
47 : :
48 : 1214 : 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 : 1214 : strv_free(c->cmdline_array);
56 : 1214 : }
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 : 60 : _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
79 : :
80 [ - + ]: 60 : if (!c)
81 : 0 : return NULL;
82 : :
83 [ + - ]: 60 : if (c->allocated) {
84 [ - + ]: 60 : assert(c->n_ref > 0);
85 : 60 : c->n_ref--;
86 : :
87 [ + - ]: 60 : if (c->n_ref == 0) {
88 : 60 : free(c->comm);
89 : 60 : free(c->tid_comm);
90 : 60 : free(c->exe);
91 : 60 : free(c->cmdline);
92 : 60 : free(c->cgroup);
93 : 60 : free(c->capability);
94 : 60 : free(c->label);
95 : 60 : free(c->unique_name);
96 : 60 : free(c->cgroup_root);
97 : 60 : free(c->description);
98 : :
99 : 60 : c->supplementary_gids = mfree(c->supplementary_gids);
100 : :
101 : 60 : c->well_known_names = strv_free(c->well_known_names);
102 : :
103 : 60 : bus_creds_done(c);
104 : :
105 : 60 : 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 : 60 : 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 : 104 : _public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
124 [ - + - + ]: 104 : assert_return(c, 0);
125 : :
126 : 104 : return c->augmented;
127 : : }
128 : :
129 : 60 : sd_bus_creds* bus_creds_new(void) {
130 : : sd_bus_creds *c;
131 : :
132 : 60 : c = new0(sd_bus_creds, 1);
133 [ - + ]: 60 : if (!c)
134 : 0 : return NULL;
135 : :
136 : 60 : c->allocated = true;
137 : 60 : c->n_ref = 1;
138 : 60 : return c;
139 : : }
140 : :
141 : 8 : _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 [ - + - + ]: 8 : assert_return(pid >= 0, -EINVAL);
146 [ - + - + ]: 8 : assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
147 [ - + - + ]: 8 : assert_return(ret, -EINVAL);
148 : :
149 [ + + ]: 8 : if (pid == 0)
150 : 4 : pid = getpid_cached();
151 : :
152 : 8 : c = bus_creds_new();
153 [ - + ]: 8 : if (!c)
154 : 0 : return -ENOMEM;
155 : :
156 : 8 : r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
157 [ - + ]: 8 : 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 [ - + ]: 8 : if (!pid_is_alive(pid)) {
165 : 0 : sd_bus_creds_unref(c);
166 : 0 : return -ESRCH;
167 : : }
168 : :
169 : 8 : *ret = c;
170 : 8 : 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 : 52 : _public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
185 [ - + - + ]: 52 : assert_return(c, -EINVAL);
186 [ - + - + ]: 52 : assert_return(euid, -EINVAL);
187 : :
188 [ - + ]: 52 : if (!(c->mask & SD_BUS_CREDS_EUID))
189 : 0 : return -ENODATA;
190 : :
191 : 52 : *euid = c->euid;
192 : 52 : 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 : 48 : _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
273 [ + + + + ]: 48 : assert_return(c, -EINVAL);
274 [ - + - + ]: 28 : assert_return(pid, -EINVAL);
275 : :
276 [ + - ]: 28 : if (!(c->mask & SD_BUS_CREDS_PID))
277 : 28 : 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 : 48 : _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
314 [ + + + + ]: 48 : assert_return(c, -EINVAL);
315 : :
316 [ + - ]: 28 : if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
317 : 28 : 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 : 60 : _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
375 : : int r;
376 : :
377 [ - + - + ]: 60 : assert_return(c, -EINVAL);
378 [ - + - + ]: 60 : assert_return(ret, -EINVAL);
379 : :
380 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_UNIT))
381 : 52 : return -ENODATA;
382 : :
383 [ - + ]: 8 : assert(c->cgroup);
384 : :
385 [ + - ]: 8 : if (!c->unit) {
386 : : const char *shifted;
387 : :
388 : 8 : r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
389 [ - + ]: 8 : if (r < 0)
390 : 0 : return r;
391 : :
392 : 8 : r = cg_path_get_unit(shifted, (char**) &c->unit);
393 [ - + ]: 8 : if (r < 0)
394 : 0 : return r;
395 : : }
396 : :
397 : 8 : *ret = c->unit;
398 : 8 : return 0;
399 : : }
400 : :
401 : 60 : _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
402 : : int r;
403 : :
404 [ - + - + ]: 60 : assert_return(c, -EINVAL);
405 [ - + - + ]: 60 : assert_return(ret, -EINVAL);
406 : :
407 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
408 : 52 : return -ENODATA;
409 : :
410 [ - + ]: 8 : assert(c->cgroup);
411 : :
412 [ + - ]: 8 : if (!c->user_unit) {
413 : : const char *shifted;
414 : :
415 : 8 : r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
416 [ - + ]: 8 : if (r < 0)
417 : 8 : return r;
418 : :
419 : 8 : r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
420 [ + - ]: 8 : if (r < 0)
421 : 8 : return r;
422 : : }
423 : :
424 : 0 : *ret = c->user_unit;
425 : 0 : return 0;
426 : : }
427 : :
428 : 60 : _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
429 : : int r;
430 : :
431 [ - + - + ]: 60 : assert_return(c, -EINVAL);
432 [ - + - + ]: 60 : assert_return(ret, -EINVAL);
433 : :
434 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_SLICE))
435 : 52 : return -ENODATA;
436 : :
437 [ - + ]: 8 : assert(c->cgroup);
438 : :
439 [ + - ]: 8 : if (!c->slice) {
440 : : const char *shifted;
441 : :
442 : 8 : r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
443 [ - + ]: 8 : if (r < 0)
444 : 0 : return r;
445 : :
446 : 8 : r = cg_path_get_slice(shifted, (char**) &c->slice);
447 [ - + ]: 8 : if (r < 0)
448 : 0 : return r;
449 : : }
450 : :
451 : 8 : *ret = c->slice;
452 : 8 : return 0;
453 : : }
454 : :
455 : 60 : _public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
456 : : int r;
457 : :
458 [ - + - + ]: 60 : assert_return(c, -EINVAL);
459 [ - + - + ]: 60 : assert_return(ret, -EINVAL);
460 : :
461 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
462 : 52 : return -ENODATA;
463 : :
464 [ - + ]: 8 : assert(c->cgroup);
465 : :
466 [ + - ]: 8 : if (!c->user_slice) {
467 : : const char *shifted;
468 : :
469 : 8 : r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
470 [ - + ]: 8 : if (r < 0)
471 : 4 : return r;
472 : :
473 : 8 : r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
474 [ + + ]: 8 : if (r < 0)
475 : 4 : return r;
476 : : }
477 : :
478 : 4 : *ret = c->user_slice;
479 : 4 : return 0;
480 : : }
481 : :
482 : 60 : _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
483 : : int r;
484 : :
485 [ - + - + ]: 60 : assert_return(c, -EINVAL);
486 [ - + - + ]: 60 : assert_return(ret, -EINVAL);
487 : :
488 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_SESSION))
489 : 52 : return -ENODATA;
490 : :
491 [ - + ]: 8 : assert(c->cgroup);
492 : :
493 [ + - ]: 8 : if (!c->session) {
494 : : const char *shifted;
495 : :
496 : 8 : r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
497 [ - + ]: 8 : if (r < 0)
498 : 4 : return r;
499 : :
500 : 8 : r = cg_path_get_session(shifted, (char**) &c->session);
501 [ + + ]: 8 : if (r < 0)
502 : 4 : return r;
503 : : }
504 : :
505 : 4 : *ret = c->session;
506 : 4 : return 0;
507 : : }
508 : :
509 : 60 : _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
510 : : const char *shifted;
511 : : int r;
512 : :
513 [ - + - + ]: 60 : assert_return(c, -EINVAL);
514 [ - + - + ]: 60 : assert_return(uid, -EINVAL);
515 : :
516 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
517 : 52 : return -ENODATA;
518 : :
519 [ - + ]: 8 : assert(c->cgroup);
520 : :
521 : 8 : r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
522 [ - + ]: 8 : if (r < 0)
523 : 0 : return r;
524 : :
525 : 8 : return cg_path_get_owner_uid(shifted, uid);
526 : : }
527 : :
528 : 60 : _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
529 [ - + - + ]: 60 : assert_return(c, -EINVAL);
530 : :
531 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_CMDLINE))
532 : 52 : return -ENODATA;
533 : :
534 [ - + ]: 8 : if (!c->cmdline)
535 : 0 : return -ENXIO;
536 : :
537 [ + - ]: 8 : if (!c->cmdline_array) {
538 : 8 : c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
539 [ - + ]: 8 : if (!c->cmdline_array)
540 : 0 : return -ENOMEM;
541 : : }
542 : :
543 : 8 : *cmdline = c->cmdline_array;
544 : 8 : return 0;
545 : : }
546 : :
547 : 60 : _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
548 [ - + - + ]: 60 : assert_return(c, -EINVAL);
549 [ - + - + ]: 60 : assert_return(sessionid, -EINVAL);
550 : :
551 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
552 : 52 : return -ENODATA;
553 : :
554 [ + + ]: 8 : if (!audit_session_is_valid(c->audit_session_id))
555 : 4 : return -ENXIO;
556 : :
557 : 4 : *sessionid = c->audit_session_id;
558 : 4 : return 0;
559 : : }
560 : :
561 : 60 : _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
562 [ - + - + ]: 60 : assert_return(c, -EINVAL);
563 [ - + - + ]: 60 : assert_return(uid, -EINVAL);
564 : :
565 [ + + ]: 60 : if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
566 : 52 : return -ENODATA;
567 : :
568 [ + + ]: 8 : if (!uid_is_valid(c->audit_login_uid))
569 : 4 : return -ENXIO;
570 : :
571 : 4 : *uid = c->audit_login_uid;
572 : 4 : 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 : 60 : _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
601 [ - + - + ]: 60 : assert_return(c, -EINVAL);
602 [ - + - + ]: 60 : assert_return(well_known_names, -EINVAL);
603 : :
604 [ + - ]: 60 : if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
605 : 60 : 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 : 1216 : static int has_cap(sd_bus_creds *c, size_t offset, int capability) {
653 : : unsigned long lc;
654 : : size_t sz;
655 : :
656 [ - + ]: 1216 : assert(c);
657 [ - + ]: 1216 : assert(capability >= 0);
658 [ - + ]: 1216 : assert(c->capability);
659 : :
660 : 1216 : lc = cap_last_cap();
661 : :
662 [ - + ]: 1216 : 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 : 1216 : sz = DIV_ROUND_UP(lc+1, 32LU);
668 : :
669 : 1216 : return !!(c->capability[offset * sz + CAP_TO_INDEX((uint32_t) capability)] & CAP_TO_MASK_CORRECTED((uint32_t) capability));
670 : : }
671 : :
672 : 408 : _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
673 [ - + - + ]: 408 : assert_return(c, -EINVAL);
674 [ - + - + ]: 408 : assert_return(capability >= 0, -EINVAL);
675 : :
676 [ + + ]: 408 : if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
677 : 104 : return -ENODATA;
678 : :
679 : 304 : return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
680 : : }
681 : :
682 : 356 : _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
683 [ - + - + ]: 356 : assert_return(c, -EINVAL);
684 [ - + - + ]: 356 : assert_return(capability >= 0, -EINVAL);
685 : :
686 [ + + ]: 356 : if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
687 : 52 : return -ENODATA;
688 : :
689 : 304 : return has_cap(c, CAP_OFFSET_PERMITTED, capability);
690 : : }
691 : :
692 : 356 : _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
693 [ - + - + ]: 356 : assert_return(c, -EINVAL);
694 [ - + - + ]: 356 : assert_return(capability >= 0, -EINVAL);
695 : :
696 [ + + ]: 356 : if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
697 : 52 : return -ENODATA;
698 : :
699 : 304 : return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
700 : : }
701 : :
702 : 356 : _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
703 [ - + - + ]: 356 : assert_return(c, -EINVAL);
704 [ - + - + ]: 356 : assert_return(capability >= 0, -EINVAL);
705 : :
706 [ + + ]: 356 : if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
707 : 52 : return -ENODATA;
708 : :
709 : 304 : return has_cap(c, CAP_OFFSET_BOUNDING, capability);
710 : : }
711 : :
712 : 32 : static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
713 : : size_t sz, max;
714 : : unsigned i, j;
715 : :
716 [ - + ]: 32 : assert(c);
717 [ - + ]: 32 : assert(p);
718 : :
719 : 32 : max = DIV_ROUND_UP(cap_last_cap()+1, 32U);
720 : 32 : p += strspn(p, WHITESPACE);
721 : :
722 : 32 : sz = strlen(p);
723 [ - + ]: 32 : if (sz % 8 != 0)
724 : 0 : return -EINVAL;
725 : :
726 : 32 : sz /= 8;
727 [ - + ]: 32 : if (sz > max)
728 : 0 : return -EINVAL;
729 : :
730 [ + + ]: 32 : if (!c->capability) {
731 [ + - ]: 8 : c->capability = new0(uint32_t, max * 4);
732 [ - + ]: 8 : if (!c->capability)
733 : 0 : return -ENOMEM;
734 : : }
735 : :
736 [ + + ]: 96 : for (i = 0; i < sz; i ++) {
737 : 64 : uint32_t v = 0;
738 : :
739 [ + + ]: 576 : for (j = 0; j < 8; ++j) {
740 : : int t;
741 : :
742 : 512 : t = unhexchar(*p++);
743 [ - + ]: 512 : if (t < 0)
744 : 0 : return -EINVAL;
745 : :
746 : 512 : v = (v << 4) | t;
747 : : }
748 : :
749 : 64 : c->capability[offset * max + (sz - i - 1)] = v;
750 : : }
751 : :
752 : 32 : return 0;
753 : : }
754 : :
755 : 60 : 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 [ - + ]: 60 : assert(c);
760 [ - + ]: 60 : assert(c->allocated);
761 : :
762 [ + + ]: 60 : if (!(mask & SD_BUS_CREDS_AUGMENT))
763 : 52 : return 0;
764 : :
765 : : /* Try to retrieve PID from creds if it wasn't passed to us */
766 [ + - ]: 8 : if (pid > 0) {
767 : 8 : c->pid = pid;
768 : 8 : 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 [ + - - + ]: 8 : if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
777 : 0 : tid = c->tid;
778 : :
779 : : /* Calculate what we shall and can add */
780 : 8 : 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 [ - + ]: 8 : if (missing == 0)
782 : 0 : return 0;
783 : :
784 [ - + ]: 8 : if (tid > 0) {
785 : 0 : c->tid = tid;
786 : 0 : c->mask |= SD_BUS_CREDS_TID;
787 : : }
788 : :
789 [ + - ]: 8 : 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 [ + - ]: 8 : _cleanup_fclose_ FILE *f = NULL;
797 : : const char *p;
798 : :
799 [ - + - + : 8 : p = procfs_file_alloca(pid, "status");
- + ]
800 : :
801 : 8 : f = fopen(p, "re");
802 [ - + ]: 8 : 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 : 440 : for (;;) {
810 [ + - + + ]: 448 : _cleanup_free_ char *line = NULL;
811 : :
812 : 448 : r = read_line(f, LONG_LINE_MAX, &line);
813 [ - + ]: 448 : if (r < 0)
814 : 0 : return r;
815 [ + + ]: 448 : if (r == 0)
816 : 8 : break;
817 : :
818 [ + - ]: 440 : if (missing & SD_BUS_CREDS_PPID) {
819 : 440 : p = startswith(line, "PPid:");
820 [ + + ]: 440 : if (p) {
821 : 8 : p += strspn(p, WHITESPACE);
822 : :
823 : : /* Explicitly check for PPID 0 (which is the case for PID 1) */
824 [ + + ]: 8 : if (!streq(p, "0")) {
825 : 4 : r = parse_pid(p, &c->ppid);
826 [ - + ]: 4 : if (r < 0)
827 : 0 : return r;
828 : :
829 : : } else
830 : 4 : c->ppid = 0;
831 : :
832 : 8 : c->mask |= SD_BUS_CREDS_PPID;
833 : 8 : continue;
834 : : }
835 : : }
836 : :
837 [ + - ]: 432 : if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
838 : 432 : p = startswith(line, "Uid:");
839 [ + + ]: 432 : if (p) {
840 : : unsigned long uid, euid, suid, fsuid;
841 : :
842 : 8 : p += strspn(p, WHITESPACE);
843 [ - + ]: 8 : if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
844 : 0 : return -EIO;
845 : :
846 [ + - ]: 8 : if (missing & SD_BUS_CREDS_UID)
847 : 8 : c->uid = (uid_t) uid;
848 [ + - ]: 8 : if (missing & SD_BUS_CREDS_EUID)
849 : 8 : c->euid = (uid_t) euid;
850 [ + - ]: 8 : if (missing & SD_BUS_CREDS_SUID)
851 : 8 : c->suid = (uid_t) suid;
852 [ + - ]: 8 : if (missing & SD_BUS_CREDS_FSUID)
853 : 8 : c->fsuid = (uid_t) fsuid;
854 : :
855 : 8 : c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
856 : 8 : continue;
857 : : }
858 : : }
859 : :
860 [ + - ]: 424 : if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
861 : 424 : p = startswith(line, "Gid:");
862 [ + + ]: 424 : if (p) {
863 : : unsigned long gid, egid, sgid, fsgid;
864 : :
865 : 8 : p += strspn(p, WHITESPACE);
866 [ - + ]: 8 : if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
867 : 0 : return -EIO;
868 : :
869 [ + - ]: 8 : if (missing & SD_BUS_CREDS_GID)
870 : 8 : c->gid = (gid_t) gid;
871 [ + - ]: 8 : if (missing & SD_BUS_CREDS_EGID)
872 : 8 : c->egid = (gid_t) egid;
873 [ + - ]: 8 : if (missing & SD_BUS_CREDS_SGID)
874 : 8 : c->sgid = (gid_t) sgid;
875 [ + - ]: 8 : if (missing & SD_BUS_CREDS_FSGID)
876 : 8 : c->fsgid = (gid_t) fsgid;
877 : :
878 : 8 : c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
879 : 8 : continue;
880 : : }
881 : : }
882 : :
883 [ + - ]: 416 : if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
884 : 416 : p = startswith(line, "Groups:");
885 [ + + ]: 416 : if (p) {
886 : 8 : size_t allocated = 0;
887 : :
888 : 36 : for (;;) {
889 : : unsigned long g;
890 : 44 : int n = 0;
891 : :
892 : 44 : p += strspn(p, WHITESPACE);
893 [ + + ]: 44 : if (*p == 0)
894 : 8 : break;
895 : :
896 [ - + ]: 36 : if (sscanf(p, "%lu%n", &g, &n) != 1)
897 : 0 : return -EIO;
898 : :
899 [ - + ]: 36 : if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
900 : 0 : return -ENOMEM;
901 : :
902 : 36 : c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
903 : 36 : p += n;
904 : : }
905 : :
906 : 8 : c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
907 : 8 : continue;
908 : : }
909 : : }
910 : :
911 [ + - ]: 408 : if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
912 : 408 : p = startswith(line, "CapEff:");
913 [ + + ]: 408 : if (p) {
914 : 8 : r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
915 [ - + ]: 8 : if (r < 0)
916 : 0 : return r;
917 : :
918 : 8 : c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
919 : 8 : continue;
920 : : }
921 : : }
922 : :
923 [ + - ]: 400 : if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
924 : 400 : p = startswith(line, "CapPrm:");
925 [ + + ]: 400 : if (p) {
926 : 8 : r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
927 [ - + ]: 8 : if (r < 0)
928 : 0 : return r;
929 : :
930 : 8 : c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
931 : 8 : continue;
932 : : }
933 : : }
934 : :
935 [ + - ]: 392 : if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
936 : 392 : p = startswith(line, "CapInh:");
937 [ + + ]: 392 : if (p) {
938 : 8 : r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
939 [ - + ]: 8 : if (r < 0)
940 : 0 : return r;
941 : :
942 : 8 : c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
943 : 8 : continue;
944 : : }
945 : : }
946 : :
947 [ + - ]: 384 : if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
948 : 384 : p = startswith(line, "CapBnd:");
949 [ + + ]: 384 : if (p) {
950 : 8 : r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
951 [ - + ]: 8 : if (r < 0)
952 : 0 : return r;
953 : :
954 : 8 : c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
955 : 8 : continue;
956 : : }
957 : : }
958 : : }
959 : : }
960 : : }
961 : :
962 [ + - ]: 8 : if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
963 : : const char *p;
964 : :
965 [ - + - + : 8 : p = procfs_file_alloca(pid, "attr/current");
- + ]
966 : 8 : r = read_one_line_file(p, &c->label);
967 [ - + ]: 8 : if (r < 0) {
968 [ # # # # ]: 0 : if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES))
969 : 0 : return r;
970 : : } else
971 : 8 : c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
972 : : }
973 : :
974 [ + - ]: 8 : if (missing & SD_BUS_CREDS_COMM) {
975 : 8 : r = get_process_comm(pid, &c->comm);
976 [ - + ]: 8 : if (r < 0) {
977 [ # # # # ]: 0 : if (!IN_SET(r, -EPERM, -EACCES))
978 : 0 : return r;
979 : : } else
980 : 8 : c->mask |= SD_BUS_CREDS_COMM;
981 : : }
982 : :
983 [ + - ]: 8 : if (missing & SD_BUS_CREDS_EXE) {
984 : 8 : r = get_process_exe(pid, &c->exe);
985 [ - + ]: 8 : 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 [ + + ]: 8 : } else if (r < 0) {
996 [ + - - + ]: 4 : if (!IN_SET(r, -EPERM, -EACCES))
997 : 0 : return r;
998 : : } else
999 : 4 : c->mask |= SD_BUS_CREDS_EXE;
1000 : : }
1001 : :
1002 [ + - ]: 8 : if (missing & SD_BUS_CREDS_CMDLINE) {
1003 : : const char *p;
1004 : :
1005 [ - + - + : 8 : p = procfs_file_alloca(pid, "cmdline");
- + ]
1006 : 8 : r = read_full_file(p, &c->cmdline, &c->cmdline_size);
1007 [ - + ]: 8 : if (r == -ENOENT)
1008 : 0 : return -ESRCH;
1009 [ - + ]: 8 : if (r < 0) {
1010 [ # # # # ]: 0 : if (!IN_SET(r, -EPERM, -EACCES))
1011 : 0 : return r;
1012 : : } else {
1013 [ - + ]: 8 : if (c->cmdline_size == 0)
1014 : 0 : c->cmdline = mfree(c->cmdline);
1015 : :
1016 : 8 : c->mask |= SD_BUS_CREDS_CMDLINE;
1017 : : }
1018 : : }
1019 : :
1020 [ - + # # ]: 8 : 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 [ + - ]: 8 : 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 [ + - ]: 8 : if (!c->cgroup) {
1039 : 8 : r = cg_pid_get_path(NULL, pid, &c->cgroup);
1040 [ - + ]: 8 : if (r < 0) {
1041 [ # # # # ]: 0 : if (!IN_SET(r, -EPERM, -EACCES))
1042 : 0 : return r;
1043 : : }
1044 : : }
1045 : :
1046 [ + - ]: 8 : if (!c->cgroup_root) {
1047 : 8 : r = cg_get_root_path(&c->cgroup_root);
1048 [ - + ]: 8 : if (r < 0)
1049 : 0 : return r;
1050 : : }
1051 : :
1052 [ + - ]: 8 : if (c->cgroup)
1053 : 8 : 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 [ + - ]: 8 : if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
1057 : 8 : r = audit_session_from_pid(pid, &c->audit_session_id);
1058 [ + + ]: 8 : if (r == -ENODATA) {
1059 : : /* ENODATA means: no audit session id assigned */
1060 : 4 : c->audit_session_id = AUDIT_SESSION_INVALID;
1061 : 4 : c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1062 [ - + ]: 4 : } else if (r < 0) {
1063 [ # # # # ]: 0 : if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
1064 : 0 : return r;
1065 : : } else
1066 : 4 : c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
1067 : : }
1068 : :
1069 [ + - ]: 8 : if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
1070 : 8 : r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
1071 [ + + ]: 8 : if (r == -ENODATA) {
1072 : : /* ENODATA means: no audit login uid assigned */
1073 : 4 : c->audit_login_uid = UID_INVALID;
1074 : 4 : c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1075 [ - + ]: 4 : } else if (r < 0) {
1076 [ # # # # ]: 0 : if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES))
1077 : 0 : return r;
1078 : : } else
1079 : 4 : c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
1080 : : }
1081 : :
1082 [ + - ]: 8 : if (missing & SD_BUS_CREDS_TTY) {
1083 : 8 : r = get_ctty(pid, NULL, &c->tty);
1084 [ + - ]: 8 : if (r == -ENXIO) {
1085 : : /* ENXIO means: process has no controlling TTY */
1086 : 8 : c->tty = NULL;
1087 : 8 : 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 [ - + ]: 8 : if (!pid_is_alive(pid))
1101 : 0 : return -ESRCH;
1102 : :
1103 [ - + # # : 8 : if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
# # ]
1104 : 0 : return -ESRCH;
1105 : :
1106 : 8 : c->augmented = missing & c->mask;
1107 : :
1108 : 8 : 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 : : }
|