From patchwork Tue Jan 13 20:03:37 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Geert Uytterhoeven X-Patchwork-Id: 5624001 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 278EAC058D for ; Tue, 13 Jan 2015 20:03:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 496D7202C8 for ; Tue, 13 Jan 2015 20:03:55 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id 207232026C for ; Tue, 13 Jan 2015 20:03:54 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 3F4792605D4; Tue, 13 Jan 2015 21:03:53 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_00, SUBJ_OBFU_PUNCT_MANY, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id E514A260487; Tue, 13 Jan 2015 21:03:44 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id E89BE26048B; Tue, 13 Jan 2015 21:03:43 +0100 (CET) Received: from andre.telenet-ops.be (andre.telenet-ops.be [195.130.132.53]) by alsa0.perex.cz (Postfix) with ESMTP id F3B64260483 for ; Tue, 13 Jan 2015 21:03:36 +0100 (CET) Received: from ayla.of.borg ([84.193.93.87]) by andre.telenet-ops.be with bizsmtp id fY3c1p0051t5w8s01Y3cWD; Tue, 13 Jan 2015 21:03:36 +0100 Received: from ramsan.of.borg ([192.168.97.29] helo=ramsan) by ayla.of.borg with esmtp (Exim 4.82) (envelope-from ) id 1YB7gd-0003iA-Sz; Tue, 13 Jan 2015 21:03:35 +0100 Received: from geert by ramsan with local (Exim 4.82) (envelope-from ) id 1YB7gh-0006Ap-Ds; Tue, 13 Jan 2015 21:03:39 +0100 From: Geert Uytterhoeven To: Liam Girdwood , Mark Brown , Jean-Francois Moine Date: Tue, 13 Jan 2015 21:03:37 +0100 Message-Id: <1421179417-23698-1-git-send-email-geert+renesas@glider.be> X-Mailer: git-send-email 1.9.1 Cc: alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven , linux-sh@vger.kernel.org Subject: [alsa-devel] [PATCH] ASoC: simple-card: Fix crash in asoc_simple_card_unref() X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP If asoc_simple_card_probe() fails, asoc_simple_card_unref() may be called before dev_set_drvdata(), causing a NULL pointer dereference in asoc_simple_card_unref(): Unable to handle kernel NULL pointer dereference at virtual address 000000d4 ... PC is at asoc_simple_card_unref+0x14/0x48 LR is at asoc_simple_card_probe+0x3d4/0x40c This typically happens because asoc_simple_card_parse_of() returns -EPROBE_DEFER, but other failure modes are possible. devm_snd_soc_register_card()/snd_soc_register_card() may fail either before or after dev_set_drvdata(). Pass a snd_soc_card pointer instead of a platform_device pointer to asoc_simple_card_unref() to fix this. Note that if CONFIG_OF_DYNAMIC=n, of_node_put() is a dummy, and gcc may optimize away the loop over card->dai_link, never actually dereferencing card, and thus avoiding the crash... Signed-off-by: Geert Uytterhoeven Fixes: e512e001dafa54e5 ("ASoC: simple-card: Fix the reference count of device nodes") --- Seen on sh73a0/kzm9g-multiplatform and r8a7740/armadillo-multiplatform, first with CONFIG_OF_DYNAMIC=y, later with extra debug code that caused the loop not to be optimized away. It took me a while to understand what was really happening... I think this should be applied to -stable. In v3.15 and v3.16, only 8xx, pseries, and wsp selected OF_DYNAMIC, and I believe they don't use aSoC? In v3.17 and later, OF_DYNAMIC is selected by OF_SELFTEST/OF_UNITTEST. --- sound/soc/generic/simple-card.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index fb9240fdc9b70095..7fe3009b1c43c63c 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -452,9 +452,8 @@ static int asoc_simple_card_parse_of(struct device_node *node, } /* Decrease the reference count of the device nodes */ -static int asoc_simple_card_unref(struct platform_device *pdev) +static int asoc_simple_card_unref(struct snd_soc_card *card) { - struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_dai_link *dai_link; int num_links; @@ -556,7 +555,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev) return ret; err: - asoc_simple_card_unref(pdev); + asoc_simple_card_unref(&priv->snd_card); return ret; } @@ -572,7 +571,7 @@ static int asoc_simple_card_remove(struct platform_device *pdev) snd_soc_jack_free_gpios(&simple_card_mic_jack, 1, &simple_card_mic_jack_gpio); - return asoc_simple_card_unref(pdev); + return asoc_simple_card_unref(card); } static const struct of_device_id asoc_simple_of_match[] = {