aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-08-25 20:27:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-08-25 20:27:26 -0400
commit105065c3f7164d756ee5495b8670e57f2bcf65c3 (patch)
treed0cf33dfc3f01f8dc596329844dcc695f4d079b5
parent8c7932a32e1ebf6e845bd32a5399cce442d2e745 (diff)
parenteebe53e87f97975ee58a21693e44797608bf679c (diff)
Merge tag 'nfsd-4.13-2' of git://linux-nfs.org/~bfields/linux
Pull nfsd fixes from Bruce Fields: "Two nfsd bugfixes, neither 4.13 regressions, but both potentially serious" * tag 'nfsd-4.13-2' of git://linux-nfs.org/~bfields/linux: net: sunrpc: svcsock: fix NULL-pointer exception nfsd: Limit end of page list when decoding NFSv4 WRITE
-rw-r--r--fs/nfsd/nfs4xdr.c6
-rw-r--r--net/sunrpc/svcsock.c22
2 files changed, 22 insertions, 6 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 20fbcab97753..5f940d2a136b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -144,7 +144,7 @@ static void next_decode_page(struct nfsd4_compoundargs *argp)
144 argp->p = page_address(argp->pagelist[0]); 144 argp->p = page_address(argp->pagelist[0]);
145 argp->pagelist++; 145 argp->pagelist++;
146 if (argp->pagelen < PAGE_SIZE) { 146 if (argp->pagelen < PAGE_SIZE) {
147 argp->end = argp->p + (argp->pagelen>>2); 147 argp->end = argp->p + XDR_QUADLEN(argp->pagelen);
148 argp->pagelen = 0; 148 argp->pagelen = 0;
149 } else { 149 } else {
150 argp->end = argp->p + (PAGE_SIZE>>2); 150 argp->end = argp->p + (PAGE_SIZE>>2);
@@ -1279,9 +1279,7 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1279 argp->pagelen -= pages * PAGE_SIZE; 1279 argp->pagelen -= pages * PAGE_SIZE;
1280 len -= pages * PAGE_SIZE; 1280 len -= pages * PAGE_SIZE;
1281 1281
1282 argp->p = (__be32 *)page_address(argp->pagelist[0]); 1282 next_decode_page(argp);
1283 argp->pagelist++;
1284 argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
1285 } 1283 }
1286 argp->p += XDR_QUADLEN(len); 1284 argp->p += XDR_QUADLEN(len);
1287 1285
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 2b720fa35c4f..e18500151236 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -421,6 +421,9 @@ static void svc_data_ready(struct sock *sk)
421 dprintk("svc: socket %p(inet %p), busy=%d\n", 421 dprintk("svc: socket %p(inet %p), busy=%d\n",
422 svsk, sk, 422 svsk, sk,
423 test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); 423 test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
424
425 /* Refer to svc_setup_socket() for details. */
426 rmb();
424 svsk->sk_odata(sk); 427 svsk->sk_odata(sk);
425 if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags)) 428 if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags))
426 svc_xprt_enqueue(&svsk->sk_xprt); 429 svc_xprt_enqueue(&svsk->sk_xprt);
@@ -437,6 +440,9 @@ static void svc_write_space(struct sock *sk)
437 if (svsk) { 440 if (svsk) {
438 dprintk("svc: socket %p(inet %p), write_space busy=%d\n", 441 dprintk("svc: socket %p(inet %p), write_space busy=%d\n",
439 svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); 442 svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
443
444 /* Refer to svc_setup_socket() for details. */
445 rmb();
440 svsk->sk_owspace(sk); 446 svsk->sk_owspace(sk);
441 svc_xprt_enqueue(&svsk->sk_xprt); 447 svc_xprt_enqueue(&svsk->sk_xprt);
442 } 448 }
@@ -760,8 +766,12 @@ static void svc_tcp_listen_data_ready(struct sock *sk)
760 dprintk("svc: socket %p TCP (listen) state change %d\n", 766 dprintk("svc: socket %p TCP (listen) state change %d\n",
761 sk, sk->sk_state); 767 sk, sk->sk_state);
762 768
763 if (svsk) 769 if (svsk) {
770 /* Refer to svc_setup_socket() for details. */
771 rmb();
764 svsk->sk_odata(sk); 772 svsk->sk_odata(sk);
773 }
774
765 /* 775 /*
766 * This callback may called twice when a new connection 776 * This callback may called twice when a new connection
767 * is established as a child socket inherits everything 777 * is established as a child socket inherits everything
@@ -794,6 +804,8 @@ static void svc_tcp_state_change(struct sock *sk)
794 if (!svsk) 804 if (!svsk)
795 printk("svc: socket %p: no user data\n", sk); 805 printk("svc: socket %p: no user data\n", sk);
796 else { 806 else {
807 /* Refer to svc_setup_socket() for details. */
808 rmb();
797 svsk->sk_ostate(sk); 809 svsk->sk_ostate(sk);
798 if (sk->sk_state != TCP_ESTABLISHED) { 810 if (sk->sk_state != TCP_ESTABLISHED) {
799 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); 811 set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
@@ -1381,12 +1393,18 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
1381 return ERR_PTR(err); 1393 return ERR_PTR(err);
1382 } 1394 }
1383 1395
1384 inet->sk_user_data = svsk;
1385 svsk->sk_sock = sock; 1396 svsk->sk_sock = sock;
1386 svsk->sk_sk = inet; 1397 svsk->sk_sk = inet;
1387 svsk->sk_ostate = inet->sk_state_change; 1398 svsk->sk_ostate = inet->sk_state_change;
1388 svsk->sk_odata = inet->sk_data_ready; 1399 svsk->sk_odata = inet->sk_data_ready;
1389 svsk->sk_owspace = inet->sk_write_space; 1400 svsk->sk_owspace = inet->sk_write_space;
1401 /*
1402 * This barrier is necessary in order to prevent race condition
1403 * with svc_data_ready(), svc_listen_data_ready() and others
1404 * when calling callbacks above.
1405 */
1406 wmb();
1407 inet->sk_user_data = svsk;
1390 1408
1391 /* Initialize the socket */ 1409 /* Initialize the socket */
1392 if (sock->type == SOCK_DGRAM) 1410 if (sock->type == SOCK_DGRAM)