]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
privsep: Drain the link socket as we can't re-open it.
authorRoy Marples <roy@marples.name>
Sat, 30 May 2020 12:25:41 +0000 (13:25 +0100)
committerRoy Marples <roy@marples.name>
Sat, 30 May 2020 12:25:41 +0000 (13:25 +0100)
Add debug per 100 messages.

src/dhcpcd.c
src/if-linux.c
src/if.h
src/privsep-linux.c

index 182b298912acd214a591a8a827a532e8a6e18cb0..d8f90626de8cd4e261e3c7b0d3b26926dd665e39 100644 (file)
@@ -1165,6 +1165,9 @@ dhcpcd_linkoverflow(struct dhcpcd_ctx *ctx)
 {
        socklen_t socklen;
        int rcvbuflen;
+       char buf[2048];
+       ssize_t rlen;
+       size_t rcnt;
        struct if_head *ifaces;
        struct ifaddrs *ifaddrs;
        struct interface *ifp, *ifn, *ifp1;
@@ -1181,24 +1184,18 @@ dhcpcd_linkoverflow(struct dhcpcd_ctx *ctx)
        logerrx("route socket overflowed (rcvbuflen %d)"
            " - learning interface state", rcvbuflen);
 
-#ifndef HAVE_PLEDGE
-       /* Close the existing socket and open a new one.
-        * This is easier than draining the kernel buffer of an
-        * in-determinate size. */
-       eloop_event_delete(ctx->eloop, ctx->link_fd);
-       close(ctx->link_fd);
-       if_closesockets_os(ctx);
-       if (if_opensockets_os(ctx) == -1) {
-               logerr("%s: if_opensockets", __func__);
-               eloop_exit(ctx->eloop, EXIT_FAILURE);
-               return;
-       }
-#endif
-
-#ifndef SMALL
-       dhcpcd_setlinkrcvbuf(ctx);
-#endif
-       eloop_event_add(ctx->eloop, ctx->link_fd, dhcpcd_handlelink, ctx);
+       /* Drain the socket.
+        * We cannot open a new one due to privsep. */
+       rcnt = 0;
+       do {
+               rlen = read(ctx->link_fd, buf, sizeof(buf));
+               if (++rcnt == 100) {
+                       logwarnx("drained %zu messages", rcnt);
+                       rcnt = 0;
+               }
+       } while (rlen != -1 || errno == ENOBUFS || errno == ENOMEM);
+       if (rcnt != 100)
+               logwarnx("drained %zu messages", rcnt);
 
        /* Work out the current interfaces. */
        ifaces = if_discover(ctx, &ifaddrs, ctx->ifc, ctx->ifv);
index 348db0e6d92179664487f4f36699d3f49fda1632..9e87cef4b647bdd2ffb0bb94601d4e51b3cc7327 100644 (file)
@@ -355,11 +355,12 @@ if_vlanid(const struct interface *ifp)
 }
 
 int
-if_linksocket(struct sockaddr_nl *nl, int protocol)
+if_linksocket(struct sockaddr_nl *nl, int protocol, int flags)
 {
        int fd;
 
-       if ((fd = xsocket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol)) == -1)
+       fd = xsocket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC | flags, protocol);
+       if (fd == -1)
                return -1;
        nl->nl_family = AF_NETLINK;
        if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) {
@@ -392,7 +393,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
        snl.nl_groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH;
 #endif
 
-       ctx->link_fd = if_linksocket(&snl, NETLINK_ROUTE);
+       ctx->link_fd = if_linksocket(&snl, NETLINK_ROUTE, SOCK_NONBLOCK);
        if (ctx->link_fd == -1)
                return -1;
 #ifdef NETLINK_BROADCAST_ERROR
@@ -406,7 +407,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
 
        ctx->priv = priv;
        memset(&snl, 0, sizeof(snl));
-       priv->route_fd = if_linksocket(&snl, NETLINK_ROUTE);
+       priv->route_fd = if_linksocket(&snl, NETLINK_ROUTE, 0);
        if (priv->route_fd == -1)
                return -1;
        len = sizeof(snl);
@@ -1002,7 +1003,7 @@ if_sendnetlink(struct dhcpcd_ctx *ctx, int protocol, struct nlmsghdr *hdr,
 
                s = priv->route_fd;
        } else {
-               if ((s = if_linksocket(&snl, protocol)) == -1)
+               if ((s = if_linksocket(&snl, protocol, 0)) == -1)
                        return -1;
 #ifdef NETLINK_GET_STRICT_CHK
                if (hdr->nlmsg_type == RTM_GETADDR) {
index ad1239fd92a6cbdb0a4376a6304c6d827afeea4e..e644afc8c025738b2e1510980bebd2ab0eedcf93 100644 (file)
--- a/src/if.h
+++ b/src/if.h
@@ -256,7 +256,7 @@ struct interface *if_findifpfromcmsg(struct dhcpcd_ctx *,
 int xsocket(int, int, int);
 
 #ifdef __linux__
-int if_linksocket(struct sockaddr_nl *, int);
+int if_linksocket(struct sockaddr_nl *, int, int);
 int if_getnetlink(struct dhcpcd_ctx *, struct iovec *, int, int,
     int (*)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *);
 #endif
index 6b6400a0b2dcd8430a3b1b89446cfb27b98e9b2a..1cfd3efdea008fbe9db2d13035f3c29c7797a678 100644 (file)
@@ -50,7 +50,7 @@ ps_root_dosendnetlink(int protocol, struct msghdr *msg)
        };
        ssize_t retval;
 
-       if ((s = if_linksocket(&snl, protocol)) == -1)
+       if ((s = if_linksocket(&snl, protocol, 0)) == -1)
                return -1;
 
        if (sendmsg(s, msg, 0) == -1) {