diff options
-rw-r--r-- | net/netfilter/xt_TCPMSS.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index eda64c1cb1e5..6f21b4377dbb 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -60,17 +60,9 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
60 | tcplen = skb->len - tcphoff; | 60 | tcplen = skb->len - tcphoff; |
61 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 61 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
62 | 62 | ||
63 | /* Since it passed flags test in tcp match, we know it is is | 63 | /* Header cannot be larger than the packet */ |
64 | not a fragment, and has data >= tcp header length. SYN | 64 | if (tcplen < tcph->doff*4) |
65 | packets should not contain data: if they did, then we risk | ||
66 | running over MTU, sending Frag Needed and breaking things | ||
67 | badly. --RR */ | ||
68 | if (tcplen != tcph->doff*4) { | ||
69 | if (net_ratelimit()) | ||
70 | printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", | ||
71 | skb->len); | ||
72 | return -1; | 65 | return -1; |
73 | } | ||
74 | 66 | ||
75 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | 67 | if (info->mss == XT_TCPMSS_CLAMP_PMTU) { |
76 | if (dst_mtu(skb_dst(skb)) <= minlen) { | 68 | if (dst_mtu(skb_dst(skb)) <= minlen) { |
@@ -115,6 +107,12 @@ tcpmss_mangle_packet(struct sk_buff *skb, | |||
115 | } | 107 | } |
116 | } | 108 | } |
117 | 109 | ||
110 | /* There is data after the header so the option can't be added | ||
111 | without moving it, and doing so may make the SYN packet | ||
112 | itself too large. Accept the packet unmodified instead. */ | ||
113 | if (tcplen > tcph->doff*4) | ||
114 | return 0; | ||
115 | |||
118 | /* | 116 | /* |
119 | * MSS Option not found ?! add it.. | 117 | * MSS Option not found ?! add it.. |
120 | */ | 118 | */ |