Commit 793d5d61 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: flowtable: reduce calls to pskb_may_pull()

Make two unfront calls to pskb_may_pull() to linearize the network and
transport header.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent d3519cb8
...@@ -395,8 +395,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, ...@@ -395,8 +395,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
{ {
struct tcphdr *tcph; struct tcphdr *tcph;
if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
skb_try_make_writable(skb, thoff + sizeof(*tcph)))
return -1; return -1;
tcph = (void *)(skb_network_header(skb) + thoff); tcph = (void *)(skb_network_header(skb) + thoff);
...@@ -410,8 +409,7 @@ static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, ...@@ -410,8 +409,7 @@ static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
{ {
struct udphdr *udph; struct udphdr *udph;
if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
skb_try_make_writable(skb, thoff + sizeof(*udph)))
return -1; return -1;
udph = (void *)(skb_network_header(skb) + thoff); udph = (void *)(skb_network_header(skb) + thoff);
...@@ -449,8 +447,7 @@ int nf_flow_snat_port(const struct flow_offload *flow, ...@@ -449,8 +447,7 @@ int nf_flow_snat_port(const struct flow_offload *flow,
struct flow_ports *hdr; struct flow_ports *hdr;
__be16 port, new_port; __be16 port, new_port;
if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || if (skb_try_make_writable(skb, thoff + sizeof(*hdr)))
skb_try_make_writable(skb, thoff + sizeof(*hdr)))
return -1; return -1;
hdr = (void *)(skb_network_header(skb) + thoff); hdr = (void *)(skb_network_header(skb) + thoff);
...@@ -481,8 +478,7 @@ int nf_flow_dnat_port(const struct flow_offload *flow, ...@@ -481,8 +478,7 @@ int nf_flow_dnat_port(const struct flow_offload *flow,
struct flow_ports *hdr; struct flow_ports *hdr;
__be16 port, new_port; __be16 port, new_port;
if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) || if (skb_try_make_writable(skb, thoff + sizeof(*hdr)))
skb_try_make_writable(skb, thoff + sizeof(*hdr)))
return -1; return -1;
hdr = (void *)(skb_network_header(skb) + thoff); hdr = (void *)(skb_network_header(skb) + thoff);
......
...@@ -25,9 +25,6 @@ static int nf_flow_state_check(struct flow_offload *flow, int proto, ...@@ -25,9 +25,6 @@ static int nf_flow_state_check(struct flow_offload *flow, int proto,
if (proto != IPPROTO_TCP) if (proto != IPPROTO_TCP)
return 0; return 0;
if (!pskb_may_pull(skb, thoff + sizeof(*tcph)))
return -1;
tcph = (void *)(skb_network_header(skb) + thoff); tcph = (void *)(skb_network_header(skb) + thoff);
if (unlikely(tcph->fin || tcph->rst)) { if (unlikely(tcph->fin || tcph->rst)) {
flow_offload_teardown(flow); flow_offload_teardown(flow);
...@@ -42,8 +39,7 @@ static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, ...@@ -42,8 +39,7 @@ static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
{ {
struct tcphdr *tcph; struct tcphdr *tcph;
if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
skb_try_make_writable(skb, thoff + sizeof(*tcph)))
return -1; return -1;
tcph = (void *)(skb_network_header(skb) + thoff); tcph = (void *)(skb_network_header(skb) + thoff);
...@@ -57,8 +53,7 @@ static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, ...@@ -57,8 +53,7 @@ static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
{ {
struct udphdr *udph; struct udphdr *udph;
if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
skb_try_make_writable(skb, thoff + sizeof(*udph)))
return -1; return -1;
udph = (void *)(skb_network_header(skb) + thoff); udph = (void *)(skb_network_header(skb) + thoff);
...@@ -167,8 +162,8 @@ static bool ip_has_options(unsigned int thoff) ...@@ -167,8 +162,8 @@ static bool ip_has_options(unsigned int thoff)
static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
struct flow_offload_tuple *tuple) struct flow_offload_tuple *tuple)
{ {
unsigned int thoff, hdrsize;
struct flow_ports *ports; struct flow_ports *ports;
unsigned int thoff;
struct iphdr *iph; struct iphdr *iph;
if (!pskb_may_pull(skb, sizeof(*iph))) if (!pskb_may_pull(skb, sizeof(*iph)))
...@@ -181,15 +176,22 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, ...@@ -181,15 +176,22 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
unlikely(ip_has_options(thoff))) unlikely(ip_has_options(thoff)))
return -1; return -1;
if (iph->protocol != IPPROTO_TCP && switch (iph->protocol) {
iph->protocol != IPPROTO_UDP) case IPPROTO_TCP:
hdrsize = sizeof(struct tcphdr);
break;
case IPPROTO_UDP:
hdrsize = sizeof(struct udphdr);
break;
default:
return -1; return -1;
}
if (iph->ttl <= 1) if (iph->ttl <= 1)
return -1; return -1;
thoff = iph->ihl * 4; thoff = iph->ihl * 4;
if (!pskb_may_pull(skb, thoff + sizeof(*ports))) if (!pskb_may_pull(skb, thoff + hdrsize))
return -1; return -1;
iph = ip_hdr(skb); iph = ip_hdr(skb);
...@@ -315,8 +317,7 @@ static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, ...@@ -315,8 +317,7 @@ static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
{ {
struct tcphdr *tcph; struct tcphdr *tcph;
if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) || if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
skb_try_make_writable(skb, thoff + sizeof(*tcph)))
return -1; return -1;
tcph = (void *)(skb_network_header(skb) + thoff); tcph = (void *)(skb_network_header(skb) + thoff);
...@@ -332,8 +333,7 @@ static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, ...@@ -332,8 +333,7 @@ static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
{ {
struct udphdr *udph; struct udphdr *udph;
if (!pskb_may_pull(skb, thoff + sizeof(*udph)) || if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
skb_try_make_writable(skb, thoff + sizeof(*udph)))
return -1; return -1;
udph = (void *)(skb_network_header(skb) + thoff); udph = (void *)(skb_network_header(skb) + thoff);
...@@ -439,24 +439,31 @@ static int nf_flow_nat_ipv6(const struct flow_offload *flow, ...@@ -439,24 +439,31 @@ static int nf_flow_nat_ipv6(const struct flow_offload *flow,
static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
struct flow_offload_tuple *tuple) struct flow_offload_tuple *tuple)
{ {
unsigned int thoff, hdrsize;
struct flow_ports *ports; struct flow_ports *ports;
struct ipv6hdr *ip6h; struct ipv6hdr *ip6h;
unsigned int thoff;
if (!pskb_may_pull(skb, sizeof(*ip6h))) if (!pskb_may_pull(skb, sizeof(*ip6h)))
return -1; return -1;
ip6h = ipv6_hdr(skb); ip6h = ipv6_hdr(skb);
if (ip6h->nexthdr != IPPROTO_TCP && switch (ip6h->nexthdr) {
ip6h->nexthdr != IPPROTO_UDP) case IPPROTO_TCP:
hdrsize = sizeof(struct tcphdr);
break;
case IPPROTO_UDP:
hdrsize = sizeof(struct udphdr);
break;
default:
return -1; return -1;
}
if (ip6h->hop_limit <= 1) if (ip6h->hop_limit <= 1)
return -1; return -1;
thoff = sizeof(*ip6h); thoff = sizeof(*ip6h);
if (!pskb_may_pull(skb, thoff + sizeof(*ports))) if (!pskb_may_pull(skb, thoff + hdrsize))
return -1; return -1;
ip6h = ipv6_hdr(skb); ip6h = ipv6_hdr(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment