| From 7c9526b1e36c4ead68cd0caa2aac02374b490ddc Mon Sep 17 00:00:00 2001 |
| From: Chuck Lever <chuck.lever@oracle.com> |
| Date: Tue, 29 Nov 2016 11:04:34 -0500 |
| Subject: [PATCH] svcauth_gss: Close connection when dropping an incoming |
| message |
| |
| commit 4d712ef1db05c3aa5c3b690a50c37ebad584c53f upstream. |
| |
| S5.3.3.1 of RFC 2203 requires that an incoming GSS-wrapped message |
| whose sequence number lies outside the current window is dropped. |
| The rationale is: |
| |
| The reason for discarding requests silently is that the server |
| is unable to determine if the duplicate or out of range request |
| was due to a sequencing problem in the client, network, or the |
| operating system, or due to some quirk in routing, or a replay |
| attack by an intruder. Discarding the request allows the client |
| to recover after timing out, if indeed the duplication was |
| unintentional or well intended. |
| |
| However, clients may rely on the server dropping the connection to |
| indicate that a retransmit is needed. Without a connection reset, a |
| client can wait forever without retransmitting, and the workload |
| just stops dead. I've reproduced this behavior by running xfstests |
| generic/323 on an NFSv4.0 mount with proto=rdma and sec=krb5i. |
| |
| To address this issue, have the server close the connection when it |
| silently discards an incoming message due to a GSS sequence number |
| problem. |
| |
| There are a few other places where the server will never reply. |
| Change those spots in a similar fashion. |
| |
| Signed-off-by: Chuck Lever <chuck.lever@oracle.com> |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c |
| index a16b5a3e983c..74a1b77d3697 100644 |
| --- a/net/sunrpc/auth_gss/svcauth_gss.c |
| +++ b/net/sunrpc/auth_gss/svcauth_gss.c |
| @@ -1541,7 +1541,7 @@ complete: |
| ret = SVC_COMPLETE; |
| goto out; |
| drop: |
| - ret = SVC_DROP; |
| + ret = SVC_CLOSE; |
| out: |
| if (rsci) |
| cache_put(&rsci->h, sn->rsc_cache); |
| diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c |
| index c5b0cb4f4056..463d417ed77c 100644 |
| --- a/net/sunrpc/svc.c |
| +++ b/net/sunrpc/svc.c |
| @@ -1138,8 +1138,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) |
| case SVC_DENIED: |
| goto err_bad_auth; |
| case SVC_CLOSE: |
| - if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) |
| - svc_close_xprt(rqstp->rq_xprt); |
| + goto close; |
| case SVC_DROP: |
| goto dropit; |
| case SVC_COMPLETE: |
| @@ -1229,7 +1228,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) |
| |
| sendit: |
| if (svc_authorise(rqstp)) |
| - goto dropit; |
| + goto close; |
| return 1; /* Caller can now send it */ |
| |
| dropit: |
| @@ -1237,11 +1236,16 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) |
| dprintk("svc: svc_process dropit\n"); |
| return 0; |
| |
| + close: |
| + if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) |
| + svc_close_xprt(rqstp->rq_xprt); |
| + dprintk("svc: svc_process close\n"); |
| + return 0; |
| + |
| err_short_len: |
| svc_printk(rqstp, "short len %Zd, dropping request\n", |
| argv->iov_len); |
| - |
| - goto dropit; /* drop request */ |
| + goto close; |
| |
| err_bad_rpc: |
| serv->sv_stats->rpcbadfmt++; |
| -- |
| 2.12.0 |
| |