| From b84d211b1fd8dbaa6710ea2dcbfc05209822bb18 Mon Sep 17 00:00:00 2001 |
| From: Gerrit Renker <gerrit@erg.abdn.ac.uk> |
| Date: Tue, 1 Mar 2011 23:02:07 -0800 |
| Subject: [PATCH] dccp: fix oops on Reset after close |
| |
| commit 720dc34bbbe9493c7bd48b2243058b4e447a929d upstream. |
| |
| This fixes a bug in the order of dccp_rcv_state_process() that still permitted |
| reception even after closing the socket. A Reset after close thus causes a NULL |
| pointer dereference by not preventing operations on an already torn-down socket. |
| |
| dccp_v4_do_rcv() |
| | |
| | state other than OPEN |
| v |
| dccp_rcv_state_process() |
| | |
| | DCCP_PKT_RESET |
| v |
| dccp_rcv_reset() |
| | |
| v |
| dccp_time_wait() |
| |
| WARNING: at net/ipv4/inet_timewait_sock.c:141 __inet_twsk_hashdance+0x48/0x128() |
| Modules linked in: arc4 ecb carl9170 rt2870sta(C) mac80211 r8712u(C) crc_ccitt ah |
| [<c0038850>] (unwind_backtrace+0x0/0xec) from [<c0055364>] (warn_slowpath_common) |
| [<c0055364>] (warn_slowpath_common+0x4c/0x64) from [<c0055398>] (warn_slowpath_n) |
| [<c0055398>] (warn_slowpath_null+0x1c/0x24) from [<c02b72d0>] (__inet_twsk_hashd) |
| [<c02b72d0>] (__inet_twsk_hashdance+0x48/0x128) from [<c031caa0>] (dccp_time_wai) |
| [<c031caa0>] (dccp_time_wait+0x40/0xc8) from [<c031c15c>] (dccp_rcv_state_proces) |
| [<c031c15c>] (dccp_rcv_state_process+0x120/0x538) from [<c032609c>] (dccp_v4_do_) |
| [<c032609c>] (dccp_v4_do_rcv+0x11c/0x14c) from [<c0286594>] (release_sock+0xac/0) |
| [<c0286594>] (release_sock+0xac/0x110) from [<c031fd34>] (dccp_close+0x28c/0x380) |
| [<c031fd34>] (dccp_close+0x28c/0x380) from [<c02d9a78>] (inet_release+0x64/0x70) |
| |
| The fix is by testing the socket state first. Receiving a packet in Closed state |
| now also produces the required "No connection" Reset reply of RFC 4340, 8.3.1. |
| |
| Reported-and-tested-by: Johan Hovold <jhovold@gmail.com> |
| Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/dccp/input.c b/net/dccp/input.c |
| index def29ca..3caceee 100644 |
| --- a/net/dccp/input.c |
| +++ b/net/dccp/input.c |
| @@ -617,6 +617,9 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, |
| /* Caller (dccp_v4_do_rcv) will send Reset */ |
| dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; |
| return 1; |
| + } else if (sk->sk_state == DCCP_CLOSED) { |
| + dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; |
| + return 1; |
| } |
| |
| if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) { |
| @@ -679,10 +682,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, |
| } |
| |
| switch (sk->sk_state) { |
| - case DCCP_CLOSED: |
| - dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; |
| - return 1; |
| - |
| case DCCP_REQUESTING: |
| queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); |
| if (queued >= 0) |
| -- |
| 1.7.4.4 |
| |