git: e7f9171b6738 - main - pf: Handle m_len < sizeof(struct ether_header) case
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 21 Aug 2024 12:11:52 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=e7f9171b6738809ded7250bc5c78368421255b1b commit e7f9171b6738809ded7250bc5c78368421255b1b Author: Igor Ostapenko <pm@igoro.pro> AuthorDate: 2024-08-21 10:01:34 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2024-08-21 12:10:03 +0000 pf: Handle m_len < sizeof(struct ether_header) case Reviewed by: kp Differential Revision: https://reviews.freebsd.org/D46391 --- sys/netpfil/pf/pf.c | 7 +++++ tests/sys/netpfil/pf/mbuf.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index ad2dc2e707ed..cb69d06b1fe6 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -4365,6 +4365,13 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0) r = TAILQ_FIRST(rules); rm = NULL; + if (__predict_false(m->m_len < sizeof(struct ether_header)) && + (m = *m0 = m_pullup(*m0, sizeof(struct ether_header))) == NULL) { + DPFPRINTF(PF_DEBUG_URGENT, + ("pf_test_eth_rule: m_len < sizeof(struct ether_header)" + ", pullup failed\n")); + return (PF_DROP); + } e = mtod(m, struct ether_header *); proto = ntohs(e->ether_type); diff --git a/tests/sys/netpfil/pf/mbuf.sh b/tests/sys/netpfil/pf/mbuf.sh index 2dffa48ed2f5..a4664718093a 100644 --- a/tests/sys/netpfil/pf/mbuf.sh +++ b/tests/sys/netpfil/pf/mbuf.sh @@ -151,8 +151,81 @@ inet6_in_mbuf_len_cleanup() pft_cleanup } +atf_test_case "ethernet_in_mbuf_len" "cleanup" +ethernet_in_mbuf_len_head() +{ + atf_set descr 'Test that pf can handle inbound with the first mbuf with m_len < sizeof(struct ether_header)' + atf_set require.user root +} +ethernet_in_mbuf_len_body() +{ + pft_init + dummymbuf_init + + epair=$(vnet_mkepair) + epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }') + ifconfig ${epair}a 192.0.2.1/24 up + + # Set up a simple jail with one interface + vnet_mkjail alcatraz ${epair}b + jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up + epair_b_mac=$(jexec alcatraz ifconfig ${epair}b ether | awk '/ether/ { print $2; }') + + # Sanity check + atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 + + # Should be denied + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "ether block" \ + "pass" + atf_check -s not-exit:0 -o ignore ping -c1 -t1 192.0.2.2 + + # Should be allowed by from/to addresses + echo $epair_a_mac + echo $epair_b_mac + pft_set_rules alcatraz \ + "ether block" \ + "ether pass in from ${epair_a_mac} to ${epair_b_mac}" \ + "ether pass out from ${epair_b_mac} to ${epair_a_mac}" \ + "pass" + atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 + + # Should still work for m_len=0 + jexec alcatraz pfilctl link -i dummymbuf:ethernet ethernet + jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 0;" + atf_check_equal "0" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" + atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 + atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" + + # m_len=1 + jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 1;" + jexec alcatraz sysctl net.dummymbuf.hits=0 + atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 + atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" + + # m_len=11 + # for the simplest L2 Ethernet frame it should impact src field + jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 11;" + jexec alcatraz sysctl net.dummymbuf.hits=0 + atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 + atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" + + # m_len=13 + # provided L2 Ethernet simplest header is 14 bytes long, it should impact ethertype field + jexec alcatraz sysctl net.dummymbuf.rules="ethernet in ${epair}b pull-head 13;" + jexec alcatraz sysctl net.dummymbuf.hits=0 + atf_check -s exit:0 -o ignore ping -c1 192.0.2.2 + atf_check_equal "1" "$(jexec alcatraz sysctl -n net.dummymbuf.hits)" +} +ethernet_in_mbuf_len_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "inet_in_mbuf_len" atf_add_test_case "inet6_in_mbuf_len" + atf_add_test_case "ethernet_in_mbuf_len" }