From patchwork Mon Jun 16 02:11:55 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: 4355741 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 CD2059F333 for ; Mon, 16 Jun 2014 02:16:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E22FB2026C for ; Mon, 16 Jun 2014 02:16:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B559920148 for ; Mon, 16 Jun 2014 02:16:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752542AbaFPCQG (ORCPT ); Sun, 15 Jun 2014 22:16:06 -0400 Received: from mail-pb0-f46.google.com ([209.85.160.46]:34681 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752478AbaFPCQF (ORCPT ); Sun, 15 Jun 2014 22:16:05 -0400 Received: by mail-pb0-f46.google.com with SMTP id md12so3089030pbc.33 for ; Sun, 15 Jun 2014 19:16:03 -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=GL+dH/B00NTiKjE25XLV89D4M1dupiDo8XQa7WPPgXXherdw2nB/3VxCsXvJDzQb0C dP3gIbXDdm5xznZyYeO5OR2oXKJjTGw/76nFy/ysgH+1j6eat1DXtW9J7BuLW4Job0O2 O6vIvZyqrFDZmtntvwGlYPCmF64OVw+1EXgYWAhzVHGw+XFCO+JMIRXC4deHGHpEPcIr ooEGX7JdvLi0BkBi5EbHi+6YNX1MwAhYkMSHoD5YfYmx21RGXri7dGBvrWHm0QQVllen wEMku7D3JG6pSsQFj+t8xN7Qv9XGdN5dI8GFCef1gRpRUfsSACBPg7jG6Ywir8KiUZI8 89LA== X-Received: by 10.69.10.164 with SMTP id eb4mr20741668pbd.35.1402884963900; Sun, 15 Jun 2014 19:16:03 -0700 (PDT) Received: from linux-rxt1.site ([130.57.30.250]) by mx.google.com with ESMTPSA id br1sm15619792pbc.6.2014.06.15.19.16.00 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 15 Jun 2014 19:16:03 -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, 16 Jun 2014 10:11:55 +0800 Message-Id: <1402884715-25049-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=ham 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 */