2023-05-10 22:30:29

by NeilBrown

[permalink] [raw]
Subject: [PATCH 0/2] Support abstract addresses for rpcbind in rpcbind

If the previous patch sets to the kernel and the libtirpc are accepted,
we need rpcbind to listen on the new abstract address.

We could unconditionally listen, but as current libtirpc rejects sockets
bound to abstract addresses, this would result in unsightly errors.

So only add the new ListenStream to rpcbind.socket if it is likely to
work.

Also enhance rpcinfo to use the new abstract address if possible.

NeilBrown

---

NeilBrown (2):
Listen on an AF_UNIX abstract address if supported.
rpcinfo: try connecting using abstract address.


configure.ac | 13 ++++++++++++-
src/rpcinfo.c | 24 +++++++++++++++++++++++-
systemd/rpcbind.socket | 18 ------------------
systemd/rpcbind.socket.in | 19 +++++++++++++++++++
4 files changed, 54 insertions(+), 20 deletions(-)
delete mode 100644 systemd/rpcbind.socket
create mode 100644 systemd/rpcbind.socket.in

--
Signature



2023-05-10 22:32:46

by NeilBrown

[permalink] [raw]
Subject: [PATCH 1/2] Listen on an AF_UNIX abstract address if supported.

As RPC is primarily a network service it is best, on Linux, to use
network namespaces to isolate it. However contacting rpcbind via an
AF_UNIX socket allows escape from the network namespace.
If clients could use an abstract address, that would ensure clients
contact an rpcbind in the same network namespace.

systemd can pass in a listening abstract socket by providing an '@'
prefix. However with libtirpc 1.3.3 or earlier attempting this will
fail as the library mistakenly determines that the socket is not bound.
This generates unsightly error messages.
So it is best not to request the abstract address when it is not likely
to work.

A patch to fix this also proposes adding a define for
_PATH_RPCBINDSOCK_ABSTRACT to the header files. We can check for this
and only include the new ListenStream when that define is present.

Signed-off-by: NeilBrown <[email protected]>
---
configure.ac | 13 ++++++++++++-
systemd/rpcbind.socket | 18 ------------------
systemd/rpcbind.socket.in | 19 +++++++++++++++++++
3 files changed, 31 insertions(+), 19 deletions(-)
delete mode 100644 systemd/rpcbind.socket
create mode 100644 systemd/rpcbind.socket.in

diff --git a/configure.ac b/configure.ac
index c2069a2b3b0e..573e4fdf3a3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,6 +50,17 @@ AC_SUBST([nss_modules], [$with_nss_modules])

PKG_CHECK_MODULES([TIRPC], [libtirpc])

+CPPFLAGS=$TIRPC_CFLAGS
+AC_MSG_CHECKING([for abstract socket support in libtirpc])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#include <rpc/rpc.h>
+],[
+char *path = _PATH_RPCBINDSOCK_ABSTRACT;
+])], [have_abstract=yes], [have_abstract=no])
+CPPFLAGS=
+AC_MSG_RESULT([$have_abstract])
+AM_CONDITIONAL(ABSTRACT, [ test "x$have_abstract" = "xyes" ])
+
PKG_PROG_PKG_CONFIG
AC_ARG_WITH([systemdsystemunitdir],
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
@@ -76,4 +87,4 @@ AC_CHECK_HEADERS([nss.h])
AC_SUBST([_sbindir])
AC_CONFIG_COMMANDS_PRE([eval eval _sbindir=$sbindir])

-AC_OUTPUT([Makefile systemd/rpcbind.service])
+AC_OUTPUT([Makefile systemd/rpcbind.service systemd/rpcbind.socket])
diff --git a/systemd/rpcbind.socket b/systemd/rpcbind.socket
deleted file mode 100644
index 3b1a93694c21..000000000000
--- a/systemd/rpcbind.socket
+++ /dev/null
@@ -1,18 +0,0 @@
-[Unit]
-Description=RPCbind Server Activation Socket
-DefaultDependencies=no
-Wants=rpcbind.target
-Before=rpcbind.target
-
-[Socket]
-ListenStream=/run/rpcbind.sock
-
-# RPC netconfig can't handle ipv6/ipv4 dual sockets
-BindIPv6Only=ipv6-only
-ListenStream=0.0.0.0:111
-ListenDatagram=0.0.0.0:111
-ListenStream=[::]:111
-ListenDatagram=[::]:111
-
-[Install]
-WantedBy=sockets.target
diff --git a/systemd/rpcbind.socket.in b/systemd/rpcbind.socket.in
new file mode 100644
index 000000000000..5dd09a143e16
--- /dev/null
+++ b/systemd/rpcbind.socket.in
@@ -0,0 +1,19 @@
+[Unit]
+Description=RPCbind Server Activation Socket
+DefaultDependencies=no
+Wants=rpcbind.target
+Before=rpcbind.target
+
+[Socket]
+ListenStream=/run/rpcbind.sock
+@ABSTRACT_TRUE@ListenStream=@/run/rpcbind.sock
+
+# RPC netconfig can't handle ipv6/ipv4 dual sockets
+BindIPv6Only=ipv6-only
+ListenStream=0.0.0.0:111
+ListenDatagram=0.0.0.0:111
+ListenStream=[::]:111
+ListenDatagram=[::]:111
+
+[Install]
+WantedBy=sockets.target



2023-05-10 22:34:41

by NeilBrown

[permalink] [raw]
Subject: [PATCH 2/2] rpcinfo: try connecting using abstract address.

rpcinfo doesn't use library calls to set up the address for rpcbind. So
to get to it try the new abstract address, we need to explicitly
teach it how.

Signed-off-by: NeilBrown <[email protected]>
---
src/rpcinfo.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/rpcinfo.c b/src/rpcinfo.c
index 0e14f78ad2de..4464cbc0941b 100644
--- a/src/rpcinfo.c
+++ b/src/rpcinfo.c
@@ -311,6 +311,13 @@ main (int argc, char **argv)
return (0);
}

+/* Evaluate to actual length of the `sockaddr_un' structure, whether
+ * abstract or not.
+ */
+#include <stddef.h>
+#define SUN_LEN_A(ptr) (offsetof(struct sockaddr_un, sun_path) \
+ + 1 + strlen((ptr)->sun_path + 1))
+
static CLIENT *
local_rpcb (rpcprog_t prog, rpcvers_t vers)
{
@@ -334,6 +341,7 @@ local_rpcb (rpcprog_t prog, rpcvers_t vers)
endnetconfig(localhandle);
return clnt;
#else
+ CLIENT *clnt;
struct netbuf nbuf;
struct sockaddr_un sun;
int sock;
@@ -344,12 +352,26 @@ local_rpcb (rpcprog_t prog, rpcvers_t vers)
return NULL;

sun.sun_family = AF_LOCAL;
+
+#ifdef _PATH_RPCBINDSOCK_ABSTRACT
+ memcpy(sun.sun_path, _PATH_RPCBINDSOCK_ABSTRACT,
+ sizeof(_PATH_RPCBINDSOCK_ABSTRACT));
+ nbuf.len = SUN_LEN_A (&sun);
+ nbuf.maxlen = sizeof (struct sockaddr_un);
+ nbuf.buf = &sun;
+
+ clnt = clnt_vc_create (sock, &nbuf, prog, vers, 0, 0);
+ if (clnt)
+ return clnt;
+#endif
+
strcpy (sun.sun_path, _PATH_RPCBINDSOCK);
nbuf.len = SUN_LEN (&sun);
nbuf.maxlen = sizeof (struct sockaddr_un);
nbuf.buf = &sun;

- return clnt_vc_create (sock, &nbuf, prog, vers, 0, 0);
+ clnt = clnt_vc_create (sock, &nbuf, prog, vers, 0, 0);
+ return clnt;
#endif
}