From patchwork Wed Jan 18 15:32:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Shearman X-Patchwork-Id: 716698 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 3v3WGY36RMz9ryr for ; Thu, 19 Jan 2017 02:33:57 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752180AbdARPdz (ORCPT ); Wed, 18 Jan 2017 10:33:55 -0500 Received: from mx0a-000f0801.pphosted.com ([67.231.144.122]:38099 "EHLO mx0a-000f0801.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751642AbdARPdx (ORCPT ); Wed, 18 Jan 2017 10:33:53 -0500 Received: from pps.filterd (m0048193.ppops.net [127.0.0.1]) by mx0a-000f0801.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v0IFPEMe008016; Wed, 18 Jan 2017 07:33:52 -0800 Received: from brmwp-exmb12.corp.brocade.com ([208.47.132.227]) by mx0a-000f0801.pphosted.com with ESMTP id 2829np8fe5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Wed, 18 Jan 2017 07:33:51 -0800 Received: from EMEAWP-EXMB11.corp.brocade.com (172.29.11.85) by BRMWP-EXMB12.corp.brocade.com (172.16.59.130) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Wed, 18 Jan 2017 08:33:48 -0700 Received: from BRA-2XN4P12.vyatta.com (172.29.196.96) by EMEAWP-EXMB11.corp.brocade.com (172.29.11.85) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Wed, 18 Jan 2017 16:33:43 +0100 From: Robert Shearman To: CC: , Tom Herbert , Roopa Prabhu , Robert Shearman Subject: [PATCH net 1/2] lwtunnel: Fix oops on state free after encap module unload Date: Wed, 18 Jan 2017 15:32:02 +0000 Message-ID: <1484753523-26230-2-git-send-email-rshearma@brocade.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1484753523-26230-1-git-send-email-rshearma@brocade.com> References: <1484753523-26230-1-git-send-email-rshearma@brocade.com> MIME-Version: 1.0 X-Originating-IP: [172.29.196.96] X-ClientProxiedBy: hq1wp-excas11.corp.brocade.com (10.70.36.102) To EMEAWP-EXMB11.corp.brocade.com (172.29.11.85) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-01-18_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1701180202 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When attempting to free lwtunnel state after the module for the encap has been unloaded an oops occurs: BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 IP: lwtstate_free+0x18/0x40 [..] task: ffff88003e372380 task.stack: ffffc900001fc000 RIP: 0010:lwtstate_free+0x18/0x40 RSP: 0018:ffff88003fd83e88 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88002bbb3380 RCX: ffff88000c91a300 [..] Call Trace: free_fib_info_rcu+0x195/0x1a0 ? rt_fibinfo_free+0x50/0x50 rcu_process_callbacks+0x2d3/0x850 ? rcu_process_callbacks+0x296/0x850 __do_softirq+0xe4/0x4cb irq_exit+0xb0/0xc0 smp_apic_timer_interrupt+0x3d/0x50 apic_timer_interrupt+0x93/0xa0 [..] Code: e8 6e c6 fc ff 89 d8 5b 5d c3 bb de ff ff ff eb f4 66 90 66 66 66 66 90 55 48 89 e5 53 0f b7 07 48 89 fb 48 8b 04 c5 00 81 d5 81 <48> 8b 40 08 48 85 c0 74 13 ff d0 48 8d 7b 20 be 20 00 00 00 e8 The problem is that we don't check for NULL ops in lwtstate_free. Adding the check fixes the immediate problem but will then won't properly clean up for ops that implement the ->destroy_state function if the implementing module has been unloaded, resulting in memory leaks or other problems. So in addition, refcount the module when the ops implements ->destroy_state so it can't be unloaded while there is still state around. Fixes: 1104d9ba443a ("lwtunnel: Add destroy state operation") Signed-off-by: Robert Shearman --- include/net/lwtunnel.h | 2 ++ net/core/lwtunnel.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index d4c1c75b8862..2b9993f33198 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -44,6 +44,8 @@ struct lwtunnel_encap_ops { int (*get_encap_size)(struct lwtunnel_state *lwtstate); int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b); int (*xmit)(struct sk_buff *skb); + + struct module *owner; }; #ifdef CONFIG_LWTUNNEL diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index a5d4e866ce88..3dc3cc3b38ec 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -126,8 +126,14 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type, } } #endif - if (likely(ops && ops->build_state)) + /* take module reference if destroy_state is in use */ + if (unlikely(ops && ops->destroy_state && !try_module_get(ops->owner))) + ops = NULL; + if (likely(ops && ops->build_state)) { ret = ops->build_state(dev, encap, family, cfg, lws); + if (ret && ops->destroy_state) + module_put(ops->owner); + } rcu_read_unlock(); return ret; @@ -138,9 +144,10 @@ void lwtstate_free(struct lwtunnel_state *lws) { const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type]; - if (ops->destroy_state) { + if (ops && ops->destroy_state) { ops->destroy_state(lws); kfree_rcu(lws, rcu); + module_put(ops->owner); } else { kfree(lws); }