I think I got the cause for the Oops observed in http://www.mail-archive.com/dccp@xxxxxxxxxxxxxxx/msg00578.html The problem is always with applications listening on PF_INET6 sockets. Apart from the mentioned oops, I observed another one one, triggered at irregular intervals via timer interrupt: run_timer_softirq -> dccp_keepalive_timer -> inet_csk_reqsk_queue_prune -> reqsk_free -> dccp_v6_reqsk_destructor The latter function is the problem and is also the last function to be called in said kernel panic. In any case, there is a real problem with allocating the right request_sock which is what this patch tackles. It fixes the following problem: - application listens on PF_INET6 - DCCPv4 packet comes in, is handed over to dccp_v4_do_rcv, from there to dccp_v4_conn_request Now: socket is PF_INET6, packet is IPv4. The following code then furnishes the connection with IPv6 - request_sock operations: req = reqsk_alloc(sk->sk_prot->rsk_prot); The first problem is that all further incoming packets will get a Reset since the connection can not be looked up. The second problem is worse: --> reqsk_alloc is called instead of inet6_reqsk_alloc --> consequently inet6_rsk_offset is never set (dangling pointer) --> the request_sock_ops are nevertheless still dccp6_request_ops --> destructor is called via reqsk_free --> dccp_v6_reqsk_destructor tries to free random memory location (inet6_rsk_offset not set) --> panic I have tested this for a while, DCCP sockets are now handled correctly in all three scenarios (v4/v6 only/v4-mapped). Signed-off-by: Gerrit Renker <gerrit@xxxxxxxxxxxxxx> --- ipv4.c | 2 +- ipv6.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 7e746c4..d27e208 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -489,7 +489,7 @@ int dccp_v4_conn_request(struct sock *sk if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = reqsk_alloc(sk->sk_prot->rsk_prot); + req = reqsk_alloc(&dccp_request_sock_ops); if (req == NULL) goto drop; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 7171a78..91e7b12 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -672,7 +672,6 @@ static struct sock *dccp_v6_hnd_req(stru static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) { - struct inet_request_sock *ireq; struct dccp_sock dp; struct request_sock *req; struct dccp_request_sock *dreq; @@ -701,7 +700,7 @@ static int dccp_v6_conn_request(struct s if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = inet6_reqsk_alloc(sk->sk_prot->rsk_prot); + req = inet6_reqsk_alloc(&dccp6_request_sock_ops); if (req == NULL) goto drop; @@ -713,7 +712,6 @@ static int dccp_v6_conn_request(struct s goto drop_and_free; ireq6 = inet6_rsk(req); - ireq = inet_rsk(req); ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr); ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr); req->rcv_wnd = dccp_feat_default_sequence_window; - To unsubscribe from this list: send the line "unsubscribe dccp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html