From patchwork Tue Apr 12 09:16:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Amadeusz_S=C5=82awi=C5=84ski?= X-Patchwork-Id: 12810251 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 40DF7C433F5 for ; Tue, 12 Apr 2022 09:17:31 +0000 (UTC) Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 4673A1712; Tue, 12 Apr 2022 11:16:39 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 4673A1712 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1649755049; bh=/xDxbIG5fwapg9sVV5GxgapCMbdv6bbINA6bS0/HPps=; h=From:To:Subject:Date:Cc:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From; b=CAnN3s1Tg/waA1tUn1h99YUJNpJylKIno6MN9utquac76kP8bKkQV8i0rX8f1kjWD /SvCewCQZGapdFBw16jLbjRof6Ng4yQ/e4nXCfaQ7lxNemchZOUJbFpXdLLvwKIcf3 23vx1A0MVjNHvZTiEy7LVgNXOFSpT2jy649Wss7Q= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id D3892F80134; Tue, 12 Apr 2022 11:16:38 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 459B4F80095; Tue, 12 Apr 2022 11:16:37 +0200 (CEST) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 765C0F80095 for ; Tue, 12 Apr 2022 11:16:29 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 765C0F80095 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="fq+VRfVj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1649754991; x=1681290991; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=/xDxbIG5fwapg9sVV5GxgapCMbdv6bbINA6bS0/HPps=; b=fq+VRfVjyzGkewFu+hHxUAnq67EP/+i6ky1ssvieJXuZa4xX5kMhLtRI ema5k7FZQTVNv+RjS08CJ7adNCiMzqwVNcC0M+s+YWtSo37p4EQhd6IEC T7WoLATZ7fi++V9MkGlr3leKYB3Qq/x0lkwVmuCEAJh3vH8c7+l1A7HIF U/Ej3lQ0ldoHHcEsB2X58VwetE9ObVySM8oeLLEYF1mDjN/fDyHGxXfsU fAvlQd4/gqmiYe14Nv8J8ZJjYAY8EbGGDYrgN3Vbh+o/ADOs+qR/TtjDN r183TOXTN3QsPgoB8MExc/YUJtjJzVlPtH2ePgmjZ1Kz4V+oO9aMEpJeH g==; X-IronPort-AV: E=McAfee;i="6400,9594,10314"; a="242912113" X-IronPort-AV: E=Sophos;i="5.90,253,1643702400"; d="scan'208";a="242912113" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Apr 2022 02:16:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,253,1643702400"; d="scan'208";a="724366262" Received: from dev2.igk.intel.com ([10.237.148.94]) by orsmga005.jf.intel.com with ESMTP; 12 Apr 2022 02:16:24 -0700 From: =?utf-8?q?Amadeusz_S=C5=82awi=C5=84ski?= To: Takashi Iwai Subject: [PATCH v2] ALSA: jack: Access input_dev under mutex Date: Tue, 12 Apr 2022 11:16:28 +0200 Message-Id: <20220412091628.3056922-1-amadeuszx.slawinski@linux.intel.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Cc: alsa-devel@alsa-project.org, =?utf-8?q?Amadeusz_S=C5=82awi=C5=84ski?= , Cezary Rojewski X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 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: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" It is possible when using ASoC that input_dev is unregistered while calling snd_jack_report, which causes NULL pointer dereference. In order to prevent this serialize access to input_dev using mutex lock. Signed-off-by: Amadeusz Sławiński Reviewed-by: Cezary Rojewski --- Changes: v2: - drop mutex in snd_jack_new - add comment that snd_jack_report() should be called in context where it can sleep --- include/sound/jack.h | 1 + sound/core/jack.c | 34 +++++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/sound/jack.h b/include/sound/jack.h index 1181f536557e..1ed90e2109e9 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -62,6 +62,7 @@ struct snd_jack { const char *id; #ifdef CONFIG_SND_JACK_INPUT_DEV struct input_dev *input_dev; + struct mutex input_dev_lock; int registered; int type; char name[100]; diff --git a/sound/core/jack.c b/sound/core/jack.c index d1e3055f2b6a..88493cc31914 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -42,8 +42,11 @@ static int snd_jack_dev_disconnect(struct snd_device *device) #ifdef CONFIG_SND_JACK_INPUT_DEV struct snd_jack *jack = device->device_data; - if (!jack->input_dev) + mutex_lock(&jack->input_dev_lock); + if (!jack->input_dev) { + mutex_unlock(&jack->input_dev_lock); return 0; + } /* If the input device is registered with the input subsystem * then we need to use a different deallocator. */ @@ -52,6 +55,7 @@ static int snd_jack_dev_disconnect(struct snd_device *device) else input_free_device(jack->input_dev); jack->input_dev = NULL; + mutex_unlock(&jack->input_dev_lock); #endif /* CONFIG_SND_JACK_INPUT_DEV */ return 0; } @@ -90,8 +94,11 @@ static int snd_jack_dev_register(struct snd_device *device) snprintf(jack->name, sizeof(jack->name), "%s %s", card->shortname, jack->id); - if (!jack->input_dev) + mutex_lock(&jack->input_dev_lock); + if (!jack->input_dev) { + mutex_unlock(&jack->input_dev_lock); return 0; + } jack->input_dev->name = jack->name; @@ -116,6 +123,7 @@ static int snd_jack_dev_register(struct snd_device *device) if (err == 0) jack->registered = 1; + mutex_unlock(&jack->input_dev_lock); return err; } #endif /* CONFIG_SND_JACK_INPUT_DEV */ @@ -517,9 +525,11 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, return -ENOMEM; } - /* don't creat input device for phantom jack */ - if (!phantom_jack) { #ifdef CONFIG_SND_JACK_INPUT_DEV + mutex_init(&jack->input_dev_lock); + + /* don't create input device for phantom jack */ + if (!phantom_jack) { int i; jack->input_dev = input_allocate_device(); @@ -537,8 +547,8 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, input_set_capability(jack->input_dev, EV_SW, jack_switch_types[i]); -#endif /* CONFIG_SND_JACK_INPUT_DEV */ } +#endif /* CONFIG_SND_JACK_INPUT_DEV */ err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); if (err < 0) @@ -578,10 +588,14 @@ EXPORT_SYMBOL(snd_jack_new); void snd_jack_set_parent(struct snd_jack *jack, struct device *parent) { WARN_ON(jack->registered); - if (!jack->input_dev) + mutex_lock(&jack->input_dev_lock); + if (!jack->input_dev) { + mutex_unlock(&jack->input_dev_lock); return; + } jack->input_dev->dev.parent = parent; + mutex_unlock(&jack->input_dev_lock); } EXPORT_SYMBOL(snd_jack_set_parent); @@ -629,6 +643,8 @@ EXPORT_SYMBOL(snd_jack_set_key); /** * snd_jack_report - Report the current status of a jack + * Note: This function uses mutexes and should be called from a + * context which can sleep (such as a workqueue). * * @jack: The jack to report status for * @status: The current status of the jack @@ -654,8 +670,11 @@ void snd_jack_report(struct snd_jack *jack, int status) status & jack_kctl->mask_bits); #ifdef CONFIG_SND_JACK_INPUT_DEV - if (!jack->input_dev) + mutex_lock(&jack->input_dev_lock); + if (!jack->input_dev) { + mutex_unlock(&jack->input_dev_lock); return; + } for (i = 0; i < ARRAY_SIZE(jack->key); i++) { int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits); @@ -675,6 +694,7 @@ void snd_jack_report(struct snd_jack *jack, int status) } input_sync(jack->input_dev); + mutex_unlock(&jack->input_dev_lock); #endif /* CONFIG_SND_JACK_INPUT_DEV */ } EXPORT_SYMBOL(snd_jack_report);