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