In _eth_tcp_has_data() we calculate the length of the rest of the packet after the ipv4 header by subtracting the header offset from the packet length. If this subtraction underflows we'll return the wrong answer. This shouldn't cause any problems if other layers of the code are checking lengths and offsets, but defence-in-depth suggests doing a checked-subtraction and returning "has no data" if the subtraction underflows.
Cc: [email protected] Fixes: eb700029c783 ("net_pkt: Extend packet abstraction as required by e1000e functionality") Signed-off-by: Peter Maydell <[email protected]> --- net/eth.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/eth.c b/net/eth.c index e2c1e08ed28..955f2bff5e6 100644 --- a/net/eth.c +++ b/net/eth.c @@ -117,10 +117,20 @@ _eth_tcp_has_data(bool is_ip4, uint32_t l4len; if (is_ip4) { - l4len = be16_to_cpu(ip4_hdr->ip_len) - IP_HDR_GET_LEN(ip4_hdr); + if (usub32_overflow(be16_to_cpu(ip4_hdr->ip_len), + IP_HDR_GET_LEN(ip4_hdr), &l4len)) { + /* packet too short for claimed IP header: no data */ + return false; + } } else { size_t opts_len = full_ip6hdr_len - sizeof(struct ip6_header); - l4len = be16_to_cpu(ip6_hdr->ip6_ctlun.ip6_un1.ip6_un1_plen) - opts_len; + uint64_t l4len_64; + if (usub64_overflow(be16_to_cpu(ip6_hdr->ip6_ctlun.ip6_un1.ip6_un1_plen), + opts_len, &l4len_64)) { + /* packet too short for claimed IP header: no data */ + return false; + } + l4len = l4len_64; } return l4len > TCP_HEADER_DATA_OFFSET(tcp); -- 2.43.0
