Commit graph

1239 commits

Author SHA1 Message Date
Mark Johnston 66b8cac8d8 pf: Sprinkle const qualifiers in state lookup routines
State keys are trivially const in lookup routines, so annotate them as
such.  No functional change intended.

Reviewed by:	kp
MFC after:	1 week
Sponsored by:	Klara, Inc.
Sponsored by:	Modirum
Differential Revision:	https://reviews.freebsd.org/D45671
2024-06-24 10:46:55 -04:00
Doug Moore 0839258c56 ipfw: Use roundup_pow_of_two
Use roundup_pow_of_two in place of a local function that does the same thing.

Reviewed by:	alc, markj
Differential Revision:	https://reviews.freebsd.org/D45536
2024-06-24 02:24:24 -05:00
Mateusz Guzik b6196537b0 pf: fix the "keepcounters" to stop truncating to 32-bit
The machinery to support 64-bit counters even on 32-bit kernels had a
bug where it would unitentionally truncate the value back to 32-bits
when transferring to a new counter. This resulted in buggy be behavior
on 64-bit kernels as well.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-06-20 17:55:43 +00:00
Kristof Provost 07ed239698 pf: make TCP sequence number tracking less strict by one octet for FIN packets
The data of a TCP packet must fit into the announced window, but this is not
required for the sequence number of the FIN.  A packet with the FIN bit set and
containing data that fits exactly into the announced window was blocked. Our
stack generates such packets when the receive buffer size is set to 1024. Now
pf uses only the data lenght for window comparison.
OK henning@

Obtained From:	OpenBSD
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-06-12 23:33:11 +02:00
Kristof Provost 20a2fe68fa pf: correctly reset max_win if the SYN-ACK lacks a wscale option.
pf was setting max_win to 0 and discarded retransmitted SYN-ACK segments without
wscale if the original SYN contained a wscale option. with gerhard@, ok
henning@

Obtained From:	OpenBSD
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-06-12 23:33:11 +02:00
Doug Moore f0a0420dfd powerof2: replace loops with fls or ilog2
In several places, a loop tests for powers of two, or iterates through
powers of two.  In those places, replace the loop with an invocation
of fls or ilog2 without changing the meaning of the code.

Reviewed by:	alc, markj, kib, np, erj, avg (previous version)
Differential Revision:	https://reviews.freebsd.org/D45494
2024-06-12 05:00:48 -05:00
Zhenlei Huang 2671bde992 pfsync: Correctly check if bpf peers are present
On creating the pfsync(4) interface, pfsync_clone_create() does an
unconditional bpfattach(). Use bpf_peers_present() which was introduced
in commit 16d878cc99 [1] to check the presence of bpf peers.

This will save a little CPU cycles and memory usage when the
synchronisation interface is not configured and there is no bpf peers
present. There should be no functional change.

1. 16d878cc99 Fix the following bpf(4) race condition which can result in a panic

Reviewed by:	kp
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D45533
2024-06-09 09:05:22 +08:00
Zhenlei Huang ebc2bab048 pflog: Correctly check if bpf peers are present
On creating the pflog(4) interface, pflog_clone_create() does an
unconditional bpfattach(). Use bpf_peers_present() which was introduced
in commit 16d878cc99 [1] to check the presence of bpf peers.

This will save a little CPU cycles when no bpf peers present. There
should be no functional change.

1. 16d878cc99 Fix the following bpf(4) race condition which can result in a panic

Reviewed by:	kp
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D45532
2024-06-09 09:05:22 +08:00
Kristof Provost ba2a920786 pf: convert DIOCBEGINADDRS to netlink 2024-06-08 04:46:43 +02:00
Kristof Provost d9ab899931 pf: migrate DIOCGETLIMIT/DIOCSETLIMIT to netlink
Event:		Kitchener-Waterloo Hackathon 202406
2024-06-07 20:59:02 +02:00
Kristof Provost f042e15154 pf: add sctp multihome probe points
Add probe points to allow us to probe when we add or remove multihome addresses.

Example use:
	pf:sctp:multihome:add
	{
		printf("Add tag %x address %x", arg0,
		    ((struct pf_sctp_source *)arg1)->addr.v4.s_addr);
	}

	pf:sctp:multihome:remove
	{
		printf("Remove tag %x address %x", arg0,
		    ((struct pf_sctp_source *)arg2)->addr.v4.s_addr);
	}

MFC after:	1 week
Sponsored by:	Orange Business Services
2024-06-06 20:46:19 +02:00
Kristof Provost 30bad751e8 pf: convert DIOCGETTIMEOUT/DIOCSETTIMEOUT to netlink 2024-06-06 20:46:18 +02:00
Kristof Provost 8f04209d37 pf: simplify pf_addrcpy() and pf_match_addr()
Use the v4/v6 union members rather than the uint32_t ones.
Export IN_ARE_MASKED_ADDR_EQUAL() in in_var.h and use it (and its IPv6
equivalent) for masked comparisons rather than hand-rolled code.

Event:		Kitchener-Waterloo Hackathon 202406
2024-06-06 15:45:31 +02:00
Kristof Provost 8ca12190bf pf: remove incorrect SUNION2PF() macro
It casts in_addr to pf_addr, which is smaller, so this isn't quite right.
Replace it with a function that will only read the actual address.

Reported by:	CheriBSD
Event:		Kitchener-Waterloo Hackathon 202406
2024-06-06 15:45:30 +02:00
Kristof Provost 84ff9e9122 pf: fix overly large memcpy()
We only want to copy the labels array, we don't want to copy the counter as well.

Reported by:	CheriBSD
Event:		Kitchener-Waterloo Hackathon 202406
2024-06-04 19:44:20 +02:00
Kristof Provost 4779b16fa6 pf: fix overly large copy in pf_rule_to_krule()
The timeout array in struct pf_rule has PFTM_OLD_MAX entries, the one in
struct pf_krule has PFTM_MAX entries (and PFTM_MAX > PFTM_OLD_MAX).
Use the smaller of the sizes when copying.

Reported by:	CheriBSD
MFC after:	1 week
Event:		Kitchener-Waterloo Hackathon 202406
2024-06-04 19:44:20 +02:00
Kristof Provost c36c90a2cc pf: convert DIOCSETDEBUG to netlink
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-06-04 14:59:59 +02:00
Kristof Provost 71d3c7041d pf: convert DIOCNATLOOK to netlink
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-06-04 14:59:58 +02:00
Kristof Provost 9dbbe68bc5 pf: convert DIOCCLRSTATUS to netlink
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-06-04 14:59:58 +02:00
Kristof Provost 6ee3e37682 pf: fix incorrect anchor_call to userspace
777a4702c changed how we copy out the anchor_call string, and
incorrectly limited it to 8 (4 on 32-bit systems) bytes. Fix that so we
get the full anchor path, rather than just the first few characters.

PR:		279225
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-05-28 22:27:22 +02:00
Kristof Provost 301ec2cebb pf: always mark states as unlinked before detaching them
Users have reported crashes in pf_test_state_udp() where at least one state key
is NULL.

That suggests that pf_detach_state() ran concurrently with pf_test_state_udp().
pf_test_state_udp() holds the state lock (aka the id lock), but
pf_detach_state() does not.
The intent is that detached states are not returned by STATE_LOOKUP/
pf_find_state(), as the state's timeout is set to PFTM_UNLINKED and thus
pf_find_state() does not find the state.

There are other paths to pf_detach_state() (outside of pf_unlink_state())
though, where we did not set the timeout to PFTM_UNLINKED. Fix those, and assert
that the timeout is set correctly when we enter pf_detach_state().

MFC after:	1 week
See also:	https://redmine.pfsense.org/issues/15413
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D45101
2024-05-08 13:19:05 +02:00
Kristof Provost 221d459fbc pflow: handle unattached states
It's possible for states to be cleaned up (through pf_detach_state()) that
have not been fully attached. For example if there's an ID conflict during
pf_state_insert().

pflow exports states from pf_detach_state(), so it can get called on such
states, but did not account for this and could end up dereferencing a NULL
state key.

Check for this in export_pflow() and do not export unattached states.

See also:	https://redmine.pfsense.org/issues/15446
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-04-29 18:13:19 +02:00
Kristof Provost 5824df8d99 pf: convert DIOCGETSTATUS to netlink
Introduce pfctl_get_status_h() because we need the pfctl_handle. In this variant
use netlink to obtain the information.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-04-29 16:32:23 +02:00
Lexi Winter 93c5ba5a83 sys/netpfil/pf: fix non-INET module build
pf.ko, when built as a module without 'options INET' but with 'options
VIMAGE', won't load:

link_elf_obj: symbol vnet_entry_in_loopback_mask undefined

This is because it uses IN_LOOPBACK(), which in the VIMAGE case uses
INET-specific symbols.

Fix by making this check conditional on #ifdef INET.

Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1157
2024-04-23 15:13:21 -06:00
Gordon Bergling 8ce3ef5f35 netpfil: Fix typos in source code comments
- s/addres/address/

MFC after:	3 days
2024-04-18 16:17:10 +02:00
Kristof Provost a983cea4e9 pf: fix reply-to after rdr and dummynet
If we redirect a packet to localhost and it gets dummynet'd it may be
re-injected later (e.g. when delayed) which means it will be passed
through ip_input() again. ip_input() will then reject the packet because
it's directed to the loopback address, but did not arrive on a loopback
interface.

Fix this by having pf set the rcvif to V_iflo if we redirect to
loopback.

See also:	https://redmine.pfsense.org/issues/15363
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-03-28 17:06:01 +01:00
Kristof Provost caccf6d3c0 pfsync: cope with multiple pending plus messages
It's possible for pfsync to add a plus message when one is already queued.
Append both, rather than overwriting the already pending one.

MFC after:	1 week
2024-03-25 05:44:24 +01:00
Kristof Provost 81debbd60e pfsync: fix use of invalidated stack variable
Calls to pfsync_send_plus() pass pointers to stack variables.
If pfsync_sendout() then fails it retains the pointer to these stack
variables, accesing them later.

Allocate a buffer and copy the data instead, so that we can retain the
pointer safely.

Reported by:	CI KASAN, markj
MFC after:	1 week
2024-03-25 05:44:24 +01:00
Kristof Provost a1ecbc5701 pf: fix use-after-free
If we fragment the packet in pf_route() the first transmitted packet
will free the pf_mtag we have stored in pf_pdesc (pd). Ensure we
update that pointer for every packet to avoid using a freed pointer in
pf_dummynet_route().

Reported by:	CI KASAN, markj
MFC after:	1 week
2024-03-25 05:44:23 +01:00
Kristof Provost 470a2b3346 pf: convert DIOCSETSTATUSIF to netlink
While here also add a basic test case for it.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D44368
2024-03-19 16:30:08 +01:00
Kristof Provost c6f1116357 pf: fix dummynet + route-to
Ensure that we pick the correct dummynet pipe (i.e. forward vs. reverse
direction) when applying route-to.

We mark the processing as outbound so that dummynet will re-inject in
the correct phase of processing after it's done with the packet, but
that will cause us to pick the wrong pipe number. Reverse them so that
the incorrect decision ends up picking the correct pipe.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D44366
2024-03-19 16:29:29 +01:00
Kristof Provost 0ea0c02655 pf: avoid passing through dummynet multiple times
In some setups we end up with multiple states created for a single
packet, which in turn can mean we run the packet through dummynet
multiple times. That's not expected or intended. Mark each packet when
it goes through dummynet, and do not pass packet through dummynet if
they're marked as having already passed through.

See also:	https://redmine.pfsense.org/issues/14854
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D44365
2024-03-19 16:29:29 +01:00
Kristof Provost 6460322a0a pf: support if-bound with reply-to
On reply-to we don't know what interface to bind to when we create
the state. Create any reply-to state as floating, but bind to the
appropriate interface once we're handling the reply.

See also:	https://redmine.pfsense.org/issues/15220
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-03-01 09:39:43 +01:00
Kristof Provost 706d465dae pf: convert kill/clear state to use netlink
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D44090
2024-02-28 23:26:18 +01:00
Kristof Provost 9566d92726 pf: fix packet-to-big for route-to as well
When we handle a packet via route-to (i.e. pf_route6()) we still need to
verify the MTU. However, we only run that check in the forwarding case.

Set the PFIL_FWD tag when running the pf_test6(PF_OUT) check from
pf_route6(). We are in fact forwarding, so should call the test function
as such. This will cause us to run the MTU check, and generate an ICMP6
packet-too-big error when required.

See also:	54c62e3e5d
See also:	f1c0030bb0
See also:	https://redmine.pfsense.org/issues/14290
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-02-27 14:38:38 +01:00
Karim Fodil-Lemelin 62b1faa3b7 ipfw: Skip to the start of the loop when following a keep-state rule
When a packet matches an existing dynamic rule for a keep-state rule,
the matching engine advances the "instruction pointer" to the action
portion of the rule skipping over the match conditions.  However, the
code was merely breaking out of the switch statement rather than doing
a continue, so the remainder of the loop body after the switch was
still executed.  If the first action opcode contains an F_NOT but not
an F_OR (such as an "untag" action), then match is toggled to 0, and
the code exits the inner loop via a break which aborts processing of
the actions.

To fix, just use a continue instead of a break.

PR:		276732
Reviewed by:	jhb, ae
MFC after:	2 weeks
2024-02-15 17:57:51 -08:00
Kajetan Staszkiewicz 50edc63071 pfsync: Fix offset calculation
Even though message version is automatically recognized and the top of
the struct is identical for different versions, when iterating over
multiple messages proper message length must be used. That's the length
of an union member for given version, not of the union itself.

Reviewed by:	kp
Differential Revision:	https://reviews.freebsd.org/D43862
2024-02-15 12:54:02 +01:00
Kristof Provost 04c68025ea pf: add a probe point to BOUND_IFACE
It's been useful at least once, so we may as well keep it.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-02-06 18:47:07 +01:00
Kajetan Staszkiewicz 58a2674314 pf: Ensure that st->kif is obtained in a way which respects the r->rpool->mtx mutex
The redirection pool stored in r->rpool.cur is used for loadbalancing
and cur can change whenever loadbalancing happens, which is for every
new connection. Therefore it can't be trusted outside of pf_map_addr()
and the r->rpool->mtx mutex. After evaluating the ruleset, loadbalancing
decission is made in pf_map_addr() called from within pf_create_state()
and stored in the state itself.

This patch modifies BOUND_IFACE() so that it only uses the information
already stored in the state which has been obtained in a way which
respects the r->rpool->mtx mutex.

Reviewed by:	kp
Differential Revision:	https://reviews.freebsd.org/D43741
2024-02-06 17:24:28 +01:00
Kristof Provost 8a16fd431d Revert "pf: Ensure that st->kif is obtained in a way which respects the r->rpool->mtx mutex"
This commit is correct, but was misattributed. Revert so we can re-apply
with the correct author set.

This reverts commit 6d4a140acf.
2024-02-06 17:22:59 +01:00
Igor Ostapenko 6d4a140acf pf: Ensure that st->kif is obtained in a way which respects the r->rpool->mtx mutex
The redirection pool stored in r->rpool.cur is used for loadbalancing
and cur can change whenever loadbalancing happens, which is for every
new connection. Therefore it can't be trusted outside of pf_map_addr()
and the r->rpool->mtx mutex. After evaluating the ruleset, loadbalancing
decission is made in pf_map_addr() called from within pf_create_state()
and stored in the state itself.

This patch modifies BOUND_IFACE() so that it only uses the information
already stored in the state which has been obtained in a way which
respects the r->rpool->mtx mutex.

Reviewed by:	kp
Differential Revision:	https://reviews.freebsd.org/D43741
2024-02-05 22:18:11 +01:00
rilysh 11ff3552fd sys/netpfil/pf/pf.c: remove an extra semicolon
Signed-off-by: rilysh <nightquick@proton.me>
Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/959
2024-02-02 18:35:01 -07:00
rilysh c07087988b sys/netpfil/pf/pf.c: remove an extra semicolon
Signed-off-by: rilysh <nightquick@proton.me>
Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/959
2024-02-02 18:35:01 -07:00
Kristof Provost 777a4702c5 pf: implement addrule via netlink
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-02-02 17:55:16 +01:00
Kristof Provost b8ef285f6c pf: ensure dummynet gets the correct direction after route-to
If we apply a route-to to an inbound packet pf_route() may hand that
packet over to dummynet. Dummynet may then delay the packet, and later
re-inject it. This re-injection (in dummynet_send()) needs to know
if the packet was inbound or outbound, to call the correct path for
continued processing.

That's done based on the pf_pdesc we pass along (through
pf_dummynet_route() and pf_pdesc_to_dnflow()). In the case of pf_route()
on inbound packets that may be wrong, because we're called in the input
path, and didn't update pf_pdesc->dir.

This can manifest in issues with fragmented packets. For example, a
fragmented packet will be re-fragmented in pf_route(), and if dummynet
makes different decisions for some of the fragments (that is, it delays
some and allows others to pass through directly) this will break.

The packets that pass through dummynet without delay will be transmitted
correctly (through the ifp->if_output() call in pf_route()), but
the delayed packets will be re-injected in the input path (and not
the output path, as they should be). These packets will pass through
pf_test(PF_IN) as they're tagged PF_MTAG_FLAG_DUMMYNET. However,
this tag is then removed and the packet will be routed and enter
pf_test(PF_OUT) where pf_reassemble() will hold them indefinitely
(as some fragments have been transmitted directly, and will never hit
pf_test(PF_OUT)).

The fix is simple: we must update pf_pfdesc->dir to PF_OUT before we
pass the packet to dummynet.

See also:	https://redmine.pfsense.org/issues/15156
Reviewed by:	rcm
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-02-02 17:55:16 +01:00
Igor Ostapenko 9d784da3a7 pf: uncomment counter asserts after mem leak fix
Reviewed by:	kp
Differential Revision:	https://reviews.freebsd.org/D43657
2024-01-30 22:58:50 +01:00
Kristof Provost 31828075e4 pf: bind route-to states to their route-to interface
When we route-to the state should be bound to the route-to interface,
not the default route interface. However, we should only do so for
outbound traffic, because inbound traffic should bind on the arriving
interface, not the one we eventually transmit on.

Explicitly check for this in BOUND_IFACE().

We must also extend pf_find_state(), because subsequent packets within
the established state will attempt to match the original interface, not
the route-to interface.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D43589
2024-01-29 14:10:26 +01:00
Kristof Provost ffeab76b68 pfil: PFIL_PASS never frees the mbuf
pfil hooks (i.e. firewalls) may pass, modify or free the mbuf passed
to them. (E.g. when rejecting a packet, or when gathering up packets
for reassembly).

If the hook returns PFIL_PASS the mbuf must still be present. Assert
this in pfil_mem_common() and ensure that ipfilter follows this
convention. pf and ipfw already did.
Similarly, if the hook returns PFIL_DROPPED or PFIL_CONSUMED the mbuf
must have been freed (or now be owned by the firewall for further
processing, like packet scheduling or reassembly).

This allows us to remove a few extraneous NULL checks.

Suggested by:	tuexen
Reviewed by:	tuexen, zlei
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D43617
2024-01-29 14:10:19 +01:00
Kristof Provost e95025ed93 pflow: show socket status in verbose mode
Introduce a verbose output mode to pflowctl, and expose the status of
the socket to userspace. This can be helpful in debugging configuration
errors.

Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-01-25 17:37:51 +01:00
Kristof Provost f1c0030bb0 pf: only check MTU for IPv6 packets when forwarding
When the packets are generated locally (i.e. PFIL_FWD is not set) we
might generate overly large packets and rely on the NIC to fragment it
for us. In that case we'd reject a valid packet.

Reported by:	Herbert J. Skuhra <herbert@gojira.at>
Tested by:	Herbert J. Skuhra <herbert@gojira.at>
Fixes:		54c62e3e5d
Sponsored by:	Rubicon Communications, LLC ("Netgate")
2024-01-24 19:08:29 +01:00