From patchwork Wed Apr 14 15:50:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 1466303 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=F1hcOBTb; dkim-atps=neutral Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FL6Pw5JSgz9sRf for ; Thu, 15 Apr 2021 01:50:44 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 15D0540198; Wed, 14 Apr 2021 15:50:42 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id lcXW-VYBTerF; Wed, 14 Apr 2021 15:50:41 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTP id 5EA38400D2; Wed, 14 Apr 2021 15:50:40 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 37852C000C; Wed, 14 Apr 2021 15:50:40 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 64D7BC000A for ; Wed, 14 Apr 2021 15:50:39 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 47BB284439 for ; Wed, 14 Apr 2021 15:50:39 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp1.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id costsv23sGRG for ; Wed, 14 Apr 2021 15:50:38 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id 662BB84424 for ; Wed, 14 Apr 2021 15:50:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618415437; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=AokeQ34bIchYe2nsxmaGAn6qzNLM39zfAdBZ/b4275c=; b=F1hcOBTbLYpIlnJvvBncTfa19yV+48jbZXr78PBMC418yp4soH+H8jFECtuQahXM0g7Efj L8d9D77V/LFi0UUql7hH4P/C3S2SeMeoc8YVywRQiSLW3LCaUuEsSRjTiFl6nejS6U4tt4 r7SjdCvQsWfZRTUtbFYUOePUSpr2hCI= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-212-o8x4V4neOAKGnR4v4t5K1Q-1; Wed, 14 Apr 2021 11:50:35 -0400 X-MC-Unique: o8x4V4neOAKGnR4v4t5K1Q-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D0827802B40; Wed, 14 Apr 2021 15:50:34 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.192.93]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3C603694CC; Wed, 14 Apr 2021 15:50:28 +0000 (UTC) From: David Marchand To: dev@openvswitch.org Date: Wed, 14 Apr 2021 17:50:23 +0200 Message-Id: <20210414155023.27266-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: fbl@redhat.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH] flow: Count and dump invalid IP packets. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Skipping further processing of invalid IP packets helps avoid crashes but it does not help to figure out if the malformed packets are still present on the network. Add coverage counters for IPv4 and IPv6 sanity checks so that we know there are some invalid packets. Dump such whole packets in debug mode. Signed-off-by: David Marchand --- lib/flow.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/lib/flow.c b/lib/flow.c index 729d59b1b3..2b55244190 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -44,8 +44,15 @@ #include "openvswitch/nsh.h" #include "ovs-router.h" #include "lib/netdev-provider.h" +#include "openvswitch/vlog.h" + +VLOG_DEFINE_THIS_MODULE(flow); COVERAGE_DEFINE(flow_extract); +COVERAGE_DEFINE(ipv4_check_too_short); +COVERAGE_DEFINE(ipv4_check_length_error); +COVERAGE_DEFINE(ipv6_check_too_short); +COVERAGE_DEFINE(ipv6_check_length_error); COVERAGE_DEFINE(miniflow_malloc); /* U64 indices for segmented flow classification. */ @@ -645,17 +652,20 @@ ipv4_sanity_check(const struct ip_header *nh, size_t size, uint16_t tot_len; if (OVS_UNLIKELY(size < IP_HEADER_LEN)) { + COVERAGE_INC(ipv4_check_too_short); return false; } ip_len = IP_IHL(nh->ip_ihl_ver) * 4; if (OVS_UNLIKELY(ip_len < IP_HEADER_LEN || size < ip_len)) { + COVERAGE_INC(ipv4_check_length_error); return false; } tot_len = ntohs(nh->ip_tot_len); if (OVS_UNLIKELY(tot_len > size || ip_len > tot_len || size - tot_len > UINT16_MAX)) { + COVERAGE_INC(ipv4_check_length_error); return false; } @@ -686,21 +696,41 @@ ipv6_sanity_check(const struct ovs_16aligned_ip6_hdr *nh, size_t size) uint16_t plen; if (OVS_UNLIKELY(size < sizeof *nh)) { + COVERAGE_INC(ipv6_check_too_short); return false; } plen = ntohs(nh->ip6_plen); if (OVS_UNLIKELY(plen + IPV6_HEADER_LEN > size)) { + COVERAGE_INC(ipv6_check_length_error); return false; } if (OVS_UNLIKELY(size - (plen + IPV6_HEADER_LEN) > UINT16_MAX)) { + COVERAGE_INC(ipv6_check_length_error); return false; } return true; } +static void +dump_invalid_packet(struct dp_packet *packet, const char *reason) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + struct ds ds = DS_EMPTY_INITIALIZER; + size_t size; + + if (VLOG_DROP_DBG(&rl)) { + return; + } + size = dp_packet_size(packet); + ds_put_hex_dump(&ds, dp_packet_data(packet), size, 0, false); + VLOG_DBG("invalid packet for %s: port %"PRIu32", size %"PRIuSIZE"\n%s", + reason, packet->md.in_port.odp_port, size, ds_cstr(&ds)); + ds_destroy(&ds); +} + /* Initializes 'dst' from 'packet' and 'md', taking the packet type into * account. 'dst' must have enough space for FLOW_U64S * 8 bytes. * @@ -850,6 +880,9 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) uint16_t tot_len; if (OVS_UNLIKELY(!ipv4_sanity_check(nh, size, &ip_len, &tot_len))) { + if (OVS_UNLIKELY(VLOG_IS_DBG_ENABLED())) { + dump_invalid_packet(packet, "ipv4_sanity_check"); + } goto out; } dp_packet_set_l2_pad_size(packet, size - tot_len); @@ -880,6 +913,9 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) uint16_t plen; if (OVS_UNLIKELY(!ipv6_sanity_check(nh, size))) { + if (OVS_UNLIKELY(VLOG_IS_DBG_ENABLED())) { + dump_invalid_packet(packet, "ipv6_sanity_check"); + } goto out; } data_pull(&data, &size, sizeof *nh); @@ -1114,6 +1150,9 @@ parse_tcp_flags(struct dp_packet *packet) uint16_t tot_len; if (OVS_UNLIKELY(!ipv4_sanity_check(nh, size, &ip_len, &tot_len))) { + if (OVS_UNLIKELY(VLOG_IS_DBG_ENABLED())) { + dump_invalid_packet(packet, "ipv4_sanity_check"); + } return 0; } dp_packet_set_l2_pad_size(packet, size - tot_len); @@ -1127,6 +1166,9 @@ parse_tcp_flags(struct dp_packet *packet) uint16_t plen; if (OVS_UNLIKELY(!ipv6_sanity_check(nh, size))) { + if (OVS_UNLIKELY(VLOG_IS_DBG_ENABLED())) { + dump_invalid_packet(packet, "ipv6_sanity_check"); + } return 0; } data_pull(&data, &size, sizeof *nh);