]>
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> | |
23 | ||
24 | #include "util.h" | |
25 | #include "cgroup-util.h" | |
26 | #include "fileio.h" | |
27 | #include "audit.h" | |
28 | #include "bus-message.h" | |
29 | #include "bus-util.h" | |
30 | #include "time-util.h" | |
49b832c5 | 31 | #include "strv.h" |
5b12334d LP |
32 | #include "bus-creds.h" |
33 | ||
34 | enum { | |
35 | CAP_OFFSET_INHERITABLE = 0, | |
36 | CAP_OFFSET_PERMITTED = 1, | |
37 | CAP_OFFSET_EFFECTIVE = 2, | |
38 | CAP_OFFSET_BOUNDING = 3 | |
39 | }; | |
40 | ||
41 | void bus_creds_done(sd_bus_creds *c) { | |
42 | assert(c); | |
43 | ||
44 | /* For internal bus cred structures that are allocated by | |
45 | * something else */ | |
46 | ||
47 | free(c->session); | |
48 | free(c->unit); | |
49 | free(c->user_unit); | |
50 | free(c->slice); | |
51 | ||
49b832c5 | 52 | strv_free(c->cmdline_array); |
65dae17a | 53 | strv_free(c->well_known_names); |
5b12334d LP |
54 | } |
55 | ||
56 | _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) { | |
57 | assert_return(c, NULL); | |
58 | ||
59 | if (c->allocated) { | |
60 | assert(c->n_ref > 0); | |
61 | c->n_ref++; | |
62 | } else { | |
63 | sd_bus_message *m; | |
64 | ||
65 | /* If this is an embedded creds structure, then | |
66 | * forward ref counting to the message */ | |
67 | m = container_of(c, sd_bus_message, creds); | |
68 | sd_bus_message_ref(m); | |
69 | } | |
70 | ||
71 | return c; | |
72 | } | |
73 | ||
74 | _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { | |
5b1bc83f LP |
75 | |
76 | if (!c) | |
77 | return NULL; | |
5b12334d LP |
78 | |
79 | if (c->allocated) { | |
80 | assert(c->n_ref > 0); | |
81 | c->n_ref--; | |
82 | ||
83 | if (c->n_ref == 0) { | |
84 | bus_creds_done(c); | |
85 | ||
86 | free(c->comm); | |
87 | free(c->tid_comm); | |
88 | free(c->exe); | |
89 | free(c->cmdline); | |
90 | free(c->cgroup); | |
91 | free(c->capability); | |
92 | free(c->label); | |
49b832c5 | 93 | free(c->unique_name); |
751bc6ac | 94 | free(c->cgroup_root); |
cccb0b2c | 95 | free(c->conn_name); |
5b12334d LP |
96 | free(c); |
97 | } | |
98 | } else { | |
99 | sd_bus_message *m; | |
100 | ||
101 | m = container_of(c, sd_bus_message, creds); | |
102 | sd_bus_message_unref(m); | |
103 | } | |
104 | ||
105 | ||
106 | return NULL; | |
107 | } | |
108 | ||
4cf8496d | 109 | _public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) { |
5b12334d LP |
110 | assert_return(c, 0); |
111 | ||
112 | return c->mask; | |
113 | } | |
114 | ||
115 | sd_bus_creds* bus_creds_new(void) { | |
116 | sd_bus_creds *c; | |
117 | ||
118 | c = new0(sd_bus_creds, 1); | |
119 | if (!c) | |
120 | return NULL; | |
121 | ||
122 | c->allocated = true; | |
123 | c->n_ref = 1; | |
124 | return c; | |
125 | } | |
126 | ||
127 | _public_ int sd_bus_creds_new_from_pid(pid_t pid, uint64_t mask, sd_bus_creds **ret) { | |
128 | sd_bus_creds *c; | |
129 | int r; | |
130 | ||
131 | assert_return(pid >= 0, -EINVAL); | |
95c4fe82 | 132 | assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP); |
5b12334d LP |
133 | assert_return(ret, -EINVAL); |
134 | ||
135 | if (pid == 0) | |
136 | pid = getpid(); | |
137 | ||
138 | c = bus_creds_new(); | |
139 | if (!c) | |
140 | return -ENOMEM; | |
141 | ||
142 | r = bus_creds_add_more(c, mask, pid, 0); | |
143 | if (r < 0) { | |
0349c608 | 144 | sd_bus_creds_unref(c); |
5b12334d LP |
145 | return r; |
146 | } | |
147 | ||
148 | /* Check if the process existed at all, in case we haven't | |
149 | * figured that out already */ | |
150 | if (kill(pid, 0) < 0 && errno == ESRCH) { | |
151 | sd_bus_creds_unref(c); | |
152 | return -ESRCH; | |
153 | } | |
154 | ||
155 | *ret = c; | |
156 | return 0; | |
157 | } | |
158 | ||
159 | _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) { | |
160 | assert_return(c, -EINVAL); | |
161 | assert_return(uid, -EINVAL); | |
6a4abbc8 LP |
162 | |
163 | if (!(c->mask & SD_BUS_CREDS_UID)) | |
164 | return -ENODATA; | |
5b12334d LP |
165 | |
166 | *uid = c->uid; | |
167 | return 0; | |
168 | } | |
169 | ||
170 | _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) { | |
171 | assert_return(c, -EINVAL); | |
172 | assert_return(gid, -EINVAL); | |
6a4abbc8 LP |
173 | |
174 | if (!(c->mask & SD_BUS_CREDS_UID)) | |
175 | return -ENODATA; | |
5b12334d LP |
176 | |
177 | *gid = c->gid; | |
178 | return 0; | |
179 | } | |
180 | ||
181 | _public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) { | |
182 | assert_return(c, -EINVAL); | |
183 | assert_return(pid, -EINVAL); | |
6a4abbc8 LP |
184 | |
185 | if (!(c->mask & SD_BUS_CREDS_PID)) | |
186 | return -ENODATA; | |
5b12334d LP |
187 | |
188 | assert(c->pid > 0); | |
189 | *pid = c->pid; | |
190 | return 0; | |
191 | } | |
192 | ||
193 | _public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) { | |
194 | assert_return(c, -EINVAL); | |
195 | assert_return(tid, -EINVAL); | |
6a4abbc8 LP |
196 | |
197 | if (!(c->mask & SD_BUS_CREDS_TID)) | |
198 | return -ENODATA; | |
5b12334d LP |
199 | |
200 | assert(c->tid > 0); | |
201 | *tid = c->tid; | |
202 | return 0; | |
203 | } | |
204 | ||
205 | _public_ int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec) { | |
206 | assert_return(c, -EINVAL); | |
207 | assert_return(usec, -EINVAL); | |
6a4abbc8 LP |
208 | |
209 | if (!(c->mask & SD_BUS_CREDS_PID_STARTTIME)) | |
210 | return -ENODATA; | |
5b12334d LP |
211 | |
212 | assert(c->pid_starttime > 0); | |
213 | *usec = c->pid_starttime; | |
214 | return 0; | |
215 | } | |
216 | ||
217 | _public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) { | |
218 | assert_return(c, -EINVAL); | |
6a4abbc8 LP |
219 | |
220 | if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)) | |
221 | return -ENODATA; | |
5b12334d LP |
222 | |
223 | assert(c->label); | |
224 | *ret = c->label; | |
225 | return 0; | |
226 | } | |
227 | ||
228 | _public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) { | |
229 | assert_return(c, -EINVAL); | |
230 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
231 | |
232 | if (!(c->mask & SD_BUS_CREDS_COMM)) | |
233 | return -ENODATA; | |
5b12334d LP |
234 | |
235 | assert(c->comm); | |
236 | *ret = c->comm; | |
237 | return 0; | |
238 | } | |
239 | ||
240 | _public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) { | |
241 | assert_return(c, -EINVAL); | |
242 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
243 | |
244 | if (!(c->mask & SD_BUS_CREDS_TID_COMM)) | |
245 | return -ENODATA; | |
5b12334d LP |
246 | |
247 | assert(c->tid_comm); | |
248 | *ret = c->tid_comm; | |
249 | return 0; | |
250 | } | |
251 | ||
252 | _public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) { | |
253 | assert_return(c, -EINVAL); | |
254 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
255 | |
256 | if (!(c->mask & SD_BUS_CREDS_EXE)) | |
257 | return -ENODATA; | |
5b12334d LP |
258 | |
259 | assert(c->exe); | |
260 | *ret = c->exe; | |
261 | return 0; | |
262 | } | |
263 | ||
264 | _public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) { | |
265 | assert_return(c, -EINVAL); | |
266 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
267 | |
268 | if (!(c->mask & SD_BUS_CREDS_CGROUP)) | |
269 | return -ENODATA; | |
5b12334d LP |
270 | |
271 | assert(c->cgroup); | |
272 | *ret = c->cgroup; | |
273 | return 0; | |
274 | } | |
275 | ||
276 | _public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) { | |
277 | int r; | |
278 | ||
279 | assert_return(c, -EINVAL); | |
280 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
281 | |
282 | if (!(c->mask & SD_BUS_CREDS_UNIT)) | |
283 | return -ENODATA; | |
5b12334d LP |
284 | |
285 | assert(c->cgroup); | |
286 | ||
287 | if (!c->unit) { | |
751bc6ac LP |
288 | const char *shifted; |
289 | ||
290 | r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); | |
291 | if (r < 0) | |
292 | return r; | |
293 | ||
294 | r = cg_path_get_unit(shifted, (char**) &c->unit); | |
5b12334d LP |
295 | if (r < 0) |
296 | return r; | |
297 | } | |
298 | ||
299 | *ret = c->unit; | |
300 | return 0; | |
301 | } | |
302 | ||
303 | _public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) { | |
304 | int r; | |
305 | ||
306 | assert_return(c, -EINVAL); | |
307 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
308 | |
309 | if (!(c->mask & SD_BUS_CREDS_USER_UNIT)) | |
310 | return -ENODATA; | |
5b12334d LP |
311 | |
312 | assert(c->cgroup); | |
313 | ||
314 | if (!c->user_unit) { | |
751bc6ac LP |
315 | const char *shifted; |
316 | ||
317 | r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); | |
318 | if (r < 0) | |
319 | return r; | |
320 | ||
321 | r = cg_path_get_user_unit(shifted, (char**) &c->user_unit); | |
5b12334d LP |
322 | if (r < 0) |
323 | return r; | |
324 | } | |
325 | ||
326 | *ret = c->user_unit; | |
327 | return 0; | |
328 | } | |
329 | ||
330 | _public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) { | |
331 | int r; | |
332 | ||
333 | assert_return(c, -EINVAL); | |
334 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
335 | |
336 | if (!(c->mask & SD_BUS_CREDS_SLICE)) | |
337 | return -ENODATA; | |
5b12334d LP |
338 | |
339 | assert(c->cgroup); | |
340 | ||
341 | if (!c->slice) { | |
751bc6ac LP |
342 | const char *shifted; |
343 | ||
344 | r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); | |
345 | if (r < 0) | |
346 | return r; | |
347 | ||
348 | r = cg_path_get_slice(shifted, (char**) &c->slice); | |
5b12334d LP |
349 | if (r < 0) |
350 | return r; | |
351 | } | |
352 | ||
353 | *ret = c->slice; | |
354 | return 0; | |
355 | } | |
356 | ||
357 | _public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) { | |
358 | int r; | |
359 | ||
360 | assert_return(c, -EINVAL); | |
361 | assert_return(ret, -EINVAL); | |
6a4abbc8 LP |
362 | |
363 | if (!(c->mask & SD_BUS_CREDS_SESSION)) | |
364 | return -ENODATA; | |
5b12334d LP |
365 | |
366 | assert(c->cgroup); | |
367 | ||
368 | if (!c->session) { | |
751bc6ac LP |
369 | const char *shifted; |
370 | ||
371 | r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); | |
372 | if (r < 0) | |
373 | return r; | |
374 | ||
375 | r = cg_path_get_session(shifted, (char**) &c->session); | |
5b12334d LP |
376 | if (r < 0) |
377 | return r; | |
378 | } | |
379 | ||
380 | *ret = c->session; | |
381 | return 0; | |
382 | } | |
383 | ||
384 | _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) { | |
751bc6ac LP |
385 | const char *shifted; |
386 | int r; | |
387 | ||
5b12334d LP |
388 | assert_return(c, -EINVAL); |
389 | assert_return(uid, -EINVAL); | |
6a4abbc8 LP |
390 | |
391 | if (!(c->mask & SD_BUS_CREDS_OWNER_UID)) | |
392 | return -ENODATA; | |
5b12334d LP |
393 | |
394 | assert(c->cgroup); | |
395 | ||
751bc6ac LP |
396 | r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); |
397 | if (r < 0) | |
398 | return r; | |
399 | ||
400 | return cg_path_get_owner_uid(shifted, uid); | |
5b12334d LP |
401 | } |
402 | ||
403 | _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) { | |
5b12334d | 404 | assert_return(c, -EINVAL); |
6a4abbc8 LP |
405 | |
406 | if (!(c->mask & SD_BUS_CREDS_CMDLINE)) | |
407 | return -ENODATA; | |
5b12334d | 408 | |
689bd78d | 409 | assert_return(c->cmdline, -ESRCH); |
5b12334d LP |
410 | assert(c->cmdline); |
411 | ||
49b832c5 LP |
412 | if (!c->cmdline_array) { |
413 | c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size); | |
414 | if (!c->cmdline_array) | |
415 | return -ENOMEM; | |
5b12334d LP |
416 | } |
417 | ||
5b12334d | 418 | *cmdline = c->cmdline_array; |
5b12334d LP |
419 | return 0; |
420 | } | |
421 | ||
422 | _public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) { | |
423 | assert_return(c, -EINVAL); | |
424 | assert_return(sessionid, -EINVAL); | |
6a4abbc8 LP |
425 | |
426 | if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID)) | |
427 | return -ENODATA; | |
5b12334d LP |
428 | |
429 | *sessionid = c->audit_session_id; | |
430 | return 0; | |
431 | } | |
432 | ||
433 | _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) { | |
434 | assert_return(c, -EINVAL); | |
435 | assert_return(uid, -EINVAL); | |
6a4abbc8 LP |
436 | |
437 | if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID)) | |
438 | return -ENODATA; | |
5b12334d LP |
439 | |
440 | *uid = c->audit_login_uid; | |
441 | return 0; | |
442 | } | |
443 | ||
49b832c5 LP |
444 | _public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) { |
445 | assert_return(c, -EINVAL); | |
446 | assert_return(unique_name, -EINVAL); | |
6a4abbc8 LP |
447 | |
448 | if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME)) | |
449 | return -ENODATA; | |
49b832c5 LP |
450 | |
451 | *unique_name = c->unique_name; | |
452 | return 0; | |
453 | } | |
454 | ||
455 | _public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) { | |
456 | assert_return(c, -EINVAL); | |
457 | assert_return(well_known_names, -EINVAL); | |
6a4abbc8 LP |
458 | |
459 | if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)) | |
460 | return -ENODATA; | |
49b832c5 | 461 | |
65dae17a | 462 | *well_known_names = c->well_known_names; |
49b832c5 LP |
463 | return 0; |
464 | } | |
465 | ||
cccb0b2c LP |
466 | _public_ int sd_bus_creds_get_connection_name(sd_bus_creds *c, const char **ret) { |
467 | assert_return(c, -EINVAL); | |
468 | assert_return(ret, -EINVAL); | |
469 | ||
470 | if (!(c->mask & SD_BUS_CREDS_CONNECTION_NAME)) | |
471 | return -ENODATA; | |
472 | ||
473 | assert(c->conn_name); | |
474 | *ret = c->conn_name; | |
475 | return 0; | |
476 | } | |
477 | ||
5b12334d LP |
478 | static int has_cap(sd_bus_creds *c, unsigned offset, int capability) { |
479 | size_t sz; | |
480 | ||
481 | assert(c); | |
482 | assert(c->capability); | |
483 | ||
484 | sz = c->capability_size / 4; | |
485 | if ((size_t) capability >= sz*8) | |
486 | return 0; | |
487 | ||
488 | return !!(c->capability[offset * sz + (capability / 8)] & (1 << (capability % 8))); | |
489 | } | |
490 | ||
491 | _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) { | |
492 | assert_return(c, -EINVAL); | |
493 | assert_return(capability >= 0, -EINVAL); | |
6a4abbc8 LP |
494 | |
495 | if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS)) | |
496 | return -ENODATA; | |
5b12334d LP |
497 | |
498 | return has_cap(c, CAP_OFFSET_EFFECTIVE, capability); | |
499 | } | |
500 | ||
501 | _public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) { | |
502 | assert_return(c, -EINVAL); | |
503 | assert_return(capability >= 0, -EINVAL); | |
6a4abbc8 LP |
504 | |
505 | if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS)) | |
506 | return -ENODATA; | |
5b12334d LP |
507 | |
508 | return has_cap(c, CAP_OFFSET_PERMITTED, capability); | |
509 | } | |
510 | ||
511 | _public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) { | |
512 | assert_return(c, -EINVAL); | |
513 | assert_return(capability >= 0, -EINVAL); | |
6a4abbc8 LP |
514 | |
515 | if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS)) | |
516 | return -ENODATA; | |
5b12334d LP |
517 | |
518 | return has_cap(c, CAP_OFFSET_INHERITABLE, capability); | |
519 | } | |
520 | ||
521 | _public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) { | |
522 | assert_return(c, -EINVAL); | |
523 | assert_return(capability >= 0, -EINVAL); | |
6a4abbc8 LP |
524 | |
525 | if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS)) | |
526 | return -ENODATA; | |
5b12334d LP |
527 | |
528 | return has_cap(c, CAP_OFFSET_BOUNDING, capability); | |
529 | } | |
530 | ||
531 | static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) { | |
532 | size_t sz; | |
533 | unsigned i; | |
534 | ||
535 | assert(c); | |
536 | assert(p); | |
537 | ||
538 | p += strspn(p, WHITESPACE); | |
539 | ||
540 | sz = strlen(p); | |
541 | if (sz % 2 != 0) | |
542 | return -EINVAL; | |
543 | ||
544 | sz /= 2; | |
545 | if (!c->capability) { | |
546 | c->capability = new0(uint8_t, sz * 4); | |
547 | if (!c->capability) | |
548 | return -ENOMEM; | |
549 | ||
550 | c->capability_size = sz * 4; | |
551 | } | |
552 | ||
553 | for (i = 0; i < sz; i ++) { | |
554 | int x, y; | |
555 | ||
556 | x = unhexchar(p[i*2]); | |
557 | y = unhexchar(p[i*2+1]); | |
558 | ||
559 | if (x < 0 || y < 0) | |
560 | return -EINVAL; | |
561 | ||
562 | c->capability[offset * sz + (sz - i - 1)] = (uint8_t) x << 4 | (uint8_t) y; | |
563 | } | |
564 | ||
565 | return 0; | |
566 | } | |
567 | ||
568 | int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { | |
569 | uint64_t missing; | |
570 | int r; | |
571 | ||
572 | assert(c); | |
573 | assert(c->allocated); | |
574 | ||
575 | missing = mask & ~c->mask; | |
576 | if (missing == 0) | |
577 | return 0; | |
578 | ||
579 | /* Try to retrieve PID from creds if it wasn't passed to us */ | |
580 | if (pid <= 0 && (c->mask & SD_BUS_CREDS_PID)) | |
581 | pid = c->pid; | |
582 | ||
583 | if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) | |
584 | tid = c->pid; | |
585 | ||
586 | /* Without pid we cannot do much... */ | |
587 | if (pid <= 0) | |
588 | return 0; | |
589 | ||
590 | if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | | |
591 | SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS | | |
592 | SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) { | |
593 | ||
594 | _cleanup_fclose_ FILE *f = NULL; | |
595 | char line[LINE_MAX]; | |
596 | const char *p; | |
597 | ||
598 | p = procfs_file_alloca(pid, "status"); | |
599 | ||
600 | f = fopen(p, "re"); | |
601 | if (!f) | |
602 | return errno == ENOENT ? -ESRCH : -errno; | |
603 | ||
604 | FOREACH_LINE(line, f, return -errno) { | |
605 | truncate_nl(line); | |
606 | ||
607 | if (missing & SD_BUS_CREDS_UID) { | |
608 | p = startswith(line, "Uid:"); | |
609 | if (p) { | |
610 | unsigned long uid; | |
611 | ||
612 | p += strspn(p, WHITESPACE); | |
613 | if (sscanf(p, "%lu", &uid) != 1) | |
614 | return -EIO; | |
615 | ||
616 | c->uid = (uid_t) uid; | |
617 | c->mask |= SD_BUS_CREDS_UID; | |
618 | continue; | |
619 | } | |
620 | } | |
621 | ||
622 | if (missing & SD_BUS_CREDS_GID) { | |
623 | p = startswith(line, "Gid:"); | |
624 | if (p) { | |
625 | unsigned long gid; | |
626 | ||
627 | p += strspn(p, WHITESPACE); | |
628 | if (sscanf(p, "%lu", &gid) != 1) | |
629 | return -EIO; | |
630 | ||
631 | c->gid = (uid_t) gid; | |
632 | c->mask |= SD_BUS_CREDS_GID; | |
633 | continue; | |
634 | } | |
635 | } | |
636 | ||
637 | if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) { | |
638 | p = startswith(line, "CapEff:"); | |
639 | if (p) { | |
640 | r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p); | |
641 | if (r < 0) | |
642 | return r; | |
643 | ||
644 | c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS; | |
645 | continue; | |
646 | } | |
647 | } | |
648 | ||
649 | if (missing & SD_BUS_CREDS_PERMITTED_CAPS) { | |
650 | p = startswith(line, "CapPrm:"); | |
651 | if (p) { | |
652 | r = parse_caps(c, CAP_OFFSET_PERMITTED, p); | |
653 | if (r < 0) | |
654 | return r; | |
655 | ||
656 | c->mask |= SD_BUS_CREDS_PERMITTED_CAPS; | |
657 | continue; | |
658 | } | |
659 | } | |
660 | ||
661 | if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) { | |
662 | p = startswith(line, "CapInh:"); | |
663 | if (p) { | |
664 | r = parse_caps(c, CAP_OFFSET_INHERITABLE, p); | |
665 | if (r < 0) | |
666 | return r; | |
667 | ||
668 | c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS; | |
669 | continue; | |
670 | } | |
671 | } | |
672 | ||
673 | if (missing & SD_BUS_CREDS_BOUNDING_CAPS) { | |
674 | p = startswith(line, "CapBnd:"); | |
675 | if (p) { | |
676 | r = parse_caps(c, CAP_OFFSET_BOUNDING, p); | |
677 | if (r < 0) | |
678 | return r; | |
679 | ||
680 | c->mask |= SD_BUS_CREDS_BOUNDING_CAPS; | |
681 | continue; | |
682 | } | |
683 | } | |
684 | } | |
685 | } | |
686 | ||
687 | if (missing & (SD_BUS_CREDS_PID_STARTTIME)) { | |
688 | unsigned long long st; | |
689 | ||
690 | r = get_starttime_of_pid(pid, &st); | |
691 | if (r < 0) | |
692 | return r; | |
693 | ||
694 | c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK); | |
695 | c->mask |= SD_BUS_CREDS_PID_STARTTIME; | |
696 | } | |
697 | ||
698 | if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) { | |
699 | const char *p; | |
700 | ||
701 | p = procfs_file_alloca(pid, "attr/current"); | |
702 | r = read_one_line_file(p, &c->label); | |
76037bae | 703 | if (r < 0 && r != -ENOENT && r != -EINVAL) |
5b12334d LP |
704 | return r; |
705 | else if (r >= 0) | |
706 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
707 | } | |
708 | ||
709 | if (missing & SD_BUS_CREDS_COMM) { | |
710 | r = get_process_comm(pid, &c->comm); | |
4efbd13a | 711 | if (r < 0) |
5b12334d | 712 | return r; |
4efbd13a KS |
713 | |
714 | c->mask |= SD_BUS_CREDS_COMM; | |
5b12334d LP |
715 | } |
716 | ||
717 | if (missing & SD_BUS_CREDS_EXE) { | |
718 | r = get_process_exe(pid, &c->exe); | |
719 | if (r < 0) | |
720 | return r; | |
721 | ||
722 | c->mask |= SD_BUS_CREDS_EXE; | |
723 | } | |
724 | ||
725 | if (missing & SD_BUS_CREDS_CMDLINE) { | |
726 | const char *p; | |
727 | ||
728 | p = procfs_file_alloca(pid, "cmdline"); | |
49b832c5 | 729 | r = read_full_file(p, &c->cmdline, &c->cmdline_size); |
5b12334d LP |
730 | if (r < 0) |
731 | return r; | |
732 | ||
49b832c5 | 733 | if (c->cmdline_size == 0) { |
5b12334d LP |
734 | free(c->cmdline); |
735 | c->cmdline = NULL; | |
736 | } else | |
737 | c->mask |= SD_BUS_CREDS_CMDLINE; | |
738 | } | |
739 | ||
740 | if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) { | |
741 | _cleanup_free_ char *p = NULL; | |
742 | ||
743 | if (asprintf(&p, "/proc/%lu/task/%lu/comm", (unsigned long) pid, (unsigned long) tid) < 0) | |
744 | return -ENOMEM; | |
745 | ||
746 | r = read_one_line_file(p, &c->tid_comm); | |
4efbd13a | 747 | if (r < 0) |
5b12334d | 748 | return r == -ENOENT ? -ESRCH : r; |
4efbd13a KS |
749 | |
750 | c->mask |= SD_BUS_CREDS_TID_COMM; | |
5b12334d LP |
751 | } |
752 | ||
753 | if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) { | |
754 | ||
755 | r = cg_pid_get_path(NULL, pid, &c->cgroup); | |
4efbd13a | 756 | if (r < 0) |
5b12334d | 757 | return r; |
4efbd13a | 758 | |
751bc6ac LP |
759 | r = cg_get_root_path(&c->cgroup_root); |
760 | if (r < 0) | |
761 | return r; | |
762 | ||
4efbd13a | 763 | c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID); |
5b12334d LP |
764 | } |
765 | ||
766 | if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) { | |
767 | r = audit_session_from_pid(pid, &c->audit_session_id); | |
547708f5 | 768 | if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != -ENOENT) |
5b12334d LP |
769 | return r; |
770 | else if (r >= 0) | |
771 | c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; | |
772 | } | |
773 | ||
774 | if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) { | |
775 | r = audit_loginuid_from_pid(pid, &c->audit_login_uid); | |
547708f5 | 776 | if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != -ENOENT) |
5b12334d LP |
777 | return r; |
778 | else if (r >= 0) | |
779 | c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; | |
780 | } | |
781 | ||
782 | return 0; | |
783 | } | |
784 | ||
49b832c5 | 785 | int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) { |
5b12334d LP |
786 | _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL; |
787 | int r; | |
788 | ||
49b832c5 LP |
789 | assert(c); |
790 | assert(ret); | |
5b12334d LP |
791 | |
792 | if ((mask & ~c->mask) == 0) { | |
793 | /* There's already all data we need. */ | |
794 | ||
795 | *ret = sd_bus_creds_ref(c); | |
796 | return 0; | |
797 | } | |
798 | ||
799 | n = bus_creds_new(); | |
800 | if (!n) | |
801 | return -ENOMEM; | |
802 | ||
803 | /* Copy the original data over */ | |
804 | ||
805 | if (c->mask & mask & SD_BUS_CREDS_UID) { | |
806 | n->uid = c->uid; | |
807 | n->mask |= SD_BUS_CREDS_UID; | |
808 | } | |
809 | ||
810 | if (c->mask & mask & SD_BUS_CREDS_GID) { | |
811 | n->gid = c->gid; | |
812 | n->mask |= SD_BUS_CREDS_GID; | |
813 | } | |
814 | ||
815 | if (c->mask & mask & SD_BUS_CREDS_PID) { | |
816 | n->pid = c->pid; | |
817 | n->mask |= SD_BUS_CREDS_PID; | |
818 | } | |
819 | ||
820 | if (c->mask & mask & SD_BUS_CREDS_TID) { | |
821 | n->tid = c->tid; | |
822 | n->mask |= SD_BUS_CREDS_TID; | |
823 | } | |
824 | ||
825 | if (c->mask & mask & SD_BUS_CREDS_PID_STARTTIME) { | |
826 | n->pid_starttime = c->pid_starttime; | |
827 | n->mask |= SD_BUS_CREDS_PID_STARTTIME; | |
828 | } | |
829 | ||
830 | if (c->mask & mask & SD_BUS_CREDS_COMM) { | |
831 | n->comm = strdup(c->comm); | |
832 | if (!n->comm) | |
833 | return -ENOMEM; | |
834 | ||
835 | n->mask |= SD_BUS_CREDS_COMM; | |
836 | } | |
837 | ||
838 | if (c->mask & mask & SD_BUS_CREDS_TID_COMM) { | |
839 | n->tid_comm = strdup(c->tid_comm); | |
840 | if (!n->tid_comm) | |
841 | return -ENOMEM; | |
842 | ||
843 | n->mask |= SD_BUS_CREDS_TID_COMM; | |
844 | } | |
845 | ||
846 | if (c->mask & mask & SD_BUS_CREDS_EXE) { | |
847 | n->exe = strdup(c->exe); | |
848 | if (!n->exe) | |
849 | return -ENOMEM; | |
850 | ||
851 | n->mask |= SD_BUS_CREDS_EXE; | |
852 | } | |
853 | ||
854 | if (c->mask & mask & SD_BUS_CREDS_CMDLINE) { | |
49b832c5 | 855 | n->cmdline = memdup(c->cmdline, c->cmdline_size); |
5b12334d LP |
856 | if (!n->cmdline) |
857 | return -ENOMEM; | |
858 | ||
49b832c5 | 859 | n->cmdline_size = c->cmdline_size; |
5b12334d LP |
860 | n->mask |= SD_BUS_CREDS_CMDLINE; |
861 | } | |
862 | ||
863 | 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_OWNER_UID)) { | |
864 | n->cgroup = strdup(c->cgroup); | |
865 | if (!n->cgroup) | |
866 | return -ENOMEM; | |
867 | ||
751bc6ac LP |
868 | n->cgroup_root = strdup(c->cgroup_root); |
869 | if (!n->cgroup_root) | |
870 | return -ENOMEM; | |
871 | ||
5b12334d LP |
872 | 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_OWNER_UID); |
873 | } | |
874 | ||
875 | if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) { | |
876 | n->capability = memdup(c->capability, c->capability_size); | |
877 | if (!n->capability) | |
878 | return -ENOMEM; | |
879 | ||
880 | n->capability_size = c->capability_size; | |
881 | 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); | |
882 | } | |
883 | ||
884 | if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) { | |
885 | n->audit_session_id = c->audit_session_id; | |
886 | n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; | |
887 | } | |
888 | ||
889 | if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) { | |
890 | n->audit_login_uid = c->audit_login_uid; | |
891 | n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; | |
892 | } | |
893 | ||
49b832c5 LP |
894 | if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) { |
895 | n->unique_name = strdup(c->unique_name); | |
896 | if (!n->unique_name) | |
897 | return -ENOMEM; | |
898 | } | |
899 | ||
900 | if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { | |
65dae17a | 901 | n->well_known_names = strv_copy(c->well_known_names); |
49b832c5 LP |
902 | if (!n->well_known_names) |
903 | return -ENOMEM; | |
49b832c5 LP |
904 | } |
905 | ||
5b12334d LP |
906 | /* Get more data */ |
907 | ||
908 | r = bus_creds_add_more(n, mask, | |
909 | c->mask & SD_BUS_CREDS_PID ? c->pid : 0, | |
910 | c->mask & SD_BUS_CREDS_TID ? c->tid : 0); | |
911 | if (r < 0) | |
912 | return r; | |
913 | ||
914 | *ret = n; | |
915 | n = NULL; | |
916 | return 0; | |
917 | } |