diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-05-06 21:22:18 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-05-16 11:35:53 -0400 |
commit | bc6bcb59dd7c184d229f9e86d08aa56059938a4c (patch) | |
tree | 1305eb74bb354d76cc815910a3ebe1f803b7a6f4 /net/netfilter | |
parent | 8cdb46da06ea94543a3b2e53e3e92736421d1093 (diff) |
netfilter: xt_TCPOPTSTRIP: fix possible mangling beyond packet boundary
This target assumes that tcph->doff is well-formed, that may be well
not the case. Add extra sanity checkings to avoid possible crash due
to read/write out of the real packet boundary. After this patch, the
default action on malformed TCP packets is to drop them. Moreover,
fragments are skipped.
Reported-by: Rafal Kupka <rkupka@telemetry.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/xt_TCPOPTSTRIP.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index 25fd1c4e1eec..1eb1a44bfd3d 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c | |||
@@ -30,17 +30,28 @@ static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset) | |||
30 | 30 | ||
31 | static unsigned int | 31 | static unsigned int |
32 | tcpoptstrip_mangle_packet(struct sk_buff *skb, | 32 | tcpoptstrip_mangle_packet(struct sk_buff *skb, |
33 | const struct xt_tcpoptstrip_target_info *info, | 33 | const struct xt_action_param *par, |
34 | unsigned int tcphoff, unsigned int minlen) | 34 | unsigned int tcphoff, unsigned int minlen) |
35 | { | 35 | { |
36 | const struct xt_tcpoptstrip_target_info *info = par->targinfo; | ||
36 | unsigned int optl, i, j; | 37 | unsigned int optl, i, j; |
37 | struct tcphdr *tcph; | 38 | struct tcphdr *tcph; |
38 | u_int16_t n, o; | 39 | u_int16_t n, o; |
39 | u_int8_t *opt; | 40 | u_int8_t *opt; |
41 | int len; | ||
42 | |||
43 | /* This is a fragment, no TCP header is available */ | ||
44 | if (par->fragoff != 0) | ||
45 | return XT_CONTINUE; | ||
40 | 46 | ||
41 | if (!skb_make_writable(skb, skb->len)) | 47 | if (!skb_make_writable(skb, skb->len)) |
42 | return NF_DROP; | 48 | return NF_DROP; |
43 | 49 | ||
50 | len = skb->len - tcphoff; | ||
51 | if (len < (int)sizeof(struct tcphdr) || | ||
52 | tcp_hdr(skb)->doff * 4 > len) | ||
53 | return NF_DROP; | ||
54 | |||
44 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 55 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
45 | opt = (u_int8_t *)tcph; | 56 | opt = (u_int8_t *)tcph; |
46 | 57 | ||
@@ -76,7 +87,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
76 | static unsigned int | 87 | static unsigned int |
77 | tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) | 88 | tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) |
78 | { | 89 | { |
79 | return tcpoptstrip_mangle_packet(skb, par->targinfo, ip_hdrlen(skb), | 90 | return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb), |
80 | sizeof(struct iphdr) + sizeof(struct tcphdr)); | 91 | sizeof(struct iphdr) + sizeof(struct tcphdr)); |
81 | } | 92 | } |
82 | 93 | ||
@@ -94,7 +105,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
94 | if (tcphoff < 0) | 105 | if (tcphoff < 0) |
95 | return NF_DROP; | 106 | return NF_DROP; |
96 | 107 | ||
97 | return tcpoptstrip_mangle_packet(skb, par->targinfo, tcphoff, | 108 | return tcpoptstrip_mangle_packet(skb, par, tcphoff, |
98 | sizeof(*ipv6h) + sizeof(struct tcphdr)); | 109 | sizeof(*ipv6h) + sizeof(struct tcphdr)); |
99 | } | 110 | } |
100 | #endif | 111 | #endif |