changeset 5282:8afafcabcfa5 draft

privsep: Drain the link socket as we can't re-open it. Add debug per 100 messages.
author Roy Marples <roy@marples.name>
date Sat, 30 May 2020 13:25:41 +0100
parents 9f9a330f6e24
children 87cdd74ea98e
files src/dhcpcd.c src/if-linux.c src/if.h src/privsep-linux.c
diffstat 4 files changed, 23 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcpcd.c	Sat May 30 10:36:20 2020 +0000
+++ b/src/dhcpcd.c	Sat May 30 13:25:41 2020 +0100
@@ -1165,6 +1165,9 @@
 {
 	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 @@
 	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);
--- a/src/if-linux.c	Sat May 30 10:36:20 2020 +0000
+++ b/src/if-linux.c	Sat May 30 13:25:41 2020 +0100
@@ -355,11 +355,12 @@
 }
 
 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 @@
 	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 @@
 
 	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 @@
 
 		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) {
--- a/src/if.h	Sat May 30 10:36:20 2020 +0000
+++ b/src/if.h	Sat May 30 13:25:41 2020 +0100
@@ -256,7 +256,7 @@
 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
--- a/src/privsep-linux.c	Sat May 30 10:36:20 2020 +0000
+++ b/src/privsep-linux.c	Sat May 30 13:25:41 2020 +0100
@@ -50,7 +50,7 @@
 	};
 	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) {