Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <endian.h>
4 : : #include <poll.h>
5 : : #include <stdlib.h>
6 : : #include <unistd.h>
7 : :
8 : : #include "sd-bus.h"
9 : : #include "sd-daemon.h"
10 : :
11 : : #include "alloc-util.h"
12 : : #include "bus-internal.h"
13 : : #include "bus-message.h"
14 : : #include "bus-socket.h"
15 : : #include "fd-util.h"
16 : : #include "format-util.h"
17 : : #include "fs-util.h"
18 : : #include "hexdecoct.h"
19 : : #include "io-util.h"
20 : : #include "macro.h"
21 : : #include "memory-util.h"
22 : : #include "missing.h"
23 : : #include "path-util.h"
24 : : #include "process-util.h"
25 : : #include "rlimit-util.h"
26 : : #include "selinux-util.h"
27 : : #include "signal-util.h"
28 : : #include "stdio-util.h"
29 : : #include "string-util.h"
30 : : #include "user-util.h"
31 : : #include "utf8.h"
32 : :
33 : : #define SNDBUF_SIZE (8*1024*1024)
34 : :
35 : 740 : static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
36 : :
37 [ + + ]: 1256 : while (size > 0) {
38 : 516 : struct iovec *i = iov + *idx;
39 : :
40 [ - + ]: 516 : if (i->iov_len > size) {
41 : 0 : i->iov_base = (uint8_t*) i->iov_base + size;
42 : 0 : i->iov_len -= size;
43 : 0 : return;
44 : : }
45 : :
46 : 516 : size -= i->iov_len;
47 : :
48 : 516 : *i = IOVEC_MAKE(NULL, 0);
49 : :
50 : 516 : (*idx)++;
51 : : }
52 : : }
53 : :
54 : 760 : static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
55 [ - + ]: 760 : assert(m);
56 [ - + ]: 760 : assert(p);
57 [ - + ]: 760 : assert(sz > 0);
58 : :
59 : 760 : m->iovec[m->n_iovec++] = IOVEC_MAKE((void*) p, sz);
60 : :
61 : 760 : return 0;
62 : : }
63 : :
64 : 536 : static int bus_message_setup_iovec(sd_bus_message *m) {
65 : : struct bus_body_part *part;
66 : : unsigned n, i;
67 : : int r;
68 : :
69 [ - + ]: 536 : assert(m);
70 [ - + ]: 536 : assert(m->sealed);
71 : :
72 [ - + ]: 536 : if (m->n_iovec > 0)
73 : 0 : return 0;
74 : :
75 [ - + ]: 536 : assert(!m->iovec);
76 : :
77 : 536 : n = 1 + m->n_body_parts;
78 [ + + ]: 536 : if (n < ELEMENTSOF(m->iovec_fixed))
79 : 312 : m->iovec = m->iovec_fixed;
80 : : else {
81 : 224 : m->iovec = new(struct iovec, n);
82 [ - + ]: 224 : if (!m->iovec) {
83 : 0 : r = -ENOMEM;
84 : 0 : goto fail;
85 : : }
86 : : }
87 : :
88 : 536 : r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m));
89 [ - + ]: 536 : if (r < 0)
90 : 0 : goto fail;
91 : :
92 [ + + ]: 760 : MESSAGE_FOREACH_PART(part, i, m) {
93 : 224 : r = bus_body_part_map(part);
94 [ - + ]: 224 : if (r < 0)
95 : 0 : goto fail;
96 : :
97 : 224 : r = append_iovec(m, part->data, part->size);
98 [ - + ]: 224 : if (r < 0)
99 : 0 : goto fail;
100 : : }
101 : :
102 [ - + ]: 536 : assert(n == m->n_iovec);
103 : :
104 : 536 : return 0;
105 : :
106 : 0 : fail:
107 : 0 : m->poisoned = true;
108 : 0 : return r;
109 : : }
110 : :
111 : 700 : bool bus_socket_auth_needs_write(sd_bus *b) {
112 : :
113 : : unsigned i;
114 : :
115 [ + + ]: 700 : if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
116 : 303 : return false;
117 : :
118 [ + + ]: 670 : for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) {
119 : 529 : struct iovec *j = b->auth_iovec + i;
120 : :
121 [ + + ]: 529 : if (j->iov_len > 0)
122 : 256 : return true;
123 : : }
124 : :
125 : 141 : return false;
126 : : }
127 : :
128 : 463 : static int bus_socket_write_auth(sd_bus *b) {
129 : : ssize_t k;
130 : :
131 [ - + ]: 463 : assert(b);
132 [ - + ]: 463 : assert(b->state == BUS_AUTHENTICATING);
133 : :
134 [ + + ]: 463 : if (!bus_socket_auth_needs_write(b))
135 : 259 : return 0;
136 : :
137 [ - + ]: 204 : if (b->prefer_writev)
138 : 0 : k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
139 : : else {
140 : : struct msghdr mh;
141 [ + - ]: 204 : zero(mh);
142 : :
143 : 204 : mh.msg_iov = b->auth_iovec + b->auth_index;
144 : 204 : mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
145 : :
146 : 204 : k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
147 [ - + # # ]: 204 : if (k < 0 && errno == ENOTSOCK) {
148 : 0 : b->prefer_writev = true;
149 : 0 : k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
150 : : }
151 : : }
152 : :
153 [ - + ]: 204 : if (k < 0)
154 [ # # ]: 0 : return errno == EAGAIN ? 0 : -errno;
155 : :
156 : 204 : iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
157 : 204 : return 1;
158 : : }
159 : :
160 : 342 : static int bus_socket_auth_verify_client(sd_bus *b) {
161 : : char *d, *e, *f, *start;
162 : : sd_id128_t peer;
163 : : int r;
164 : :
165 [ - + ]: 342 : assert(b);
166 : :
167 : : /*
168 : : * We expect three response lines:
169 : : * "DATA\r\n"
170 : : * "OK <server-id>\r\n"
171 : : * "AGREE_UNIX_FD\r\n" (optional)
172 : : */
173 : :
174 : 342 : d = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
175 [ + + ]: 342 : if (!d)
176 : 202 : return 0;
177 : :
178 : 140 : e = memmem(d + 2, b->rbuffer_size - (d - (char*) b->rbuffer) - 2, "\r\n", 2);
179 [ - + ]: 140 : if (!e)
180 : 0 : return 0;
181 : :
182 [ + + ]: 140 : if (b->accept_fd) {
183 : 132 : f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
184 [ - + ]: 132 : if (!f)
185 : 0 : return 0;
186 : :
187 : 132 : start = f + 2;
188 : : } else {
189 : 8 : f = NULL;
190 : 8 : start = e + 2;
191 : : }
192 : :
193 : : /* Nice! We got all the lines we need. First check the DATA line. */
194 : :
195 [ + + ]: 140 : if (d - (char*) b->rbuffer == 4) {
196 [ - + ]: 136 : if (memcmp(b->rbuffer, "DATA", 4))
197 : 0 : return -EPERM;
198 [ - + ]: 4 : } else if (d - (char*) b->rbuffer == 3 + 32) {
199 : : /*
200 : : * Old versions of the server-side implementation of `sd-bus` replied with "OK <id>" to
201 : : * "AUTH" requests from a client, even if the "AUTH" line did not contain inlined
202 : : * arguments. Therefore, we also accept "OK <id>" here, even though it is technically the
203 : : * wrong reply. We ignore the "<id>" parameter, though, since it has no real value.
204 : : */
205 [ # # ]: 0 : if (memcmp(b->rbuffer, "OK ", 3))
206 : 0 : return -EPERM;
207 : : } else
208 : 4 : return -EPERM;
209 : :
210 : : /* Now check the OK line. */
211 : :
212 [ - + ]: 136 : if (e - d != 2 + 3 + 32)
213 : 0 : return -EPERM;
214 : :
215 [ - + ]: 136 : if (memcmp(d + 2, "OK ", 3))
216 : 0 : return -EPERM;
217 : :
218 [ + + ]: 136 : b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
219 : :
220 [ + + ]: 2312 : for (unsigned i = 0; i < 32; i += 2) {
221 : : int x, y;
222 : :
223 : 2176 : x = unhexchar(d[2 + 3 + i]);
224 : 2176 : y = unhexchar(d[2 + 3 + i + 1]);
225 : :
226 [ + - - + ]: 2176 : if (x < 0 || y < 0)
227 : 0 : return -EINVAL;
228 : :
229 : 2176 : peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
230 : : }
231 : :
232 [ - + ]: 136 : if (!sd_id128_is_null(b->server_id) &&
233 [ # # ]: 0 : !sd_id128_equal(b->server_id, peer))
234 : 0 : return -EPERM;
235 : :
236 : 136 : b->server_id = peer;
237 : :
238 : : /* And possibly check the third line, too */
239 : :
240 [ + + ]: 136 : if (f)
241 : 128 : b->can_fds =
242 [ + + ]: 252 : (f - e == STRLEN("\r\nAGREE_UNIX_FD")) &&
243 [ + - ]: 124 : memcmp(e + 2, "AGREE_UNIX_FD",
244 : : STRLEN("AGREE_UNIX_FD")) == 0;
245 : :
246 : 136 : b->rbuffer_size -= (start - (char*) b->rbuffer);
247 : 136 : memmove(b->rbuffer, start, b->rbuffer_size);
248 : :
249 : 136 : r = bus_start_running(b);
250 [ - + ]: 136 : if (r < 0)
251 : 0 : return r;
252 : :
253 : 136 : return 1;
254 : : }
255 : :
256 : 364 : static bool line_equals(const char *s, size_t m, const char *line) {
257 : : size_t l;
258 : :
259 : 364 : l = strlen(line);
260 [ + + ]: 364 : if (l != m)
261 : 244 : return false;
262 : :
263 : 120 : return memcmp(s, line, l) == 0;
264 : : }
265 : :
266 : 816 : static bool line_begins(const char *s, size_t m, const char *word) {
267 : : const char *p;
268 : :
269 : 816 : p = memory_startswith(s, m, word);
270 [ + + + + : 816 : return p && (p == (s + m) || *p == ' ');
+ - ]
271 : : }
272 : :
273 : 12 : static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
274 : 12 : _cleanup_free_ char *token = NULL;
275 : : size_t len;
276 : : int r;
277 : :
278 [ + + ]: 12 : if (!b->anonymous_auth)
279 : 4 : return 0;
280 : :
281 [ + + ]: 8 : if (l <= 0)
282 : 4 : return 1;
283 : :
284 [ - + ]: 4 : assert(p[0] == ' ');
285 : 4 : p++; l--;
286 : :
287 [ - + ]: 4 : if (l % 2 != 0)
288 : 0 : return 0;
289 : :
290 : 4 : r = unhexmem(p, l, (void **) &token, &len);
291 [ - + ]: 4 : if (r < 0)
292 : 0 : return 0;
293 : :
294 [ - + ]: 4 : if (memchr(token, 0, len))
295 : 0 : return 0;
296 : :
297 : 4 : return !!utf8_is_valid(token);
298 : : }
299 : :
300 : 72 : static int verify_external_token(sd_bus *b, const char *p, size_t l) {
301 : 72 : _cleanup_free_ char *token = NULL;
302 : : size_t len;
303 : : uid_t u;
304 : : int r;
305 : :
306 : : /* We don't do any real authentication here. Instead, we if
307 : : * the owner of this bus wanted authentication he should have
308 : : * checked SO_PEERCRED before even creating the bus object. */
309 : :
310 [ + + - + ]: 72 : if (!b->anonymous_auth && !b->ucred_valid)
311 : 0 : return 0;
312 : :
313 [ + - ]: 72 : if (l <= 0)
314 : 72 : return 1;
315 : :
316 [ # # ]: 0 : assert(p[0] == ' ');
317 : 0 : p++; l--;
318 : :
319 [ # # ]: 0 : if (l % 2 != 0)
320 : 0 : return 0;
321 : :
322 : 0 : r = unhexmem(p, l, (void**) &token, &len);
323 [ # # ]: 0 : if (r < 0)
324 : 0 : return 0;
325 : :
326 [ # # ]: 0 : if (memchr(token, 0, len))
327 : 0 : return 0;
328 : :
329 : 0 : r = parse_uid(token, &u);
330 [ # # ]: 0 : if (r < 0)
331 : 0 : return 0;
332 : :
333 : : /* We ignore the passed value if anonymous authentication is
334 : : * on anyway. */
335 [ # # # # ]: 0 : if (!b->anonymous_auth && u != b->ucred.uid)
336 : 0 : return 0;
337 : :
338 : 0 : return 1;
339 : : }
340 : :
341 : 128 : static int bus_socket_auth_write(sd_bus *b, const char *t) {
342 : : char *p;
343 : : size_t l;
344 : :
345 [ - + ]: 128 : assert(b);
346 [ - + ]: 128 : assert(t);
347 : :
348 : : /* We only make use of the first iovec */
349 [ + - - + ]: 128 : assert(IN_SET(b->auth_index, 0, 1));
350 : :
351 : 128 : l = strlen(t);
352 : 128 : p = malloc(b->auth_iovec[0].iov_len + l);
353 [ - + ]: 128 : if (!p)
354 : 0 : return -ENOMEM;
355 : :
356 : 128 : memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
357 : 128 : memcpy(p + b->auth_iovec[0].iov_len, t, l);
358 : :
359 : 128 : b->auth_iovec[0].iov_base = p;
360 : 128 : b->auth_iovec[0].iov_len += l;
361 : :
362 : 128 : free(b->auth_buffer);
363 : 128 : b->auth_buffer = p;
364 : 128 : b->auth_index = 0;
365 : 128 : return 0;
366 : : }
367 : :
368 : 40 : static int bus_socket_auth_write_ok(sd_bus *b) {
369 : : char t[3 + 32 + 2 + 1];
370 : :
371 [ - + ]: 40 : assert(b);
372 : :
373 [ - + ]: 40 : xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
374 : :
375 : 40 : return bus_socket_auth_write(b, t);
376 : : }
377 : :
378 : 145 : static int bus_socket_auth_verify_server(sd_bus *b) {
379 : : char *e;
380 : : const char *line;
381 : : size_t l;
382 : 145 : bool processed = false;
383 : : int r;
384 : :
385 [ - + ]: 145 : assert(b);
386 : :
387 [ + + ]: 145 : if (b->rbuffer_size < 1)
388 : 54 : return 0;
389 : :
390 : : /* First char must be a NUL byte */
391 [ - + ]: 91 : if (*(char*) b->rbuffer != 0)
392 : 0 : return -EIO;
393 : :
394 [ - + ]: 91 : if (b->rbuffer_size < 3)
395 : 0 : return 0;
396 : :
397 : : /* Begin with the first line */
398 [ + + ]: 91 : if (b->auth_rbegin <= 0)
399 : 44 : b->auth_rbegin = 1;
400 : :
401 : : for (;;) {
402 : : /* Check if line is complete */
403 : 347 : line = (char*) b->rbuffer + b->auth_rbegin;
404 : 219 : e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
405 [ + + ]: 219 : if (!e)
406 : 11 : return processed;
407 : :
408 : 208 : l = e - line;
409 : :
410 [ + + ]: 208 : if (line_begins(line, l, "AUTH ANONYMOUS")) {
411 : :
412 : 8 : r = verify_anonymous_token(b,
413 : : line + strlen("AUTH ANONYMOUS"),
414 : : l - strlen("AUTH ANONYMOUS"));
415 [ - + ]: 8 : if (r < 0)
416 : 0 : return r;
417 [ + + ]: 8 : if (r == 0)
418 : 4 : r = bus_socket_auth_write(b, "REJECTED\r\n");
419 : : else {
420 : 4 : b->auth = BUS_AUTH_ANONYMOUS;
421 [ + - ]: 4 : if (l <= strlen("AUTH ANONYMOUS"))
422 : 4 : r = bus_socket_auth_write(b, "DATA\r\n");
423 : : else
424 : 0 : r = bus_socket_auth_write_ok(b);
425 : : }
426 : :
427 [ + + ]: 200 : } else if (line_begins(line, l, "AUTH EXTERNAL")) {
428 : :
429 : 36 : r = verify_external_token(b,
430 : : line + strlen("AUTH EXTERNAL"),
431 : : l - strlen("AUTH EXTERNAL"));
432 [ - + ]: 36 : if (r < 0)
433 : 0 : return r;
434 [ - + ]: 36 : if (r == 0)
435 : 0 : r = bus_socket_auth_write(b, "REJECTED\r\n");
436 : : else {
437 : 36 : b->auth = BUS_AUTH_EXTERNAL;
438 [ + - ]: 36 : if (l <= strlen("AUTH EXTERNAL"))
439 : 36 : r = bus_socket_auth_write(b, "DATA\r\n");
440 : : else
441 : 0 : r = bus_socket_auth_write_ok(b);
442 : : }
443 : :
444 [ - + ]: 164 : } else if (line_begins(line, l, "AUTH"))
445 : 0 : r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
446 [ + - - + ]: 328 : else if (line_equals(line, l, "CANCEL") ||
447 : 164 : line_begins(line, l, "ERROR")) {
448 : :
449 : 0 : b->auth = _BUS_AUTH_INVALID;
450 : 0 : r = bus_socket_auth_write(b, "REJECTED\r\n");
451 : :
452 [ + + ]: 164 : } else if (line_equals(line, l, "BEGIN")) {
453 : :
454 [ + + ]: 84 : if (b->auth == _BUS_AUTH_INVALID)
455 : 4 : r = bus_socket_auth_write(b, "ERROR\r\n");
456 : : else {
457 : : /* We can't leave from the auth phase
458 : : * before we haven't written
459 : : * everything queued, so let's check
460 : : * that */
461 : :
462 [ + + ]: 80 : if (bus_socket_auth_needs_write(b))
463 : 40 : return 1;
464 : :
465 : 40 : b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
466 : 40 : memmove(b->rbuffer, e + 2, b->rbuffer_size);
467 : 40 : return bus_start_running(b);
468 : : }
469 : :
470 [ + + ]: 80 : } else if (line_begins(line, l, "DATA")) {
471 : :
472 [ + + ]: 44 : if (b->auth == _BUS_AUTH_INVALID)
473 : 4 : r = bus_socket_auth_write(b, "ERROR\r\n");
474 : : else {
475 [ + + ]: 40 : if (b->auth == BUS_AUTH_ANONYMOUS)
476 : 4 : r = verify_anonymous_token(b, line + 4, l - 4);
477 : : else
478 : 36 : r = verify_external_token(b, line + 4, l - 4);
479 : :
480 [ - + ]: 40 : if (r < 0)
481 : 0 : return r;
482 [ - + ]: 40 : if (r == 0) {
483 : 0 : b->auth = _BUS_AUTH_INVALID;
484 : 0 : r = bus_socket_auth_write(b, "REJECTED\r\n");
485 : : } else
486 : 40 : r = bus_socket_auth_write_ok(b);
487 : : }
488 [ + - ]: 36 : } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
489 [ + + + + ]: 36 : if (b->auth == _BUS_AUTH_INVALID || !b->accept_fd)
490 : 8 : r = bus_socket_auth_write(b, "ERROR\r\n");
491 : : else {
492 : 28 : b->can_fds = true;
493 : 28 : r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n");
494 : : }
495 : : } else
496 : 0 : r = bus_socket_auth_write(b, "ERROR\r\n");
497 : :
498 [ - + ]: 128 : if (r < 0)
499 : 0 : return r;
500 : :
501 : 128 : b->auth_rbegin = e + 2 - (char*) b->rbuffer;
502 : :
503 : 128 : processed = true;
504 : : }
505 : : }
506 : :
507 : 487 : static int bus_socket_auth_verify(sd_bus *b) {
508 [ - + ]: 487 : assert(b);
509 : :
510 [ + + ]: 487 : if (b->is_server)
511 : 145 : return bus_socket_auth_verify_server(b);
512 : : else
513 : 342 : return bus_socket_auth_verify_client(b);
514 : : }
515 : :
516 : 303 : static int bus_socket_read_auth(sd_bus *b) {
517 : : struct msghdr mh;
518 : 303 : struct iovec iov = {};
519 : : size_t n;
520 : : ssize_t k;
521 : : int r;
522 : : void *p;
523 : : union {
524 : : struct cmsghdr cmsghdr;
525 : : uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
526 : : } control;
527 : 303 : bool handle_cmsg = false;
528 : :
529 [ - + ]: 303 : assert(b);
530 [ - + ]: 303 : assert(b->state == BUS_AUTHENTICATING);
531 : :
532 : 303 : r = bus_socket_auth_verify(b);
533 [ + + ]: 303 : if (r != 0)
534 : 40 : return r;
535 : :
536 : 263 : n = MAX(256u, b->rbuffer_size * 2);
537 : :
538 [ - + ]: 263 : if (n > BUS_AUTH_SIZE_MAX)
539 : 0 : n = BUS_AUTH_SIZE_MAX;
540 : :
541 [ - + ]: 263 : if (b->rbuffer_size >= n)
542 : 0 : return -ENOBUFS;
543 : :
544 : 263 : p = realloc(b->rbuffer, n);
545 [ - + ]: 263 : if (!p)
546 : 0 : return -ENOMEM;
547 : :
548 : 263 : b->rbuffer = p;
549 : :
550 : 263 : iov = IOVEC_MAKE((uint8_t *)b->rbuffer + b->rbuffer_size, n - b->rbuffer_size);
551 : :
552 [ - + ]: 263 : if (b->prefer_readv)
553 : 0 : k = readv(b->input_fd, &iov, 1);
554 : : else {
555 [ + - ]: 263 : zero(mh);
556 : 263 : mh.msg_iov = &iov;
557 : 263 : mh.msg_iovlen = 1;
558 : 263 : mh.msg_control = &control;
559 : 263 : mh.msg_controllen = sizeof(control);
560 : :
561 : 263 : k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
562 [ + + - + ]: 263 : if (k < 0 && errno == ENOTSOCK) {
563 : 0 : b->prefer_readv = true;
564 : 0 : k = readv(b->input_fd, &iov, 1);
565 : : } else
566 : 263 : handle_cmsg = true;
567 : : }
568 [ + + ]: 263 : if (k < 0)
569 [ - + ]: 75 : return errno == EAGAIN ? 0 : -errno;
570 [ + + ]: 188 : if (k == 0)
571 : 4 : return -ECONNRESET;
572 : :
573 : 184 : b->rbuffer_size += k;
574 : :
575 [ + - ]: 184 : if (handle_cmsg) {
576 : : struct cmsghdr *cmsg;
577 : :
578 [ - + - + ]: 184 : CMSG_FOREACH(cmsg, &mh)
579 [ # # ]: 0 : if (cmsg->cmsg_level == SOL_SOCKET &&
580 [ # # ]: 0 : cmsg->cmsg_type == SCM_RIGHTS) {
581 : : int j;
582 : :
583 : : /* Whut? We received fds during the auth
584 : : * protocol? Somebody is playing games with
585 : : * us. Close them all, and fail */
586 : 0 : j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
587 : 0 : close_many((int*) CMSG_DATA(cmsg), j);
588 : 0 : return -EIO;
589 : : } else
590 [ # # ]: 0 : log_debug("Got unexpected auxiliary data with level=%d and type=%d",
591 : : cmsg->cmsg_level, cmsg->cmsg_type);
592 : : }
593 : :
594 : 184 : r = bus_socket_auth_verify(b);
595 [ + - ]: 184 : if (r != 0)
596 : 184 : return r;
597 : :
598 : 0 : return 1;
599 : : }
600 : :
601 : 316 : void bus_socket_setup(sd_bus *b) {
602 [ - + ]: 316 : assert(b);
603 : :
604 : : /* Increase the buffers to 8 MB */
605 : 316 : (void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
606 : 316 : (void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
607 : :
608 : 316 : b->message_version = 1;
609 : 316 : b->message_endian = 0;
610 : 316 : }
611 : :
612 : 204 : static void bus_get_peercred(sd_bus *b) {
613 : : int r;
614 : :
615 [ - + ]: 204 : assert(b);
616 [ - + ]: 204 : assert(!b->ucred_valid);
617 [ - + ]: 204 : assert(!b->label);
618 [ - + ]: 204 : assert(b->n_groups == (size_t) -1);
619 : :
620 : : /* Get the peer for socketpair() sockets */
621 : 204 : b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
622 : :
623 : : /* Get the SELinux context of the peer */
624 : 204 : r = getpeersec(b->input_fd, &b->label);
625 [ - + # # : 204 : if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
# # ]
626 [ # # ]: 0 : log_debug_errno(r, "Failed to determine peer security context: %m");
627 : :
628 : : /* Get the list of auxiliary groups of the peer */
629 : 204 : r = getpeergroups(b->input_fd, &b->groups);
630 [ + - ]: 204 : if (r >= 0)
631 : 204 : b->n_groups = (size_t) r;
632 [ # # # # ]: 0 : else if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
633 [ # # ]: 0 : log_debug_errno(r, "Failed to determine peer's group list: %m");
634 : 204 : }
635 : :
636 : 160 : static int bus_socket_start_auth_client(sd_bus *b) {
637 : : static const char sasl_auth_anonymous[] = {
638 : : /*
639 : : * We use an arbitrary trace-string for the ANONYMOUS authentication. It can be used by the
640 : : * message broker to aid debugging of clients. We fully anonymize the connection and use a
641 : : * static default.
642 : : */
643 : : "\0AUTH ANONYMOUS\r\n"
644 : : /* HEX a n o n y m o u s */
645 : : "DATA 616e6f6e796d6f7573\r\n"
646 : : };
647 : : static const char sasl_auth_external[] = {
648 : : "\0AUTH EXTERNAL\r\n"
649 : : "DATA\r\n"
650 : : };
651 : : static const char sasl_negotiate_unix_fd[] = {
652 : : "NEGOTIATE_UNIX_FD\r\n"
653 : : };
654 : : static const char sasl_begin[] = {
655 : : "BEGIN\r\n"
656 : : };
657 : 160 : size_t i = 0;
658 : :
659 [ - + ]: 160 : assert(b);
660 : :
661 [ + + ]: 160 : if (b->anonymous_auth)
662 : 8 : b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_anonymous, sizeof(sasl_auth_anonymous) - 1);
663 : : else
664 : 152 : b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_external, sizeof(sasl_auth_external) - 1);
665 : :
666 [ + + ]: 160 : if (b->accept_fd)
667 : 152 : b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_negotiate_unix_fd);
668 : :
669 : 160 : b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_begin);
670 : :
671 : 160 : return bus_socket_write_auth(b);
672 : : }
673 : :
674 : 204 : int bus_socket_start_auth(sd_bus *b) {
675 [ - + ]: 204 : assert(b);
676 : :
677 : 204 : bus_get_peercred(b);
678 : :
679 : 204 : bus_set_state(b, BUS_AUTHENTICATING);
680 : 204 : b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT;
681 : :
682 [ - + ]: 204 : if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
683 : 0 : b->accept_fd = false;
684 : :
685 [ - + ]: 204 : if (b->output_fd != b->input_fd)
686 [ # # ]: 0 : if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
687 : 0 : b->accept_fd = false;
688 : :
689 [ + + ]: 204 : if (b->is_server)
690 : 44 : return bus_socket_read_auth(b);
691 : : else
692 : 160 : return bus_socket_start_auth_client(b);
693 : : }
694 : :
695 : 56 : static int bus_socket_inotify_setup(sd_bus *b) {
696 : 56 : _cleanup_free_ int *new_watches = NULL;
697 : 56 : _cleanup_free_ char *absolute = NULL;
698 : 56 : size_t n_allocated = 0, n = 0, done = 0, i;
699 : 56 : unsigned max_follow = 32;
700 : : const char *p;
701 : : int wd, r;
702 : :
703 [ - + ]: 56 : assert(b);
704 [ - + ]: 56 : assert(b->watch_bind);
705 [ - + ]: 56 : assert(b->sockaddr.sa.sa_family == AF_UNIX);
706 [ - + ]: 56 : assert(b->sockaddr.un.sun_path[0] != 0);
707 : :
708 : : /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket
709 : : * appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes
710 : : * to all prefix components of the path, and every time we get an event for that we try to reconnect again,
711 : : * without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe
712 : : * to all relevant changes of anything in the path, so that our watches include any possibly newly created path
713 : : * components. */
714 : :
715 [ + + ]: 56 : if (b->inotify_fd < 0) {
716 : 8 : b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
717 [ - + ]: 8 : if (b->inotify_fd < 0)
718 : 0 : return -errno;
719 : :
720 : 8 : b->inotify_fd = fd_move_above_stdio(b->inotify_fd);
721 : : }
722 : :
723 : : /* Make sure the path is NUL terminated */
724 : 56 : p = strndupa(b->sockaddr.un.sun_path, sizeof(b->sockaddr.un.sun_path));
725 : :
726 : : /* Make sure the path is absolute */
727 : 56 : r = path_make_absolute_cwd(p, &absolute);
728 [ - + ]: 56 : if (r < 0)
729 : 0 : goto fail;
730 : :
731 : : /* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory
732 : : * that exists we want to know when files are created or moved into it. For all parents of it we just care if
733 : : * they are removed or renamed. */
734 : :
735 [ - + ]: 56 : if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
736 : 0 : r = -ENOMEM;
737 : 0 : goto fail;
738 : : }
739 : :
740 : : /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and
741 : : * always exists */
742 : 56 : wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
743 [ - + ]: 56 : if (wd < 0) {
744 [ # # ]: 0 : r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
745 : 0 : goto fail;
746 : : } else
747 : 56 : new_watches[n++] = wd;
748 : :
749 : 456 : for (;;) {
750 [ + + - + : 1456 : _cleanup_free_ char *component = NULL, *prefix = NULL, *destination = NULL;
- + + - +
- + + - +
- ]
751 : : size_t n_slashes, n_component;
752 : 512 : char *c = NULL;
753 : :
754 : 512 : n_slashes = strspn(absolute + done, "/");
755 : 512 : n_component = n_slashes + strcspn(absolute + done + n_slashes, "/");
756 : :
757 [ + + ]: 512 : if (n_component == 0) /* The end */
758 : 8 : break;
759 : :
760 : 504 : component = strndup(absolute + done, n_component);
761 [ - + ]: 504 : if (!component) {
762 : 0 : r = -ENOMEM;
763 : 0 : goto fail;
764 : : }
765 : :
766 : : /* A trailing slash? That's a directory, and not a socket then */
767 [ - + ]: 504 : if (path_equal(component, "/")) {
768 : 0 : r = -EISDIR;
769 : 0 : goto fail;
770 : : }
771 : :
772 : : /* A single dot? Let's eat this up */
773 [ - + ]: 504 : if (path_equal(component, "/.")) {
774 : 0 : done += n_component;
775 : 0 : continue;
776 : : }
777 : :
778 : 504 : prefix = strndup(absolute, done + n_component);
779 [ - + ]: 504 : if (!prefix) {
780 : 0 : r = -ENOMEM;
781 : 0 : goto fail;
782 : : }
783 : :
784 [ - + ]: 504 : if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
785 : 0 : r = -ENOMEM;
786 : 0 : goto fail;
787 : : }
788 : :
789 : 504 : wd = inotify_add_watch(b->inotify_fd, prefix, IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO|IN_DONT_FOLLOW);
790 [ + - ]: 504 : log_debug("Added inotify watch for %s on bus %s: %i", prefix, strna(b->description), wd);
791 : :
792 [ + + ]: 504 : if (wd < 0) {
793 [ + - + - ]: 48 : if (IN_SET(errno, ENOENT, ELOOP))
794 : 48 : break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */
795 : :
796 [ # # ]: 0 : r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", empty_to_root(prefix));
797 : 0 : goto fail;
798 : : } else
799 : 456 : new_watches[n++] = wd;
800 : :
801 : : /* Check if this is possibly a symlink. If so, let's follow it and watch it too. */
802 : 456 : r = readlink_malloc(prefix, &destination);
803 [ + + ]: 456 : if (r == -EINVAL) { /* not a symlink */
804 : 416 : done += n_component;
805 : 416 : continue;
806 : : }
807 [ - + ]: 40 : if (r < 0)
808 : 0 : goto fail;
809 : :
810 [ - + ]: 40 : if (isempty(destination)) { /* Empty symlink target? Yuck! */
811 : 0 : r = -EINVAL;
812 : 0 : goto fail;
813 : : }
814 : :
815 [ - + ]: 40 : if (max_follow <= 0) { /* Let's make sure we don't follow symlinks forever */
816 : 0 : r = -ELOOP;
817 : 0 : goto fail;
818 : : }
819 : :
820 [ + + ]: 40 : if (path_is_absolute(destination)) {
821 : : /* For absolute symlinks we build the new path and start anew */
822 : 24 : c = strjoin(destination, absolute + done + n_component);
823 : 24 : done = 0;
824 : : } else {
825 [ + - ]: 16 : _cleanup_free_ char *t = NULL;
826 : :
827 : : /* For relative symlinks we replace the last component, and try again */
828 : 16 : t = strndup(absolute, done);
829 [ - + ]: 16 : if (!t)
830 : 0 : return -ENOMEM;
831 : :
832 : 16 : c = strjoin(t, "/", destination, absolute + done + n_component);
833 : : }
834 [ - + ]: 40 : if (!c) {
835 : 0 : r = -ENOMEM;
836 : 0 : goto fail;
837 : : }
838 : :
839 : 40 : free(absolute);
840 : 40 : absolute = c;
841 : :
842 : 40 : max_follow--;
843 : : }
844 : :
845 : : /* And now, let's remove all watches from the previous iteration we don't need anymore */
846 [ + + ]: 448 : for (i = 0; i < b->n_inotify_watches; i++) {
847 : 392 : bool found = false;
848 : : size_t j;
849 : :
850 [ + + ]: 1624 : for (j = 0; j < n; j++)
851 [ + + ]: 1616 : if (new_watches[j] == b->inotify_watches[i]) {
852 : 384 : found = true;
853 : 384 : break;
854 : : }
855 : :
856 [ + + ]: 392 : if (found)
857 : 384 : continue;
858 : :
859 : 8 : (void) inotify_rm_watch(b->inotify_fd, b->inotify_watches[i]);
860 : : }
861 : :
862 : 56 : free_and_replace(b->inotify_watches, new_watches);
863 : 56 : b->n_inotify_watches = n;
864 : :
865 : 56 : return 0;
866 : :
867 : 0 : fail:
868 : 0 : bus_close_inotify_fd(b);
869 : 0 : return r;
870 : : }
871 : :
872 : 184 : int bus_socket_connect(sd_bus *b) {
873 : 184 : bool inotify_done = false;
874 : : int r;
875 : :
876 [ - + ]: 184 : assert(b);
877 : :
878 : : for (;;) {
879 [ - + ]: 240 : assert(b->input_fd < 0);
880 [ - + ]: 240 : assert(b->output_fd < 0);
881 [ - + ]: 240 : assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
882 : :
883 : 240 : b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
884 [ - + ]: 240 : if (b->input_fd < 0)
885 : 0 : return -errno;
886 : :
887 : 240 : b->input_fd = fd_move_above_stdio(b->input_fd);
888 : :
889 : 240 : b->output_fd = b->input_fd;
890 : 240 : bus_socket_setup(b);
891 : :
892 [ + + ]: 240 : if (connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size) < 0) {
893 [ - + ]: 112 : if (errno == EINPROGRESS) {
894 : :
895 : : /* If we have any inotify watches open, close them now, we don't need them anymore, as
896 : : * we have successfully initiated a connection */
897 : 0 : bus_close_inotify_fd(b);
898 : :
899 : : /* Note that very likely we are already in BUS_OPENING state here, as we enter it when
900 : : * we start parsing the address string. The only reason we set the state explicitly
901 : : * here, is to undo BUS_WATCH_BIND, in case we did the inotify magic. */
902 : 0 : bus_set_state(b, BUS_OPENING);
903 : 0 : return 1;
904 : : }
905 : :
906 [ + - + - : 112 : if (IN_SET(errno, ENOENT, ECONNREFUSED) && /* ENOENT → unix socket doesn't exist at all; ECONNREFUSED → unix socket stale */
+ - ]
907 : 112 : b->watch_bind &&
908 [ + - ]: 112 : b->sockaddr.sa.sa_family == AF_UNIX &&
909 [ + - ]: 112 : b->sockaddr.un.sun_path[0] != 0) {
910 : :
911 : : /* This connection attempt failed, let's release the socket for now, and start with a
912 : : * fresh one when reconnecting. */
913 : 112 : bus_close_io_fds(b);
914 : :
915 [ + + ]: 112 : if (inotify_done) {
916 : : /* inotify set up already, don't do it again, just return now, and remember
917 : : * that we are waiting for inotify events now. */
918 : 56 : bus_set_state(b, BUS_WATCH_BIND);
919 : 56 : return 1;
920 : : }
921 : :
922 : : /* This is a file system socket, and the inotify logic is enabled. Let's create the necessary inotify fd. */
923 : 56 : r = bus_socket_inotify_setup(b);
924 [ - + ]: 56 : if (r < 0)
925 : 0 : return r;
926 : :
927 : : /* Let's now try to connect a second time, because in theory there's otherwise a race
928 : : * here: the socket might have been created in the time between our first connect() and
929 : : * the time we set up the inotify logic. But let's remember that we set up inotify now,
930 : : * so that we don't do the connect() more than twice. */
931 : 56 : inotify_done = true;
932 : :
933 : : } else
934 : 0 : return -errno;
935 : : } else
936 : 128 : break;
937 : : }
938 : :
939 : : /* Yay, established, we don't need no inotify anymore! */
940 : 128 : bus_close_inotify_fd(b);
941 : :
942 : 128 : return bus_socket_start_auth(b);
943 : : }
944 : :
945 : 0 : int bus_socket_exec(sd_bus *b) {
946 : : int s[2], r;
947 : :
948 [ # # ]: 0 : assert(b);
949 [ # # ]: 0 : assert(b->input_fd < 0);
950 [ # # ]: 0 : assert(b->output_fd < 0);
951 [ # # ]: 0 : assert(b->exec_path);
952 [ # # ]: 0 : assert(b->busexec_pid == 0);
953 : :
954 : 0 : r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
955 [ # # ]: 0 : if (r < 0)
956 : 0 : return -errno;
957 : :
958 : 0 : r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &b->busexec_pid);
959 [ # # ]: 0 : if (r < 0) {
960 : 0 : safe_close_pair(s);
961 : 0 : return r;
962 : : }
963 [ # # ]: 0 : if (r == 0) {
964 : : /* Child */
965 : :
966 [ # # ]: 0 : if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0)
967 : 0 : _exit(EXIT_FAILURE);
968 : :
969 : 0 : (void) rlimit_nofile_safe();
970 : :
971 [ # # ]: 0 : if (b->exec_argv)
972 : 0 : execvp(b->exec_path, b->exec_argv);
973 : : else {
974 : 0 : const char *argv[] = { b->exec_path, NULL };
975 : 0 : execvp(b->exec_path, (char**) argv);
976 : : }
977 : :
978 : 0 : _exit(EXIT_FAILURE);
979 : : }
980 : :
981 : 0 : safe_close(s[1]);
982 : 0 : b->output_fd = b->input_fd = fd_move_above_stdio(s[0]);
983 : :
984 : 0 : bus_socket_setup(b);
985 : :
986 : 0 : return bus_socket_start_auth(b);
987 : : }
988 : :
989 : 76 : int bus_socket_take_fd(sd_bus *b) {
990 [ - + ]: 76 : assert(b);
991 : :
992 : 76 : bus_socket_setup(b);
993 : :
994 : 76 : return bus_socket_start_auth(b);
995 : : }
996 : :
997 : 536 : int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
998 : : struct iovec *iov;
999 : : ssize_t k;
1000 : : size_t n;
1001 : : unsigned j;
1002 : : int r;
1003 : :
1004 [ - + ]: 536 : assert(bus);
1005 [ - + ]: 536 : assert(m);
1006 [ - + ]: 536 : assert(idx);
1007 [ + - - + ]: 536 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
1008 : :
1009 [ - + ]: 536 : if (*idx >= BUS_MESSAGE_SIZE(m))
1010 : 0 : return 0;
1011 : :
1012 : 536 : r = bus_message_setup_iovec(m);
1013 [ - + ]: 536 : if (r < 0)
1014 : 0 : return r;
1015 : :
1016 : 536 : n = m->n_iovec * sizeof(struct iovec);
1017 [ - + - + ]: 536 : iov = newa(struct iovec, n);
1018 : 536 : memcpy_safe(iov, m->iovec, n);
1019 : :
1020 : 536 : j = 0;
1021 : 536 : iovec_advance(iov, &j, *idx);
1022 : :
1023 [ - + ]: 536 : if (bus->prefer_writev)
1024 : 0 : k = writev(bus->output_fd, iov, m->n_iovec);
1025 : : else {
1026 : 1072 : struct msghdr mh = {
1027 : : .msg_iov = iov,
1028 : 536 : .msg_iovlen = m->n_iovec,
1029 : : };
1030 : :
1031 [ + + + - ]: 536 : if (m->n_fds > 0 && *idx == 0) {
1032 : : struct cmsghdr *control;
1033 : :
1034 : 4 : mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
1035 : 4 : mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
1036 : 4 : control->cmsg_level = SOL_SOCKET;
1037 : 4 : control->cmsg_type = SCM_RIGHTS;
1038 : 4 : memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
1039 : : }
1040 : :
1041 : 536 : k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
1042 [ - + # # ]: 536 : if (k < 0 && errno == ENOTSOCK) {
1043 : 0 : bus->prefer_writev = true;
1044 : 0 : k = writev(bus->output_fd, iov, m->n_iovec);
1045 : : }
1046 : : }
1047 : :
1048 [ - + ]: 536 : if (k < 0)
1049 [ # # ]: 0 : return errno == EAGAIN ? 0 : -errno;
1050 : :
1051 : 536 : *idx += (size_t) k;
1052 : 536 : return 1;
1053 : : }
1054 : :
1055 : 2313 : static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
1056 : : uint32_t a, b;
1057 : : uint8_t e;
1058 : : uint64_t sum;
1059 : :
1060 [ - + ]: 2313 : assert(bus);
1061 [ - + ]: 2313 : assert(need);
1062 [ + - - + ]: 2313 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
1063 : :
1064 [ + + ]: 2313 : if (bus->rbuffer_size < sizeof(struct bus_header)) {
1065 : 895 : *need = sizeof(struct bus_header) + 8;
1066 : :
1067 : : /* Minimum message size:
1068 : : *
1069 : : * Header +
1070 : : *
1071 : : * Method Call: +2 string headers
1072 : : * Signal: +3 string headers
1073 : : * Method Error: +1 string headers
1074 : : * +1 uint32 headers
1075 : : * Method Reply: +1 uint32 headers
1076 : : *
1077 : : * A string header is at least 9 bytes
1078 : : * A uint32 header is at least 8 bytes
1079 : : *
1080 : : * Hence the minimum message size of a valid message
1081 : : * is header + 8 bytes */
1082 : :
1083 : 895 : return 0;
1084 : : }
1085 : :
1086 : 1418 : a = ((const uint32_t*) bus->rbuffer)[1];
1087 : 1418 : b = ((const uint32_t*) bus->rbuffer)[3];
1088 : :
1089 : 1418 : e = ((const uint8_t*) bus->rbuffer)[0];
1090 [ + - ]: 1418 : if (e == BUS_LITTLE_ENDIAN) {
1091 : 1418 : a = le32toh(a);
1092 : 1418 : b = le32toh(b);
1093 [ # # ]: 0 : } else if (e == BUS_BIG_ENDIAN) {
1094 : 0 : a = be32toh(a);
1095 : 0 : b = be32toh(b);
1096 : : } else
1097 : 0 : return -EBADMSG;
1098 : :
1099 : 1418 : sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
1100 [ - + ]: 1418 : if (sum >= BUS_MESSAGE_SIZE_MAX)
1101 : 0 : return -ENOBUFS;
1102 : :
1103 : 1418 : *need = (size_t) sum;
1104 : 1418 : return 0;
1105 : : }
1106 : :
1107 : 526 : static int bus_socket_make_message(sd_bus *bus, size_t size) {
1108 : 526 : sd_bus_message *t = NULL;
1109 : : void *b;
1110 : : int r;
1111 : :
1112 [ - + ]: 526 : assert(bus);
1113 [ - + ]: 526 : assert(bus->rbuffer_size >= size);
1114 [ + - - + ]: 526 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
1115 : :
1116 : 526 : r = bus_rqueue_make_room(bus);
1117 [ - + ]: 526 : if (r < 0)
1118 : 0 : return r;
1119 : :
1120 [ - + ]: 526 : if (bus->rbuffer_size > size) {
1121 : 0 : b = memdup((const uint8_t*) bus->rbuffer + size,
1122 : 0 : bus->rbuffer_size - size);
1123 [ # # ]: 0 : if (!b)
1124 : 0 : return -ENOMEM;
1125 : : } else
1126 : 526 : b = NULL;
1127 : :
1128 : 526 : r = bus_message_from_malloc(bus,
1129 : : bus->rbuffer, size,
1130 : : bus->fds, bus->n_fds,
1131 : : NULL,
1132 : : &t);
1133 [ - + ]: 526 : if (r == -EBADMSG) {
1134 [ # # ]: 0 : log_debug_errno(r, "Received invalid message from connection %s, dropping.", strna(bus->description));
1135 : 0 : free(bus->rbuffer); /* We want to drop current rbuffer and proceed with whatever remains in b */
1136 [ - + ]: 526 : } else if (r < 0) {
1137 : 0 : free(b);
1138 : 0 : return r;
1139 : : }
1140 : :
1141 : : /* rbuffer ownership was either transferred to t, or we got EBADMSG and dropped it. */
1142 : 526 : bus->rbuffer = b;
1143 : 526 : bus->rbuffer_size -= size;
1144 : :
1145 : 526 : bus->fds = NULL;
1146 : 526 : bus->n_fds = 0;
1147 : :
1148 [ + - ]: 526 : if (t) {
1149 : 526 : t->read_counter = ++bus->read_counter;
1150 : 526 : bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus);
1151 : 526 : sd_bus_message_unref(t);
1152 : : }
1153 : :
1154 : 526 : return 1;
1155 : : }
1156 : :
1157 : 1341 : int bus_socket_read_message(sd_bus *bus) {
1158 : : struct msghdr mh;
1159 : 1341 : struct iovec iov = {};
1160 : : ssize_t k;
1161 : : size_t need;
1162 : : int r;
1163 : : void *b;
1164 : : union {
1165 : : struct cmsghdr cmsghdr;
1166 : : uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
1167 : : } control;
1168 : 1341 : bool handle_cmsg = false;
1169 : :
1170 [ - + ]: 1341 : assert(bus);
1171 [ + - - + ]: 1341 : assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO));
1172 : :
1173 : 1341 : r = bus_socket_read_message_need(bus, &need);
1174 [ - + ]: 1341 : if (r < 0)
1175 : 0 : return r;
1176 : :
1177 [ - + ]: 1341 : if (bus->rbuffer_size >= need)
1178 : 0 : return bus_socket_make_message(bus, need);
1179 : :
1180 : 1341 : b = realloc(bus->rbuffer, need);
1181 [ - + ]: 1341 : if (!b)
1182 : 0 : return -ENOMEM;
1183 : :
1184 : 1341 : bus->rbuffer = b;
1185 : :
1186 : 1341 : iov = IOVEC_MAKE((uint8_t *)bus->rbuffer + bus->rbuffer_size, need - bus->rbuffer_size);
1187 : :
1188 [ - + ]: 1341 : if (bus->prefer_readv)
1189 : 0 : k = readv(bus->input_fd, &iov, 1);
1190 : : else {
1191 [ + - ]: 1341 : zero(mh);
1192 : 1341 : mh.msg_iov = &iov;
1193 : 1341 : mh.msg_iovlen = 1;
1194 : 1341 : mh.msg_control = &control;
1195 : 1341 : mh.msg_controllen = sizeof(control);
1196 : :
1197 : 1341 : k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
1198 [ + + - + ]: 1341 : if (k < 0 && errno == ENOTSOCK) {
1199 : 0 : bus->prefer_readv = true;
1200 : 0 : k = readv(bus->input_fd, &iov, 1);
1201 : : } else
1202 : 1341 : handle_cmsg = true;
1203 : : }
1204 [ + + ]: 1341 : if (k < 0)
1205 [ - + ]: 365 : return errno == EAGAIN ? 0 : -errno;
1206 [ + + ]: 976 : if (k == 0)
1207 : 4 : return -ECONNRESET;
1208 : :
1209 : 972 : bus->rbuffer_size += k;
1210 : :
1211 [ + - ]: 972 : if (handle_cmsg) {
1212 : : struct cmsghdr *cmsg;
1213 : :
1214 [ + + + + ]: 976 : CMSG_FOREACH(cmsg, &mh)
1215 [ + - ]: 4 : if (cmsg->cmsg_level == SOL_SOCKET &&
1216 [ + - ]: 4 : cmsg->cmsg_type == SCM_RIGHTS) {
1217 : : int n, *f, i;
1218 : :
1219 : 4 : n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
1220 : :
1221 [ - + ]: 4 : if (!bus->can_fds) {
1222 : : /* Whut? We received fds but this
1223 : : * isn't actually enabled? Close them,
1224 : : * and fail */
1225 : :
1226 : 0 : close_many((int*) CMSG_DATA(cmsg), n);
1227 : 0 : return -EIO;
1228 : : }
1229 : :
1230 : 4 : f = reallocarray(bus->fds, bus->n_fds + n, sizeof(int));
1231 [ - + ]: 4 : if (!f) {
1232 : 0 : close_many((int*) CMSG_DATA(cmsg), n);
1233 : 0 : return -ENOMEM;
1234 : : }
1235 : :
1236 [ + + ]: 8 : for (i = 0; i < n; i++)
1237 : 4 : f[bus->n_fds++] = fd_move_above_stdio(((int*) CMSG_DATA(cmsg))[i]);
1238 : 4 : bus->fds = f;
1239 : : } else
1240 [ # # ]: 0 : log_debug("Got unexpected auxiliary data with level=%d and type=%d",
1241 : : cmsg->cmsg_level, cmsg->cmsg_type);
1242 : : }
1243 : :
1244 : 972 : r = bus_socket_read_message_need(bus, &need);
1245 [ - + ]: 972 : if (r < 0)
1246 : 0 : return r;
1247 : :
1248 [ + + ]: 972 : if (bus->rbuffer_size >= need)
1249 : 526 : return bus_socket_make_message(bus, need);
1250 : :
1251 : 446 : return 1;
1252 : : }
1253 : :
1254 : 0 : int bus_socket_process_opening(sd_bus *b) {
1255 : 0 : int error = 0;
1256 : 0 : socklen_t slen = sizeof(error);
1257 : 0 : struct pollfd p = {
1258 : 0 : .fd = b->output_fd,
1259 : : .events = POLLOUT,
1260 : : };
1261 : : int r;
1262 : :
1263 [ # # ]: 0 : assert(b->state == BUS_OPENING);
1264 : :
1265 : 0 : r = poll(&p, 1, 0);
1266 [ # # ]: 0 : if (r < 0)
1267 : 0 : return -errno;
1268 : :
1269 [ # # ]: 0 : if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
1270 : 0 : return 0;
1271 : :
1272 : 0 : r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
1273 [ # # ]: 0 : if (r < 0)
1274 : 0 : b->last_connect_error = errno;
1275 [ # # ]: 0 : else if (error != 0)
1276 : 0 : b->last_connect_error = error;
1277 [ # # ]: 0 : else if (p.revents & (POLLERR|POLLHUP))
1278 : 0 : b->last_connect_error = ECONNREFUSED;
1279 : : else
1280 : 0 : return bus_socket_start_auth(b);
1281 : :
1282 : 0 : return bus_next_address(b);
1283 : : }
1284 : :
1285 : 303 : int bus_socket_process_authenticating(sd_bus *b) {
1286 : : int r;
1287 : :
1288 [ - + ]: 303 : assert(b);
1289 [ - + ]: 303 : assert(b->state == BUS_AUTHENTICATING);
1290 : :
1291 [ - + ]: 303 : if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
1292 : 0 : return -ETIMEDOUT;
1293 : :
1294 : 303 : r = bus_socket_write_auth(b);
1295 [ + + ]: 303 : if (r != 0)
1296 : 44 : return r;
1297 : :
1298 : 259 : return bus_socket_read_auth(b);
1299 : : }
1300 : :
1301 : 84 : int bus_socket_process_watch_bind(sd_bus *b) {
1302 : : int r, q;
1303 : :
1304 [ - + ]: 84 : assert(b);
1305 [ - + ]: 84 : assert(b->state == BUS_WATCH_BIND);
1306 [ - + ]: 84 : assert(b->inotify_fd >= 0);
1307 : :
1308 : 84 : r = flush_fd(b->inotify_fd);
1309 [ + + ]: 84 : if (r <= 0)
1310 : 28 : return r;
1311 : :
1312 [ + - ]: 56 : log_debug("Got inotify event on bus %s.", strna(b->description));
1313 : :
1314 : : /* We flushed events out of the inotify fd. In that case, maybe the socket is valid now? Let's try to connect
1315 : : * to it again */
1316 : :
1317 : 56 : r = bus_socket_connect(b);
1318 [ - + ]: 56 : if (r < 0)
1319 : 0 : return r;
1320 : :
1321 : 56 : q = bus_attach_io_events(b);
1322 [ - + ]: 56 : if (q < 0)
1323 : 0 : return q;
1324 : :
1325 : 56 : q = bus_attach_inotify_event(b);
1326 [ - + ]: 56 : if (q < 0)
1327 : 0 : return q;
1328 : :
1329 : 56 : return r;
1330 : : }
|