diff options
author | Florian Westphal <fw@strlen.de> | 2010-06-16 17:42:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-16 17:42:15 -0400 |
commit | 8c76368174ed2359739f1b7b8a9c042b1ef839c4 (patch) | |
tree | 143aa28c9438b24154bc3d1e36b432a534eca50c /net/ipv4 | |
parent | 317fe0e6c5dc9448bcef41a2e31fecfd3dba7f55 (diff) |
syncookies: check decoded options against sysctl settings
Discard the ACK if we find options that do not match current sysctl
settings.
Previously it was possible to create a connection with sack, wscale,
etc. enabled even if the feature was disabled via sysctl.
Also remove an unneeded call to tcp_sack_reset() in
cookie_check_timestamp: Both call sites (cookie_v4_check,
cookie_v6_check) zero "struct tcp_options_received", hand it to
tcp_parse_options() (which does not change tcp_opt->num_sacks/dsack)
and then call cookie_check_timestamp().
Even if num_sacks/dsacks were changed, the structure is allocated on
the stack and after cookie_check_timestamp returns only a few selected
members are copied to the inet_request_sock.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/syncookies.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 02bef6aa8b30..51b5662545d6 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -230,23 +230,36 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
230 | * The lowest 4 bits are for snd_wscale | 230 | * The lowest 4 bits are for snd_wscale |
231 | * The next 4 lsb are for rcv_wscale | 231 | * The next 4 lsb are for rcv_wscale |
232 | * The next lsb is for sack_ok | 232 | * The next lsb is for sack_ok |
233 | * | ||
234 | * return false if we decode an option that should not be. | ||
233 | */ | 235 | */ |
234 | void cookie_check_timestamp(struct tcp_options_received *tcp_opt) | 236 | bool cookie_check_timestamp(struct tcp_options_received *tcp_opt) |
235 | { | 237 | { |
236 | /* echoed timestamp, 9 lowest bits contain options */ | 238 | /* echoed timestamp, 9 lowest bits contain options */ |
237 | u32 options = tcp_opt->rcv_tsecr & TSMASK; | 239 | u32 options = tcp_opt->rcv_tsecr & TSMASK; |
238 | 240 | ||
241 | if (!tcp_opt->saw_tstamp) { | ||
242 | tcp_clear_options(tcp_opt); | ||
243 | return true; | ||
244 | } | ||
245 | |||
246 | if (!sysctl_tcp_timestamps) | ||
247 | return false; | ||
248 | |||
239 | tcp_opt->snd_wscale = options & 0xf; | 249 | tcp_opt->snd_wscale = options & 0xf; |
240 | options >>= 4; | 250 | options >>= 4; |
241 | tcp_opt->rcv_wscale = options & 0xf; | 251 | tcp_opt->rcv_wscale = options & 0xf; |
242 | 252 | ||
243 | tcp_opt->sack_ok = (options >> 4) & 0x1; | 253 | tcp_opt->sack_ok = (options >> 4) & 0x1; |
244 | 254 | ||
245 | if (tcp_opt->sack_ok) | 255 | if (tcp_opt->sack_ok && !sysctl_tcp_sack) |
246 | tcp_sack_reset(tcp_opt); | 256 | return false; |
247 | 257 | ||
248 | if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) | 258 | if (tcp_opt->snd_wscale || tcp_opt->rcv_wscale) { |
249 | tcp_opt->wscale_ok = 1; | 259 | tcp_opt->wscale_ok = 1; |
260 | return sysctl_tcp_window_scaling != 0; | ||
261 | } | ||
262 | return true; | ||
250 | } | 263 | } |
251 | EXPORT_SYMBOL(cookie_check_timestamp); | 264 | EXPORT_SYMBOL(cookie_check_timestamp); |
252 | 265 | ||
@@ -281,8 +294,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
281 | memset(&tcp_opt, 0, sizeof(tcp_opt)); | 294 | memset(&tcp_opt, 0, sizeof(tcp_opt)); |
282 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); | 295 | tcp_parse_options(skb, &tcp_opt, &hash_location, 0); |
283 | 296 | ||
284 | if (tcp_opt.saw_tstamp) | 297 | if (!cookie_check_timestamp(&tcp_opt)) |
285 | cookie_check_timestamp(&tcp_opt); | 298 | goto out; |
286 | 299 | ||
287 | ret = NULL; | 300 | ret = NULL; |
288 | req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ | 301 | req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ |