[PATCH] DCCP: Fix to handle invalid packets in REQUEST state

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch fix two problem in REQUEST state while received invalid packets.

1. If invalid Dccp-DataAck packets is received in the REQUEST state, the socket just send back Dccp-Rest with invalid packet error, but the socket is not reset, Dccp-Request will be continue retranmitted. The procedure is like this:

Endpoint A                   Endpint B
        <-----------------  Request
DataAck -----------------> <----------------- Reset (invalid packet)
        <-----------------  Request (retranmit)

2. If sequence-invalid Dccp-Response is received in the REQUEST state, kernel will panic. This is because that after send reset when received sequence-invalid Dccp-Response, the state of socket not be changed. The procedure is like this:

Endpoint A                   Endpint B
        <-----------------  Request
Response -----------------> (sequence-invalid)
        <-----------------  Reset (invalid packet)
Response ----------------->  kernel panic

Pid: 0, comm: swapper Not tainted (2.6.26 #1)
EIP: 0060:[<c05b426d>] EFLAGS: 00010282 CPU: 0
EIP is at skb_release_all+0x6/0x7e
EAX: 00000000 EBX: 00000000 ECX: 00000046 EDX: c4fdd000
ESI: c79aad80 EDI: c4fdd000 EBP: c077ee0c ESP: c077ee08
DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
Process swapper (pid: 0, ti=c077e000 task=c0700340 task.ti=c0734000)
Stack: 00000000 c077ee18 c05b3bf3 c79a9234 c077ee58 c8ab1db5 c79aad80 c4fdd000
      02000015 c79aada0 00000c3c 00000854 c79aad80 c077ee50 c04260db c8ac176e
      0059b20e c4fdd000 c79aad80 c4fdd000 c077ee78 c8ac06e3 0000001c c79a9234
Call Trace:
[<c05b3bf3>] ? __kfree_skb+0xb/0x66
[<c8ab1db5>] ? dccp_rcv_state_process+0x195/0x4b0 [dccp]
[<c04260db>] ? printk+0x15/0x17
[<c8ac06e3>] ? dccp_v4_do_rcv+0xed/0x112 [dccp_ipv4]
[<c05c257d>] ? sk_filter+0x66/0x6d
[<c05b23bf>] ? sk_receive_skb+0x32/0x7c
[<c8ac14d4>] ? dccp_v4_rcv+0x3b5/0x42d [dccp_ipv4]
[<c05d400a>] ? ip_local_deliver_finish+0xb5/0x151
[<c05d43f3>] ? ip_local_deliver+0x61/0x6a
[<c05d3f36>] ? ip_rcv_finish+0x28e/0x2ad
[<c05d4368>] ? ip_rcv+0x1f2/0x21c
[<c05b8599>] ? netif_receive_skb+0x2ea/0x352
[<c88cea9b>] ? pcnet32_poll+0x32f/0x689 [pcnet32]
[<c0404257>] ? common_interrupt+0x23/0x28
[<c05ba0f1>] ? net_rx_action+0x8f/0x146
[<c0429a95>] ? __do_softirq+0x64/0xcd
[<c0429a31>] ? __do_softirq+0x0/0xcd
[<c0405788>] ? do_softirq+0x5c/0x92
[<c0429a2f>] ? irq_exit+0x38/0x3a
[<c0412eda>] ? smp_apic_timer_interrupt+0x71/0x7f
[<c0404344>] ? apic_timer_interrupt+0x28/0x30
[<c0408588>] ? default_idle+0x2d/0x42
[<c040257d>] ? cpu_idle+0xab/0xc3
[<c0614ba2>] ? rest_init+0x4e/0x50
=======================


Signed-off-by: Wei Yongjun <yjwei@xxxxxxxxxxxxxx>
---
net/dccp/input.c |   21 ++++++++++++---------
1 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/net/dccp/input.c b/net/dccp/input.c
index 0beb29e..7d7b4f7
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -388,6 +388,14 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
					       const struct dccp_hdr *dh,
					       const unsigned len)
{
+	const struct inet_connection_sock *icsk = inet_csk(sk);
+
+	/* Stop the REQUEST timer */
+	inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
+	BUG_TRAP(sk->sk_send_head != NULL);
+	__kfree_skb(sk->sk_send_head);
+	sk->sk_send_head = NULL;
+
	/*
	 *  Step 4: Prepare sequence numbers in REQUEST
	 *     If S.state == REQUEST,
@@ -400,16 +408,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
	 *		processing continues in Step 9 * /
	*/
	if (dh->dccph_type == DCCP_PKT_RESPONSE) {
-		const struct inet_connection_sock *icsk = inet_csk(sk);
		struct dccp_sock *dp = dccp_sk(sk);
		long tstamp = dccp_timestamp();

-		/* Stop the REQUEST timer */
-		inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
-		BUG_TRAP(sk->sk_send_head != NULL);
-		__kfree_skb(sk->sk_send_head);
-		sk->sk_send_head = NULL;
-
		if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
			       dp->dccps_awl, dp->dccps_awh)) {
			dccp_pr_debug("invalid ackno: S.AWL=%llu, "
@@ -426,7 +427,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
		 * the option type and is set in dccp_parse_options().
		 */
		if (dccp_parse_options(sk, NULL, skb))
-			return 1;
+			goto out_err;

		/* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
		if (likely(dp->dccps_options_received.dccpor_timestamp_echo))
@@ -503,10 +504,12 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
out_invalid_packet:
	/* dccp_v4_do_rcv will send a reset */
	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
-	return 1;
+	goto out_err;

unable_to_proceed:
	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED;
+
+out_err:
	/*
	 * We mark this socket as no longer usable, so that the loop in
	 * dccp_sendmsg() terminates and the application gets notified.
--
1.5.3.8



--
To unsubscribe from this list: send the line "unsubscribe dccp" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [IETF DCCP]     [Linux Networking]     [Git]     [Security]     [Linux Assembly]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux