BPF List
 help / color / mirror / Atom feed
From: Daniel Xu <dxu@dxuuu.xyz>
To: davem@davemloft.net, yoshfuji@linux-ipv6.org, dsahern@kernel.org,
	martin.lau@linux.dev, daniel@iogearbox.net, ast@kernel.org,
	andrii@kernel.org
Cc: ppenkov@aviatrix.com, dbird@aviatrix.com, netdev@vger.kernel.org,
	bpf@vger.kernel.org
Subject: [PATCH bpf-next 0/6] Support defragmenting IPv4 packets in BPF
Date: Wed, 14 Dec 2022 16:25:27 -0700	[thread overview]
Message-ID: <cover.1671049840.git.dxu@dxuuu.xyz> (raw)

=== Context ===

In the context of a middlebox, fragmented packets are tricky to handle.
The full 5-tuple of a packet is often only available in the first
fragment which makes enforcing consistent policy difficult. There are
really only two stateless options, neither of which are very nice:

1. Enforce policy on first fragment and accept all subsequent fragments.
   This works but may let in certain attacks or allow data exfiltration.

2. Enforce policy on first fragment and drop all subsequent fragments.
   This does not really work b/c some protocols may rely on
   fragmentation. For example, DNS may rely on oversized UDP packets for
   large responses.

So stateful tracking is the only sane option. RFC 8900 [0] calls this
out as well in section 6.3:

    Middleboxes [...] should process IP fragments in a manner that is
    consistent with [RFC0791] and [RFC8200]. In many cases, middleboxes
    must maintain state in order to achieve this goal.

=== BPF related bits ===

However, when policy is enforced through BPF, the prog is run before the
kernel reassembles fragmented packets. This leaves BPF developers in a
awkward place: implement reassembly (possibly poorly) or use a stateless
method as described above.

Fortunately, the kernel has robust support for fragmented ipv4 packets.
This patchset wraps the existing defragmentation facilities in a kfunc so
that BPF progs running on middleboxes can reassemble fragmented packets
before applying policy.

=== Patchset details ===

This patchset is (hopefully) relatively straightforward from BPF perspective.
One thing I'd like to call out is the skb_copy()ing of the prog skb. I
did this to maintain the invariant that the ctx remains valid after prog
has run. This is relevant b/c ip_defrag() and ip_check_defrag() may
consume the skb if the skb is a fragment.

Originally I did play around with teaching the verifier about kfuncs
that may consume the ctx and disallowing ctx accesses in ret != 0
branches. It worked ok, but it seemed too complex to modify the
surrounding assumptions about ctx validity.

[0]: https://datatracker.ietf.org/doc/html/rfc8900

Daniel Xu (6):
  ip: frags: Return actual error codes from ip_check_defrag()
  bpf: verifier: Support KF_CHANGES_PKT flag
  bpf, net, frags: Add bpf_ip_check_defrag() kfunc
  bpf: selftests: Support not connecting client socket
  bpf: selftests: Support custom type and proto for client sockets
  bpf: selftests: Add bpf_ip_check_defrag() selftest

 Documentation/bpf/kfuncs.rst                  |   7 +
 drivers/net/macvlan.c                         |   2 +-
 include/linux/btf.h                           |   1 +
 include/net/ip.h                              |  11 +
 kernel/bpf/verifier.c                         |   8 +
 net/ipv4/Makefile                             |   1 +
 net/ipv4/ip_fragment.c                        |  13 +-
 net/ipv4/ip_fragment_bpf.c                    |  98 ++++++
 net/packet/af_packet.c                        |   2 +-
 .../selftests/bpf/generate_udp_fragments.py   |  52 +++
 tools/testing/selftests/bpf/network_helpers.c |  26 +-
 tools/testing/selftests/bpf/network_helpers.h |   3 +
 .../bpf/prog_tests/ip_check_defrag.c          | 296 ++++++++++++++++++
 .../selftests/bpf/progs/bpf_tracing_net.h     |   1 +
 .../selftests/bpf/progs/ip_check_defrag.c     |  83 +++++
 15 files changed, 589 insertions(+), 15 deletions(-)
 create mode 100644 net/ipv4/ip_fragment_bpf.c
 create mode 100755 tools/testing/selftests/bpf/generate_udp_fragments.py
 create mode 100644 tools/testing/selftests/bpf/prog_tests/ip_check_defrag.c
 create mode 100644 tools/testing/selftests/bpf/progs/ip_check_defrag.c

-- 
2.39.0


             reply	other threads:[~2022-12-14 23:28 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-14 23:25 Daniel Xu [this message]
2022-12-14 23:25 ` [PATCH bpf-next 1/6] ip: frags: Return actual error codes from ip_check_defrag() Daniel Xu
2022-12-14 23:25 ` [PATCH bpf-next 2/6] bpf: verifier: Support KF_CHANGES_PKT flag Daniel Xu
2022-12-17 18:08   ` kernel test robot
2022-12-14 23:25 ` [PATCH bpf-next 3/6] bpf, net, frags: Add bpf_ip_check_defrag() kfunc Daniel Xu
2022-12-15 22:31   ` Daniel Borkmann
2022-12-15 23:58     ` Daniel Xu
2022-12-14 23:25 ` [PATCH bpf-next 4/6] bpf: selftests: Support not connecting client socket Daniel Xu
2022-12-14 23:25 ` [PATCH bpf-next 5/6] bpf: selftests: Support custom type and proto for client sockets Daniel Xu
2022-12-14 23:25 ` [PATCH bpf-next 6/6] bpf: selftests: Add bpf_ip_check_defrag() selftest Daniel Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1671049840.git.dxu@dxuuu.xyz \
    --to=dxu@dxuuu.xyz \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=dbird@aviatrix.com \
    --cc=dsahern@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=netdev@vger.kernel.org \
    --cc=ppenkov@aviatrix.com \
    --cc=yoshfuji@linux-ipv6.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox