From patchwork Tue Jan 22 10:01:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffen Klassert X-Patchwork-Id: 214483 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 2111B2C0080 for ; Tue, 22 Jan 2013 21:02:00 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753194Ab3AVKBz (ORCPT ); Tue, 22 Jan 2013 05:01:55 -0500 Received: from a.mx.secunet.com ([195.81.216.161]:35048 "EHLO a.mx.secunet.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752898Ab3AVKBv (ORCPT ); Tue, 22 Jan 2013 05:01:51 -0500 Received: from localhost (alg1 [127.0.0.1]) by a.mx.secunet.com (Postfix) with ESMTP id B37221A007E; Tue, 22 Jan 2013 11:01:49 +0100 (CET) X-Virus-Scanned: by secunet Received: from mail-srv1.secumail.de (unknown [10.53.40.200]) by a.mx.secunet.com (Postfix) with ESMTP id ACDB71A007C; Tue, 22 Jan 2013 11:01:28 +0100 (CET) Received: from gauss.dd.secunet.de ([10.182.7.102]) by mail-srv1.secumail.de with Microsoft SMTPSVC(6.0.3790.4675); Tue, 22 Jan 2013 11:01:28 +0100 Received: by gauss.dd.secunet.de (Postfix, from userid 1000) id 21DC15C0A8C; Tue, 22 Jan 2013 11:01:28 +0100 (CET) Date: Tue, 22 Jan 2013 11:01:28 +0100 From: Steffen Klassert To: David Miller Cc: Julian Anastasov , netdev@vger.kernel.org Subject: [PATCH] ipv4: Fix route refcount on pmtu discovery Message-ID: <20130122100128.GD9147@secunet.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-OriginalArrivalTime: 22 Jan 2013 10:01:28.0458 (UTC) FILETIME=[723E6EA0:01CDF887] Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org git commit 9cb3a50c (ipv4: Invalidate the socket cached route on pmtu events if possible) introduced a refcount problem. We don't get a refcount on the route if we get it from__sk_dst_get(), but we need one if we want to reuse this route because __sk_dst_set() releases the refcount of the old route. This patch adds proper refcount handling for that case. We introduce a 'new' flag to indicate that we are going to use a new route and we release the old route only if we replace it by a new one. Reported-by: Julian Anastasov Signed-off-by: Steffen Klassert --- net/ipv4/route.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 132737a..a0fcc47 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -985,6 +985,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) struct flowi4 fl4; struct rtable *rt; struct dst_entry *dst; + bool new = false; bh_lock_sock(sk); rt = (struct rtable *) __sk_dst_get(sk); @@ -1000,20 +1001,26 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) rt = ip_route_output_flow(sock_net(sk), &fl4, sk); if (IS_ERR(rt)) goto out; + + new = true; } __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); dst = dst_check(&rt->dst, 0); if (!dst) { + if (new) + dst_release(&rt->dst); + rt = ip_route_output_flow(sock_net(sk), &fl4, sk); if (IS_ERR(rt)) goto out; - dst = &rt->dst; + new = true; } - __sk_dst_set(sk, dst); + if (new) + __sk_dst_set(sk, &rt->dst); out: bh_unlock_sock(sk);