diff options
author | Dan Williams <dan.j.williams@intel.com> | 2020-07-31 18:38:26 -0700 |
---|---|---|
committer | Vishal Verma <vishal.l.verma@intel.com> | 2020-08-03 12:36:34 -0600 |
commit | 9f1048d47e8ae4cc21e80facf2ba4b01a6623b67 (patch) | |
tree | 63ddcda40da7133d559b65d2c3b0615073453590 /drivers/acpi/nfit | |
parent | 49688e654e48ae176b5bfda33d2416b68e607ce8 (diff) | |
download | linux-stable-9f1048d47e8ae4cc21e80facf2ba4b01a6623b67.tar.gz linux-stable-9f1048d47e8ae4cc21e80facf2ba4b01a6623b67.tar.bz2 linux-stable-9f1048d47e8ae4cc21e80facf2ba4b01a6623b67.zip |
ACPI: NFIT: Fix ARS zero-sized allocation
Pending commit in -next "devres: handle zero size in devm_kmalloc()"
triggers a boot regression due to the ARS implementation expecting NULL
from a zero-sized allocation. Avoid the zero-sized allocation by
skipping ARS, otherwise crashes with the following signature when
de-referencing ZERO_SIZE_PTR.
BUG: kernel NULL pointer dereference, address: 0000000000000018
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
RIP: 0010:__acpi_nfit_scrub+0x28a/0x350 [nfit]
[..]
Call Trace:
? acpi_nfit_query_poison+0x6a/0x180 [nfit]
acpi_nfit_scrub+0x36/0xb0 [nfit]
process_one_work+0x23c/0x580
worker_thread+0x50/0x3b0
Otherwise the implementation correctly aborts when NULL is returned from
devm_kzalloc() in ars_status_alloc().
Link: https://lore.kernel.org/r/159624590643.3037264.14157533719042907758.stgit@dwillia2-desk3.amr.corp.intel.com
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Diffstat (limited to 'drivers/acpi/nfit')
-rw-r--r-- | drivers/acpi/nfit/core.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index fb775b967c52..26dd208a0d63 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -3334,7 +3334,7 @@ static void acpi_nfit_init_ars(struct acpi_nfit_desc *acpi_desc, static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) { struct nfit_spa *nfit_spa; - int rc; + int rc, do_sched_ars = 0; set_bit(ARS_VALID, &acpi_desc->scrub_flags); list_for_each_entry(nfit_spa, &acpi_desc->spas, list) { @@ -3346,7 +3346,7 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) } } - list_for_each_entry(nfit_spa, &acpi_desc->spas, list) + list_for_each_entry(nfit_spa, &acpi_desc->spas, list) { switch (nfit_spa_type(nfit_spa->spa)) { case NFIT_SPA_VOLATILE: case NFIT_SPA_PM: @@ -3354,6 +3354,13 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) rc = ars_register(acpi_desc, nfit_spa); if (rc) return rc; + + /* + * Kick off background ARS if at least one + * region successfully registered ARS + */ + if (!test_bit(ARS_FAILED, &nfit_spa->ars_state)) + do_sched_ars++; break; case NFIT_SPA_BDW: /* nothing to register */ @@ -3372,8 +3379,10 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc) /* don't register unknown regions */ break; } + } - sched_ars(acpi_desc); + if (do_sched_ars) + sched_ars(acpi_desc); return 0; } |