Message ID | 20240828214708.619261-2-pablo@netfilter.org |
---|---|
State | Accepted |
Headers | show |
Series | [net,1/2] netfilter: nf_tables: restore IP sanity checks for netdev/egress | expand |
Hello: This series was applied to netdev/net.git (main) by Pablo Neira Ayuso <pablo@netfilter.org>: On Wed, 28 Aug 2024 23:47:07 +0200 you wrote: > Subtract network offset to skb->len before performing IPv4 header sanity > checks, then adjust transport offset from offset from mac header. > > Jorge Ortiz says: > > When small UDP packets (< 4 bytes payload) are sent from eth0, > `meta l4proto udp` condition is not met because `NFT_PKTINFO_L4PROTO` is > not set. This happens because there is a comparison that checks if the > transport header offset exceeds the total length. This comparison does > not take into account the fact that the skb network offset might be > non-zero in egress mode (e.g., 14 bytes for Ethernet header). > > [...] Here is the summary with links: - [net,1/2] netfilter: nf_tables: restore IP sanity checks for netdev/egress https://git.kernel.org/netdev/net/c/5fd062891897 - [net,2/2] netfilter: nf_tables_ipv6: consider network offset in netdev/egress validation https://git.kernel.org/netdev/net/c/70c261d50095 You are awesome, thank you!
diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h index 60a7d0ce3080..fcf967286e37 100644 --- a/include/net/netfilter/nf_tables_ipv4.h +++ b/include/net/netfilter/nf_tables_ipv4.h @@ -19,7 +19,7 @@ static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt) static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt) { struct iphdr *iph, _iph; - u32 len, thoff; + u32 len, thoff, skb_len; iph = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb), sizeof(*iph), &_iph); @@ -30,8 +30,10 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt) return -1; len = iph_totlen(pkt->skb, iph); - thoff = skb_network_offset(pkt->skb) + (iph->ihl * 4); - if (pkt->skb->len < len) + thoff = iph->ihl * 4; + skb_len = pkt->skb->len - skb_network_offset(pkt->skb); + + if (skb_len < len) return -1; else if (len < thoff) return -1; @@ -40,7 +42,7 @@ static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt) pkt->flags = NFT_PKTINFO_L4PROTO; pkt->tprot = iph->protocol; - pkt->thoff = thoff; + pkt->thoff = skb_network_offset(pkt->skb) + thoff; pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET; return 0;
Subtract network offset to skb->len before performing IPv4 header sanity checks, then adjust transport offset from offset from mac header. Jorge Ortiz says: When small UDP packets (< 4 bytes payload) are sent from eth0, `meta l4proto udp` condition is not met because `NFT_PKTINFO_L4PROTO` is not set. This happens because there is a comparison that checks if the transport header offset exceeds the total length. This comparison does not take into account the fact that the skb network offset might be non-zero in egress mode (e.g., 14 bytes for Ethernet header). Fixes: 0ae8e4cca787 ("netfilter: nf_tables: set transport offset from mac header for netdev/egress") Reported-by: Jorge Ortiz <jorge.ortiz.escribano@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> --- include/net/netfilter/nf_tables_ipv4.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)