History log of /freebsd-10-stable/sys/netpfil/pf/pf_norm.c
Revision Date Author Comments
# 338106 20-Aug-2018 kp

MFC r337969:

pf: Limit the maximum number of fragments per packet

Similar to the network stack issue fixed in r337782 pf did not limit the number
of fragments per packet, which could be exploited to generate high CPU loads
with a crafted series of packets.

Limit each packet to no more than 64 fragments. This should be sufficient on
typical networks to allow maximum-sized IP frames.

This addresses the issue for both IPv4 and IPv6.

Security: CVE-2018-5391
Sponsored by: Klara Systems


# 317335 23-Apr-2017 kp

MFC r317186

pf: Fix possible incorrect IPv6 fragmentation

When forwarding pf tracks the size of the largest fragment in a fragmented
packet, and refragments based on this size.
It failed to ensure that this size was a multiple of 8 (as is required for all
but the last fragment), so it could end up generating incorrect fragments.

For example, if we received an 8 byte and 12 byte fragment pf would emit a first
fragment with 12 bytes of payload and the final fragment would claim to be at
offset 8 (not 12).

We now assert that the fragment size is a multiple of 8 in ip6_fragment(), so
other users won't make the same mistake.

Reported by: Antonios Atlasis <aatlasis at secfu net>


# 300552 24-May-2016 kp

MFC 300307:

pf: Fix fragment timeout

We were inconsistent about the use of time_second vs. time_uptime.
Always use time_uptime so the value can be meaningfully compared.

Submitted by: "Max" <maximos@als.nnov.ru>


# 289703 21-Oct-2015 kp

MFC r289316:

pf: Fix TSO issues

In certain configurations (mostly but not exclusively as a VM on Xen) pf
produced packets with an invalid TCP checksum.

The problem was that pf could only handle packets with a full checksum. The
FreeBSD IP stack produces TCP packets with a pseudo-header checksum (only
addresses, length and protocol).
Certain network interfaces expect to see the pseudo-header checksum, so they
end up producing packets with invalid checksums.

To fix this stop calculating the full checksum and teach pf to only update TCP
checksums if TSO is disabled or the change affects the pseudo-header checksum.

PR: 154428, 193579, 198868
Relnotes: yes
Sponsored by: RootBSD


# 286079 30-Jul-2015 gjb

MFC r285999 (kp):
pf: Always initialise pf_fragment.fr_flags

When we allocate the struct pf_fragment in pf_fillup_fragment() we
forgot to initialise the fr_flags field. As a result we sometimes
mistakenly thought the fragment to not be a buffered fragment.
This resulted in panics because we'd end up freeing the pf_fragment
but not removing it from V_pf_fragqueue (believing it to be part of
V_pf_cachequeue). The next time we iterated V_pf_fragqueue we'd use
a freed object and panic.

While here also fix a pf_fragment use after free in pf_normalize_ip().
pf_reassemble() frees the pf_fragment, so we can't use it any more.

X-MFS-To: releng/10.2
Sponsored by: The FreeBSD Foundation


# 284581 18-Jun-2015 kp

Merge r284280

pf: Remove frc_direction

We don't use the direction of the fragments for anything. The frc_direction
field is assigned, but never read.
Just remove it.

Differential Revision: https://reviews.freebsd.org/D2825
Reviewed by: gnn


# 284580 18-Jun-2015 kp

Merge r284222, r284260

pf: address family must be set when creating a pf_fragment

Fix a panic when handling fragmented ip4 packets with 'drop-ovl' set.
In that scenario we take a different branch in pf_normalize_ip(), taking us to
pf_fragcache() (rather than pf_reassemble()). In pf_fragcache() we create a
pf_fragment, but do not set the address family. This leads to a panic when we
try to insert that into pf_frag_tree because pf_addr_cmp(), which is used to
compare the pf_fragments doesn't know what to do if the address family is not
set.

Simply ensure that the address family is set correctly (always AF_INET in this
path).

When we try to look up a pf_fragment with pf_find_fragment() we compare (see
pf_frag_compare()) addresses (and family), but also protocol. We failed to
save the protocol to the pf_fragment in pf_fragcache(), resulting in failing
reassembly.

PR: 200330
Differential Revision: https://reviews.freebsd.org/D2824
Reviewed by: gnn


# 284579 18-Jun-2015 kp

Merge r278874, r278925, r278868

- Improve INET/INET6 scope.
- style(9) declarations.
- Make couple of local functions static.
- Even more fixes to !INET and !INET6 kernels.
In collaboration with pluknet
- Toss declarations to fix regular build and NO_INET6 build.

Differential Revision: https://reviews.freebsd.org/D2823
Reviewed by: gnn


# 284574 18-Jun-2015 kp

Merge r281164

pf: Skip firewall for refragmented ip6 packets

In cases where we scrub (fragment reassemble) on both input and output
we risk ending up in infinite loops when forwarding packets.

Fragmented packets come in and get collected until we can defragment. At
that point the defragmented packet is handed back to the ip stack (at
the pfil point in ip6_input(). Normal processing continues.

Eventually we figure out that the packet has to be forwarded and we end
up at the pfil hook in ip6_forward(). After doing the inspection on the
defragmented packet we see that the packet has been defragmented and
because we're forwarding we have to refragment it.

In pf_refragment6() we split the packet up again and then ip6_forward()
the individual fragments. Those fragments hit the pfil hook on the way
out, so they're collected until we can reconstruct the full packet, at
which point we're right back where we left off and things continue until
we run out of stack.

Break that loop by marking the fragments generated by pf_refragment6()
as M_SKIP_FIREWALL. There's no point in processing those packets in the
firewall anyway. We've already filtered on the full packet.

Differential Revision: https://reviews.freebsd.org/D2819
Reviewed by: gnn


# 284573 18-Jun-2015 kp

Merge r280956

pf: Deal with runt packets

On Ethernet packets have a minimal length, so very short packets get padding
appended to them. This padding is not stripped off in ip6_input() (due to
support for IPv6 Jumbograms, RFC2675).
That means PF needs to be careful when reassembling fragmented packets to not
include the padding in the reassembled packet.

While here also remove the 'Magic from ip_input.' bits. Splitting up and
re-joining an mbuf chain here doesn't make any sense.

Differential Revision: https://reviews.freebsd.org/D2818
Reviewed by: gnn


# 284572 18-Jun-2015 kp

Merge r280955

Preserve IPv6 fragment IDs accross reassembly and refragmentation

When forwarding fragmented IPv6 packets and filtering with PF we
reassemble and refragment. That means we generate new fragment headers
and a new fragment ID.

We already save the fragment IDs so we can do the reassembly so it's
straightforward to apply the incoming fragment ID on the refragmented
packets.

Differential Revision: https://reviews.freebsd.org/D2817
Reviewed by: gnn


# 284571 18-Jun-2015 kp

Merge r278843, r278858

In the forwarding case refragment the reassembled packets with the same
size as they arrived in. This allows the sender to determine the optimal
fragment size by Path MTU Discovery.

Roughly based on the OpenBSD work by Alexander Bluhm.

Differential Revision: https://reviews.freebsd.org/D2816
Reviewed by: gnn


# 284569 18-Jun-2015 kp

Merge r278831, r278834

Update the pf fragment handling code to closer match recent OpenBSD.
That partially fixes IPv6 fragment handling.

Differential Revision: https://reviews.freebsd.org/D2814
Reviewed by: gnn


# 282688 09-May-2015 gnn

MFC: 281529

I can find no reason to allow packets with both SYN and FIN bits
set past this point in the code. The packet should be dropped and
not massaged as it is here.

Differential Revision: https://reviews.freebsd.org/D2266
Submitted by: eri
Sponsored by: Rubicon Communications (Netgate)


# 263086 12-Mar-2014 glebius

Bulk sync of pf changes from head, in attempt to fixup broken build I
made in r263029.

Merge r257186,257215,257349,259736,261797.

These changesets split pfvar.h into several smaller headers and make
userland utilities to include only some of them.


# 286079 30-Jul-2015 gjb

MFC r285999 (kp):
pf: Always initialise pf_fragment.fr_flags

When we allocate the struct pf_fragment in pf_fillup_fragment() we
forgot to initialise the fr_flags field. As a result we sometimes
mistakenly thought the fragment to not be a buffered fragment.
This resulted in panics because we'd end up freeing the pf_fragment
but not removing it from V_pf_fragqueue (believing it to be part of
V_pf_cachequeue). The next time we iterated V_pf_fragqueue we'd use
a freed object and panic.

While here also fix a pf_fragment use after free in pf_normalize_ip().
pf_reassemble() frees the pf_fragment, so we can't use it any more.

X-MFS-To: releng/10.2
Sponsored by: The FreeBSD Foundation


# 284581 18-Jun-2015 kp

Merge r284280

pf: Remove frc_direction

We don't use the direction of the fragments for anything. The frc_direction
field is assigned, but never read.
Just remove it.

Differential Revision: https://reviews.freebsd.org/D2825
Reviewed by: gnn


# 284580 18-Jun-2015 kp

Merge r284222, r284260

pf: address family must be set when creating a pf_fragment

Fix a panic when handling fragmented ip4 packets with 'drop-ovl' set.
In that scenario we take a different branch in pf_normalize_ip(), taking us to
pf_fragcache() (rather than pf_reassemble()). In pf_fragcache() we create a
pf_fragment, but do not set the address family. This leads to a panic when we
try to insert that into pf_frag_tree because pf_addr_cmp(), which is used to
compare the pf_fragments doesn't know what to do if the address family is not
set.

Simply ensure that the address family is set correctly (always AF_INET in this
path).

When we try to look up a pf_fragment with pf_find_fragment() we compare (see
pf_frag_compare()) addresses (and family), but also protocol. We failed to
save the protocol to the pf_fragment in pf_fragcache(), resulting in failing
reassembly.

PR: 200330
Differential Revision: https://reviews.freebsd.org/D2824
Reviewed by: gnn


# 284579 18-Jun-2015 kp

Merge r278874, r278925, r278868

- Improve INET/INET6 scope.
- style(9) declarations.
- Make couple of local functions static.
- Even more fixes to !INET and !INET6 kernels.
In collaboration with pluknet
- Toss declarations to fix regular build and NO_INET6 build.

Differential Revision: https://reviews.freebsd.org/D2823
Reviewed by: gnn


# 284574 18-Jun-2015 kp

Merge r281164

pf: Skip firewall for refragmented ip6 packets

In cases where we scrub (fragment reassemble) on both input and output
we risk ending up in infinite loops when forwarding packets.

Fragmented packets come in and get collected until we can defragment. At
that point the defragmented packet is handed back to the ip stack (at
the pfil point in ip6_input(). Normal processing continues.

Eventually we figure out that the packet has to be forwarded and we end
up at the pfil hook in ip6_forward(). After doing the inspection on the
defragmented packet we see that the packet has been defragmented and
because we're forwarding we have to refragment it.

In pf_refragment6() we split the packet up again and then ip6_forward()
the individual fragments. Those fragments hit the pfil hook on the way
out, so they're collected until we can reconstruct the full packet, at
which point we're right back where we left off and things continue until
we run out of stack.

Break that loop by marking the fragments generated by pf_refragment6()
as M_SKIP_FIREWALL. There's no point in processing those packets in the
firewall anyway. We've already filtered on the full packet.

Differential Revision: https://reviews.freebsd.org/D2819
Reviewed by: gnn


# 284573 18-Jun-2015 kp

Merge r280956

pf: Deal with runt packets

On Ethernet packets have a minimal length, so very short packets get padding
appended to them. This padding is not stripped off in ip6_input() (due to
support for IPv6 Jumbograms, RFC2675).
That means PF needs to be careful when reassembling fragmented packets to not
include the padding in the reassembled packet.

While here also remove the 'Magic from ip_input.' bits. Splitting up and
re-joining an mbuf chain here doesn't make any sense.

Differential Revision: https://reviews.freebsd.org/D2818
Reviewed by: gnn


# 284572 18-Jun-2015 kp

Merge r280955

Preserve IPv6 fragment IDs accross reassembly and refragmentation

When forwarding fragmented IPv6 packets and filtering with PF we
reassemble and refragment. That means we generate new fragment headers
and a new fragment ID.

We already save the fragment IDs so we can do the reassembly so it's
straightforward to apply the incoming fragment ID on the refragmented
packets.

Differential Revision: https://reviews.freebsd.org/D2817
Reviewed by: gnn


# 284571 18-Jun-2015 kp

Merge r278843, r278858

In the forwarding case refragment the reassembled packets with the same
size as they arrived in. This allows the sender to determine the optimal
fragment size by Path MTU Discovery.

Roughly based on the OpenBSD work by Alexander Bluhm.

Differential Revision: https://reviews.freebsd.org/D2816
Reviewed by: gnn


# 284569 18-Jun-2015 kp

Merge r278831, r278834

Update the pf fragment handling code to closer match recent OpenBSD.
That partially fixes IPv6 fragment handling.

Differential Revision: https://reviews.freebsd.org/D2814
Reviewed by: gnn


# 282688 09-May-2015 gnn

MFC: 281529

I can find no reason to allow packets with both SYN and FIN bits
set past this point in the code. The packet should be dropped and
not massaged as it is here.

Differential Revision: https://reviews.freebsd.org/D2266
Submitted by: eri
Sponsored by: Rubicon Communications (Netgate)


# 263086 12-Mar-2014 glebius

Bulk sync of pf changes from head, in attempt to fixup broken build I
made in r263029.

Merge r257186,257215,257349,259736,261797.

These changesets split pfvar.h into several smaller headers and make
userland utilities to include only some of them.