5.0-stable review patch.  If anyone has any objections, please let me know.

------------------

From: J. Bruce Fields <bfie...@redhat.com>

commit b7e5034cbecf5a65b7bfdc2b20a8378039577706 upstream.

James Pearson found that an NFS server stopped responding to UDP
requests if started with more than 1017 threads.

sv_max_mesg is about 2^20, so that is probably where the calculation
performed by

        svc_sock_setbufsize(svsk->sk_sock,
                            (serv->sv_nrthreads+3) * serv->sv_max_mesg,
                            (serv->sv_nrthreads+3) * serv->sv_max_mesg);

starts to overflow an int.

Reported-by: James Pearson <jcpear...@gmail.com>
Tested-by: James Pearson <jcpear...@gmail.com>
Cc: sta...@vger.kernel.org
Signed-off-by: J. Bruce Fields <bfie...@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 net/sunrpc/svcsock.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -349,12 +349,16 @@ static ssize_t svc_recvfrom(struct svc_r
 /*
  * Set socket snd and rcv buffer lengths
  */
-static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
-                               unsigned int rcv)
+static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
 {
+       unsigned int max_mesg = svsk->sk_xprt.xpt_server->sv_max_mesg;
+       struct socket *sock = svsk->sk_sock;
+
+       nreqs = min(nreqs, INT_MAX / 2 / max_mesg);
+
        lock_sock(sock->sk);
-       sock->sk->sk_sndbuf = snd * 2;
-       sock->sk->sk_rcvbuf = rcv * 2;
+       sock->sk->sk_sndbuf = nreqs * max_mesg * 2;
+       sock->sk->sk_rcvbuf = nreqs * max_mesg * 2;
        sock->sk->sk_write_space(sock->sk);
        release_sock(sock->sk);
 }
@@ -516,9 +520,7 @@ static int svc_udp_recvfrom(struct svc_r
             * provides an upper bound on the number of threads
             * which will access the socket.
             */
-           svc_sock_setbufsize(svsk->sk_sock,
-                               (serv->sv_nrthreads+3) * serv->sv_max_mesg,
-                               (serv->sv_nrthreads+3) * serv->sv_max_mesg);
+           svc_sock_setbufsize(svsk, serv->sv_nrthreads + 3);
 
        clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
        skb = NULL;
@@ -681,9 +683,7 @@ static void svc_udp_init(struct svc_sock
         * receive and respond to one request.
         * svc_udp_recvfrom will re-adjust if necessary
         */
-       svc_sock_setbufsize(svsk->sk_sock,
-                           3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
-                           3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
+       svc_sock_setbufsize(svsk, 3);
 
        /* data might have come in before data_ready set up */
        set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);


Reply via email to