diff options
author | J. Bruce Fields <bfields@redhat.com> | 2013-06-26 11:09:06 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2013-07-01 17:32:04 -0400 |
commit | cf3aa02cb4a0c5af5557dd47f15a08a7df33182a (patch) | |
tree | 54995388695e95c0abed33d68171ca160c5bfd2d /net | |
parent | 590b743143eae8db40abdfd1ab20bc51ee0ee5db (diff) |
svcrpc: fix handling of too-short rpc's
If we detect that an rpc is too short, we abort and close the
connection. Except, there's a bug here: we're leaving sk_datalen
nonzero without leaving any pages in the sk_pages array. The most
likely result of the inconsistency is a subsequent crash in
svc_tcp_clear_pages.
Also demote the BUG_ON in svc_tcp_clear_pages to a WARN.
Cc: stable@kernel.org
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svcsock.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 0f679df7d072..df74919c81c0 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -917,7 +917,10 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk) | |||
917 | len = svsk->sk_datalen; | 917 | len = svsk->sk_datalen; |
918 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 918 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
919 | for (i = 0; i < npages; i++) { | 919 | for (i = 0; i < npages; i++) { |
920 | BUG_ON(svsk->sk_pages[i] == NULL); | 920 | if (svsk->sk_pages[i] == NULL) { |
921 | WARN_ON_ONCE(1); | ||
922 | continue; | ||
923 | } | ||
921 | put_page(svsk->sk_pages[i]); | 924 | put_page(svsk->sk_pages[i]); |
922 | svsk->sk_pages[i] = NULL; | 925 | svsk->sk_pages[i] = NULL; |
923 | } | 926 | } |
@@ -1092,8 +1095,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1092 | goto err_noclose; | 1095 | goto err_noclose; |
1093 | } | 1096 | } |
1094 | 1097 | ||
1095 | if (svc_sock_reclen(svsk) < 8) | 1098 | if (svc_sock_reclen(svsk) < 8) { |
1099 | svsk->sk_datalen = 0; | ||
1096 | goto err_delete; /* client is nuts. */ | 1100 | goto err_delete; /* client is nuts. */ |
1101 | } | ||
1097 | 1102 | ||
1098 | rqstp->rq_arg.len = svsk->sk_datalen; | 1103 | rqstp->rq_arg.len = svsk->sk_datalen; |
1099 | rqstp->rq_arg.page_base = 0; | 1104 | rqstp->rq_arg.page_base = 0; |