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