aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorSamuel Jero <sj323707@ohio.edu>2012-02-26 20:22:02 -0500
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2012-03-03 11:02:52 -0500
commitf541fb7e20c848f947ca65fbf169efe69400c942 (patch)
tree689f3a7a46ca00b6610667e33313f339645b229d /net/dccp
parent793734b587a670e47a8d65f9e5211ba2188bb904 (diff)
dccp: fix bug in sequence number validation during connection setup
This fixes a bug in the sequence number validation during the initial handshake. The code did not treat the initial sequence numbers ISS and ISR as read-only and did not keep state for GSR and GSS as required by the specification. This causes problems with retransmissions during the initial handshake, causing the budding connection to be reset. This patch now treats ISS/ISR as read-only and tracks GSS/GSR as required. Signed-off-by: Samuel Jero <sj323707@ohio.edu> Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ipv4.c8
-rw-r--r--net/dccp/ipv6.c8
-rw-r--r--net/dccp/minisocks.c18
-rw-r--r--net/dccp/output.c10
4 files changed, 26 insertions, 18 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 1c67fe8ff90d..caf6e1734b62 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -300,7 +300,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
300 */ 300 */
301 WARN_ON(req->sk); 301 WARN_ON(req->sk);
302 302
303 if (seq != dccp_rsk(req)->dreq_iss) { 303 if (!between48(seq, dccp_rsk(req)->dreq_iss,
304 dccp_rsk(req)->dreq_gss)) {
304 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); 305 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
305 goto out; 306 goto out;
306 } 307 }
@@ -639,11 +640,12 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
639 * 640 *
640 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie 641 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
641 * 642 *
642 * In fact we defer setting S.GSR, S.SWL, S.SWH to 643 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
643 * dccp_create_openreq_child.
644 */ 644 */
645 dreq->dreq_isr = dcb->dccpd_seq; 645 dreq->dreq_isr = dcb->dccpd_seq;
646 dreq->dreq_gsr = dreq->dreq_isr;
646 dreq->dreq_iss = dccp_v4_init_sequence(skb); 647 dreq->dreq_iss = dccp_v4_init_sequence(skb);
648 dreq->dreq_gss = dreq->dreq_iss;
647 dreq->dreq_service = service; 649 dreq->dreq_service = service;
648 650
649 if (dccp_v4_send_response(sk, req, NULL)) 651 if (dccp_v4_send_response(sk, req, NULL))
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index ce903f747e64..4dc588f520e0 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -193,7 +193,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
193 */ 193 */
194 WARN_ON(req->sk != NULL); 194 WARN_ON(req->sk != NULL);
195 195
196 if (seq != dccp_rsk(req)->dreq_iss) { 196 if (!between48(seq, dccp_rsk(req)->dreq_iss,
197 dccp_rsk(req)->dreq_gss)) {
197 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); 198 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
198 goto out; 199 goto out;
199 } 200 }
@@ -440,11 +441,12 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
440 * 441 *
441 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie 442 * Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init Cookie
442 * 443 *
443 * In fact we defer setting S.GSR, S.SWL, S.SWH to 444 * Setting S.SWL/S.SWH to is deferred to dccp_create_openreq_child().
444 * dccp_create_openreq_child.
445 */ 445 */
446 dreq->dreq_isr = dcb->dccpd_seq; 446 dreq->dreq_isr = dcb->dccpd_seq;
447 dreq->dreq_gsr = dreq->dreq_isr;
447 dreq->dreq_iss = dccp_v6_init_sequence(skb); 448 dreq->dreq_iss = dccp_v6_init_sequence(skb);
449 dreq->dreq_gss = dreq->dreq_iss;
448 dreq->dreq_service = service; 450 dreq->dreq_service = service;
449 451
450 if (dccp_v6_send_response(sk, req, NULL)) 452 if (dccp_v6_send_response(sk, req, NULL))
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 5a7f90bbffac..ea850ce35d4a 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -127,9 +127,11 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
127 * activation below, as these windows all depend on the local 127 * activation below, as these windows all depend on the local
128 * and remote Sequence Window feature values (7.5.2). 128 * and remote Sequence Window feature values (7.5.2).
129 */ 129 */
130 newdp->dccps_gss = newdp->dccps_iss = dreq->dreq_iss; 130 newdp->dccps_iss = dreq->dreq_iss;
131 newdp->dccps_gss = dreq->dreq_gss;
131 newdp->dccps_gar = newdp->dccps_iss; 132 newdp->dccps_gar = newdp->dccps_iss;
132 newdp->dccps_gsr = newdp->dccps_isr = dreq->dreq_isr; 133 newdp->dccps_isr = dreq->dreq_isr;
134 newdp->dccps_gsr = dreq->dreq_gsr;
133 135
134 /* 136 /*
135 * Activate features: initialise CCIDs, sequence windows etc. 137 * Activate features: initialise CCIDs, sequence windows etc.
@@ -164,9 +166,9 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
164 /* Check for retransmitted REQUEST */ 166 /* Check for retransmitted REQUEST */
165 if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) { 167 if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
166 168
167 if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_isr)) { 169 if (after48(DCCP_SKB_CB(skb)->dccpd_seq, dreq->dreq_gsr)) {
168 dccp_pr_debug("Retransmitted REQUEST\n"); 170 dccp_pr_debug("Retransmitted REQUEST\n");
169 dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; 171 dreq->dreq_gsr = DCCP_SKB_CB(skb)->dccpd_seq;
170 /* 172 /*
171 * Send another RESPONSE packet 173 * Send another RESPONSE packet
172 * To protect against Request floods, increment retrans 174 * To protect against Request floods, increment retrans
@@ -186,12 +188,14 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
186 goto drop; 188 goto drop;
187 189
188 /* Invalid ACK */ 190 /* Invalid ACK */
189 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != dreq->dreq_iss) { 191 if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,
192 dreq->dreq_iss, dreq->dreq_gss)) {
190 dccp_pr_debug("Invalid ACK number: ack_seq=%llu, " 193 dccp_pr_debug("Invalid ACK number: ack_seq=%llu, "
191 "dreq_iss=%llu\n", 194 "dreq_iss=%llu, dreq_gss=%llu\n",
192 (unsigned long long) 195 (unsigned long long)
193 DCCP_SKB_CB(skb)->dccpd_ack_seq, 196 DCCP_SKB_CB(skb)->dccpd_ack_seq,
194 (unsigned long long) dreq->dreq_iss); 197 (unsigned long long) dreq->dreq_iss,
198 (unsigned long long) dreq->dreq_gss);
195 goto drop; 199 goto drop;
196 } 200 }
197 201
diff --git a/net/dccp/output.c b/net/dccp/output.c
index dede3edb8849..787367308797 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -408,10 +408,10 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
408 skb_dst_set(skb, dst_clone(dst)); 408 skb_dst_set(skb, dst_clone(dst));
409 409
410 dreq = dccp_rsk(req); 410 dreq = dccp_rsk(req);
411 if (inet_rsk(req)->acked) /* increase ISS upon retransmission */ 411 if (inet_rsk(req)->acked) /* increase GSS upon retransmission */
412 dccp_inc_seqno(&dreq->dreq_iss); 412 dccp_inc_seqno(&dreq->dreq_gss);
413 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; 413 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE;
414 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; 414 DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_gss;
415 415
416 /* Resolve feature dependencies resulting from choice of CCID */ 416 /* Resolve feature dependencies resulting from choice of CCID */
417 if (dccp_feat_server_ccid_dependencies(dreq)) 417 if (dccp_feat_server_ccid_dependencies(dreq))
@@ -429,8 +429,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
429 DCCP_SKB_CB(skb)->dccpd_opt_len) / 4; 429 DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
430 dh->dccph_type = DCCP_PKT_RESPONSE; 430 dh->dccph_type = DCCP_PKT_RESPONSE;
431 dh->dccph_x = 1; 431 dh->dccph_x = 1;
432 dccp_hdr_set_seq(dh, dreq->dreq_iss); 432 dccp_hdr_set_seq(dh, dreq->dreq_gss);
433 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); 433 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_gsr);
434 dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; 434 dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service;
435 435
436 dccp_csum_outgoing(skb); 436 dccp_csum_outgoing(skb);