Skip to content

Commit a7f87b4

Browse files
committed
netfilter: remove defensive check on malformed packets from raw sockets
Users cannot forge malformed IPv4/IPv6 headers via raw sockets that they can inject into the stack. Specifically, not for IPv4 since 55888df ("AF_RAW: Augment raw_send_hdrinc to expand skb to fit iphdr->ihl (v2)"). IPv6 raw sockets also ensure that packets have a well-formed IPv6 header available in the skbuff. At quick glance, br_netfilter also validates layer 3 headers and it drops malformed both IPv4 and IPv6 packets. Therefore, let's remove this defensive check all over the place. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent f6931f5 commit a7f87b4

13 files changed

+3
-128
lines changed

net/ipv4/netfilter/iptable_filter.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,6 @@ static unsigned int
3838
iptable_filter_hook(void *priv, struct sk_buff *skb,
3939
const struct nf_hook_state *state)
4040
{
41-
if (state->hook == NF_INET_LOCAL_OUT &&
42-
(skb->len < sizeof(struct iphdr) ||
43-
ip_hdrlen(skb) < sizeof(struct iphdr)))
44-
/* root is playing with raw sockets. */
45-
return NF_ACCEPT;
46-
4741
return ipt_do_table(skb, state, state->net->ipv4.iptable_filter);
4842
}
4943

net/ipv4/netfilter/iptable_mangle.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,6 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
4949
u_int32_t mark;
5050
int err;
5151

52-
/* root is playing with raw sockets. */
53-
if (skb->len < sizeof(struct iphdr) ||
54-
ip_hdrlen(skb) < sizeof(struct iphdr))
55-
return NF_ACCEPT;
56-
5752
/* Save things which could affect route */
5853
mark = skb->mark;
5954
iph = ip_hdr(skb);

net/ipv4/netfilter/iptable_raw.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ static unsigned int
2626
iptable_raw_hook(void *priv, struct sk_buff *skb,
2727
const struct nf_hook_state *state)
2828
{
29-
if (state->hook == NF_INET_LOCAL_OUT &&
30-
(skb->len < sizeof(struct iphdr) ||
31-
ip_hdrlen(skb) < sizeof(struct iphdr)))
32-
/* root is playing with raw sockets. */
33-
return NF_ACCEPT;
34-
3529
return ipt_do_table(skb, state, state->net->ipv4.iptable_raw);
3630
}
3731

net/ipv4/netfilter/iptable_security.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ static unsigned int
4343
iptable_security_hook(void *priv, struct sk_buff *skb,
4444
const struct nf_hook_state *state)
4545
{
46-
if (state->hook == NF_INET_LOCAL_OUT &&
47-
(skb->len < sizeof(struct iphdr) ||
48-
ip_hdrlen(skb) < sizeof(struct iphdr)))
49-
/* Somebody is playing with raw sockets. */
50-
return NF_ACCEPT;
51-
5246
return ipt_do_table(skb, state, state->net->ipv4.iptable_security);
5347
}
5448

net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,6 @@ static unsigned int ipv4_conntrack_local(void *priv,
154154
struct sk_buff *skb,
155155
const struct nf_hook_state *state)
156156
{
157-
/* root is playing with raw sockets. */
158-
if (skb->len < sizeof(struct iphdr) ||
159-
ip_hdrlen(skb) < sizeof(struct iphdr))
160-
return NF_ACCEPT;
161-
162157
if (ip_is_fragment(ip_hdr(skb))) /* IP_NODEFRAG setsockopt set */
163158
return NF_ACCEPT;
164159

net/ipv4/netfilter/nf_nat_l3proto_ipv4.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,6 @@ nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
356356
#endif
357357
unsigned int ret;
358358

359-
/* root is playing with raw sockets. */
360-
if (skb->len < sizeof(struct iphdr) ||
361-
ip_hdrlen(skb) < sizeof(struct iphdr))
362-
return NF_ACCEPT;
363-
364359
ret = nf_nat_ipv4_fn(priv, skb, state, do_chain);
365360
#ifdef CONFIG_XFRM
366361
if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -396,11 +391,6 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
396391
unsigned int ret;
397392
int err;
398393

399-
/* root is playing with raw sockets. */
400-
if (skb->len < sizeof(struct iphdr) ||
401-
ip_hdrlen(skb) < sizeof(struct iphdr))
402-
return NF_ACCEPT;
403-
404394
ret = nf_nat_ipv4_fn(priv, skb, state, do_chain);
405395
if (ret != NF_DROP && ret != NF_STOLEN &&
406396
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {

net/ipv4/netfilter/nf_tables_ipv4.c

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,6 @@ static unsigned int nft_do_chain_ipv4(void *priv,
3030
return nft_do_chain(&pkt, priv);
3131
}
3232

33-
static unsigned int nft_ipv4_output(void *priv,
34-
struct sk_buff *skb,
35-
const struct nf_hook_state *state)
36-
{
37-
if (unlikely(skb->len < sizeof(struct iphdr) ||
38-
ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
39-
if (net_ratelimit())
40-
pr_info("nf_tables_ipv4: ignoring short SOCK_RAW "
41-
"packet\n");
42-
return NF_ACCEPT;
43-
}
44-
45-
return nft_do_chain_ipv4(priv, skb, state);
46-
}
47-
4833
static struct nft_af_info nft_af_ipv4 __read_mostly = {
4934
.family = NFPROTO_IPV4,
5035
.nhooks = NF_INET_NUMHOOKS,
@@ -91,7 +76,7 @@ static const struct nf_chain_type filter_ipv4 = {
9176
(1 << NF_INET_POST_ROUTING),
9277
.hooks = {
9378
[NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
94-
[NF_INET_LOCAL_OUT] = nft_ipv4_output,
79+
[NF_INET_LOCAL_OUT] = nft_do_chain_ipv4,
9580
[NF_INET_FORWARD] = nft_do_chain_ipv4,
9681
[NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
9782
[NF_INET_POST_ROUTING] = nft_do_chain_ipv4,

net/ipv4/netfilter/nft_chain_route_ipv4.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,6 @@ static unsigned int nf_route_table_hook(void *priv,
3333
const struct iphdr *iph;
3434
int err;
3535

36-
/* root is playing with raw sockets. */
37-
if (skb->len < sizeof(struct iphdr) ||
38-
ip_hdrlen(skb) < sizeof(struct iphdr))
39-
return NF_ACCEPT;
40-
4136
nft_set_pktinfo(&pkt, skb, state);
4237
nft_set_pktinfo_ipv4(&pkt, skb);
4338

net/ipv6/netfilter/ip6table_mangle.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,6 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
4242
u_int8_t hop_limit;
4343
u_int32_t flowlabel, mark;
4444
int err;
45-
#if 0
46-
/* root is playing with raw sockets. */
47-
if (skb->len < sizeof(struct iphdr) ||
48-
ip_hdrlen(skb) < sizeof(struct iphdr)) {
49-
net_warn_ratelimited("ip6t_hook: happy cracking\n");
50-
return NF_ACCEPT;
51-
}
52-
#endif
5345

5446
/* save source/dest address, mark, hoplimit, flowlabel, priority, */
5547
memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(saddr));

net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,6 @@ static unsigned int ipv6_conntrack_local(void *priv,
176176
struct sk_buff *skb,
177177
const struct nf_hook_state *state)
178178
{
179-
/* root is playing with raw sockets. */
180-
if (skb->len < sizeof(struct ipv6hdr)) {
181-
net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
182-
return NF_ACCEPT;
183-
}
184179
return nf_conntrack_in(state->net, PF_INET6, state->hook, skb);
185180
}
186181

0 commit comments

Comments
 (0)