svn commit: r184921 - in head/sys: nfsserver xdr

Doug Rabson dfr at FreeBSD.org
Thu Nov 13 06:36:52 PST 2008


Author: dfr
Date: Thu Nov 13 14:36:52 2008
New Revision: 184921
URL: http://svn.freebsd.org/changeset/base/184921

Log:
  Use the remote address for access control, not the local address. This fixes
  the nfsd problems that some people have with the new code.
  
  Add support for the vfs.nfsrv.nfs_privport sysctl which denies access unless
  the client is using a port number less than 1024. Not really sure if this is
  particularly useful since it doesn't add any real security.

Modified:
  head/sys/nfsserver/nfs_srvkrpc.c
  head/sys/xdr/xdr_mbuf.c

Modified: head/sys/nfsserver/nfs_srvkrpc.c
==============================================================================
--- head/sys/nfsserver/nfs_srvkrpc.c	Thu Nov 13 11:35:18 2008	(r184920)
+++ head/sys/nfsserver/nfs_srvkrpc.c	Thu Nov 13 14:36:52 2008	(r184921)
@@ -348,19 +348,61 @@ nfssvc_program(struct svc_req *rqst, SVC
 	nfs_realign(&mreq);
 
 	/*
-	 * Note: we want rq_addr, not svc_getrpccaller -
+	 * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 -
 	 * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP
 	 * mounts.
 	 */
 	memset(&nd, 0, sizeof(nd));
 	nd.nd_md = nd.nd_mrep = mreq;
 	nd.nd_dpos = mtod(mreq, caddr_t);
-	nd.nd_nam = (struct sockaddr *) &xprt->xp_ltaddr;
+	nd.nd_nam = svc_getrpccaller(rqst);
 	nd.nd_nam2 = rqst->rq_addr;
 	nd.nd_procnum = procnum;
 	nd.nd_cr = NULL;
 	nd.nd_flag = flag;
 
+	if (nfs_privport) {
+		/* Check if source port is privileged */
+		u_short port;
+		struct sockaddr *nam = nd.nd_nam;
+		struct sockaddr_in *sin;
+
+		sin = (struct sockaddr_in *)nam;
+		/*
+		 * INET/INET6 - same code:
+		 *    sin_port and sin6_port are at same offset
+		 */
+		port = ntohs(sin->sin_port);
+		if (port >= IPPORT_RESERVED &&
+		    nd.nd_procnum != NFSPROC_NULL) {
+#ifdef INET6
+			char b6[INET6_ADDRSTRLEN];
+#if defined(KLD_MODULE)
+			/* Do not use ip6_sprintf: the nfs module should work without INET6. */
+#define ip6_sprintf(buf, a)						\
+			(sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x",	\
+			    (a)->s6_addr16[0], (a)->s6_addr16[1],	\
+			    (a)->s6_addr16[2], (a)->s6_addr16[3],	\
+			    (a)->s6_addr16[4], (a)->s6_addr16[5],	\
+			    (a)->s6_addr16[6], (a)->s6_addr16[7]),	\
+			    (buf))
+#endif
+#endif
+			printf("NFS request from unprivileged port (%s:%d)\n",
+#ifdef INET6
+			    sin->sin_family == AF_INET6 ?
+			    ip6_sprintf(b6, &satosin6(sin)->sin6_addr) :
+#if defined(KLD_MODULE)
+#undef ip6_sprintf
+#endif
+#endif
+			    inet_ntoa(sin->sin_addr), port);
+			svcerr_weakauth(rqst);
+			svc_freereq(rqst);
+			return;
+		}
+	}
+
 	if (proc != nfsrv_null) {
 		if (!svc_getcred(rqst, &nd.nd_cr, &nd.nd_credflavor)) {
 			svcerr_weakauth(rqst);

Modified: head/sys/xdr/xdr_mbuf.c
==============================================================================
--- head/sys/xdr/xdr_mbuf.c	Thu Nov 13 11:35:18 2008	(r184920)
+++ head/sys/xdr/xdr_mbuf.c	Thu Nov 13 14:36:52 2008	(r184921)
@@ -65,6 +65,7 @@ void
 xdrmbuf_create(XDR *xdrs, struct mbuf *m, enum xdr_op op)
 {
 
+	KASSERT(m != NULL, ("xdrmbuf_create with NULL mbuf chain"));
 	xdrs->x_op = op;
 	xdrs->x_ops = &xdrmbuf_ops;
 	xdrs->x_base = (char *) m;


More information about the svn-src-all mailing list