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