From 25d694a6fa5656da912e1d8d2f22571f4a06b6b2 Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Thu, 6 Jul 2017 00:53:12 +0000 Subject: [PATCH] Add support for AF_LOCAL socket upcalls to the nfsuserd daemon. This patch adds support for AF_LOCAL socket upcalls to an nfsuserd daemon that supports them. A future patch to the nfsuserd daemon will use AF_LOCAL sockets to avoid a problem when using upcalls to 127.0.0.1 if jails are in use. Suggested by: dfr PR: 205193 --- sys/fs/nfs/nfs_commonkrpc.c | 2 ++ sys/fs/nfs/nfs_commonport.c | 28 ++++++++++++++++++++++++---- sys/fs/nfs/nfs_commonsubs.c | 29 +++++++++++++++++++---------- sys/fs/nfs/nfs_var.h | 2 +- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index b2c396254de..5f4d68bc697 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -199,6 +199,8 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp, nconf = getnetconfigent("udp"); else nconf = getnetconfigent("tcp"); + else if (saddr->sa_family == AF_LOCAL) + nconf = getnetconfigent("local"); else if (nrp->nr_sotype == SOCK_DGRAM) nconf = getnetconfigent("udp6"); diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 28c2d2d1d23..cebacaf6c53 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); */ #include #include +#include #include #include #include @@ -618,11 +619,30 @@ nfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) goto out; } else if (uap->flag & NFSSVC_NFSUSERDPORT) { u_short sockport; + struct sockaddr *sad; + struct sockaddr_un *sun; - error = copyin(uap->argp, (caddr_t)&sockport, - sizeof (u_short)); - if (!error) - error = nfsrv_nfsuserdport(sockport, p); + if ((uap->flag & NFSSVC_NEWSTRUCT) != 0) { + /* New nfsuserd using an AF_LOCAL socket. */ + sun = malloc(sizeof(struct sockaddr_un), M_SONAME, + M_WAITOK | M_ZERO); + error = copyinstr(uap->argp, sun->sun_path, + sizeof(sun->sun_path), NULL); + if (error != 0) { + free(sun, M_SONAME); + return (error); + } + sun->sun_family = AF_LOCAL; + sun->sun_len = SUN_LEN(sun); + sockport = 0; + sad = (struct sockaddr *)sun; + } else { + error = copyin(uap->argp, (caddr_t)&sockport, + sizeof (u_short)); + sad = NULL; + } + if (error == 0) + error = nfsrv_nfsuserdport(sad, sockport, p); } else if (uap->flag & NFSSVC_NFSUSERDDELPORT) { nfsrv_nfsuserddelport(); error = 0; diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 309553d0ef5..86819ac7f23 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -3052,7 +3052,7 @@ nfsrv_cmpmixedcase(u_char *cp, u_char *cp2, int len) * Set the port for the nfsuserd. */ APPLESTATIC int -nfsrv_nfsuserdport(u_short port, NFSPROC_T *p) +nfsrv_nfsuserdport(struct sockaddr *sad, u_short port, NFSPROC_T *p) { struct nfssockreq *rp; struct sockaddr_in *ad; @@ -3062,6 +3062,7 @@ nfsrv_nfsuserdport(u_short port, NFSPROC_T *p) if (nfsrv_nfsuserd) { NFSUNLOCKNAMEID(); error = EPERM; + NFSSOCKADDRFREE(sad); goto out; } nfsrv_nfsuserd = 1; @@ -3071,16 +3072,24 @@ nfsrv_nfsuserdport(u_short port, NFSPROC_T *p) */ rp = &nfsrv_nfsuserdsock; rp->nr_client = NULL; - rp->nr_sotype = SOCK_DGRAM; - rp->nr_soproto = IPPROTO_UDP; - rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST); rp->nr_cred = NULL; - NFSSOCKADDRALLOC(rp->nr_nam); - NFSSOCKADDRSIZE(rp->nr_nam, sizeof (struct sockaddr_in)); - ad = NFSSOCKADDR(rp->nr_nam, struct sockaddr_in *); - ad->sin_family = AF_INET; - ad->sin_addr.s_addr = htonl((u_int32_t)0x7f000001); /* 127.0.0.1 */ - ad->sin_port = port; + rp->nr_lock = (NFSR_RESERVEDPORT | NFSR_LOCALHOST); + if (sad != NULL) { + /* Use the AF_LOCAL socket address passed in. */ + rp->nr_sotype = SOCK_STREAM; + rp->nr_soproto = 0; + rp->nr_nam = sad; + } else { + /* Use the port# for a UDP socket (old nfsuserd). */ + rp->nr_sotype = SOCK_DGRAM; + rp->nr_soproto = IPPROTO_UDP; + NFSSOCKADDRALLOC(rp->nr_nam); + NFSSOCKADDRSIZE(rp->nr_nam, sizeof (struct sockaddr_in)); + ad = NFSSOCKADDR(rp->nr_nam, struct sockaddr_in *); + ad->sin_family = AF_INET; + ad->sin_addr.s_addr = htonl((u_int32_t)0x7f000001); + ad->sin_port = port; + } rp->nr_prog = RPCPROG_NFSUSERD; rp->nr_vers = RPCNFSUSERD_VERS; error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0); diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index ac023dcf451..7c0008242bd 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -128,7 +128,7 @@ int nfsrv_checksetattr(vnode_t, struct nfsrv_descript *, NFSPROC_T *); int nfsrv_checkgetattr(struct nfsrv_descript *, vnode_t, struct nfsvattr *, nfsattrbit_t *, struct ucred *, NFSPROC_T *); -int nfsrv_nfsuserdport(u_short, NFSPROC_T *); +int nfsrv_nfsuserdport(struct sockaddr *, u_short, NFSPROC_T *); void nfsrv_nfsuserddelport(void); void nfsrv_throwawayallstate(NFSPROC_T *); int nfsrv_checksequence(struct nfsrv_descript *, uint32_t, uint32_t *,