Skip to content

Commit 99b52aa

Browse files
davejiangdjbw
authored andcommitted
cxl: Fix the incorrect assignment of SSLBIS entry pointer initial location
The 'entry' pointer in cdat_sslbis_handler() is set to header + sizeof(common header). However, the math missed the addition of the SSLBIS main header. It should be header + sizeof(common header) + sizeof(*sslbis). Use a defined struct for all the SSLBIS parts in order to avoid pointer math errors. The bug causes incorrect parsing of the SSLBIS table and introduces incorrect performance values to the access_coordinates during the CXL access_coordinate calculation path if there are CXL switches present in the topology. The issue was found during testing of new code being added to add additional checks for invalid CDAT values during CXL access_coordinate calculation. The testing was done on qemu with a CXL topology including a CXL switch. Fixes: 80aa780 ("cxl: Add callback to parse the SSLBIS subtable from CDAT") Signed-off-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Fan Ni <fan.ni@samsung.com> Link: https://lore.kernel.org/r/20240301210948.1298075-1-dave.jiang@intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent d206a76 commit 99b52aa

File tree

1 file changed

+15
-15
lines changed

1 file changed

+15
-15
lines changed

drivers/cxl/core/cdat.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -389,36 +389,38 @@ EXPORT_SYMBOL_NS_GPL(cxl_endpoint_parse_cdat, CXL);
389389
static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
390390
const unsigned long end)
391391
{
392+
struct acpi_cdat_sslbis_table {
393+
struct acpi_cdat_header header;
394+
struct acpi_cdat_sslbis sslbis_header;
395+
struct acpi_cdat_sslbe entries[];
396+
} *tbl = (struct acpi_cdat_sslbis_table *)header;
397+
int size = sizeof(header->cdat) + sizeof(tbl->sslbis_header);
392398
struct acpi_cdat_sslbis *sslbis;
393-
int size = sizeof(header->cdat) + sizeof(*sslbis);
394399
struct cxl_port *port = arg;
395400
struct device *dev = &port->dev;
396-
struct acpi_cdat_sslbe *entry;
397401
int remain, entries, i;
398402
u16 len;
399403

400404
len = le16_to_cpu((__force __le16)header->cdat.length);
401405
remain = len - size;
402-
if (!remain || remain % sizeof(*entry) ||
406+
if (!remain || remain % sizeof(tbl->entries[0]) ||
403407
(unsigned long)header + len > end) {
404408
dev_warn(dev, "Malformed SSLBIS table length: (%u)\n", len);
405409
return -EINVAL;
406410
}
407411

408-
/* Skip common header */
409-
sslbis = (struct acpi_cdat_sslbis *)((unsigned long)header +
410-
sizeof(header->cdat));
411-
412+
sslbis = &tbl->sslbis_header;
412413
/* Unrecognized data type, we can skip */
413414
if (sslbis->data_type > ACPI_HMAT_WRITE_BANDWIDTH)
414415
return 0;
415416

416-
entries = remain / sizeof(*entry);
417-
entry = (struct acpi_cdat_sslbe *)((unsigned long)header + sizeof(*sslbis));
417+
entries = remain / sizeof(tbl->entries[0]);
418+
if (struct_size(tbl, entries, entries) != len)
419+
return -EINVAL;
418420

419421
for (i = 0; i < entries; i++) {
420-
u16 x = le16_to_cpu((__force __le16)entry->portx_id);
421-
u16 y = le16_to_cpu((__force __le16)entry->porty_id);
422+
u16 x = le16_to_cpu((__force __le16)tbl->entries[i].portx_id);
423+
u16 y = le16_to_cpu((__force __le16)tbl->entries[i].porty_id);
422424
__le64 le_base;
423425
__le16 le_val;
424426
struct cxl_dport *dport;
@@ -448,8 +450,8 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
448450
break;
449451
}
450452

451-
le_base = (__force __le64)sslbis->entry_base_unit;
452-
le_val = (__force __le16)entry->latency_or_bandwidth;
453+
le_base = (__force __le64)tbl->sslbis_header.entry_base_unit;
454+
le_val = (__force __le16)tbl->entries[i].latency_or_bandwidth;
453455

454456
if (check_mul_overflow(le64_to_cpu(le_base),
455457
le16_to_cpu(le_val), &val))
@@ -462,8 +464,6 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
462464
sslbis->data_type,
463465
val);
464466
}
465-
466-
entry++;
467467
}
468468

469469
return 0;

0 commit comments

Comments
 (0)