X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibelogind%2Fsd-daemon%2Fsd-daemon.c;h=47fc3a422fe9c480c7491d8e1f0e4d0b9387101a;hb=f34e11cabee7e2de9095d617b60004383ee74eb2;hp=b26ecf26d5fff5d0c6041aeae6b26639df21fc3d;hpb=2e694aaeec158dba9dc12d8eea1755e201830a81;p=elogind.git diff --git a/src/libelogind/sd-daemon/sd-daemon.c b/src/libelogind/sd-daemon/sd-daemon.c index b26ecf26d..47fc3a422 100644 --- a/src/libelogind/sd-daemon/sd-daemon.c +++ b/src/libelogind/sd-daemon/sd-daemon.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -21,7 +19,7 @@ #include #include -//#include +#include #include #include #include @@ -33,15 +31,19 @@ #include #include +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "parse-util.h" #include "path-util.h" #include "socket-util.h" -//#include "strv.h" +#include "strv.h" #include "util.h" -#include "sd-daemon.h" +#define SNDBUF_SIZE (8*1024*1024) -/// UNNEEDED by elogind -#if 0 static void unsetenv_all(bool unset_environment) { if (!unset_environment) @@ -54,8 +56,7 @@ static void unsetenv_all(bool unset_environment) { _public_ int sd_listen_fds(int unset_environment) { const char *e; - unsigned n; - int r, fd; + int n, r, fd; pid_t pid; e = getenv("LISTEN_PID"); @@ -80,22 +81,28 @@ _public_ int sd_listen_fds(int unset_environment) { goto finish; } - r = safe_atou(e, &n); + r = safe_atoi(e, &n); if (r < 0) goto finish; - for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) n; fd ++) { + assert_cc(SD_LISTEN_FDS_START < INT_MAX); + if (n <= 0 || n > INT_MAX - SD_LISTEN_FDS_START) { + r = -EINVAL; + goto finish; + } + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { r = fd_cloexec(fd, true); if (r < 0) goto finish; } - r = (int) n; + r = n; finish: unsetenv_all(unset_environment); return r; - } +} _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) { _cleanup_strv_free_ char **l = NULL; @@ -129,8 +136,8 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) { } else { r = strv_extend_n(&l, "unknown", n_fds); if (r < 0) - return r; -} + return r; + } *names = l; l = NULL; @@ -202,7 +209,6 @@ _public_ int sd_is_special(int fd, const char *path) { return 1; } -#endif // 0 static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; @@ -273,8 +279,6 @@ _public_ int sd_is_socket(int fd, int family, int type, int listening) { return 1; } -/// UNNEEDED by elogind -#if 0 _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { union sockaddr_union sockaddr = {}; socklen_t l = sizeof(sockaddr); @@ -306,18 +310,78 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint if (l < sizeof(struct sockaddr_in)) return -EINVAL; - return htons(port) == sockaddr.in.sin_port; + return htobe16(port) == sockaddr.in.sin_port; } else { if (l < sizeof(struct sockaddr_in6)) return -EINVAL; - return htons(port) == sockaddr.in6.sin6_port; + return htobe16(port) == sockaddr.in6.sin6_port; } } return 1; } +#if 0 /// UNNEEDED by elogind +_public_ int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(addr, -EINVAL); + assert_return(addr_len >= sizeof(sa_family_t), -ENOBUFS); + assert_return(IN_SET(addr->sa_family, AF_INET, AF_INET6), -EPFNOSUPPORT); + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (sockaddr.sa.sa_family != addr->sa_family) + return 0; + + if (sockaddr.sa.sa_family == AF_INET) { + const struct sockaddr_in *in = (const struct sockaddr_in *) addr; + + if (l < sizeof(struct sockaddr_in) || addr_len < sizeof(struct sockaddr_in)) + return -EINVAL; + + if (in->sin_port != 0 && + sockaddr.in.sin_port != in->sin_port) + return false; + + return sockaddr.in.sin_addr.s_addr == in->sin_addr.s_addr; + + } else { + const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) addr; + + if (l < sizeof(struct sockaddr_in6) || addr_len < sizeof(struct sockaddr_in6)) + return -EINVAL; + + if (in->sin6_port != 0 && + sockaddr.in6.sin6_port != in->sin6_port) + return false; + + if (in->sin6_flowinfo != 0 && + sockaddr.in6.sin6_flowinfo != in->sin6_flowinfo) + return false; + + if (in->sin6_scope_id != 0 && + sockaddr.in6.sin6_scope_id != in->sin6_scope_id) + return false; + + return memcmp(sockaddr.in6.sin6_addr.s6_addr, in->sin6_addr.s6_addr, + sizeof(in->sin6_addr.s6_addr)) == 0; + } +} +#endif // 0 + _public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { union sockaddr_union sockaddr = {}; socklen_t l = sizeof(sockaddr); @@ -361,6 +425,7 @@ _public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path return 1; } +#if 0 /// UNNEEDED by elogind _public_ int sd_is_mq(int fd, const char *path) { struct mq_attr attr; @@ -436,29 +501,36 @@ _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char goto finish; } + if (strlen(e) > sizeof(sockaddr.un.sun_path)) { + r = -EINVAL; + goto finish; + } + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (fd < 0) { r = -errno; goto finish; } + fd_inc_sndbuf(fd, SNDBUF_SIZE); + iovec.iov_len = strlen(state); strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); if (sockaddr.un.sun_path[0] == '@') sockaddr.un.sun_path[0] = 0; - msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); - if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) - msghdr.msg_namelen = sizeof(struct sockaddr_un); + msghdr.msg_namelen = SOCKADDR_UN_LEN(sockaddr.un); have_pid = pid != 0 && pid != getpid(); if (n_fds > 0 || have_pid) { - /* CMSG_SPACE(0) may return value different then zero, which results in miscalculated controllen. */ - msghdr.msg_controllen = (n_fds ? CMSG_SPACE(sizeof(int) * n_fds) : 0) + - CMSG_SPACE(sizeof(struct ucred)) * have_pid; - msghdr.msg_control = alloca(msghdr.msg_controllen); + /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */ + msghdr.msg_controllen = + (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) + + (have_pid ? CMSG_SPACE(sizeof(struct ucred)) : 0); + + msghdr.msg_control = alloca0(msghdr.msg_controllen); cmsg = CMSG_FIRSTHDR(&msghdr); if (n_fds > 0) { @@ -513,19 +585,14 @@ finish: return r; } -/// UNNEEDED by elogind -#if 0 _public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) { return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0); } -#endif // 0 _public_ int sd_notify(int unset_environment, const char *state) { return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0); } -/// UNNEEDED by elogind -#if 0 _public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) { _cleanup_free_ char *p = NULL; int r; @@ -563,13 +630,16 @@ _public_ int sd_notifyf(int unset_environment, const char *format, ...) { } _public_ int sd_booted(void) { +#if 0 /// With elogind, the system is (should never be) booted by systemd /* We test whether the runtime unit file directory has been * created. This takes place in mount-setup.c, so is * guaranteed to happen very early during boot. */ return laccess("/run/systemd/system/", F_OK) >= 0; -} +#else + return 0; #endif // 0 +} _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { const char *s, *p = ""; /* p is set to dummy value to do unsetting */ @@ -583,7 +653,7 @@ _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { r = safe_atou64(s, &u); if (r < 0) goto finish; - if (u <= 0) { + if (u <= 0 || u >= USEC_INFINITY) { r = -EINVAL; goto finish; }