zbyszek / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
07864a2
diff -up nfs-utils-1.3.1/support/include/nfslib.h.save nfs-utils-1.3.1/support/include/nfslib.h
07864a2
--- nfs-utils-1.3.1/support/include/nfslib.h.save	2014-11-13 13:36:10.054248000 -0500
07864a2
+++ nfs-utils-1.3.1/support/include/nfslib.h	2014-11-13 13:37:14.045142000 -0500
07864a2
@@ -174,6 +174,7 @@ void closeall(int min);
07864a2
 
07864a2
 int			svctcp_socket (u_long __number, int __reuse);
07864a2
 int			svcudp_socket (u_long __number);
07864a2
+int			svcsock_nonblock (int __sock);
07864a2
 
07864a2
 /* Misc shared code prototypes */
07864a2
 size_t  strlcat(char *, const char *, size_t);
07864a2
diff -up nfs-utils-1.3.1/support/nfs/rpcmisc.c.save nfs-utils-1.3.1/support/nfs/rpcmisc.c
07864a2
--- nfs-utils-1.3.1/support/nfs/rpcmisc.c.save	2014-11-13 13:36:19.386524000 -0500
07864a2
+++ nfs-utils-1.3.1/support/nfs/rpcmisc.c	2014-11-13 13:37:14.051143000 -0500
07864a2
@@ -104,7 +104,7 @@ makesock(int port, int proto)
07864a2
 		return -1;
07864a2
 	}
07864a2
 
07864a2
-	return sock;
07864a2
+	return svcsock_nonblock(sock);
07864a2
 }
07864a2
 
07864a2
 void
07864a2
diff -up nfs-utils-1.3.1/support/nfs/svc_create.c.save nfs-utils-1.3.1/support/nfs/svc_create.c
07864a2
--- nfs-utils-1.3.1/support/nfs/svc_create.c.save	2014-11-13 13:36:44.554269000 -0500
07864a2
+++ nfs-utils-1.3.1/support/nfs/svc_create.c	2014-11-13 13:37:29.571601000 -0500
07864a2
@@ -49,6 +49,8 @@
07864a2
 
07864a2
 #ifdef HAVE_LIBTIRPC
07864a2
 
07864a2
+#include <rpc/rpc_com.h>
07864a2
+
07864a2
 #define SVC_CREATE_XPRT_CACHE_SIZE	(8)
07864a2
 static SVCXPRT *svc_create_xprt_cache[SVC_CREATE_XPRT_CACHE_SIZE] = { NULL, };
07864a2
 
07864a2
@@ -277,6 +279,12 @@ svc_create_nconf_rand_port(const char *n
07864a2
 			"(%s, %u, %s)", name, version, nconf->nc_netid);
07864a2
 		return 0;
07864a2
 	}
07864a2
+	if (svcsock_nonblock(xprt->xp_fd) < 0) {
07864a2
+		/* close() already done by svcsock_nonblock() */
07864a2
+		xprt->xp_fd = RPC_ANYFD;
07864a2
+		SVC_DESTROY(xprt);
07864a2
+		return 0;
07864a2
+	}
07864a2
 
07864a2
 	if (!svc_reg(xprt, program, version, dispatch, nconf)) {
07864a2
 		/* svc_reg(3) destroys @xprt in this case */
07864a2
@@ -332,6 +340,7 @@ svc_create_nconf_fixed_port(const char *
07864a2
 		int fd;
07864a2
 
07864a2
 		fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf);
07864a2
+		fd = svcsock_nonblock(fd);
07864a2
 		if (fd == -1)
07864a2
 			goto out_free;
07864a2
 
07864a2
@@ -394,6 +403,7 @@ nfs_svc_create(char *name, const rpcprog
07864a2
 	const struct sigaction create_sigaction = {
07864a2
 		.sa_handler	= SIG_IGN,
07864a2
 	};
07864a2
+	int maxrec = RPC_MAXDATASIZE;
07864a2
 	unsigned int visible, up, servport;
07864a2
 	struct netconfig *nconf;
07864a2
 	void *handlep;
07864a2
@@ -405,6 +415,20 @@ nfs_svc_create(char *name, const rpcprog
07864a2
 	 */
07864a2
 	(void)sigaction(SIGPIPE, &create_sigaction, NULL);
07864a2
 
07864a2
+	/*
07864a2
+	 * Setting MAXREC also enables non-blocking mode for tcp connections.
07864a2
+	 * This avoids DOS attacks by a client sending many requests but never
07864a2
+	 * reading the reply:
07864a2
+	 * - if a second request already is present for reading in the socket,
07864a2
+	 *   after the first request just was read, libtirpc will break the
07864a2
+	 *   connection. Thus an attacker can't simply send requests as fast as
07864a2
+	 *   he can without waiting for the response.
07864a2
+	 * - if the write buffer of the socket is full, the next write() will
07864a2
+	 *   fail with EAGAIN. libtirpc will retry the write in a loop for max.
07864a2
+	 *   2 seconds. If write still fails, the connection will be closed.
07864a2
+	 */   
07864a2
+	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
07864a2
+
07864a2
 	handlep = setnetconfig();
07864a2
 	if (handlep == NULL) {
07864a2
 		xlog(L_ERROR, "Failed to access local netconfig database: %s",
07864a2
diff -up nfs-utils-1.3.1/support/nfs/svc_socket.c.save nfs-utils-1.3.1/support/nfs/svc_socket.c
07864a2
--- nfs-utils-1.3.1/support/nfs/svc_socket.c.save	2014-11-13 13:36:29.925836000 -0500
07864a2
+++ nfs-utils-1.3.1/support/nfs/svc_socket.c	2014-11-13 13:37:14.055142000 -0500
07864a2
@@ -76,6 +76,39 @@ int getservport(u_long number, const cha
07864a2
 	return 0;
07864a2
 }
07864a2
 
07864a2
+int
07864a2
+svcsock_nonblock(int sock)
07864a2
+{
07864a2
+	int flags;
07864a2
+
07864a2
+	if (sock < 0)
07864a2
+		return sock;
07864a2
+
07864a2
+	/* This socket might be shared among multiple processes
07864a2
+	 * if mountd is run multi-threaded.  So it is safest to
07864a2
+	 * make it non-blocking, else all threads might wake
07864a2
+	 * one will get the data, and the others will block
07864a2
+	 * indefinitely.
07864a2
+	 * In all cases, transaction on this socket are atomic
07864a2
+	 * (accept for TCP, packet-read and packet-write for UDP)
07864a2
+	 * so O_NONBLOCK will not confuse unprepared code causing
07864a2
+	 * it to corrupt messages.
07864a2
+	 * It generally safest to have O_NONBLOCK when doing an accept
07864a2
+	 * as if we get a RST after the SYN and before accept runs,
07864a2
+	 * we can block despite being told there was an acceptable
07864a2
+	 * connection.
07864a2
+	 */
07864a2
+	if ((flags = fcntl(sock, F_GETFL)) < 0)
07864a2
+		perror(_("svc_socket: can't get socket flags"));
07864a2
+	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
07864a2
+		perror(_("svc_socket: can't set socket flags"));
07864a2
+	else
07864a2
+		return sock;
07864a2
+
07864a2
+	(void) __close(sock);
07864a2
+	return -1;
07864a2
+}
07864a2
+
07864a2
 static int
07864a2
 svc_socket (u_long number, int type, int protocol, int reuse)
07864a2
 {
07864a2
@@ -113,38 +146,7 @@ svc_socket (u_long number, int type, int
07864a2
       sock = -1;
07864a2
     }
07864a2
 
07864a2
-  if (sock >= 0)
07864a2
-    {
07864a2
-	    /* This socket might be shared among multiple processes
07864a2
-	     * if mountd is run multi-threaded.  So it is safest to
07864a2
-	     * make it non-blocking, else all threads might wake
07864a2
-	     * one will get the data, and the others will block
07864a2
-	     * indefinitely.
07864a2
-	     * In all cases, transaction on this socket are atomic
07864a2
-	     * (accept for TCP, packet-read and packet-write for UDP)
07864a2
-	     * so O_NONBLOCK will not confuse unprepared code causing
07864a2
-	     * it to corrupt messages.
07864a2
-	     * It generally safest to have O_NONBLOCK when doing an accept
07864a2
-	     * as if we get a RST after the SYN and before accept runs,
07864a2
-	     * we can block despite being told there was an acceptable
07864a2
-	     * connection.
07864a2
-	     */
07864a2
-	int flags;
07864a2
-	if ((flags = fcntl(sock, F_GETFL)) < 0)
07864a2
-	  {
07864a2
-	      perror (_("svc_socket: can't get socket flags"));
07864a2
-	      (void) __close (sock);
07864a2
-	      sock = -1;
07864a2
-	  }
07864a2
-	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
07864a2
-	  {
07864a2
-	      perror (_("svc_socket: can't set socket flags"));
07864a2
-	      (void) __close (sock);
07864a2
-	      sock = -1;
07864a2
-	  }
07864a2
-    }
07864a2
-
07864a2
-  return sock;
07864a2
+  return svcsock_nonblock(sock);
07864a2
 }
07864a2
 
07864a2
 /*