[PATCH 2/2] multipath-tools: allow using a regular Unix socket for multipathd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Accessing multipathd's socket from a different network namespace (e.g. from a
container) is impossible with an abstract socket. Add the option to compile
multipathd using a regular Unix socket instead, by compiling with the flag
"use_regular_socket=1". By default, the socket path is /run/multipathd.

[1] https://github.com/opensvc/multipath-tools/issues/111

Signed-off-by: Martin Wilck <mwilck@xxxxxxxx>
---
 .gitignore                                    |  1 +
 Makefile.inc                                  |  9 ++++++--
 README.md                                     |  4 ++++
 libmpathcmd/mpath_cmd.c                       |  5 +++--
 libmpathutil/uxsock.c                         | 21 ++++++++++++++++---
 multipathd/Makefile                           |  6 +++---
 ...multipathd.socket => multipathd.socket.in} |  2 +-
 7 files changed, 37 insertions(+), 11 deletions(-)
 rename multipathd/{multipathd.socket => multipathd.socket.in} (87%)

diff --git a/.gitignore b/.gitignore
index 4548cfb..6a1f6fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ multipathd/multipathd
 multipathd/multipathd.8
 multipathd/multipathc
 multipathd/multipathd.service
+multipathd/multipathd.socket
 mpathpersist/mpathpersist
 mpathpersist/mpathpersist.8
 abi.tar.gz
diff --git a/Makefile.inc b/Makefile.inc
index 949e7b5..104aeaf 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -79,8 +79,11 @@ libudev_incdir	:= $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr
 kernel_incdir	:= /usr/include
 sysdir_bin      := $(sys_execprefix)bin
 
+use_regular_socket   :=
+regular_socket_path  := /run/multipathd.socket
 abstract_socket_path := /org/kernel/linux/storage/multipathd
-mpath_socket         := $(abstract_socket_path)
+mpath_socket         := $(if $(use_regular_socket),$(regular_socket_path),$(abstract_socket_path))
+mpath_socket_systemd := $(if $(use_regular_socket),$(regular_socket_path),@$(abstract_socket_path))
 
 ifeq ($(V),)
 Q		:= @
@@ -118,7 +121,8 @@ CPPFLAGS	:= $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
 		   -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \
 		   -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \
 		   -DEXTRAVERSION=\"$(EXTRAVERSION)\" \
-		   -DDEFAULT_SOCKET=\"$(mpath_socket)\" -MMD -MP
+		   -DDEFAULT_SOCKET=\"$(mpath_socket)\" -DUSE_REGULAR_SOCKET=$(if $(use_regular_socket),1,0) \
+		   -MMD -MP
 CFLAGS		:= -std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
 		   -fexceptions
 BIN_CFLAGS	:= -fPIE -DPIE
@@ -171,4 +175,5 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version)
 		-e 's:@SYSDIR_BIN@:'$(sysdir_bin)': g' \
 		-e 's:@RUNTIME_DIR@:'$(runtimedir)':g' \
 		-e 's/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g' \
+		-e 's,@MPATH_SOCKET@,'$(mpath_socket_systemd)',g' \
 		$< >$@
diff --git a/README.md b/README.md
index 530caed..f6cf675 100644
--- a/README.md
+++ b/README.md
@@ -121,6 +121,10 @@ The following variables can be passed to the `make` command line:
     stores run-time settings that need persist between reboots, such as known
 	WWIDs, user-friendly names, and persistent reservation keys.
 	The default is `$(etc_prefix)/etc/multipath`.
+ * `use_regular_socket`: if unset (default), use an abstract socket, which is
+   invisible in the file system. Otherwise, if set to 1, use the regular unix socket
+   `/run/multipathd.socket`. Setting this to 1 is necessary in order to
+   communicate with **multipathd** from containers.
  * `READLINE=libedit` or `READLINE=libreadline`: enable command line history
     and TAB completion in the interactive mode *(which is entered with `multipathd -k` or `multipathc`)*.
     The respective development package will be required for building.
diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c
index a38e8b6..fdc7951 100644
--- a/libmpathcmd/mpath_cmd.c
+++ b/libmpathcmd/mpath_cmd.c
@@ -100,12 +100,13 @@ int mpath_connect__(int nonblocking)
 	size_t len;
 	struct sockaddr_un addr;
 	int flags = 0;
+	const int offset = USE_REGULAR_SOCKET ? 0 : 1;
 
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_LOCAL;
 	addr.sun_path[0] = '\0';
-	strncpy(&addr.sun_path[1], DEFAULT_SOCKET, sizeof(addr.sun_path) - 1);
-	len = strlen(DEFAULT_SOCKET) + 1 + sizeof(sa_family_t);
+	strncpy(&addr.sun_path[offset], DEFAULT_SOCKET, sizeof(addr.sun_path) - offset);
+	len = strlen(DEFAULT_SOCKET) + offset + sizeof(sa_family_t);
 	if (len > sizeof(struct sockaddr_un))
 		len = sizeof(struct sockaddr_un);
 
diff --git a/libmpathutil/uxsock.c b/libmpathutil/uxsock.c
index 2135476..976a047 100644
--- a/libmpathutil/uxsock.c
+++ b/libmpathutil/uxsock.c
@@ -12,6 +12,7 @@
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/un.h>
 #include <poll.h>
 #include <signal.h>
@@ -45,6 +46,7 @@ int ux_socket_listen(const char *name)
 	int num;
 #endif
 	struct sockaddr_un addr;
+	const int offset = USE_REGULAR_SOCKET ? 0 : 1;
 
 #ifdef USE_SYSTEMD
 	num = sd_listen_fds(0);
@@ -56,6 +58,11 @@ int ux_socket_listen(const char *name)
 		condlog(3, "using fd %d from sd_listen_fds", fd);
 		return fd;
 	}
+#endif
+#if USE_REGULAR_SOCKET
+	/* This is after the PID check, so unlinking should be fine */
+	if (unlink(name) == -1 && errno != ENOENT)
+		condlog(1, "Failed to unlink %s", name);
 #endif
 	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
 	if (fd == -1) {
@@ -66,10 +73,10 @@ int ux_socket_listen(const char *name)
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_LOCAL;
 	addr.sun_path[0] = '\0';
-	len = strlen(name) + 1;
+	len = strlen(name) + offset;
 	if (len >= sizeof(addr.sun_path))
-		len = sizeof(addr.sun_path) - 1;
-	memcpy(&addr.sun_path[1], name, len);
+		len = sizeof(addr.sun_path);
+	memcpy(&addr.sun_path[offset], name, len);
 
 	len += sizeof(sa_family_t);
 	if (bind(fd, (struct sockaddr *)&addr, len) == -1) {
@@ -78,6 +85,14 @@ int ux_socket_listen(const char *name)
 		return -1;
 	}
 
+#if USE_REGULAR_SOCKET
+	/*
+	 * Socket needs to have rw permissions for everone.
+	 * SO_PEERCRED makes sure that only root can modify things.
+	 */
+	if (chmod(name, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1)
+		condlog(3, "failed to set permissions on %s: %s", name, strerror(errno));
+#endif
 	if (listen(fd, 10) == -1) {
 		condlog(3, "Couldn't listen to ux_socket, error %d", errno);
 		close(fd);
diff --git a/multipathd/Makefile b/multipathd/Makefile
index 997b40c..3673b1e 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -41,7 +41,7 @@ ifeq ($(FPIN_SUPPORT),1)
 OBJS += fpin_handlers.o
 endif
 
-all : $(EXEC) $(CLI) $(MANPAGES) $(EXEC).service
+all : $(EXEC) $(CLI) $(MANPAGES) $(EXEC).service $(EXEC).socket
 
 $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
 	@echo building $@ because of $?
@@ -75,10 +75,10 @@ uninstall:
 	$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
 	$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(CLI).8
 	$(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).service
-	$(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket
+	$(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket $(EXEC).service
 
 clean: dep_clean
-	$(Q)$(RM) core *.o $(EXEC) $(CLI) $(MANPAGES) $(EXEC).service
+	$(Q)$(RM) core *.o $(EXEC) $(CLI) $(MANPAGES) $(EXEC).service $(EXEC).socket
 
 include $(wildcard $(OBJS:.o=.d) $(CLI_OBJS:.o=.d))
 
diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket.in
similarity index 87%
rename from multipathd/multipathd.socket
rename to multipathd/multipathd.socket.in
index 6a62f5f..c0e86c3 100644
--- a/multipathd/multipathd.socket
+++ b/multipathd/multipathd.socket.in
@@ -7,7 +7,7 @@ ConditionVirtualization=!container
 Before=sockets.target
 
 [Socket]
-ListenStream=@/org/kernel/linux/storage/multipathd
+ListenStream=@MPATH_SOCKET@
 
 [Install]
 # Socket activation for multipathd is disabled by default.
-- 
2.48.1





[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux