aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/sock.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-05-09 10:28:16 +0000
committerBen Hutchings <ben@decadent.org.uk>2013-05-30 14:35:14 +0100
commit6b0c985d7eedd52ddba6968d46bbc12ad603a577 (patch)
tree6337e2be927da829aa3b4694c596f7e18c632894 /net/core/sock.c
parent24ac9e8939ffcbfed67eea6e82c7eb99c34d0b55 (diff)
downloadkernel_samsung_smdk4412-6b0c985d7eedd52ddba6968d46bbc12ad603a577.zip
kernel_samsung_smdk4412-6b0c985d7eedd52ddba6968d46bbc12ad603a577.tar.gz
kernel_samsung_smdk4412-6b0c985d7eedd52ddba6968d46bbc12ad603a577.tar.bz2
ipv6: do not clear pinet6 field
[ Upstream commit f77d602124d865c38705df7fa25c03de9c284ad2 ] We have seen multiple NULL dereferences in __inet6_lookup_established() After analysis, I found that inet6_sk() could be NULL while the check for sk_family == AF_INET6 was true. Bug was added in linux-2.6.29 when RCU lookups were introduced in UDP and TCP stacks. Once an IPv6 socket, using SLAB_DESTROY_BY_RCU is inserted in a hash table, we no longer can clear pinet6 field. This patch extends logic used in commit fcbdf09d9652c891 ("net: fix nulls list corruptions in sk_prot_alloc") TCP/UDP/UDPLite IPv6 protocols provide their own .clear_sk() method to make sure we do not clear pinet6 field. At socket clone phase, we do not really care, as cloning the parent (non NULL) pinet6 is not adding a fatal race. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'net/core/sock.c')
-rw-r--r--net/core/sock.c12
1 files changed, 0 insertions, 12 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index 2c73adf..8a2c2dd 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1021,18 +1021,6 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)
#endif
}
-/*
- * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes
- * un-modified. Special care is taken when initializing object to zero.
- */
-static inline void sk_prot_clear_nulls(struct sock *sk, int size)
-{
- if (offsetof(struct sock, sk_node.next) != 0)
- memset(sk, 0, offsetof(struct sock, sk_node.next));
- memset(&sk->sk_node.pprev, 0,
- size - offsetof(struct sock, sk_node.pprev));
-}
-
void sk_prot_clear_portaddr_nulls(struct sock *sk, int size)
{
unsigned long nulls1, nulls2;