From 9ca5b5eb457be4807fb0493bcc586edb11ee26b7 Mon Sep 17 00:00:00 2001 From: ratchov Date: Fri, 19 Apr 2024 06:50:37 +0000 Subject: [PATCH] nfs: Permit null requests (aka server pings) from non-reserved ports Unfortunately, this is recommended by rfc 2623 and used by Linux nfs-utils to mount NFS exports. So until nfs-utils switches into using reserved ports, this is needed to mount OpenBSD file-systems on most (all?) Linux distros. Bits from claudio, ok millert --- sys/nfs/nfs_socket.c | 18 ++---------------- sys/nfs/nfs_syscalls.c | 36 +++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c index 9760db85492..1f8635ed6ae 100644 --- a/sys/nfs/nfs_socket.c +++ b/sys/nfs/nfs_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_socket.c,v 1.147 2024/03/31 13:50:00 mvs Exp $ */ +/* $OpenBSD: nfs_socket.c,v 1.148 2024/04/19 06:50:37 ratchov Exp $ */ /* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */ /* @@ -1588,7 +1588,7 @@ nfsrv_rcv(struct socket *so, caddr_t arg, int waitflag) */ auio.uio_resid = 1000000000; flags = MSG_DONTWAIT; - error = soreceive(so, &nam, &auio, &mp, NULL, + error = soreceive(so, NULL, &auio, &mp, NULL, &flags, 0); if (error || mp == NULL) { if (error == EWOULDBLOCK) @@ -1626,20 +1626,6 @@ nfsrv_rcv(struct socket *so, caddr_t arg, int waitflag) error = soreceive(so, &nam, &auio, &mp, NULL, &flags, 0); if (mp) { - struct sockaddr_in *sin; - - if (nam == NULL) { - nfsstats.srv_errs++; - m_freem(mp); - continue; - } - if (in_nam2sin(nam, &sin) != 0 || - ntohs(sin->sin_port) >= IPPORT_RESERVED) { - nfsstats.srv_errs++; - m_freem(nam); - m_freem(mp); - continue; - } m = nam; m->m_next = mp; if (slp->ns_recend) diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c index 32f28f021e0..13bbd641d53 100644 --- a/sys/nfs/nfs_syscalls.c +++ b/sys/nfs/nfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_syscalls.c,v 1.123 2024/03/31 13:50:00 mvs Exp $ */ +/* $OpenBSD: nfs_syscalls.c,v 1.124 2024/04/19 06:50:37 ratchov Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */ /* @@ -251,18 +251,6 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam) m_freem(mynam); return (EINVAL); } - if (mynam != NULL) { - struct sockaddr_in *sin; - error = in_nam2sin(mynam, &sin); - if (error) { - m_freem(mynam); - return (error); - } - if (ntohs(sin->sin_port) >= IPPORT_RESERVED) { - m_freem(mynam); - return (ECONNREFUSED); - } - } if (so->so_type == SOCK_STREAM) siz = NFS_MAXPACKET + sizeof (u_long); @@ -323,6 +311,18 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam) return (0); } +static inline int nfssvc_checknam(struct mbuf *nam) +{ + struct sockaddr_in *sin; + + if (nam == NULL || + in_nam2sin(nam, &sin) != 0 || + ntohs(sin->sin_port) >= IPPORT_RESERVED) { + return -1; + } + return 0; +} + /* * Called by nfssvc() for nfsds. Just loops around servicing rpc requests * until it is killed by a signal. @@ -402,6 +402,16 @@ loop: cacherep = nfsrv_getcache(nd, slp, &mreq); switch (cacherep) { case RC_DOIT: + /* + * Unless this is a null request (server ping), make + * sure that the client is using a reserved source port. + */ + if (nd->nd_procnum != 0 && nfssvc_checknam(nd->nd_nam) == -1) { + /* drop it */ + m_freem(nd->nd_mrep); + m_freem(nd->nd_nam2); + break; + } error = (*(nfsrv3_procs[nd->nd_procnum]))(nd, slp, nfsd->nfsd_procp, &mreq); if (mreq == NULL) { if (nd != NULL) { -- 2.20.1