From patchwork Fri Jun 5 17:51:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Shearman X-Patchwork-Id: 481490 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 88F4014018C for ; Sat, 6 Jun 2015 03:53:07 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751013AbbFERxD (ORCPT ); Fri, 5 Jun 2015 13:53:03 -0400 Received: from mx0b-000f0801.pphosted.com ([67.231.152.113]:31728 "EHLO mx0b-000f0801.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752050AbbFERxB (ORCPT ); Fri, 5 Jun 2015 13:53:01 -0400 Received: from pps.filterd (m0000700.ppops.net [127.0.0.1]) by mx0b-000f0801.pphosted.com (8.14.7/8.14.7) with SMTP id t55HUp5g012423; Fri, 5 Jun 2015 10:52:29 -0700 Received: from hq1wp-exchub01.corp.brocade.com ([144.49.131.13]) by mx0b-000f0801.pphosted.com with ESMTP id 1uug7801ba-2 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NOT); Fri, 05 Jun 2015 10:52:28 -0700 Received: from BRMWP-EXCHUB02.corp.brocade.com (172.16.187.99) by HQ1WP-EXCHUB01.corp.brocade.com (10.70.36.101) with Microsoft SMTP Server (TLS) id 14.3.123.3; Fri, 5 Jun 2015 10:52:26 -0700 Received: from EMEAWP-EXMB11.corp.brocade.com (172.29.11.85) by BRMWP-EXCHUB02.corp.brocade.com (172.16.187.99) with Microsoft SMTP Server (TLS) id 14.3.123.3; Fri, 5 Jun 2015 11:52:26 -0600 Received: from BRA-2XN4P12.vyatta.com (172.16.180.50) by EMEAWP-EXMB11.corp.brocade.com (172.29.11.85) with Microsoft SMTP Server (TLS) id 15.0.1044.25; Fri, 5 Jun 2015 19:52:21 +0200 From: Robert Shearman To: CC: "David S. Miller" , Alexey Kuznetsov , James Morris , Hideaki YOSHIFUJI , Patrick McHardy , Robert Shearman Subject: [PATCH net] ipv6: fix possible use after free of dev stats Date: Fri, 5 Jun 2015 18:51:54 +0100 Message-ID: <1433526714-18770-1-git-send-email-rshearma@brocade.com> X-Mailer: git-send-email 2.1.4 MIME-Version: 1.0 X-Originating-IP: [172.16.180.50] X-ClientProxiedBy: hq1wp-excas12.corp.brocade.com (10.70.38.22) To EMEAWP-EXMB11.corp.brocade.com (172.29.11.85) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.14.151, 1.0.33, 0.0.0000 definitions=2015-06-05_14:2015-06-05, 2015-06-05, 1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=3 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=7.0.1-1402240000 definitions=main-1506050223 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The memory pointed to by idev->stats.icmpv6msgdev, idev->stats.icmpv6dev and idev->stats.ipv6 can each be used in an RCU read context without taking a reference on idev. For example, through IP6_*_STATS_* calls in ip6_rcv. These memory blocks are freed without waiting for an RCU grace period to elapse. This could lead to the memory being written to after it has been freed. Fix this by using call_rcu to free the memory used for stats, as well as idev after an RCU grace period has elapsed. Signed-off-by: Robert Shearman Acked-by: Hannes Frederic Sowa --- I have no evidence of this causing any problems in reality - this issue was found by inspection. net/ipv6/addrconf_core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index d873ceea86e6..ca09bf49ac68 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c @@ -133,6 +133,14 @@ static void snmp6_free_dev(struct inet6_dev *idev) free_percpu(idev->stats.ipv6); } +static void in6_dev_finish_destroy_rcu(struct rcu_head *head) +{ + struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu); + + snmp6_free_dev(idev); + kfree(idev); +} + /* Nobody refers to this device, we may destroy it. */ void in6_dev_finish_destroy(struct inet6_dev *idev) @@ -151,7 +159,6 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) pr_warn("Freeing alive inet6 device %p\n", idev); return; } - snmp6_free_dev(idev); - kfree_rcu(idev, rcu); + call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); } EXPORT_SYMBOL(in6_dev_finish_destroy);