lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Wed, 27 Oct 2010 17:30:27 +0400 From: Dmitry Popov <dp@...hloadlab.com> To: "David S. Miller" <davem@...emloft.net>, William.Allen.Simpson@...il.com, Eric Dumazet <eric.dumazet@...il.com>, Andreas Petlund <apetlund@...ula.no>, Shan Wei <shanwei@...fujitsu.com>, Herbert Xu <herbert@...dor.apana.org.au>, Octavian Purdila <opurdila@...acom.com>, Ilpo Järvinen <ilpo.jarvinen@...sinki.fi>, Alexey Dobriyan <adobriyan@...il.com>, Alexey Kuznetsov <kuznet@....inr.ac.ru>, "Pekka Savola (ipv6)" <pekkas@...core.fi>, James Morris <jmorris@...ei.org>, Hideaki YOSHIFUJI <yoshfuji@...ux-ipv6.org>, Patrick McHardy <kaber@...sh.net>, Evgeniy Polyakov <zbr@...emap.net>, Laurent Chavey <chavey@...gle.com>, Gilad Ben-Yossef <gilad@...efidence.com>, Greg Kroah-Hartman <gregkh@...e.de>, "Steven J. Magnani" <steve@...idescorp.com>, Joe Perches <joe@...ches.com>, Stephen Hemminger <shemminger@...tta.com>, Yony Amit <yony@...sleep.com>, linux-kernel@...r.kernel.org, netdev@...r.kernel.org, Artyom Gavrichenkov <ag@...hloadlab.com> Subject: [PATCH 4/5] tcp: syncookie stats counter From: Dmitry Popov <dp@...hloadlab.com> Estimation of amount of sent SYNACKs used to choose between syn_backlog and syn_cookies added. Estimation is made within TCP_TIMEOUT_INIT period. tcp_syncookie_stats struct is added to tcp_sock. Signed-off-by: Dmitry Popov <dp@...hloadlab.com> --- include/linux/tcp.h | 15 +++++++++++++++ include/net/inet_connection_sock.h | 7 +++++++ include/net/request_sock.h | 8 ++++++++ include/net/tcp.h | 29 +++++++++++++++++++++++++++++ net/ipv4/tcp_ipv4.c | 12 ++++++++++-- net/ipv6/tcp_ipv6.c | 16 ++++++++++++---- 6 files changed, 81 insertions(+), 6 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 3436176..7445d17 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -288,6 +288,17 @@ static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req) return (struct tcp_request_sock *)req; } +/* This structure is used to estimate amount of SYNs under (possible) SYNflood. + * @cookies_sent[@clock_hand] is incremented for each cookie sent. + * This counter is used while jiffies < @expires[@clock_hand], + * then clock_hand is switched (clock_hand ^= 1). + */ +struct tcp_syncookie_stats { + unsigned long expires[2]; + u32 cookies_sent[2]; + u8 clock_hand; +}; + struct tcp_sock { /* inet_connection_sock has to be the first member of tcp_sock */ struct inet_connection_sock inet_conn; @@ -471,6 +482,10 @@ struct tcp_sock { * So readers which hold this lock may omit rcu_reader_lock. */ struct tcp_cookie_values *cookie_values; + +#ifdef CONFIG_SYN_COOKIES + struct tcp_syncookie_stats syncookie_stats; +#endif }; static inline struct tcp_sock *tcp_sk(const struct sock *sk) diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 430b58f..7c63bb0 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -293,6 +293,13 @@ static inline int inet_csk_reqsk_queue_young(const struct sock *sk) return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue); } +static inline int inet_csk_reqsk_queue_is_delta_full(const struct sock *sk, + int delta) +{ + const struct request_sock_queue *aq = &inet_csk(sk)->icsk_accept_queue; + return reqsk_queue_is_delta_full(aq, delta); +} + static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk) { return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue); diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 870c46b..1154277 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -272,6 +272,14 @@ static inline int reqsk_queue_len_young(const struct request_sock_queue *queue) return queue->listen_opt->qlen_young; } +static inline int + reqsk_queue_is_delta_full(const struct request_sock_queue *queue, + int delta) +{ + struct listen_sock *lopt = queue->listen_opt; + return (lopt->qlen + delta) >> lopt->max_qlen_log; +} + static inline int reqsk_queue_is_full(const struct request_sock_queue *queue) { return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log; diff --git a/include/net/tcp.h b/include/net/tcp.h index 08e6ce1..c25d4a5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1542,6 +1542,35 @@ static inline int tcp_s_data_size(const struct tcp_sock *tp) : 0; } +/* Updates syn cookie statistics, + * should be called after new cookie(SYNACK) is sent. + */ +static inline void tcp_inc_syncookie_stats(struct tcp_syncookie_stats *stats) +{ + u8 hand = stats->clock_hand; + + if (unlikely(time_after(jiffies, stats->expires[hand]))) { + hand ^= 1; + stats->expires[hand] = jiffies + TCP_TIMEOUT_INIT; + stats->cookies_sent[hand] = 0; + stats->clock_hand = hand; + } + ++stats->cookies_sent[hand]; +} + +/* Returns previous syncookie stats(amount of cookies sent). */ +static inline u32 tcp_get_syncookie_stats(struct tcp_syncookie_stats *stats) +{ + u8 old_hand = stats->clock_hand ^ 1; + + if (time_before(jiffies, + stats->expires[old_hand] + 2 * TCP_TIMEOUT_INIT)) + /* old stats are not too old */ + return stats->cookies_sent[old_hand]; + else + return 0; +} + /** * struct tcp_extend_values - tcp_ipv?.c to tcp_output.c workspace. * diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c7e9b2a..1e641b0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1344,13 +1344,21 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * limitations, they conserve resources and peer is * evidently real one. */ - if (inet_csk_reqsk_queue_is_full(sk) && !isn) { +#ifdef CONFIG_SYN_COOKIES + if (inet_csk_reqsk_queue_is_delta_full(sk, + tcp_get_syncookie_stats(&tp->syncookie_stats)) && + !isn) + { if (net_ratelimit()) syn_flood_warning(skb); -#ifdef CONFIG_SYN_COOKIES if (sysctl_tcp_syncookies) { + tcp_inc_syncookie_stats(&tp->syncookie_stats); want_cookie = 1; } else +#else + if (inet_csk_reqsk_queue_is_full(sk) && !isn) { + if (net_ratelimit()) + syn_flood_warning(skb); #endif goto drop; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a3fa1f9..767dfde 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1275,13 +1275,21 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) goto drop; - if (inet_csk_reqsk_queue_is_full(sk) && !isn) { +#ifdef CONFIG_SYN_COOKIES + if (inet_csk_reqsk_queue_is_delta_full(sk, + tcp_get_syncookie_stats(&tp->syncookie_stats)) && + !isn) + { if (net_ratelimit()) syn_flood_warning(skb); -#ifdef CONFIG_SYN_COOKIES - if (sysctl_tcp_syncookies) + if (sysctl_tcp_syncookies) { + tcp_inc_syncookie_stats(&tp->syncookie_stats); want_cookie = 1; - else + } else +#else + if (inet_csk_reqsk_queue_is_full(sk) && !isn) { + if (net_ratelimit()) + syn_flood_warning(skb); #endif goto drop; } -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists