Skip to content

Commit b56faef

Browse files
l1kdjbw
authored andcommitted
cxl/pci: Handle truncated CDAT entries
If truncated CDAT entries are received from a device, the concatenation of those entries constitutes a corrupt CDAT, yet is happily exposed to user space. Avoid by verifying response lengths and erroring out if truncation is detected. The last CDAT entry may still be truncated despite the checks introduced herein if the length in the CDAT header is too small. However, that is easily detectable by user space because it reaches EOF prematurely. A subsequent commit which rightsizes the CDAT response allocation closes that remaining loophole. The two lines introduced here which exceed 80 chars are shortened to less than 80 chars by a subsequent commit which migrates to a synchronous DOE API and replaces "t.task.rv" by "rc". The existing acpi_cdat_header and acpi_table_cdat struct definitions provided by ACPICA cannot be used because they do not employ __le16 or __le32 types. I believe that cannot be changed because those types are Linux-specific and ACPI is specified for little endian platforms only, hence doesn't care about endianness. So duplicate the structs. Fixes: c970060 ("cxl/port: Read CDAT table") Tested-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Lukas Wunner <lukas@wunner.de> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Cc: stable@vger.kernel.org # v6.0+ Link: https://lore.kernel.org/r/bce3aebc0e8e18a1173425a7a865b232c3912963.1678543498.git.lukas@wunner.de Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 34bafc7 commit b56faef

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

drivers/cxl/core/pci.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,8 @@ static int cxl_cdat_read_table(struct device *dev,
529529

530530
do {
531531
DECLARE_CDAT_DOE_TASK(CDAT_DOE_REQ(entry_handle), t);
532+
struct cdat_entry_header *entry;
532533
size_t entry_dw;
533-
__le32 *entry;
534534
int rc;
535535

536536
rc = pci_doe_submit_task(cdat_doe, &t.task);
@@ -539,14 +539,19 @@ static int cxl_cdat_read_table(struct device *dev,
539539
return rc;
540540
}
541541
wait_for_completion(&t.c);
542-
/* 1 DW header + 1 DW data min */
543-
if (t.task.rv < (2 * sizeof(__le32)))
542+
543+
/* 1 DW Table Access Response Header + CDAT entry */
544+
entry = (struct cdat_entry_header *)(t.response_pl + 1);
545+
if ((entry_handle == 0 &&
546+
t.task.rv != sizeof(__le32) + sizeof(struct cdat_header)) ||
547+
(entry_handle > 0 &&
548+
(t.task.rv < sizeof(__le32) + sizeof(*entry) ||
549+
t.task.rv != sizeof(__le32) + le16_to_cpu(entry->length))))
544550
return -EIO;
545551

546552
/* Get the CXL table access header entry handle */
547553
entry_handle = FIELD_GET(CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE,
548554
le32_to_cpu(t.response_pl[0]));
549-
entry = t.response_pl + 1;
550555
entry_dw = t.task.rv / sizeof(__le32);
551556
/* Skip Header */
552557
entry_dw -= 1;

drivers/cxl/cxlpci.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,20 @@ enum cxl_regloc_type {
6868
CXL_REGLOC_RBI_TYPES
6969
};
7070

71+
struct cdat_header {
72+
__le32 length;
73+
u8 revision;
74+
u8 checksum;
75+
u8 reserved[6];
76+
__le32 sequence;
77+
} __packed;
78+
79+
struct cdat_entry_header {
80+
u8 type;
81+
u8 reserved;
82+
__le16 length;
83+
} __packed;
84+
7185
int devm_cxl_port_enumerate_dports(struct cxl_port *port);
7286
struct cxl_dev_state;
7387
int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,

0 commit comments

Comments
 (0)