]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-creds.c
bus: include connection name in credentials structure
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-creds.c
CommitLineData
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
34enum {
35 CAP_OFFSET_INHERITABLE = 0,
36 CAP_OFFSET_PERMITTED = 1,
37 CAP_OFFSET_EFFECTIVE = 2,
38 CAP_OFFSET_BOUNDING = 3
39};
40
41void 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
115sd_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
478static 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
531static 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
568int 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 785int 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}