From patchwork Fri Apr 16 12:06:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 1467037 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=hP2GHCeq; 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 4FMFLl49twz9sVb for ; Fri, 16 Apr 2021 22:06:54 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 8D80440393; Fri, 16 Apr 2021 12:06:52 +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 yuQIeIw7x5Qq; Fri, 16 Apr 2021 12:06:51 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTP id C1C0E4012F; Fri, 16 Apr 2021 12:06:50 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 8344CC000C; Fri, 16 Apr 2021 12:06:50 +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 369ADC000A for ; Fri, 16 Apr 2021 12:06:49 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 118E9847C9 for ; Fri, 16 Apr 2021 12:06:49 +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 v4_QS8jGgwyM for ; Fri, 16 Apr 2021 12:06:47 +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 [63.128.21.124]) by smtp1.osuosl.org (Postfix) with ESMTPS id C408A847C8 for ; Fri, 16 Apr 2021 12:06:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1618574806; 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=LYiJkOhWiF1wwcC9txeszvaJGbfa8gVx1M5rmC8vgQM=; b=hP2GHCeqVRgb94byBKef6t7fySB/qU0V6xvEQop4z7F5pksEEmQ585ZXsOX0Qp4oSxcPQD NiIShzm/ZNqJI9iiQeirR6OQo4IZt3MKL1xoXtDj98Ra59o1pkzgR8O1vnBL/D7KZkDd7s u5STFZsNVFOWXfJ0iRlPQlBDb5AVE2c= 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-562-TDhZlB_sN1OHcYcIm4lJrQ-1; Fri, 16 Apr 2021 08:06:45 -0400 X-MC-Unique: TDhZlB_sN1OHcYcIm4lJrQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 1557A100A90A; Fri, 16 Apr 2021 12:06:44 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.192.93]) by smtp.corp.redhat.com (Postfix) with ESMTP id 82B905C3DF; Fri, 16 Apr 2021 12:06:38 +0000 (UTC) From: David Marchand To: dev@openvswitch.org Date: Fri, 16 Apr 2021 14:06:31 +0200 Message-Id: <20210416120631.4584-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 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 v2] 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 Acked-by: Eelco Chaudron Acked-by: Flavio Leitner --- Changes since v1: - changed counter names to reflect they are part of miniflow_extract, --- lib/flow.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/lib/flow.c b/lib/flow.c index 729d59b1b3..89837de95d 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(miniflow_extract_ipv4_pkt_len_error); +COVERAGE_DEFINE(miniflow_extract_ipv4_pkt_too_short); +COVERAGE_DEFINE(miniflow_extract_ipv6_pkt_len_error); +COVERAGE_DEFINE(miniflow_extract_ipv6_pkt_too_short); 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(miniflow_extract_ipv4_pkt_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(miniflow_extract_ipv4_pkt_len_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(miniflow_extract_ipv4_pkt_len_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(miniflow_extract_ipv6_pkt_too_short); return false; } plen = ntohs(nh->ip6_plen); if (OVS_UNLIKELY(plen + IPV6_HEADER_LEN > size)) { + COVERAGE_INC(miniflow_extract_ipv6_pkt_len_error); return false; } if (OVS_UNLIKELY(size - (plen + IPV6_HEADER_LEN) > UINT16_MAX)) { + COVERAGE_INC(miniflow_extract_ipv6_pkt_len_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);