From patchwork Fri Nov 7 13:22:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Iwai X-Patchwork-Id: 408117 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 6D3991400B7 for ; Sat, 8 Nov 2014 00:24:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752698AbaKGNWZ (ORCPT ); Fri, 7 Nov 2014 08:22:25 -0500 Received: from cantor2.suse.de ([195.135.220.15]:48701 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752653AbaKGNWL (ORCPT ); Fri, 7 Nov 2014 08:22:11 -0500 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 6F343AC38; Fri, 7 Nov 2014 13:22:09 +0000 (UTC) Date: Fri, 07 Nov 2014 14:22:09 +0100 Message-ID: From: Takashi Iwai To: Stefan Seyfried Cc: Paul Mackerras , linux-ppp@vger.kernel.org, netdev@vger.kernel.org, LKML Subject: Re: [REGRESSION] in 3.18-rc1: ppp crashes kernel In-Reply-To: <545CA8B6.2060608@message-id.googlemail.com> References: <545CA8B6.2060608@message-id.googlemail.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/24.4 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org At Fri, 07 Nov 2014 12:10:46 +0100, Stefan Seyfried wrote: > > Hi all, > > since 3.18-rc1, setting up a PPP interface kills my kernel with > > [ 163.433251] PPP generic driver version 2.4.2 > [ 164.452474] ------------[ cut here ]------------ > [ 164.453327] kernel BUG at ../mm/vmalloc.c:1316! > [ 164.453327] invalid opcode: 0000 [#1] PREEMPT SMP > [ 164.453327] Modules linked in: ppp_async crc_ccitt ppp_generic slhc af_packet xfs libcrc32c coretemp kvm_intel > snd_hda_codec_conexant iTCO_wdt snd_hda_codec_generic iTCO_vendor_support uvcvideo snd_hda_intel snd_hda_controller mac80211 videobuf2_vmalloc snd_hda_codec kvm e1000e videobuf2_memops cfg80211 videobuf2_core v4l2_common snd_hwdep i2c_i801 videodev snd_pcm pcspkr thinkpad_acpi serio_raw wmi lpc_ich snd_timer thermal snd rfkill mfd_core tpm_tis shpchp mei_me soundcore ptp mei pps_core acpi_cpufreq tpm battery processor ac dm_mod btrfs xor raid6_pq i915 i2c_algo_bit drm_kms_helper drm video button sg > [ 164.453327] CPU: 0 PID: 6927 Comm: pppd Not tainted 3.18.0-rc3-3.ge706e91-desktop #1 > [ 164.453327] Hardware name: LENOVO 7470E36/7470E36, BIOS 6DET61WW (3.11 ) 11/10/2009 > > This is easy to reproduce with: > > linux:~ # cat bin/crashme.sh > ---- > #!/bin/bash -x > pppd local pty "netcat -l 1234" & > sleep 1 > pppd local pty "netcat localhost 1234" & > sleep 1 > ---- > > 3.17 works fine. > I bisected the issue multiple times and always arrived at > > # first bad commit: [d6dd50e07c5bec00db2005969b1a01f8ca3d25ef] Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip > > which is a merge commit unfortunately. > > The BUG encountered above is in: > > 1309 static struct vm_struct *__get_vm_area_node(unsigned long size, > 1310 unsigned long align, unsigned long flags, unsigned long start, > 1311 unsigned long end, int node, gfp_t gfp_mask, const void *caller) > 1312 { > 1313 struct vmap_area *va; > 1314 struct vm_struct *area; > 1315 > 1316 BUG_ON(in_interrupt()); > 1317 if (flags & VM_IOREMAP) > 1318 align = 1ul << clamp(fls(size), PAGE_SHIFT, IOREMAP_MAX_ORDER); > 1319 > > the call trace is: > [ 164.453327] Call Trace: > [ 164.453327] [] __vmalloc_node_range+0x6d/0x290 > [ 164.453327] [] __vmalloc+0x3e/0x50 > [ 164.453327] [] bpf_prog_alloc+0x30/0xa0 > [ 164.453327] [] bpf_prog_create+0x46/0xb0 > [ 164.453327] [] ppp_ioctl+0x420/0xe9a [ppp_generic] > [ 164.453327] [] do_vfs_ioctl+0x2e7/0x4c0 > [ 164.453327] [] SyS_ioctl+0x81/0xa0 > [ 164.453327] [] system_call_fastpath+0x16/0x1b > [ 164.453327] [<00007f4502d87397>] 0x7f4502d87397 bpf_prog_create() is called inside spin_lock_bh(), and the BUG_ON() hits. Below is a quick fix. Takashi -- 8< -- From: Takashi Iwai Subject: [PATCH] net: ppp: Don't call bpf_prog_create() in ppp_lock In ppp_ioctl(), bpf_prog_create() is called inside ppp_lock, which eventually calls vmalloc() and hits BUG_ON() in vmalloc.c. This patch works around the problem by moving the allocation outside the lock. Reported-by: Stefan Seyfried Signed-off-by: Takashi Iwai Tested-by: Stefan Seyfried --- drivers/net/ppp/ppp_generic.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 68c3a3f4e0ab..794a47329368 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -755,23 +755,23 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) err = get_filter(argp, &code); if (err >= 0) { + struct bpf_prog *pass_filter = NULL; struct sock_fprog_kern fprog = { .len = err, .filter = code, }; - ppp_lock(ppp); - if (ppp->pass_filter) { - bpf_prog_destroy(ppp->pass_filter); - ppp->pass_filter = NULL; + err = 0; + if (fprog.filter) + err = bpf_prog_create(&pass_filter, &fprog); + if (!err) { + ppp_lock(ppp); + if (ppp->pass_filter) + bpf_prog_destroy(ppp->pass_filter); + ppp->pass_filter = pass_filter; + ppp_unlock(ppp); } - if (fprog.filter != NULL) - err = bpf_prog_create(&ppp->pass_filter, - &fprog); - else - err = 0; kfree(code); - ppp_unlock(ppp); } break; } @@ -781,23 +781,23 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) err = get_filter(argp, &code); if (err >= 0) { + struct bpf_prog *active_filter = NULL; struct sock_fprog_kern fprog = { .len = err, .filter = code, }; - ppp_lock(ppp); - if (ppp->active_filter) { - bpf_prog_destroy(ppp->active_filter); - ppp->active_filter = NULL; + err = 0; + if (fprog.filter) + err = bpf_prog_create(&active_filter, &fprog); + if (!err) { + ppp_lock(ppp); + if (ppp->active_filter) + bpf_prog_destroy(ppp->active_filter); + ppp->active_filter = active_filter; + ppp_unlock(ppp); } - if (fprog.filter != NULL) - err = bpf_prog_create(&ppp->active_filter, - &fprog); - else - err = 0; kfree(code); - ppp_unlock(ppp); } break; }