mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 17:24:17 +08:00
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: ACPI / ACPICA: Implicit notify for multiple devices ACPI / debugfs: Fix buffer overflows, double free
This commit is contained in:
commit
ad4bfcb1ca
@ -416,10 +416,15 @@ struct acpi_gpe_handler_info {
|
|||||||
u8 originally_enabled; /* True if GPE was originally enabled */
|
u8 originally_enabled; /* True if GPE was originally enabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct acpi_gpe_notify_object {
|
||||||
|
struct acpi_namespace_node *node;
|
||||||
|
struct acpi_gpe_notify_object *next;
|
||||||
|
};
|
||||||
|
|
||||||
union acpi_gpe_dispatch_info {
|
union acpi_gpe_dispatch_info {
|
||||||
struct acpi_namespace_node *method_node; /* Method node for this GPE level */
|
struct acpi_namespace_node *method_node; /* Method node for this GPE level */
|
||||||
struct acpi_gpe_handler_info *handler; /* Installed GPE handler */
|
struct acpi_gpe_handler_info *handler; /* Installed GPE handler */
|
||||||
struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */
|
struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -457,6 +457,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|||||||
acpi_status status;
|
acpi_status status;
|
||||||
struct acpi_gpe_event_info *local_gpe_event_info;
|
struct acpi_gpe_event_info *local_gpe_event_info;
|
||||||
struct acpi_evaluate_info *info;
|
struct acpi_evaluate_info *info;
|
||||||
|
struct acpi_gpe_notify_object *notify_object;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
|
ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
|
||||||
|
|
||||||
@ -508,10 +509,18 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|||||||
* from this thread -- because handlers may in turn run other
|
* from this thread -- because handlers may in turn run other
|
||||||
* control methods.
|
* control methods.
|
||||||
*/
|
*/
|
||||||
status =
|
status = acpi_ev_queue_notify_request(
|
||||||
acpi_ev_queue_notify_request(local_gpe_event_info->dispatch.
|
local_gpe_event_info->dispatch.device.node,
|
||||||
device_node,
|
ACPI_NOTIFY_DEVICE_WAKE);
|
||||||
ACPI_NOTIFY_DEVICE_WAKE);
|
|
||||||
|
notify_object = local_gpe_event_info->dispatch.device.next;
|
||||||
|
while (ACPI_SUCCESS(status) && notify_object) {
|
||||||
|
status = acpi_ev_queue_notify_request(
|
||||||
|
notify_object->node,
|
||||||
|
ACPI_NOTIFY_DEVICE_WAKE);
|
||||||
|
notify_object = notify_object->next;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_GPE_DISPATCH_METHOD:
|
case ACPI_GPE_DISPATCH_METHOD:
|
||||||
|
@ -198,7 +198,9 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
|
|||||||
acpi_status status = AE_BAD_PARAMETER;
|
acpi_status status = AE_BAD_PARAMETER;
|
||||||
struct acpi_gpe_event_info *gpe_event_info;
|
struct acpi_gpe_event_info *gpe_event_info;
|
||||||
struct acpi_namespace_node *device_node;
|
struct acpi_namespace_node *device_node;
|
||||||
|
struct acpi_gpe_notify_object *notify_object;
|
||||||
acpi_cpu_flags flags;
|
acpi_cpu_flags flags;
|
||||||
|
u8 gpe_dispatch_mask;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
|
ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
|
||||||
|
|
||||||
@ -221,27 +223,49 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
|
|||||||
goto unlock_and_exit;
|
goto unlock_and_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wake_device == ACPI_ROOT_OBJECT) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is no method or handler for this GPE, then the
|
* If there is no method or handler for this GPE, then the
|
||||||
* wake_device will be notified whenever this GPE fires (aka
|
* wake_device will be notified whenever this GPE fires (aka
|
||||||
* "implicit notify") Note: The GPE is assumed to be
|
* "implicit notify") Note: The GPE is assumed to be
|
||||||
* level-triggered (for windows compatibility).
|
* level-triggered (for windows compatibility).
|
||||||
*/
|
*/
|
||||||
if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
|
gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
|
||||||
ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) {
|
if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
|
||||||
|
&& gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
|
||||||
/* Validate wake_device is of type Device */
|
goto out;
|
||||||
|
|
||||||
device_node = ACPI_CAST_PTR(struct acpi_namespace_node,
|
|
||||||
wake_device);
|
|
||||||
if (device_node->type != ACPI_TYPE_DEVICE) {
|
|
||||||
goto unlock_and_exit;
|
|
||||||
}
|
|
||||||
gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
|
|
||||||
ACPI_GPE_LEVEL_TRIGGERED);
|
|
||||||
gpe_event_info->dispatch.device_node = device_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Validate wake_device is of type Device */
|
||||||
|
|
||||||
|
device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
|
||||||
|
if (device_node->type != ACPI_TYPE_DEVICE) {
|
||||||
|
goto unlock_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) {
|
||||||
|
gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
|
||||||
|
ACPI_GPE_LEVEL_TRIGGERED);
|
||||||
|
gpe_event_info->dispatch.device.node = device_node;
|
||||||
|
gpe_event_info->dispatch.device.next = NULL;
|
||||||
|
} else {
|
||||||
|
/* There are multiple devices to notify implicitly. */
|
||||||
|
|
||||||
|
notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object));
|
||||||
|
if (!notify_object) {
|
||||||
|
status = AE_NO_MEMORY;
|
||||||
|
goto unlock_and_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_object->node = device_node;
|
||||||
|
notify_object->next = gpe_event_info->dispatch.device.next;
|
||||||
|
gpe_event_info->dispatch.device.next = notify_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
|
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
|
||||||
status = AE_OK;
|
status = AE_OK;
|
||||||
|
|
||||||
|
@ -26,7 +26,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
|
|||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
static char *buf;
|
static char *buf;
|
||||||
static int uncopied_bytes;
|
static u32 max_size;
|
||||||
|
static u32 uncopied_bytes;
|
||||||
|
|
||||||
struct acpi_table_header table;
|
struct acpi_table_header table;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
|
|
||||||
@ -37,19 +39,24 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
|
|||||||
if (copy_from_user(&table, user_buf,
|
if (copy_from_user(&table, user_buf,
|
||||||
sizeof(struct acpi_table_header)))
|
sizeof(struct acpi_table_header)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
uncopied_bytes = table.length;
|
uncopied_bytes = max_size = table.length;
|
||||||
buf = kzalloc(uncopied_bytes, GFP_KERNEL);
|
buf = kzalloc(max_size, GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uncopied_bytes < count) {
|
if (buf == NULL)
|
||||||
kfree(buf);
|
return -EINVAL;
|
||||||
|
|
||||||
|
if ((*ppos > max_size) ||
|
||||||
|
(*ppos + count > max_size) ||
|
||||||
|
(*ppos + count < count) ||
|
||||||
|
(count > uncopied_bytes))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_from_user(buf + (*ppos), user_buf, count)) {
|
if (copy_from_user(buf + (*ppos), user_buf, count)) {
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
buf = NULL;
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +66,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
|
|||||||
if (!uncopied_bytes) {
|
if (!uncopied_bytes) {
|
||||||
status = acpi_install_method(buf);
|
status = acpi_install_method(buf);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
buf = NULL;
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
|
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
|
||||||
|
Loading…
Reference in New Issue
Block a user