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