Commit 205d4b20 authored by David S. Miller's avatar David S. Miller

[TCP]: Do not access inet_sk() of a time-wait bucket.

Bug discovered by Mandred Spraul.
parent 5680d227
......@@ -208,6 +208,8 @@ struct tcp_tw_bucket {
#endif
};
#define tcptw_sk(__sk) ((struct tcp_tw_bucket *)(__sk))
extern kmem_cache_t *tcp_timewait_cachep;
static inline void tcp_tw_put(struct tcp_tw_bucket *tw)
......@@ -248,6 +250,10 @@ extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
(((*((__u64 *)&(inet_sk(__sk)->daddr)))== (__cookie)) && \
((*((__u32 *)&(inet_sk(__sk)->dport)))== (__ports)) && \
(!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
#define TCP_IPV4_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
(((*((__u64 *)&(tcptw_sk(__sk)->daddr)))== (__cookie)) && \
((*((__u32 *)&(tcptw_sk(__sk)->dport)))== (__ports)) && \
(!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
#else /* 32-bit arch */
#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr)
#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
......@@ -255,6 +261,11 @@ extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
(inet_sk(__sk)->rcv_saddr == (__daddr)) && \
((*((__u32 *)&(inet_sk(__sk)->dport)))== (__ports)) && \
(!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
#define TCP_IPV4_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
((tcptw_sk(__sk)->daddr == (__saddr)) && \
(tcptw_sk(__sk)->rcv_saddr == (__daddr)) && \
((*((__u32 *)&(tcptw_sk(__sk)->dport)))== (__ports)) && \
(!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
#endif /* 64-bit arch */
#define TCP_IPV6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \
......
......@@ -509,7 +509,7 @@ static inline struct sock *__tcp_v4_lookup_established(u32 saddr, u16 sport,
/* Must check for a TIME_WAIT'er before going to listener hash. */
for (sk = (head + tcp_ehash_size)->chain; sk; sk = sk->next)
if (TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
if (TCP_IPV4_TW_MATCH(sk, acookie, saddr, daddr, ports, dif))
goto hit;
out:
read_unlock(&head->lock);
......@@ -570,7 +570,7 @@ static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
skp = &sk2->next) {
tw = (struct tcp_tw_bucket *)sk2;
if (TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
if (TCP_IPV4_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
struct tcp_opt *tp = tcp_sk(sk);
/* With PAWS, it is safe from the viewpoint
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment