From mboxrd@z Thu Jan 1 00:00:00 1970 From: Petar Penkov Subject: [bpf-next 0/3] Introduce eBPF flow dissector Date: Thu, 30 Aug 2018 11:22:58 -0700 Message-ID: <20180830182301.89435-1-peterpenkov96@gmail.com> Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, simon.horman@netronome.com, ecree@solarflare.com, songliubraving@fb.com, tom@herbertland.com, Petar Penkov To: netdev@vger.kernel.org Return-path: Received: from mail-pf1-f195.google.com ([209.85.210.195]:45590 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728180AbeH3W0i (ORCPT ); Thu, 30 Aug 2018 18:26:38 -0400 Received: by mail-pf1-f195.google.com with SMTP id i26-v6so4241487pfo.12 for ; Thu, 30 Aug 2018 11:23:13 -0700 (PDT) Sender: netdev-owner@vger.kernel.org List-ID: From: Petar Penkov This patch series hardens the RX stack by allowing flow dissection in BPF, as previously discussed [1]. Because of the rigorous checks of the BPF verifier, this provides significant security guarantees. In particular, the BPF flow dissector cannot get inside of an infinite loop, as with CVE-2013-4348, because BPF programs are guaranteed to terminate. It cannot read outside of packet bounds, because all memory accesses are checked. Also, with BPF the administrator can decide which protocols to support, reducing potential attack surface. Rarely encountered protocols can be excluded from dissection and the program can be updated without kernel recompile or reboot if a bug is discovered. Patch 1 adds infrastructure to execute a BPF program in __skb_flow_dissect. This includes a new BPF program and attach type. Patch 2 adds a flow dissector program in BPF. This parses most protocols in __skb_flow_dissect in BPF for a subset of flow keys (basic, control, ports, and address types). Patch 3 adds a selftest that attaches the BPF program to the flow dissector and sends traffic with different levels of encapsulation. Performance Evaluation: The in-kernel implementation was compared against the demo program from patch 2 using the test in patch 3 with IPv4/UDP traffic over 10 seconds. $perf record -a -C 4 taskset -c 4 ./test_flow_dissector -i 4 -f 8 \ -t 10 In-kernel Dissector: __skb_flow_dissect overhead: 2.12% Total Packets: 3,272,597 (from output of ./test_flow_dissector) BPF Dissector: __skb_flow_dissect overhead: 1.63% Total Packets: 3,232,356 (from output of ./test_flow_dissector) No-op Dissector: __skb_flow_dissect overhead: 1.52% Total Packets: 3,330,635 (from output of ./test_flow_dissector) Changes since RFC: 1/ (Patch 1) Flow dissector hook is no longer global. Instead, it is per-netns 2/ (Patch 1) Defined struct bpf_flow_keys to be used in BPF flow dissector programs instead of exposing the internal flow keys layout. Added a function to translate from bpf_flow_keys to the internal layout after BPF dissection is complete. The pointer to this struct is stored in qdisc_skb_cb rather than inside of the 20 byte control block which simplifies verification and allows access to all 20 bytes of the cb. 3/ (Patch 2) Removed GUE parsing as it relied on a hardcoded port 4/ (Patch 2) MPLS parsing now stops at the first label which is consistent with the in-kernel flow dissector 5/ (Patch 2) Refactored to use direct packet access and to write out to struct bpf_flow_keys [1] http://vger.kernel.org/netconf2017_files/rx_hardening_and_udp_gso.pdf Petar Penkov (3): flow_dissector: implements flow dissector BPF hook flow_dissector: implements eBPF parser selftests/bpf: test bpf flow dissection include/linux/bpf.h | 1 + include/linux/bpf_types.h | 1 + include/linux/skbuff.h | 7 + include/net/net_namespace.h | 3 + include/net/sch_generic.h | 12 +- include/uapi/linux/bpf.h | 25 + kernel/bpf/syscall.c | 8 + kernel/bpf/verifier.c | 33 + net/core/filter.c | 67 ++ net/core/flow_dissector.c | 136 +++ tools/bpf/bpftool/prog.c | 1 + tools/include/uapi/linux/bpf.h | 25 + tools/lib/bpf/libbpf.c | 2 + tools/testing/selftests/bpf/.gitignore | 2 + tools/testing/selftests/bpf/Makefile | 8 +- tools/testing/selftests/bpf/bpf_flow.c | 390 +++++++++ tools/testing/selftests/bpf/config | 1 + .../selftests/bpf/flow_dissector_load.c | 140 ++++ .../selftests/bpf/test_flow_dissector.c | 782 ++++++++++++++++++ .../selftests/bpf/test_flow_dissector.sh | 115 +++ tools/testing/selftests/bpf/with_addr.sh | 54 ++ tools/testing/selftests/bpf/with_tunnels.sh | 36 + 22 files changed, 1843 insertions(+), 6 deletions(-) create mode 100644 tools/testing/selftests/bpf/bpf_flow.c create mode 100644 tools/testing/selftests/bpf/flow_dissector_load.c create mode 100644 tools/testing/selftests/bpf/test_flow_dissector.c create mode 100755 tools/testing/selftests/bpf/test_flow_dissector.sh create mode 100755 tools/testing/selftests/bpf/with_addr.sh create mode 100755 tools/testing/selftests/bpf/with_tunnels.sh -- 2.19.0.rc0.228.g281dcd1b4d0-goog