Re: [nfs-utils] [PATCH 3/3] rpc.mountd: set libtirpc nonblocking mode to avoid DOS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 05 Nov 2014 21:24:29 +0100 bstroesser@xxxxxxxxxxxxxx wrote:

> From: Bodo Stroesser <bstroesser@xxxxxxxxxxxxxx>
> Date: Thu, 09 Oct 2014 13:06:19 +0200
> Subject: [nfs-utils] [PATCH 3/3] rpc.mountd: set libtirpc nonblocking mode to avoid DOS
> 
> This patch is experimental. In works fine in that it removes the vulnerability
> against a DOS attack. rpc.mountd can be blocked by a bad client, that sends
> many RPC requests but never reads the responses. This might happen intentionally
> or caused by a wrong network config (MTU).
> The patch switches on the nonblocking mode of libtirpc. In that mode writes can
> block for a max. of 2 seconds. Attackers are forced to send requests slower, as
> libtirpc will close a connection if it finds two requests to read at the same
> time.
> I do not know, whether setting MAXREC could cause trouble e.g. with big replies.
>  
> 
> Signed-off-by: Bodo Stroesser <bstroesser@xxxxxxxxxxxxxx>
> ---
> 
> --- nfs-utils-1.3.1/support/nfs/svc_create.c	2014-10-09 12:09:15.000000000 +0200
> +++ nfs-utils-1.3.1/support/nfs/svc_create.c	2014-10-09 12:13:32.000000000 +0200
> @@ -49,6 +49,8 @@
>  
>  #ifdef HAVE_LIBTIRPC
>  
> +#include <rpc/rpc_com.h>
> +
>  #define SVC_CREATE_XPRT_CACHE_SIZE	(8)
>  static SVCXPRT *svc_create_xprt_cache[SVC_CREATE_XPRT_CACHE_SIZE] = { NULL, };
>  
> @@ -401,6 +403,7 @@
>  	const struct sigaction create_sigaction = {
>  		.sa_handler	= SIG_IGN,
>  	};
> +	int maxrec = RPC_MAXDATASIZE;
>  	unsigned int visible, up, servport;
>  	struct netconfig *nconf;
>  	void *handlep;
> @@ -412,6 +415,20 @@
>  	 */
>  	(void)sigaction(SIGPIPE, &create_sigaction, NULL);
>  
> +	/*
> +	 * Setting MAXREC also enables non-blocking mode for tcp connections.
> +	 * This avoids DOS attacks by a client sending many requests but never
> +	 * reading the reply:
> +	 * - if a second request already is present for reading in the socket,
> +	 *   after the first request just was read, libtirpc will break the
> +	 *   connection. Thus an attacker can't simply send requests as fast as
> +	 *   he can without waiting for the response.
> +	 * - if the write buffer of the socket is full, the next write() will
> +	 *   fail with EAGAIN. libtirpc will retry the write in a loop for max.
> +	 *   2 seconds. If write still fails, the connection will be closed.
> +	 */   
> +	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
> +
>  	handlep = setnetconfig();
>  	if (handlep == NULL) {
>  		xlog(L_ERROR, "Failed to access local netconfig database: %s",


RPC_MAXDATASIZE is 9000.
This number is only relevant on the receive size.
When sending, the "sendsz" passed to svc_tli_create (which default to 64K for
TCP) is used for the 'record size'.
When receiving, any 'record' in a tcp connection which is larger than 9000
bytes will be rejected.
No message to mountd or statd could ever be that large, so this number
does not impose a problematic limit.

As far as I can tell, this patch is safe and is a clear improvement.

Reviewed-by: NeilBrown <neilb@xxxxxxx>

Thanks,
NeilBrown

Attachment: pgpnanxPN1GSl.pgp
Description: OpenPGP digital signature


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux