Skip to content

Commit 94d1a94

Browse files
Jeff-A-MartinCQ Bot
authored andcommitted
[packet-formats] Fix parsing of unknown TCP Option
The original code did not correctly handle the length of unknown TCP Options, leading to parse errors. Bug: 462085360 Change-Id: Ia66c2f9e8981173c4f22148c153ee8a12ee16772 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1442312 Reviewed-by: Zeling Feng <zeling@google.com> Commit-Queue: Jeff Martin <martinjeffrey@google.com> Reviewed-by: Bruno Dal Bo <brunodalbo@google.com> Fuchsia-Auto-Submit: Jeff Martin <martinjeffrey@google.com>
1 parent d6327dc commit 94d1a94

File tree

1 file changed

+55
-6
lines changed
  • src/connectivity/lib/packet-formats/src

1 file changed

+55
-6
lines changed

src/connectivity/lib/packet-formats/src/tcp.rs

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,10 @@ pub mod options {
12611261
);
12621262
}
12631263
_ => {
1264+
// NB: Subtract 2 since we've already advanced beyond
1265+
// the kind and length fields
1266+
let len = len - 2;
1267+
12641268
// Ignore unknown options, but move `bytes` ahead to
12651269
// allow subsequent options to be parsed.
12661270
let _: B = bytes.take_front(len).ok_or(ParseError::Format)?;
@@ -1725,15 +1729,15 @@ mod tests {
17251729
builder.syn(true);
17261730

17271731
let mut buf = builder
1728-
.wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1732+
.wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
17291733
.serialize_vec_outer()
17301734
.unwrap();
17311735
// assert that we get the literal bytes we expected
17321736
assert_eq!(
17331737
buf.as_ref(),
17341738
[
1735-
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 141, 137, 0, 0, 0, 1, 2, 3, 3, 4,
1736-
5, 7, 8, 9
1739+
0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 80, 23, 0, 5, 137, 145, 0, 0, 0, 1, 2, 3, 4, 5,
1740+
7, 8, 9
17371741
]
17381742
);
17391743
let segment = buf
@@ -1746,7 +1750,7 @@ mod tests {
17461750
assert_eq!(segment.seq_num(), 3);
17471751
assert_eq!(segment.ack_num(), Some(4));
17481752
assert_eq!(segment.window_size(), 5);
1749-
assert_eq!(segment.body(), [0, 1, 2, 3, 3, 4, 5, 7, 8, 9]);
1753+
assert_eq!(segment.body(), [0, 1, 2, 3, 4, 5, 7, 8, 9]);
17501754
}
17511755

17521756
#[test]
@@ -1962,7 +1966,7 @@ mod tests {
19621966

19631967
// Serialize and Parse the segment.
19641968
let mut buf = builder
1965-
.wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1969+
.wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
19661970
.serialize_vec_outer()
19671971
.unwrap();
19681972
let segment = buf
@@ -1987,7 +1991,7 @@ mod tests {
19871991

19881992
// Serialize the segment.
19891993
let buf = builder
1990-
.wrap_body((&[0, 1, 2, 3, 3, 4, 5, 7, 8, 9]).into_serializer())
1994+
.wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
19911995
.serialize_vec_outer()
19921996
.unwrap();
19931997

@@ -2003,4 +2007,49 @@ mod tests {
20032007
&expected_options[..]
20042008
)
20052009
}
2010+
2011+
#[derive(Debug)]
2012+
struct TcpSegmentBuilderWithUnknownOption<A: IpAddress>(TcpSegmentBuilder<A>);
2013+
2014+
impl<A: IpAddress> TcpSegmentBuilderWithUnknownOption<A> {
2015+
const UNKNOWN_KIND: u8 = 255;
2016+
const OPTION_LEN: u8 = 4;
2017+
const OPTION_BYTES: [u8; 4] = [Self::UNKNOWN_KIND, Self::OPTION_LEN, 0, 0];
2018+
}
2019+
2020+
impl<A: IpAddress> PacketBuilder for TcpSegmentBuilderWithUnknownOption<A> {
2021+
fn constraints(&self) -> PacketConstraints {
2022+
let header_len = HDR_PREFIX_LEN + usize::from(Self::OPTION_LEN);
2023+
PacketConstraints::new(header_len, 0, 0, usize::MAX)
2024+
}
2025+
2026+
fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
2027+
let Self(prefix_builder) = self;
2028+
let mut header = &mut &mut target.header[..];
2029+
header.write_obj_back(&Self::OPTION_BYTES).unwrap();
2030+
prefix_builder.serialize(target, body);
2031+
}
2032+
}
2033+
2034+
#[test]
2035+
fn test_parse_unknown_option() {
2036+
let builder = TcpSegmentBuilderWithUnknownOption(new_builder(TEST_SRC_IPV4, TEST_DST_IPV4));
2037+
2038+
// Serialize and Parse the segment. Parsing should ignore the unknown
2039+
// option.
2040+
let mut buf = builder
2041+
.wrap_body((&[0, 1, 2, 3, 4, 5, 7, 8, 9]).into_serializer())
2042+
.serialize_vec_outer()
2043+
.unwrap();
2044+
let segment = buf
2045+
.parse_with::<_, TcpSegment<_>>(TcpParseArgs::new(TEST_SRC_IPV4, TEST_DST_IPV4))
2046+
.unwrap();
2047+
2048+
// Verify no options are set.
2049+
assert_eq!(segment.options().mss(), None);
2050+
assert_eq!(segment.options().window_scale(), None);
2051+
assert_eq!(segment.options().sack_permitted(), false);
2052+
assert_eq!(segment.options().sack_blocks(), None);
2053+
assert_eq!(segment.options().timestamp(), None);
2054+
}
20062055
}

0 commit comments

Comments
 (0)