diff options
author | Eric Dumazet <edumazet@google.com> | 2015-05-14 17:26:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-14 22:32:17 -0400 |
commit | 264ea103a7473f51aced838e68ed384ea2c759f5 (patch) | |
tree | 0f8366835d004fb0ee387d876f6c4b301a0ff89e /include/net/tcp.h | |
parent | c24a59649f3c8f4f78adc2d0e31423fa883b012b (diff) |
tcp: syncookies: extend validity range
Now we allow storing more request socks per listener, we might
hit syncookie mode less often and hit following bug in our stack :
When we send a burst of syncookies, then exit this mode,
tcp_synq_no_recent_overflow() can return false if the ACK packets coming
from clients are coming three seconds after the end of syncookie
episode.
This is a way too strong requirement and conflicts with rest of
syncookie code which allows ACK to be aged up to 2 minutes.
Perfectly valid ACK packets are dropped just because clients might be
in a crowded wifi environment or on another planet.
So let's fix this, and also change tcp_synq_overflow() to not
dirty a cache line for every syncookie we send, as we are under attack.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Florian Westphal <fw@strlen.de>
Acked-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/tcp.h')
-rw-r--r-- | include/net/tcp.h | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index b8ea12880fd9..7ace6acbf5fd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -326,18 +326,6 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift) | |||
326 | 326 | ||
327 | bool tcp_check_oom(struct sock *sk, int shift); | 327 | bool tcp_check_oom(struct sock *sk, int shift); |
328 | 328 | ||
329 | /* syncookies: remember time of last synqueue overflow */ | ||
330 | static inline void tcp_synq_overflow(struct sock *sk) | ||
331 | { | ||
332 | tcp_sk(sk)->rx_opt.ts_recent_stamp = jiffies; | ||
333 | } | ||
334 | |||
335 | /* syncookies: no recent synqueue overflow on this listening socket? */ | ||
336 | static inline bool tcp_synq_no_recent_overflow(const struct sock *sk) | ||
337 | { | ||
338 | unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; | ||
339 | return time_after(jiffies, last_overflow + TCP_TIMEOUT_FALLBACK); | ||
340 | } | ||
341 | 329 | ||
342 | extern struct proto tcp_prot; | 330 | extern struct proto tcp_prot; |
343 | 331 | ||
@@ -483,13 +471,35 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb); | |||
483 | * i.e. a sent cookie is valid only at most for 2*60 seconds (or less if | 471 | * i.e. a sent cookie is valid only at most for 2*60 seconds (or less if |
484 | * the counter advances immediately after a cookie is generated). | 472 | * the counter advances immediately after a cookie is generated). |
485 | */ | 473 | */ |
486 | #define MAX_SYNCOOKIE_AGE 2 | 474 | #define MAX_SYNCOOKIE_AGE 2 |
475 | #define TCP_SYNCOOKIE_PERIOD (60 * HZ) | ||
476 | #define TCP_SYNCOOKIE_VALID (MAX_SYNCOOKIE_AGE * TCP_SYNCOOKIE_PERIOD) | ||
477 | |||
478 | /* syncookies: remember time of last synqueue overflow | ||
479 | * But do not dirty this field too often (once per second is enough) | ||
480 | */ | ||
481 | static inline void tcp_synq_overflow(struct sock *sk) | ||
482 | { | ||
483 | unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; | ||
484 | unsigned long now = jiffies; | ||
485 | |||
486 | if (time_after(now, last_overflow + HZ)) | ||
487 | tcp_sk(sk)->rx_opt.ts_recent_stamp = now; | ||
488 | } | ||
489 | |||
490 | /* syncookies: no recent synqueue overflow on this listening socket? */ | ||
491 | static inline bool tcp_synq_no_recent_overflow(const struct sock *sk) | ||
492 | { | ||
493 | unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; | ||
494 | |||
495 | return time_after(jiffies, last_overflow + TCP_SYNCOOKIE_VALID); | ||
496 | } | ||
487 | 497 | ||
488 | static inline u32 tcp_cookie_time(void) | 498 | static inline u32 tcp_cookie_time(void) |
489 | { | 499 | { |
490 | u64 val = get_jiffies_64(); | 500 | u64 val = get_jiffies_64(); |
491 | 501 | ||
492 | do_div(val, 60 * HZ); | 502 | do_div(val, TCP_SYNCOOKIE_PERIOD); |
493 | return val; | 503 | return val; |
494 | } | 504 | } |
495 | 505 | ||