]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-daemon/sd-daemon.c
Merge pull request #7816 from poettering/chase-pid
[thirdparty/systemd.git] / src / libsystemd / sd-daemon / sd-daemon.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <limits.h>
23 #include <mqueue.h>
24 #include <netinet/in.h>
25 #include <stdarg.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/socket.h>
31 #include <sys/stat.h>
32 #include <sys/un.h>
33 #include <unistd.h>
34
35 #include "sd-daemon.h"
36
37 #include "alloc-util.h"
38 #include "fd-util.h"
39 #include "fs-util.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "process-util.h"
43 #include "socket-util.h"
44 #include "strv.h"
45 #include "util.h"
46
47 #define SNDBUF_SIZE (8*1024*1024)
48
49 static void unsetenv_all(bool unset_environment) {
50
51 if (!unset_environment)
52 return;
53
54 unsetenv("LISTEN_PID");
55 unsetenv("LISTEN_FDS");
56 unsetenv("LISTEN_FDNAMES");
57 }
58
59 _public_ int sd_listen_fds(int unset_environment) {
60 const char *e;
61 int n, r, fd;
62 pid_t pid;
63
64 e = getenv("LISTEN_PID");
65 if (!e) {
66 r = 0;
67 goto finish;
68 }
69
70 r = parse_pid(e, &pid);
71 if (r < 0)
72 goto finish;
73
74 /* Is this for us? */
75 if (getpid_cached() != pid) {
76 r = 0;
77 goto finish;
78 }
79
80 e = getenv("LISTEN_FDS");
81 if (!e) {
82 r = 0;
83 goto finish;
84 }
85
86 r = safe_atoi(e, &n);
87 if (r < 0)
88 goto finish;
89
90 assert_cc(SD_LISTEN_FDS_START < INT_MAX);
91 if (n <= 0 || n > INT_MAX - SD_LISTEN_FDS_START) {
92 r = -EINVAL;
93 goto finish;
94 }
95
96 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
97 r = fd_cloexec(fd, true);
98 if (r < 0)
99 goto finish;
100 }
101
102 r = n;
103
104 finish:
105 unsetenv_all(unset_environment);
106 return r;
107 }
108
109 _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) {
110 _cleanup_strv_free_ char **l = NULL;
111 bool have_names;
112 int n_names = 0, n_fds;
113 const char *e;
114 int r;
115
116 if (!names)
117 return sd_listen_fds(unset_environment);
118
119 e = getenv("LISTEN_FDNAMES");
120 if (e) {
121 n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
122 if (n_names < 0) {
123 unsetenv_all(unset_environment);
124 return n_names;
125 }
126
127 have_names = true;
128 } else
129 have_names = false;
130
131 n_fds = sd_listen_fds(unset_environment);
132 if (n_fds <= 0)
133 return n_fds;
134
135 if (have_names) {
136 if (n_names != n_fds)
137 return -EINVAL;
138 } else {
139 r = strv_extend_n(&l, "unknown", n_fds);
140 if (r < 0)
141 return r;
142 }
143
144 *names = l;
145 l = NULL;
146
147 return n_fds;
148 }
149
150 _public_ int sd_is_fifo(int fd, const char *path) {
151 struct stat st_fd;
152
153 assert_return(fd >= 0, -EBADF);
154
155 if (fstat(fd, &st_fd) < 0)
156 return -errno;
157
158 if (!S_ISFIFO(st_fd.st_mode))
159 return 0;
160
161 if (path) {
162 struct stat st_path;
163
164 if (stat(path, &st_path) < 0) {
165
166 if (IN_SET(errno, ENOENT, ENOTDIR))
167 return 0;
168
169 return -errno;
170 }
171
172 return
173 st_path.st_dev == st_fd.st_dev &&
174 st_path.st_ino == st_fd.st_ino;
175 }
176
177 return 1;
178 }
179
180 _public_ int sd_is_special(int fd, const char *path) {
181 struct stat st_fd;
182
183 assert_return(fd >= 0, -EBADF);
184
185 if (fstat(fd, &st_fd) < 0)
186 return -errno;
187
188 if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
189 return 0;
190
191 if (path) {
192 struct stat st_path;
193
194 if (stat(path, &st_path) < 0) {
195
196 if (IN_SET(errno, ENOENT, ENOTDIR))
197 return 0;
198
199 return -errno;
200 }
201
202 if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
203 return
204 st_path.st_dev == st_fd.st_dev &&
205 st_path.st_ino == st_fd.st_ino;
206 else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
207 return st_path.st_rdev == st_fd.st_rdev;
208 else
209 return 0;
210 }
211
212 return 1;
213 }
214
215 static int sd_is_socket_internal(int fd, int type, int listening) {
216 struct stat st_fd;
217
218 assert_return(fd >= 0, -EBADF);
219 assert_return(type >= 0, -EINVAL);
220
221 if (fstat(fd, &st_fd) < 0)
222 return -errno;
223
224 if (!S_ISSOCK(st_fd.st_mode))
225 return 0;
226
227 if (type != 0) {
228 int other_type = 0;
229 socklen_t l = sizeof(other_type);
230
231 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
232 return -errno;
233
234 if (l != sizeof(other_type))
235 return -EINVAL;
236
237 if (other_type != type)
238 return 0;
239 }
240
241 if (listening >= 0) {
242 int accepting = 0;
243 socklen_t l = sizeof(accepting);
244
245 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
246 return -errno;
247
248 if (l != sizeof(accepting))
249 return -EINVAL;
250
251 if (!accepting != !listening)
252 return 0;
253 }
254
255 return 1;
256 }
257
258 _public_ int sd_is_socket(int fd, int family, int type, int listening) {
259 int r;
260
261 assert_return(fd >= 0, -EBADF);
262 assert_return(family >= 0, -EINVAL);
263
264 r = sd_is_socket_internal(fd, type, listening);
265 if (r <= 0)
266 return r;
267
268 if (family > 0) {
269 union sockaddr_union sockaddr = {};
270 socklen_t l = sizeof(sockaddr);
271
272 if (getsockname(fd, &sockaddr.sa, &l) < 0)
273 return -errno;
274
275 if (l < sizeof(sa_family_t))
276 return -EINVAL;
277
278 return sockaddr.sa.sa_family == family;
279 }
280
281 return 1;
282 }
283
284 _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
285 union sockaddr_union sockaddr = {};
286 socklen_t l = sizeof(sockaddr);
287 int r;
288
289 assert_return(fd >= 0, -EBADF);
290 assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL);
291
292 r = sd_is_socket_internal(fd, type, listening);
293 if (r <= 0)
294 return r;
295
296 if (getsockname(fd, &sockaddr.sa, &l) < 0)
297 return -errno;
298
299 if (l < sizeof(sa_family_t))
300 return -EINVAL;
301
302 if (!IN_SET(sockaddr.sa.sa_family, AF_INET, AF_INET6))
303 return 0;
304
305 if (family != 0)
306 if (sockaddr.sa.sa_family != family)
307 return 0;
308
309 if (port > 0) {
310 unsigned sa_port;
311
312 r = sockaddr_port(&sockaddr.sa, &sa_port);
313 if (r < 0)
314 return r;
315
316 return port == sa_port;
317 }
318
319 return 1;
320 }
321
322 _public_ int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening) {
323 union sockaddr_union sockaddr = {};
324 socklen_t l = sizeof(sockaddr);
325 int r;
326
327 assert_return(fd >= 0, -EBADF);
328 assert_return(addr, -EINVAL);
329 assert_return(addr_len >= sizeof(sa_family_t), -ENOBUFS);
330 assert_return(IN_SET(addr->sa_family, AF_INET, AF_INET6), -EPFNOSUPPORT);
331
332 r = sd_is_socket_internal(fd, type, listening);
333 if (r <= 0)
334 return r;
335
336 if (getsockname(fd, &sockaddr.sa, &l) < 0)
337 return -errno;
338
339 if (l < sizeof(sa_family_t))
340 return -EINVAL;
341
342 if (sockaddr.sa.sa_family != addr->sa_family)
343 return 0;
344
345 if (sockaddr.sa.sa_family == AF_INET) {
346 const struct sockaddr_in *in = (const struct sockaddr_in *) addr;
347
348 if (l < sizeof(struct sockaddr_in) || addr_len < sizeof(struct sockaddr_in))
349 return -EINVAL;
350
351 if (in->sin_port != 0 &&
352 sockaddr.in.sin_port != in->sin_port)
353 return false;
354
355 return sockaddr.in.sin_addr.s_addr == in->sin_addr.s_addr;
356
357 } else {
358 const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) addr;
359
360 if (l < sizeof(struct sockaddr_in6) || addr_len < sizeof(struct sockaddr_in6))
361 return -EINVAL;
362
363 if (in->sin6_port != 0 &&
364 sockaddr.in6.sin6_port != in->sin6_port)
365 return false;
366
367 if (in->sin6_flowinfo != 0 &&
368 sockaddr.in6.sin6_flowinfo != in->sin6_flowinfo)
369 return false;
370
371 if (in->sin6_scope_id != 0 &&
372 sockaddr.in6.sin6_scope_id != in->sin6_scope_id)
373 return false;
374
375 return memcmp(sockaddr.in6.sin6_addr.s6_addr, in->sin6_addr.s6_addr,
376 sizeof(in->sin6_addr.s6_addr)) == 0;
377 }
378 }
379
380 _public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
381 union sockaddr_union sockaddr = {};
382 socklen_t l = sizeof(sockaddr);
383 int r;
384
385 assert_return(fd >= 0, -EBADF);
386
387 r = sd_is_socket_internal(fd, type, listening);
388 if (r <= 0)
389 return r;
390
391 if (getsockname(fd, &sockaddr.sa, &l) < 0)
392 return -errno;
393
394 if (l < sizeof(sa_family_t))
395 return -EINVAL;
396
397 if (sockaddr.sa.sa_family != AF_UNIX)
398 return 0;
399
400 if (path) {
401 if (length == 0)
402 length = strlen(path);
403
404 if (length == 0)
405 /* Unnamed socket */
406 return l == offsetof(struct sockaddr_un, sun_path);
407
408 if (path[0])
409 /* Normal path socket */
410 return
411 (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
412 memcmp(path, sockaddr.un.sun_path, length+1) == 0;
413 else
414 /* Abstract namespace socket */
415 return
416 (l == offsetof(struct sockaddr_un, sun_path) + length) &&
417 memcmp(path, sockaddr.un.sun_path, length) == 0;
418 }
419
420 return 1;
421 }
422
423 _public_ int sd_is_mq(int fd, const char *path) {
424 struct mq_attr attr;
425
426 /* Check that the fd is valid */
427 assert_return(fcntl(fd, F_GETFD) >= 0, -errno);
428
429 if (mq_getattr(fd, &attr) < 0) {
430 if (errno == EBADF)
431 /* A non-mq fd (or an invalid one, but we ruled that out above) */
432 return 0;
433 return -errno;
434 }
435
436 if (path) {
437 char fpath[PATH_MAX];
438 struct stat a, b;
439
440 assert_return(path_is_absolute(path), -EINVAL);
441
442 if (fstat(fd, &a) < 0)
443 return -errno;
444
445 strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
446 fpath[sizeof(fpath)-1] = 0;
447
448 if (stat(fpath, &b) < 0)
449 return -errno;
450
451 if (a.st_dev != b.st_dev ||
452 a.st_ino != b.st_ino)
453 return 0;
454 }
455
456 return 1;
457 }
458
459 _public_ int sd_pid_notify_with_fds(
460 pid_t pid,
461 int unset_environment,
462 const char *state,
463 const int *fds,
464 unsigned n_fds) {
465
466 union sockaddr_union sockaddr = {
467 .sa.sa_family = AF_UNIX,
468 };
469 struct iovec iovec = {
470 .iov_base = (char*) state,
471 };
472 struct msghdr msghdr = {
473 .msg_iov = &iovec,
474 .msg_iovlen = 1,
475 .msg_name = &sockaddr,
476 };
477 _cleanup_close_ int fd = -1;
478 struct cmsghdr *cmsg = NULL;
479 const char *e;
480 bool send_ucred;
481 int r;
482
483 if (!state) {
484 r = -EINVAL;
485 goto finish;
486 }
487
488 if (n_fds > 0 && !fds) {
489 r = -EINVAL;
490 goto finish;
491 }
492
493 e = getenv("NOTIFY_SOCKET");
494 if (!e)
495 return 0;
496
497 /* Must be an abstract socket, or an absolute path */
498 if (!IN_SET(e[0], '@', '/') || e[1] == 0) {
499 r = -EINVAL;
500 goto finish;
501 }
502
503 if (strlen(e) > sizeof(sockaddr.un.sun_path)) {
504 r = -EINVAL;
505 goto finish;
506 }
507
508 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
509 if (fd < 0) {
510 r = -errno;
511 goto finish;
512 }
513
514 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
515
516 iovec.iov_len = strlen(state);
517
518 strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
519 if (sockaddr.un.sun_path[0] == '@')
520 sockaddr.un.sun_path[0] = 0;
521
522 msghdr.msg_namelen = SOCKADDR_UN_LEN(sockaddr.un);
523
524 send_ucred =
525 (pid != 0 && pid != getpid_cached()) ||
526 getuid() != geteuid() ||
527 getgid() != getegid();
528
529 if (n_fds > 0 || send_ucred) {
530 /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
531 msghdr.msg_controllen =
532 (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) +
533 (send_ucred ? CMSG_SPACE(sizeof(struct ucred)) : 0);
534
535 msghdr.msg_control = alloca0(msghdr.msg_controllen);
536
537 cmsg = CMSG_FIRSTHDR(&msghdr);
538 if (n_fds > 0) {
539 cmsg->cmsg_level = SOL_SOCKET;
540 cmsg->cmsg_type = SCM_RIGHTS;
541 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
542
543 memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
544
545 if (send_ucred)
546 assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg));
547 }
548
549 if (send_ucred) {
550 struct ucred *ucred;
551
552 cmsg->cmsg_level = SOL_SOCKET;
553 cmsg->cmsg_type = SCM_CREDENTIALS;
554 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
555
556 ucred = (struct ucred*) CMSG_DATA(cmsg);
557 ucred->pid = pid != 0 ? pid : getpid_cached();
558 ucred->uid = getuid();
559 ucred->gid = getgid();
560 }
561 }
562
563 /* First try with fake ucred data, as requested */
564 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
565 r = 1;
566 goto finish;
567 }
568
569 /* If that failed, try with our own ucred instead */
570 if (send_ucred) {
571 msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred));
572 if (msghdr.msg_controllen == 0)
573 msghdr.msg_control = NULL;
574
575 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
576 r = 1;
577 goto finish;
578 }
579 }
580
581 r = -errno;
582
583 finish:
584 if (unset_environment)
585 unsetenv("NOTIFY_SOCKET");
586
587 return r;
588 }
589
590 _public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) {
591 return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0);
592 }
593
594 _public_ int sd_notify(int unset_environment, const char *state) {
595 return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0);
596 }
597
598 _public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) {
599 _cleanup_free_ char *p = NULL;
600 int r;
601
602 if (format) {
603 va_list ap;
604
605 va_start(ap, format);
606 r = vasprintf(&p, format, ap);
607 va_end(ap);
608
609 if (r < 0 || !p)
610 return -ENOMEM;
611 }
612
613 return sd_pid_notify(pid, unset_environment, p);
614 }
615
616 _public_ int sd_notifyf(int unset_environment, const char *format, ...) {
617 _cleanup_free_ char *p = NULL;
618 int r;
619
620 if (format) {
621 va_list ap;
622
623 va_start(ap, format);
624 r = vasprintf(&p, format, ap);
625 va_end(ap);
626
627 if (r < 0 || !p)
628 return -ENOMEM;
629 }
630
631 return sd_pid_notify(0, unset_environment, p);
632 }
633
634 _public_ int sd_booted(void) {
635 /* We test whether the runtime unit file directory has been
636 * created. This takes place in mount-setup.c, so is
637 * guaranteed to happen very early during boot. */
638
639 return laccess("/run/systemd/system/", F_OK) >= 0;
640 }
641
642 _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) {
643 const char *s, *p = ""; /* p is set to dummy value to do unsetting */
644 uint64_t u;
645 int r = 0;
646
647 s = getenv("WATCHDOG_USEC");
648 if (!s)
649 goto finish;
650
651 r = safe_atou64(s, &u);
652 if (r < 0)
653 goto finish;
654 if (u <= 0 || u >= USEC_INFINITY) {
655 r = -EINVAL;
656 goto finish;
657 }
658
659 p = getenv("WATCHDOG_PID");
660 if (p) {
661 pid_t pid;
662
663 r = parse_pid(p, &pid);
664 if (r < 0)
665 goto finish;
666
667 /* Is this for us? */
668 if (getpid_cached() != pid) {
669 r = 0;
670 goto finish;
671 }
672 }
673
674 if (usec)
675 *usec = u;
676
677 r = 1;
678
679 finish:
680 if (unset_environment && s)
681 unsetenv("WATCHDOG_USEC");
682 if (unset_environment && p)
683 unsetenv("WATCHDOG_PID");
684
685 return r;
686 }