Skip to content

Commit

Permalink
conntrack: Correct length check for tcp packet inside ICMP data.
Browse files Browse the repository at this point in the history
An ICMP packet with type destination or host not reachable also carries
28 bytes of ICMP data field. This data field contains IP header and TCP
header (partial first 8 bytes) of the original packet for which ICMP
is being generated.

Conntrack module when processing these ICMP packets checks for TCP header
length (20 bytes). Since TCP header is partial the length check fails and
packet is erroneously dropped.

This patch fixes length check for TCP header when processing ICMP data
fields.

Signed-off-by: Vishal Deep Ajmera <vishal.deep.ajmera@ericsson.com>
Signed-off-by: 0-day Robot <robot@bytheb.org>
  • Loading branch information
vishaldeepajmera authored and ovsrobot committed Aug 23, 2019
1 parent d578e06 commit 24d276e
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 3 deletions.
14 changes: 11 additions & 3 deletions lib/conntrack.c
Expand Up @@ -1513,10 +1513,18 @@ check_l4_icmp6(const struct conn_key *key, const void *data, size_t size,
return validate_checksum ? checksum_valid(key, data, size, l3) : true;
}

/* If related is NULL, we are parsing nested TCP header inside ICMP packet.
* Only 8 bytes of TCP header is required by RFC to be present in such case.
*/
static inline bool
extract_l4_tcp(struct conn_key *key, const void *data, size_t size)
extract_l4_tcp(struct conn_key *key, const void *data, size_t size,
bool *related)
{
if (OVS_UNLIKELY(size < TCP_HEADER_LEN)) {
if (!related) {
if (size < ICMP_L4_DATA_LEN) {
return false;
}
} else if (size < TCP_HEADER_LEN) {
return false;
}

Expand Down Expand Up @@ -1750,7 +1758,7 @@ extract_l4(struct conn_key *key, const void *data, size_t size, bool *related,
{
if (key->nw_proto == IPPROTO_TCP) {
return (!related || check_l4_tcp(key, data, size, l3,
validate_checksum)) && extract_l4_tcp(key, data, size);
validate_checksum)) && extract_l4_tcp(key, data, size, related);
} else if (key->nw_proto == IPPROTO_UDP) {
return (!related || check_l4_udp(key, data, size, l3,
validate_checksum)) && extract_l4_udp(key, data, size);
Expand Down
1 change: 1 addition & 0 deletions lib/packets.h
Expand Up @@ -886,6 +886,7 @@ struct tcp_header {
ovs_be16 tcp_urg;
};
BUILD_ASSERT_DECL(TCP_HEADER_LEN == sizeof(struct tcp_header));
#define ICMP_L4_DATA_LEN 8

/* Connection states.
*
Expand Down

0 comments on commit 24d276e

Please sign in to comment.