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