Browse Source

Merge tag 'acpi-urgent-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull two ACPI CPPC fixes from Rafael Wysocki:
 "One of them fixes a crash in KVM encountered by Sebastian in
  linux-next and introduced by a recent intel_pstate change that caused
  the driver to use the ACPI CPPC code and uncovered a missing NULL
  pointer check in it.

  The other one fixes a possible use-after-free in the same code area.

  Summary:

   - Fix a crash in KVM encountered in linux-next and introduced by a
     recent intel_pstate change that caused the driver to use the ACPI
     CPPC code and uncovered a missing NULL pointer check in it
     (Sebastian Andrzej Siewior).

   - Fix a possible use-after-free in the same code area (Rafael
     Wysocki)"

* tag 'acpi-urgent-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / CPPC: Fix per-CPU pointer management in acpi_cppc_processor_probe()
  ACPI / CPPC: Fix crash in acpi_cppc_processor_exit()
Linus Torvalds 8 years ago
parent
commit
7ae123edd3
1 changed files with 8 additions and 4 deletions
  1. 8 4
      drivers/acpi/cppc_acpi.c

+ 8 - 4
drivers/acpi/cppc_acpi.c

@@ -776,9 +776,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 		init_waitqueue_head(&pcc_data.pcc_write_wait_q);
 	}
 
-	/* Plug PSD data into this CPUs CPC descriptor. */
-	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
-
 	/* Everything looks okay */
 	pr_debug("Parsed CPC struct for CPU: %d\n", pr->id);
 
@@ -789,10 +786,15 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 		goto out_free;
 	}
 
+	/* Plug PSD data into this CPUs CPC descriptor. */
+	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
+
 	ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj,
 			"acpi_cppc");
-	if (ret)
+	if (ret) {
+		per_cpu(cpc_desc_ptr, pr->id) = NULL;
 		goto out_free;
+	}
 
 	kfree(output.pointer);
 	return 0;
@@ -826,6 +828,8 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
 	void __iomem *addr;
 
 	cpc_ptr = per_cpu(cpc_desc_ptr, pr->id);
+	if (!cpc_ptr)
+		return;
 
 	/* Free all the mapped sys mem areas for this CPU */
 	for (i = 2; i < cpc_ptr->num_entries; i++) {