oem-ibm: avoid file read range integer overflow Fix IBM OEM file-read range validation to avoid overflowing the 32-bit offset + length boundary check. A PLDM peer could issue ReadFile with a valid small offset and a large length, such as offset=1 and length=UINT32_MAX. The previous check computed offset + length directly, allowing the sum to wrap and skip the clamp logic. In the generic read path this could trigger an attempt to allocate a response near 4 GiB, causing std::bad_alloc and terminating pldmd. Use the overflow-safe form length > fileSize - offset after the existing offset >= fileSize validation. This preserves the existing clamp-at-EOF behavior while fixing all affected IBM file-read paths, including generic, DMA, and file-by-type reads. Change-Id: I774e0a16b9bf855b73b1456cec9a00e93fcc4cad Signed-off-by: Manjeet Singh <itsmanjeet1998@gmail.com>
diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp index 044ba0f..4fb722d 100644 --- a/oem/ibm/libpldmresponder/file_io.cpp +++ b/oem/ibm/libpldmresponder/file_io.cpp
@@ -421,7 +421,7 @@ return response; } - if (offset + length > fileSize) + if (length > fileSize - offset) { length = fileSize - offset; } @@ -687,7 +687,7 @@ return response; } - if (offset + length > fileSize) + if (length > fileSize - offset) { length = fileSize - offset; }
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp index aedee02..2c41c9e 100644 --- a/oem/ibm/libpldmresponder/file_io_by_type.cpp +++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp
@@ -89,7 +89,7 @@ "OFFSET", offset, "SIZE", fileSize, "FILE_HANDLE", fileHandle); return PLDM_DATA_OUT_OF_RANGE; } - if (offset + length > fileSize) + if (length > fileSize - offset) { length = fileSize - offset; } @@ -199,7 +199,7 @@ return PLDM_DATA_OUT_OF_RANGE; } - if (offset + length > fileSize) + if (length > fileSize - offset) { length = fileSize - offset; }
diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.cpp b/oem/ibm/libpldmresponder/file_io_type_pel.cpp index 7d3daf9..ae4181b 100644 --- a/oem/ibm/libpldmresponder/file_io_type_pel.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
@@ -152,7 +152,7 @@ "OFFSET", offset, "SIZE", fileSize, "FILE_HANDLE", fileHandle); return PLDM_DATA_OUT_OF_RANGE; } - if (offset + length > fileSize) + if (length > static_cast<uint64_t>(fileSize - offset)) { length = fileSize - offset; }
diff --git a/oem/ibm/test/libpldmresponder_fileio_test.cpp b/oem/ibm/test/libpldmresponder_fileio_test.cpp index b59b52a..0ce1d02 100644 --- a/oem/ibm/test/libpldmresponder_fileio_test.cpp +++ b/oem/ibm/test/libpldmresponder_fileio_test.cpp
@@ -712,6 +712,15 @@ ASSERT_EQ(0, memcmp(response->file_data, buffer.data(), (fileSize - request->offset))); + // A large length must be clamped without wrapping offset + length. + request->offset = 1; + request->length = UINT32_MAX; + responseMsg = handler.readFile(requestMsgPtr, payload_length); + response = reinterpret_cast<pldm_read_file_resp*>( + responseMsg.data() + sizeof(pldm_msg_hdr)); + ASSERT_EQ(response->completion_code, PLDM_SUCCESS); + ASSERT_EQ(response->length, fileSize - request->offset); + table.clear(); } @@ -996,4 +1005,11 @@ ASSERT_EQ(length, in.size()); ASSERT_EQ(response.size(), in.size()); ASSERT_EQ(std::equal(in.begin(), in.end(), response.begin()), true); + + length = UINT32_MAX; + response.clear(); + rc = handler.readFile(tmplt, 1, length, response); + ASSERT_EQ(rc, PLDM_SUCCESS); + ASSERT_EQ(length, in.size() - 1); + ASSERT_EQ(response.size(), in.size() - 1); }