From: Roy Marples Date: Sat, 19 Sep 2020 13:40:50 +0000 (+0100) Subject: Linux: detect network namespace and deny udev in one X-Git-Tag: v9.3.0~39 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1efd31813fde826b000fbc40234ea89979ef73a8;p=thirdparty%2Fdhcpcd.git 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. --- diff --git a/src/dev.c b/src/dev.c index f7da67e4..8f14bf6b 100644 --- a/src/dev.c +++ b/src/dev.c @@ -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 diff --git a/src/dev.h b/src/dev.h index d51cbbec..3bfb5729 100644 --- a/src/dev.h +++ b/src/dev.h @@ -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 @@ int dev_init(struct dev *, const struct dev_dhcpcd *); // 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 *); diff --git a/src/dev/udev.c b/src/dev/udev.c index 4fe7dde4..fefdefb2 100644 --- a/src/dev/udev.c +++ b/src/dev/udev.c @@ -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 @@ udev_listening(void) } static int -udev_initialized(const char *ifname) +udev_initialised(const char *ifname) { struct udev_device *device; int r; @@ -120,8 +121,14 @@ udev_stop(void) 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_init(struct dev *dev, const struct dev_dhcpcd *dev_dhcpcd) { 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; diff --git a/src/dhcpcd.h b/src/dhcpcd.h index 03449e58..0cf774ce 100644 --- a/src/dhcpcd.h +++ b/src/dhcpcd.h @@ -254,6 +254,10 @@ struct dhcpcd_ctx { struct dev *dev; void *dev_handle; #endif + +#ifdef __linux__ + char netns[PATH_MAX]; +#endif }; #ifdef USE_SIGNALS diff --git a/src/if-linux.c b/src/if-linux.c index 8d87d748..759b878e 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -60,6 +60,7 @@ #include #endif +#include #include #include #include @@ -144,6 +145,7 @@ struct priv { 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 @@ if_linksocket(struct sockaddr_nl *nl, int protocol, int flags) 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_opensockets_os(struct dhcpcd_ctx *ctx) 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(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af) &_if_initrt, kroutes); } - #ifdef INET /* Linux is a special snowflake when it comes to BPF. */ const char *bpf_name = "Packet Socket"; diff --git a/src/if.c b/src/if.c index 40fdadcf..cb407e19 100644 --- a/src/if.c +++ b/src/if.c @@ -519,8 +519,11 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, #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) { diff --git a/src/if.h b/src/if.h index e053fe5b..803f5818 100644 --- a/src/if.h +++ b/src/if.h @@ -191,6 +191,7 @@ int if_ignoregroup(int, const char *); 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 *); diff --git a/src/privsep-root.c b/src/privsep-root.c index 1a438b67..92faec4c 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -570,7 +570,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) #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 @@ ps_root_getauthrdm(struct dhcpcd_ctx *ctx, uint64_t *rdm) #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, diff --git a/src/privsep-root.h b/src/privsep-root.h index 5d6e1248..146622b1 100644 --- a/src/privsep-root.h +++ b/src/privsep-root.h @@ -67,7 +67,7 @@ ssize_t ps_root_sendnetlink(struct dhcpcd_ctx *, int, struct msghdr *); #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