Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

SUNRPC: attempt to reach rpcbind with an abstract socket name

NFS is primarily name-spaced using network namespaces. However it
contacts rpcbind (and gss_proxy) using AF_UNIX sockets which are
name-spaced using the mount namespaces. This requires a container using
NFSv3 (the form that requires rpcbind) to manage both network and mount
namespaces, which can seem an unnecessary burden.

As NFS is primarily a network service it makes sense to use network
namespaces as much as possible, and to prefer to communicate with an
rpcbind running in the same network namespace. This can be done, while
preserving the benefits of AF_UNIX sockets, by using an abstract socket
address.

An abstract address has a nul at the start of sun_path, and a length
that is exactly the complete size of the sockaddr_un up to the end of
the name, NOT including any trailing nul (which is not part of the
address).
Abstract addresses are local to a network namespace - regular AF_UNIX
path names a resolved in the mount namespace ignoring the network
namespace.

This patch causes rpcb to first try an abstract address before
continuing with regular AF_UNIX and then IP addresses. This ensures
backwards compatibility.

Choosing the name needs some care as the same address will be configured
for rpcbind, and needs to be built in to libtirpc for this enhancement
to be fully successful. There is no formal standard for choosing
abstract addresses. The defacto standard appears to be to use a path
name similar to what would be used for a filesystem AF_UNIX address -
but with a leading nul.

In that case
"\0/var/run/rpcbind.sock"
seems like the best choice. However at this time /var/run is deprecated
in favour of /run, so
"\0/run/rpcbind.sock"
might be better.
Though as we are deliberately moving away from using the filesystem it
might seem more sensible to explicitly break the connection and just
have
"\0rpcbind.socket"
using the same name as the systemd unit file..

This patch chooses the second option, which seems least likely to raise
objections.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>

authored by

NeilBrown and committed by
Trond Myklebust
626590ea 4388ce05

+31 -8
+31 -8
net/sunrpc/rpcb_clnt.c
··· 36 36 #include "netns.h" 37 37 38 38 #define RPCBIND_SOCK_PATHNAME "/var/run/rpcbind.sock" 39 + #define RPCBIND_SOCK_ABSTRACT_NAME "\0/run/rpcbind.sock" 39 40 40 41 #define RPCBIND_PROGRAM (100000u) 41 42 #define RPCBIND_PORT (111u) ··· 217 216 sn->rpcb_users = 1; 218 217 } 219 218 219 + /* Evaluate to actual length of the `sockaddr_un' structure. */ 220 + # define SUN_LEN(ptr) (offsetof(struct sockaddr_un, sun_path) \ 221 + + 1 + strlen((ptr)->sun_path + 1)) 222 + 220 223 /* 221 224 * Returns zero on success, otherwise a negative errno value 222 225 * is returned. 223 226 */ 224 - static int rpcb_create_local_unix(struct net *net) 227 + static int rpcb_create_af_local(struct net *net, 228 + const struct sockaddr_un *addr) 225 229 { 226 - static const struct sockaddr_un rpcb_localaddr_rpcbind = { 227 - .sun_family = AF_LOCAL, 228 - .sun_path = RPCBIND_SOCK_PATHNAME, 229 - }; 230 230 struct rpc_create_args args = { 231 231 .net = net, 232 232 .protocol = XPRT_TRANSPORT_LOCAL, 233 - .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, 234 - .addrsize = sizeof(rpcb_localaddr_rpcbind), 233 + .address = (struct sockaddr *)addr, 234 + .addrsize = SUN_LEN(addr), 235 235 .servername = "localhost", 236 236 .program = &rpcb_program, 237 237 .version = RPCBVERS_2, ··· 269 267 270 268 out: 271 269 return result; 270 + } 271 + 272 + static int rpcb_create_local_abstract(struct net *net) 273 + { 274 + static const struct sockaddr_un rpcb_localaddr_abstract = { 275 + .sun_family = AF_LOCAL, 276 + .sun_path = RPCBIND_SOCK_ABSTRACT_NAME, 277 + }; 278 + 279 + return rpcb_create_af_local(net, &rpcb_localaddr_abstract); 280 + } 281 + 282 + static int rpcb_create_local_unix(struct net *net) 283 + { 284 + static const struct sockaddr_un rpcb_localaddr_unix = { 285 + .sun_family = AF_LOCAL, 286 + .sun_path = RPCBIND_SOCK_PATHNAME, 287 + }; 288 + 289 + return rpcb_create_af_local(net, &rpcb_localaddr_unix); 272 290 } 273 291 274 292 /* ··· 354 332 if (rpcb_get_local(net)) 355 333 goto out; 356 334 357 - if (rpcb_create_local_unix(net) != 0) 335 + if (rpcb_create_local_abstract(net) != 0 && 336 + rpcb_create_local_unix(net) != 0) 358 337 result = rpcb_create_local_net(net); 359 338 360 339 out: