From a6ac7a8b64b691f0c7164abfad8061c6f87f7e30 Mon Sep 17 00:00:00 2001 From: claudio Date: Fri, 22 Mar 2024 07:15:04 +0000 Subject: [PATCH] Limit NFS connections to originate from a reserved port. For TCP connections do the check when adding the socket via nfssvc(2). For UDP do the check early after soreceive(). On top of this limit the sockets added via nfssvc(2) to IPv4 TCP and UDP sockets. OK millert@ deraadt@ --- sys/nfs/nfs_socket.c | 23 +++++++++++++++++------ sys/nfs/nfs_syscalls.c | 23 ++++++++++++++++++++++- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c index 26adde1a849..1743a0e556a 100644 --- a/sys/nfs/nfs_socket.c +++ b/sys/nfs/nfs_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_socket.c,v 1.145 2024/02/05 20:21:39 mvs Exp $ */ +/* $OpenBSD: nfs_socket.c,v 1.146 2024/03/22 07:15:04 claudio Exp $ */ /* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */ /* @@ -1624,11 +1624,22 @@ nfsrv_rcv(struct socket *so, caddr_t arg, int waitflag) error = soreceive(so, &nam, &auio, &mp, NULL, &flags, 0); if (mp) { - if (nam) { - m = nam; - m->m_next = mp; - } else - m = 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) slp->ns_recend->m_nextpkt = m; else diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c index 67539ec23bf..f3ccd3f5c16 100644 --- a/sys/nfs/nfs_syscalls.c +++ b/sys/nfs/nfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_syscalls.c,v 1.121 2024/02/05 20:21:39 mvs Exp $ */ +/* $OpenBSD: nfs_syscalls.c,v 1.122 2024/03/22 07:15:04 claudio Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */ /* @@ -243,6 +243,27 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam) return (EPERM); } } + /* + * Allow only IPv4 UDP and TCP sockets. + */ + if ((so->so_type != SOCK_STREAM && so->so_type != SOCK_DGRAM) || + so->so_proto->pr_domain->dom_family != AF_INET) { + 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); else -- 2.20.1