Skip to content

Commit 29751ae

Browse files
bors[bot]Dirbaio
andauthored
Merge #538
538: TCP fuzz fixes r=Dirbaio a=Dirbaio Fixes panics and hangs found by whole-stack fuzzing. See individual commit messages. Will post the whole-stack fuzz target when it's fully clean. Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
2 parents c4db5de + 78fb02a commit 29751ae

File tree

1 file changed

+183
-55
lines changed

1 file changed

+183
-55
lines changed

src/socket/tcp.rs

+183-55
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl RttEstimator {
110110

111111
self.rto_count = 0;
112112

113-
let rto = self.retransmission_timeout().millis();
113+
let rto = self.retransmission_timeout().total_millis();
114114
net_trace!(
115115
"rtte: sample={:?} rtt={:?} dev={:?} rto={:?}",
116116
new_rtt,
@@ -137,7 +137,7 @@ impl RttEstimator {
137137
fn on_ack(&mut self, timestamp: Instant, seq: TcpSeqNumber) {
138138
if let Some((sent_timestamp, sent_seq)) = self.timestamp {
139139
if seq >= sent_seq {
140-
self.sample((timestamp - sent_timestamp).millis() as u32);
140+
self.sample((timestamp - sent_timestamp).total_millis() as u32);
141141
self.timestamp = None;
142142
}
143143
}
@@ -158,7 +158,7 @@ impl RttEstimator {
158158
// increase if we see 3 consecutive retransmissions without any successful sample.
159159
self.rto_count = 0;
160160
self.rtt = RTTE_MAX_RTO.min(self.rtt * 2);
161-
let rto = self.retransmission_timeout().millis();
161+
let rto = self.retransmission_timeout().total_millis();
162162
net_trace!(
163163
"rtte: too many retransmissions, increasing: rtt={:?} dev={:?} rto={:?}",
164164
self.rtt,
@@ -1355,24 +1355,6 @@ impl<'a> TcpSocket<'a> {
13551355
);
13561356
return Err(Error::Dropped);
13571357
}
1358-
// Any ACK in the SYN-SENT state must have the SYN flag set.
1359-
(
1360-
State::SynSent,
1361-
&TcpRepr {
1362-
control: TcpControl::None,
1363-
ack_number: Some(_),
1364-
..
1365-
},
1366-
) => {
1367-
net_debug!(
1368-
"{}:{}:{}: expecting a SYN|ACK",
1369-
self.meta.handle,
1370-
self.local_endpoint,
1371-
self.remote_endpoint
1372-
);
1373-
self.abort();
1374-
return Err(Error::Dropped);
1375-
}
13761358
// SYN|ACK in the SYN-SENT state must have the exact ACK number.
13771359
(
13781360
State::SynSent,
@@ -1392,6 +1374,17 @@ impl<'a> TcpSocket<'a> {
13921374
return Err(Error::Dropped);
13931375
}
13941376
}
1377+
// Anything else in the SYN-SENT state is invalid.
1378+
(State::SynSent, _) => {
1379+
net_debug!(
1380+
"{}:{}:{}: expecting a SYN|ACK",
1381+
self.meta.handle,
1382+
self.local_endpoint,
1383+
self.remote_endpoint
1384+
);
1385+
self.abort();
1386+
return Err(Error::Dropped);
1387+
}
13951388
// Every acknowledgement must be for transmitted but unacknowledged data.
13961389
(
13971390
_,
@@ -1403,9 +1396,14 @@ impl<'a> TcpSocket<'a> {
14031396
let unacknowledged = self.tx_buffer.len() + control_len;
14041397

14051398
// Acceptable ACK range (both inclusive)
1406-
let ack_min = self.local_seq_no;
1399+
let mut ack_min = self.local_seq_no;
14071400
let ack_max = self.local_seq_no + unacknowledged;
14081401

1402+
// If we have sent a SYN, it MUST be acknowledged.
1403+
if sent_syn {
1404+
ack_min += 1;
1405+
}
1406+
14091407
if ack_number < ack_min {
14101408
net_debug!(
14111409
"{}:{}:{}: duplicate ACK ({} not in {}...{})",
@@ -1506,23 +1504,26 @@ impl<'a> TcpSocket<'a> {
15061504
let mut ack_of_fin = false;
15071505
if repr.control != TcpControl::Rst {
15081506
if let Some(ack_number) = repr.ack_number {
1509-
ack_len = ack_number - self.local_seq_no;
1510-
// There could have been no data sent before the SYN, so we always remove it
1511-
// from the sequence space.
1512-
if sent_syn {
1513-
ack_len -= 1
1514-
}
1515-
// We could've sent data before the FIN, so only remove FIN from the sequence
1516-
// space if all of that data is acknowledged.
1517-
if sent_fin && self.tx_buffer.len() + 1 == ack_len {
1518-
ack_len -= 1;
1519-
net_trace!(
1520-
"{}:{}:{}: received ACK of FIN",
1521-
self.meta.handle,
1522-
self.local_endpoint,
1523-
self.remote_endpoint
1524-
);
1525-
ack_of_fin = true;
1507+
// Sequence number corresponding to the first byte in `tx_buffer`.
1508+
// This normally equals `local_seq_no`, but is 1 higher if we ahve sent a SYN,
1509+
// as the SYN occupies 1 sequence number "before" the data.
1510+
let tx_buffer_start_seq = self.local_seq_no + (sent_syn as usize);
1511+
1512+
if ack_number >= tx_buffer_start_seq {
1513+
ack_len = ack_number - tx_buffer_start_seq;
1514+
1515+
// We could've sent data before the FIN, so only remove FIN from the sequence
1516+
// space if all of that data is acknowledged.
1517+
if sent_fin && self.tx_buffer.len() + 1 == ack_len {
1518+
ack_len -= 1;
1519+
net_trace!(
1520+
"{}:{}:{}: received ACK of FIN",
1521+
self.meta.handle,
1522+
self.local_endpoint,
1523+
self.remote_endpoint
1524+
);
1525+
ack_of_fin = true;
1526+
}
15261527
}
15271528

15281529
self.rtte.on_ack(cx.now, ack_number);
@@ -1575,16 +1576,26 @@ impl<'a> TcpSocket<'a> {
15751576
// SYN packets in the LISTEN state change it to SYN-RECEIVED.
15761577
(State::Listen, TcpControl::Syn) => {
15771578
net_trace!("{}:{}: received SYN", self.meta.handle, self.local_endpoint);
1579+
if let Some(max_seg_size) = repr.max_seg_size {
1580+
if max_seg_size == 0 {
1581+
net_trace!(
1582+
"{}:{}:{}: received SYNACK with zero MSS, ignoring",
1583+
self.meta.handle,
1584+
self.local_endpoint,
1585+
self.remote_endpoint
1586+
);
1587+
return Ok(None);
1588+
}
1589+
self.remote_mss = max_seg_size as usize
1590+
}
1591+
15781592
self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port);
15791593
self.remote_endpoint = IpEndpoint::new(ip_repr.src_addr(), repr.src_port);
15801594
// FIXME: use something more secure here
1581-
self.local_seq_no = TcpSeqNumber(-repr.seq_number.0);
1595+
self.local_seq_no = TcpSeqNumber(!repr.seq_number.0);
15821596
self.remote_seq_no = repr.seq_number + 1;
15831597
self.remote_last_seq = self.local_seq_no;
15841598
self.remote_has_sack = repr.sack_permitted;
1585-
if let Some(max_seg_size) = repr.max_seg_size {
1586-
self.remote_mss = max_seg_size as usize
1587-
}
15881599
self.remote_win_scale = repr.window_scale;
15891600
// Remote doesn't support window scaling, don't do it.
15901601
if self.remote_win_scale.is_none() {
@@ -1618,6 +1629,19 @@ impl<'a> TcpSocket<'a> {
16181629
self.local_endpoint,
16191630
self.remote_endpoint
16201631
);
1632+
if let Some(max_seg_size) = repr.max_seg_size {
1633+
if max_seg_size == 0 {
1634+
net_trace!(
1635+
"{}:{}:{}: received SYNACK with zero MSS, ignoring",
1636+
self.meta.handle,
1637+
self.local_endpoint,
1638+
self.remote_endpoint
1639+
);
1640+
return Ok(None);
1641+
}
1642+
self.remote_mss = max_seg_size as usize;
1643+
}
1644+
16211645
self.local_endpoint = IpEndpoint::new(ip_repr.dst_addr(), repr.dst_port);
16221646
self.remote_seq_no = repr.seq_number + 1;
16231647
self.remote_last_seq = self.local_seq_no + 1;
@@ -1628,9 +1652,6 @@ impl<'a> TcpSocket<'a> {
16281652
self.remote_win_shift = 0;
16291653
}
16301654

1631-
if let Some(max_seg_size) = repr.max_seg_size {
1632-
self.remote_mss = max_seg_size as usize;
1633-
}
16341655
self.set_state(State::Established);
16351656
self.timer.set_for_idle(cx.now, self.keep_alive);
16361657
}
@@ -1974,6 +1995,11 @@ impl<'a> TcpSocket<'a> {
19741995
// Have we sent data that hasn't been ACKed yet?
19751996
let data_in_flight = self.remote_last_seq != self.local_seq_no;
19761997

1998+
// If we want to send a SYN and we haven't done so, do it!
1999+
if matches!(self.state, State::SynSent | State::SynReceived) && !data_in_flight {
2000+
return true;
2001+
}
2002+
19772003
// max sequence number we can send.
19782004
let max_send_seq =
19792005
self.local_seq_no + core::cmp::min(self.remote_win_len, self.tx_buffer.len());
@@ -2077,7 +2103,19 @@ impl<'a> TcpSocket<'a> {
20772103
self.remote_endpoint,
20782104
retransmit_delta
20792105
);
2106+
2107+
// Rewind "last sequence number sent", as if we never
2108+
// had sent them. This will cause all data in the queue
2109+
// to be sent again.
20802110
self.remote_last_seq = self.local_seq_no;
2111+
2112+
// Clear the `should_retransmit` state. If we can't retransmit right
2113+
// now for whatever reason (like zero window), this avoids an
2114+
// infinite polling loop where `poll_at` returns `Now` but `dispatch`
2115+
// can't actually do anything.
2116+
self.timer.set_for_idle(cx.now, self.keep_alive);
2117+
2118+
// Inform RTTE, so that it can avoid bogus measurements.
20812119
self.rtte.on_retransmit();
20822120
}
20832121
}
@@ -2115,14 +2153,6 @@ impl<'a> TcpSocket<'a> {
21152153
self.local_endpoint,
21162154
self.remote_endpoint
21172155
);
2118-
} else if self.timer.should_retransmit(cx.now).is_some() {
2119-
// If we have packets to retransmit, do it.
2120-
net_trace!(
2121-
"{}:{}:{}: retransmit timer expired",
2122-
self.meta.handle,
2123-
self.local_endpoint,
2124-
self.remote_endpoint
2125-
);
21262156
} else if self.timer.should_keep_alive(cx.now) {
21272157
// If we need to transmit a keep-alive packet, do it.
21282158
net_trace!(
@@ -2459,7 +2489,7 @@ mod test {
24592489
port: REMOTE_PORT,
24602490
};
24612491
const LOCAL_SEQ: TcpSeqNumber = TcpSeqNumber(10000);
2462-
const REMOTE_SEQ: TcpSeqNumber = TcpSeqNumber(-10000);
2492+
const REMOTE_SEQ: TcpSeqNumber = TcpSeqNumber(-10001);
24632493

24642494
const SEND_IP_TEMPL: IpRepr = IpRepr::Unspecified {
24652495
src_addr: MOCK_IP_ADDR_1,
@@ -3017,6 +3047,62 @@ mod test {
30173047
sanity!(s, socket_established());
30183048
}
30193049

3050+
#[test]
3051+
fn test_syn_received_ack_too_low() {
3052+
let mut s = socket_syn_received();
3053+
recv!(
3054+
s,
3055+
[TcpRepr {
3056+
control: TcpControl::Syn,
3057+
seq_number: LOCAL_SEQ,
3058+
ack_number: Some(REMOTE_SEQ + 1),
3059+
max_seg_size: Some(BASE_MSS),
3060+
..RECV_TEMPL
3061+
}]
3062+
);
3063+
send!(
3064+
s,
3065+
TcpRepr {
3066+
seq_number: REMOTE_SEQ + 1,
3067+
ack_number: Some(LOCAL_SEQ), // wrong
3068+
..SEND_TEMPL
3069+
},
3070+
Err(Error::Dropped)
3071+
);
3072+
assert_eq!(s.state, State::SynReceived);
3073+
}
3074+
3075+
#[test]
3076+
fn test_syn_received_ack_too_high() {
3077+
let mut s = socket_syn_received();
3078+
recv!(
3079+
s,
3080+
[TcpRepr {
3081+
control: TcpControl::Syn,
3082+
seq_number: LOCAL_SEQ,
3083+
ack_number: Some(REMOTE_SEQ + 1),
3084+
max_seg_size: Some(BASE_MSS),
3085+
..RECV_TEMPL
3086+
}]
3087+
);
3088+
send!(
3089+
s,
3090+
TcpRepr {
3091+
seq_number: REMOTE_SEQ + 1,
3092+
ack_number: Some(LOCAL_SEQ + 2), // wrong
3093+
..SEND_TEMPL
3094+
},
3095+
// TODO is this correct? probably not
3096+
Ok(Some(TcpRepr {
3097+
control: TcpControl::None,
3098+
seq_number: LOCAL_SEQ + 1,
3099+
ack_number: Some(REMOTE_SEQ + 1),
3100+
..RECV_TEMPL
3101+
}))
3102+
);
3103+
assert_eq!(s.state, State::SynReceived);
3104+
}
3105+
30203106
#[test]
30213107
fn test_syn_received_fin() {
30223108
let mut s = socket_syn_received();
@@ -5486,6 +5572,48 @@ mod test {
54865572
);
54875573
}
54885574

5575+
#[test]
5576+
fn test_fast_retransmit_zero_window() {
5577+
let mut s = socket_established();
5578+
5579+
send!(s, time 1000, TcpRepr {
5580+
seq_number: REMOTE_SEQ + 1,
5581+
ack_number: Some(LOCAL_SEQ + 1),
5582+
..SEND_TEMPL
5583+
});
5584+
5585+
s.send_slice(b"abc").unwrap();
5586+
5587+
recv!(s, time 0, Ok(TcpRepr {
5588+
seq_number: LOCAL_SEQ + 1,
5589+
ack_number: Some(REMOTE_SEQ + 1),
5590+
payload: &b"abc"[..],
5591+
..RECV_TEMPL
5592+
}));
5593+
5594+
// 3 dup acks
5595+
send!(s, time 1050, TcpRepr {
5596+
seq_number: REMOTE_SEQ + 1,
5597+
ack_number: Some(LOCAL_SEQ + 1),
5598+
..SEND_TEMPL
5599+
});
5600+
send!(s, time 1050, TcpRepr {
5601+
seq_number: REMOTE_SEQ + 1,
5602+
ack_number: Some(LOCAL_SEQ + 1),
5603+
..SEND_TEMPL
5604+
});
5605+
send!(s, time 1050, TcpRepr {
5606+
seq_number: REMOTE_SEQ + 1,
5607+
ack_number: Some(LOCAL_SEQ + 1),
5608+
window_len: 0, // boom
5609+
..SEND_TEMPL
5610+
});
5611+
5612+
// even though we're in "fast retransmit", we shouldn't
5613+
// force-send anything because the remote's window is full.
5614+
recv!(s, Err(Error::Exhausted));
5615+
}
5616+
54895617
// =========================================================================================//
54905618
// Tests for window management.
54915619
// =========================================================================================//

0 commit comments

Comments
 (0)