From patchwork Mon Jun 9 04:14:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Yi Lee X-Patchwork-Id: 4317701 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C8C4A9F170 for ; Mon, 9 Jun 2014 04:18:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DF84820127 for ; Mon, 9 Jun 2014 04:18:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 17BAD2016C for ; Mon, 9 Jun 2014 04:18:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750741AbaFIESH (ORCPT ); Mon, 9 Jun 2014 00:18:07 -0400 Received: from mail-pa0-f43.google.com ([209.85.220.43]:46809 "EHLO mail-pa0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750729AbaFIESG (ORCPT ); Mon, 9 Jun 2014 00:18:06 -0400 Received: by mail-pa0-f43.google.com with SMTP id rd3so312224pab.16 for ; Sun, 08 Jun 2014 21:18:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=2JL+xV6etjlmQTCAg+/Tck4Z5swZOEPTzId9dHams5E=; b=X5cJ91NBUBtUV/NAOeOiydy6CB0s0HyFAAFVC+mHfYmTVMAU0qWUIG5ORxo8q+1VHi QCCYj+Q86ZPRBgrQPZFaD4viMym4iWPnLK06S+HxdMrswB17cqu4tjFM085NSQBsXAvn dvHMw9rRqvlVOcIJqBIXjEYEMCnYJGlf96tu0UoJna1qYgLddkyzT8a4enxKC0FosMaK mXBiRKAzTVT3vfMKo84yAdXlVRSBLSacaGpICtC242AquMWiaM9DPN+4XN3fWC75THoe JQcnvfszD/YATpUd3U0xq9HQ8gOReAVAlehkawAZBDlKMVTsqpe6Fi1R2+Mq238bxPIN VDIQ== X-Received: by 10.68.103.165 with SMTP id fx5mr1900233pbb.118.1402287485928; Sun, 08 Jun 2014 21:18:05 -0700 (PDT) Received: from linux-rxt1.site ([130.57.30.250]) by mx.google.com with ESMTPSA id tl3sm5818215pac.41.2014.06.08.21.18.02 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Jun 2014 21:18:05 -0700 (PDT) From: "Lee, Chun-Yi" X-Google-Original-From: "Lee, Chun-Yi" To: Robert Moore , Lv Zheng Cc: linux-acpi@vger.kernel.org, "Lee, Chun-Yi" Subject: [PATCH] ACPICA: Add mutex to avoid race condition of reference count of notify object Date: Mon, 9 Jun 2014 12:14:06 +0800 Message-Id: <1402287246-10669-1-git-send-email-jlee@suse.com> X-Mailer: git-send-email 1.8.4.5 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This issue found on v3.0 kernel, unfortunately there was no chance to test latest kernel on issue mchine. This patch tested on v3.0 kernel then sent to linux-acpi for review and note, maybe latest kernel also need. The problem happened when acpi thermal driver evaluate _PSL, but acpi processor driver install notify handler at the same time. In the code path of evaluate _PSL, it updates reference count of processor and its notify objects. When the notify handler installation done after the reference count of processor updated, it causes the ref_count of processor doesn't sync with its notify object's ref_count value. Here is an debugging log when issue reproduced: [ 3.481773] ACPI_TYPE_PROCESSOR set ACPI_DEVICE_NOTIFY, object_desc->common.reference_count: 3, notify_obj->common.reference_count: 1 [ 3.481958] PROCESSOR device_hid: LNXCPU ... [ 3.487427] ACPI_TYPE_PROCESSOR, action = 1 [ 3.487428] Update device_notify ref_count [ 3.487429] REF_DECREMENT ACPI_TYPE_LOCAL_NOTIFY original_count: 0 [ 3.487431] ACPI Warning: Obj ffff8800b0f40b28, Reference Count is already zero, cannot decrement [ 3.487433] (20110413/utdelete-431) [ 3.487434] REF_DECREMENT ACPI_TYPE_PROCESSOR original_count: 2 Accroding log, found the reference_count of parent object (it's processor in this case) is 3, it doesn't match with notify_object's reference_count, value is 1. It triggered "Reference Count is already zero" warning, then happen object double free issue later. To avoid rece condition, this patch introded ACPI_MTX_NOTIFY_REF_COUNT mutex to keep the ref_count of notify object sync with its parent object. And, it also set the reference_count value of new notify object equals to its parent object's reference_count. Signed-off-by: Lee, Chun-Yi --- drivers/acpi/acpica/aclocal.h | 3 ++- drivers/acpi/acpica/evxface.c | 7 ++++++- drivers/acpi/acpica/utdelete.c | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index c7f743c..e25a4af 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -85,8 +85,9 @@ union acpi_parse_object; #define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */ #define ACPI_MTX_DEBUG_CMD_COMPLETE 6 /* AML debugger */ #define ACPI_MTX_DEBUG_CMD_READY 7 /* AML debugger */ +#define ACPI_MTX_NOTIFY_REF_COUNT 8 /* Reference count of notify object */ -#define ACPI_MAX_MUTEX 7 +#define ACPI_MAX_MUTEX 8 #define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 /* Lock structure for reader/writer interfaces */ diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index e114140..213fe1a 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -495,6 +495,10 @@ acpi_install_notify_handler(acpi_handle device, handler, context, NULL); + acpi_ut_acquire_mutex(ACPI_MTX_NOTIFY_REF_COUNT); + + notify_obj->common.reference_count = obj_desc->common.reference_count; + if (handler_type & ACPI_SYSTEM_NOTIFY) { obj_desc->common_notify.system_notify = notify_obj; } @@ -503,8 +507,9 @@ acpi_install_notify_handler(acpi_handle device, obj_desc->common_notify.device_notify = notify_obj; } - if (handler_type == ACPI_ALL_NOTIFY) { + acpi_ut_release_mutex(ACPI_MTX_NOTIFY_REF_COUNT); + if (handler_type == ACPI_ALL_NOTIFY) { /* Extra ref if installed in both */ acpi_ut_add_reference(notify_obj); diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 31f5a78..7559813 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -504,6 +504,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) /* Update the notify objects for these types (if present) */ + acpi_ut_acquire_mutex(ACPI_MTX_NOTIFY_REF_COUNT); acpi_ut_update_ref_count(object->common_notify. system_notify, action); acpi_ut_update_ref_count(object->common_notify. @@ -592,6 +593,11 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) * main object to be deleted. */ acpi_ut_update_ref_count(object, action); + if (object->common.type == ACPI_TYPE_PROCESSOR || + object->common.type == ACPI_TYPE_DEVICE || + object->common.type == ACPI_TYPE_POWER || + object->common.type == ACPI_TYPE_THERMAL) + acpi_ut_release_mutex(ACPI_MTX_NOTIFY_REF_COUNT); object = NULL; /* Move on to the next object to be updated */