public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ACPICA: Add mutex to avoid race condition of reference count of notify object
@ 2014-06-16  2:11 Lee, Chun-Yi
  2014-06-16  5:10 ` Zheng, Lv
  0 siblings, 1 reply; 10+ messages in thread
From: Lee, Chun-Yi @ 2014-06-16  2:11 UTC (permalink / raw)
  To: Robert Moore, Lv Zheng; +Cc: linux-acpi, Lee, Chun-Yi

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 <jlee@suse.com>
---
 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 */
-- 
1.8.4.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH] ACPICA: Add mutex to avoid race condition of reference count of notify object
@ 2014-06-09  4:14 Lee, Chun-Yi
  0 siblings, 0 replies; 10+ messages in thread
From: Lee, Chun-Yi @ 2014-06-09  4:14 UTC (permalink / raw)
  To: Robert Moore, Lv Zheng; +Cc: linux-acpi, Lee, Chun-Yi

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 <jlee@suse.com>
---
 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 */
-- 
1.8.4.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-06-04  1:18 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-16  2:11 [PATCH] ACPICA: Add mutex to avoid race condition of reference count of notify object Lee, Chun-Yi
2014-06-16  5:10 ` Zheng, Lv
2014-06-16  9:14   ` joeyli
2014-06-17  1:03     ` Zheng, Lv
2014-06-17  9:19       ` joeyli
2014-06-18  4:42         ` Zheng, Lv
2015-06-03  6:53           ` Hanjun Guo
2015-06-03  7:38             ` Zheng, Lv
2015-06-04  1:17               ` Hanjun Guo
  -- strict thread matches above, loose matches on Subject: below --
2014-06-09  4:14 Lee, Chun-Yi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox