Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad4bfcb1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents dd9c1549 981858bd
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -416,10 +416,15 @@ struct acpi_gpe_handler_info {
	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 {
	struct acpi_namespace_node *method_node;	/* Method node for this GPE level */
	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 */
};

/*
+13 −4
Original line number Diff line number Diff line
@@ -457,6 +457,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
	acpi_status status;
	struct acpi_gpe_event_info *local_gpe_event_info;
	struct acpi_evaluate_info *info;
	struct acpi_gpe_notify_object *notify_object;

	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
		 * control methods.
		 */
		status =
		    acpi_ev_queue_notify_request(local_gpe_event_info->dispatch.
						 device_node,
		status = acpi_ev_queue_notify_request(
				local_gpe_event_info->dispatch.device.node,
				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;

	case ACPI_GPE_DISPATCH_METHOD:
+33 −9
Original line number Diff line number Diff line
@@ -198,7 +198,9 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
	acpi_status status = AE_BAD_PARAMETER;
	struct acpi_gpe_event_info *gpe_event_info;
	struct acpi_namespace_node *device_node;
	struct acpi_gpe_notify_object *notify_object;
	acpi_cpu_flags flags;
	u8 gpe_dispatch_mask;

	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;
	}

	if (wake_device == ACPI_ROOT_OBJECT) {
		goto out;
	}

	/*
	 * If there is no method or handler for this GPE, then the
	 * wake_device will be notified whenever this GPE fires (aka
	 * "implicit notify") Note: The GPE is assumed to be
	 * level-triggered (for windows compatibility).
	 */
	if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
	      ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) {
	gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
	if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
	    && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
		goto out;
	}

	/* Validate wake_device is of type Device */

		device_node = ACPI_CAST_PTR(struct acpi_namespace_node,
					    wake_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.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;
	status = AE_OK;

+14 −6
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
			size_t count, loff_t *ppos)
{
	static char *buf;
	static int uncopied_bytes;
	static u32 max_size;
	static u32 uncopied_bytes;

	struct acpi_table_header table;
	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,
				   sizeof(struct acpi_table_header)))
			return -EFAULT;
		uncopied_bytes = table.length;
		buf = kzalloc(uncopied_bytes, GFP_KERNEL);
		uncopied_bytes = max_size = table.length;
		buf = kzalloc(max_size, GFP_KERNEL);
		if (!buf)
			return -ENOMEM;
	}

	if (uncopied_bytes < count) {
		kfree(buf);
	if (buf == NULL)
		return -EINVAL;

	if ((*ppos > max_size) ||
	    (*ppos + count > max_size) ||
	    (*ppos + count < count) ||
	    (count > uncopied_bytes))
		return -EINVAL;
	}

	if (copy_from_user(buf + (*ppos), user_buf, count)) {
		kfree(buf);
		buf = NULL;
		return -EFAULT;
	}

@@ -59,6 +66,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
	if (!uncopied_bytes) {
		status = acpi_install_method(buf);
		kfree(buf);
		buf = NULL;
		if (ACPI_FAILURE(status))
			return -EINVAL;
		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);