changeset 5457:7fb0274b9127 draft

Linux: detect network namespace and deny udev in one udev says whether an interface name is stable or not. In a network namespace, udev claims the interface does not exist. This makes sense because udev only operates in the root namespace. As such disable udev in a network namespace. While here correctly spell initialise.
author Roy Marples <roy@marples.name>
date Sat, 19 Sep 2020 14:40:50 +0100
parents 9203603adc76
children dd8347a0ea1c
files src/dev.c src/dev.h src/dev/udev.c src/dhcpcd.h src/if-linux.c src/if.c src/if.h src/privsep-root.c src/privsep-root.h
diffstat 9 files changed, 61 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/dev.c	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/dev.c	Sat Sep 19 14:40:50 2020 +0100
@@ -39,18 +39,18 @@
 #include "logerr.h"
 
 int
-dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
+dev_initialised(struct dhcpcd_ctx *ctx, const char *ifname)
 {
 
 #ifdef PRIVSEP
 	if (ctx->options & DHCPCD_PRIVSEP &&
 	    !(ctx->options & DHCPCD_PRIVSEPROOT))
-		return ps_root_dev_initialized(ctx, ifname);
+		return ps_root_dev_initialised(ctx, ifname);
 #endif
 
 	if (ctx->dev == NULL)
 		return 1;
-	return ctx->dev->initialized(ifname);
+	return ctx->dev->initialised(ifname);
 }
 
 int
--- a/src/dev.h	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/dev.h	Sat Sep 19 14:40:50 2020 +0100
@@ -31,7 +31,7 @@
 // dev plugin setup
 struct dev {
 	const char *name;
-	int (*initialized)(const char *);
+	int (*initialised)(const char *);
 	int (*listening)(void);
 	int (*handle_device)(void *);
 	int (*start)(void);
@@ -47,7 +47,7 @@
 // hooks for dhcpcd
 #ifdef PLUGIN_DEV
 #include "dhcpcd.h"
-int dev_initialized(struct dhcpcd_ctx *, const char *);
+int dev_initialised(struct dhcpcd_ctx *, const char *);
 int dev_listening(struct dhcpcd_ctx *);
 int dev_start(struct dhcpcd_ctx *, int (*)(void *, int, const char *));
 void dev_stop(struct dhcpcd_ctx *);
--- a/src/dev/udev.c	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/dev/udev.c	Sat Sep 19 14:40:50 2020 +0100
@@ -39,6 +39,7 @@
 
 #include "../common.h"
 #include "../dev.h"
+#include "../if.h"
 #include "../logerr.h"
 
 static const char udev_name[] = "udev";
@@ -55,7 +56,7 @@
 }
 
 static int
-udev_initialized(const char *ifname)
+udev_initialised(const char *ifname)
 {
 	struct udev_device *device;
 	int r;
@@ -120,8 +121,14 @@
 static int
 udev_start(void)
 {
+	char netns[PATH_MAX];
 	int fd;
 
+	if (if_getnetworknamespace(netns, sizeof(netns)) != NULL) {
+		logdebugx("udev does not work in a network namespace");
+		return -1;
+	}
+
 	if (udev) {
 		logerrx("udev: already started");
 		return -1;
@@ -167,7 +174,7 @@
 {
 
 	dev->name = udev_name;
-	dev->initialized = udev_initialized;
+	dev->initialised = udev_initialised;
 	dev->listening = udev_listening;
 	dev->handle_device = udev_handle_device;
 	dev->stop = udev_stop;
--- a/src/dhcpcd.h	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/dhcpcd.h	Sat Sep 19 14:40:50 2020 +0100
@@ -254,6 +254,10 @@
 	struct dev *dev;
 	void *dev_handle;
 #endif
+
+#ifdef __linux__
+	char netns[PATH_MAX];
+#endif
 };
 
 #ifdef USE_SIGNALS
--- a/src/if-linux.c	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/if-linux.c	Sat Sep 19 14:40:50 2020 +0100
@@ -60,6 +60,7 @@
 #include <linux/if_arp.h>
 #endif
 
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <ctype.h>
@@ -144,6 +145,7 @@
 	int route_fd;
 	int generic_fd;
 	uint32_t route_pid;
+	char netns[PATH_MAX];
 };
 
 /* We need this to send a broadcast for InfiniBand.
@@ -383,6 +385,36 @@
 	return fd;
 }
 
+char *
+if_getnetworknamespace(char *buf, size_t len)
+{
+	struct stat sb_self, sb_netns;
+	DIR *dir;
+	struct dirent *de;
+	char file[PATH_MAX], *bufp = NULL;
+
+	if (stat("/proc/self/ns/net", &sb_self) == -1)
+		return NULL;
+
+	dir = opendir("/var/run/netns");
+	if (dir == NULL)
+		return NULL;
+
+	while ((de = readdir(dir)) != NULL) {
+		snprintf(file, sizeof(file), "/var/run/netns/%s", de->d_name);
+		if (stat(file, &sb_netns) == -1)
+			continue;
+		if (sb_self.st_dev != sb_netns.st_dev &&
+		    sb_self.st_ino != sb_netns.st_ino)
+			continue;
+		strlcpy(buf, de->d_name, len);
+		bufp = buf;
+		break;
+	}
+	closedir(dir);
+	return bufp;
+}
+
 int
 if_opensockets_os(struct dhcpcd_ctx *ctx)
 {
@@ -433,6 +465,9 @@
 	if (priv->generic_fd == -1)
 		return -1;
 
+	if (if_getnetworknamespace(ctx->netns, sizeof(ctx->netns)) != NULL)
+		logdebugx("network namespace: %s", ctx->netns);
+
 	return 0;
 }
 
@@ -1614,7 +1649,6 @@
 	    &_if_initrt, kroutes);
 }
 
-
 #ifdef INET
 /* Linux is a special snowflake when it comes to BPF. */
 const char *bpf_name = "Packet Socket";
--- a/src/if.c	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/if.c	Sat Sep 19 14:40:50 2020 +0100
@@ -519,8 +519,11 @@
 
 #ifdef PLUGIN_DEV
 		/* Ensure that the interface name has settled */
-		if (!dev_initialized(ctx, spec.devname))
+		if (!dev_initialised(ctx, spec.devname)) {
+			logdebugx("%s: waiting for interface to initialise",
+			    spec.devname);
 			continue;
+		}
 #endif
 
 		if (if_vimaster(ctx, spec.devname) == 1) {
--- a/src/if.h	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/if.h	Sat Sep 19 14:40:50 2020 +0100
@@ -191,6 +191,7 @@
 bool if_ignore(struct dhcpcd_ctx *, const char *);
 int if_vimaster(struct dhcpcd_ctx *ctx, const char *);
 unsigned short if_vlanid(const struct interface *);
+char * if_getnetworknamespace(char *, size_t);
 int if_opensockets(struct dhcpcd_ctx *);
 int if_opensockets_os(struct dhcpcd_ctx *);
 void if_closesockets(struct dhcpcd_ctx *);
--- a/src/privsep-root.c	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/privsep-root.c	Sat Sep 19 14:40:50 2020 +0100
@@ -570,7 +570,7 @@
 #endif
 #ifdef PLUGIN_DEV
 	case PS_DEV_INITTED:
-		err = dev_initialized(ctx, data);
+		err = dev_initialised(ctx, data);
 		break;
 	case PS_DEV_LISTENING:
 		err = dev_listening(ctx);
@@ -989,7 +989,7 @@
 
 #ifdef PLUGIN_DEV
 int
-ps_root_dev_initialized(struct dhcpcd_ctx *ctx, const char *ifname)
+ps_root_dev_initialised(struct dhcpcd_ctx *ctx, const char *ifname)
 {
 
 	if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_DEV_INITTED, 0,
--- a/src/privsep-root.h	Wed Sep 16 15:55:11 2020 +0100
+++ b/src/privsep-root.h	Sat Sep 19 14:40:50 2020 +0100
@@ -67,7 +67,7 @@
 #endif
 
 #ifdef PLUGIN_DEV
-int ps_root_dev_initialized(struct dhcpcd_ctx *, const char *);
+int ps_root_dev_initialised(struct dhcpcd_ctx *, const char *);
 int ps_root_dev_listening(struct dhcpcd_ctx *);
 #endif