mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 01:53:29 +02:00
netfilter: nf_socket: skip socket lookup for non-first fragments
Both nft_socket and xt_socket relies on L4 headers to perform socket lookup in the slow path. For fragmented packets, while the IP protocol remains constant across all fragments, only the first fragment contains the actual L4 header. As the expression/match could be attached to a chain with a priority lower than -400, it could bypass defragmentation. Add a check for fragmentation in the lookup functions directly so the problem is handled for both nft_socket and xt_socket at the same time. In addition, future users of the functions would not need to care about this. Fixes:902d6a4c2a("netfilter: nf_defrag: Skip defrag if NOTRACK is set") Fixes:554ced0a6e("netfilter: nf_tables: add support for native socket matching") Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
63bac02786
commit
0bf00859d7
|
|
@ -94,6 +94,9 @@ struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb,
|
|||
#endif
|
||||
int doff = 0;
|
||||
|
||||
if (ntohs(iph->frag_off) & IP_OFFSET)
|
||||
return NULL;
|
||||
|
||||
if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
|
||||
struct tcphdr _hdr;
|
||||
struct udphdr *hp;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
|
|||
const struct in6_addr *daddr = NULL, *saddr = NULL;
|
||||
struct ipv6hdr *iph = ipv6_hdr(skb), ipv6_var;
|
||||
struct sk_buff *data_skb = NULL;
|
||||
unsigned short fragoff = 0;
|
||||
int doff = 0;
|
||||
int thoff = 0, tproto;
|
||||
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
||||
|
|
@ -107,8 +108,8 @@ struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
|
|||
struct nf_conn const *ct;
|
||||
#endif
|
||||
|
||||
tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
|
||||
if (tproto < 0) {
|
||||
tproto = ipv6_find_hdr(skb, &thoff, -1, &fragoff, NULL);
|
||||
if (tproto < 0 || fragoff) {
|
||||
pr_debug("unable to find transport header in IPv6 packet, dropping\n");
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user