diff --git a/src/runtime_src/core/common/xclbin_parser.cpp b/src/runtime_src/core/common/xclbin_parser.cpp index dfd768afbea..2948f6aed2c 100644 --- a/src/runtime_src/core/common/xclbin_parser.cpp +++ b/src/runtime_src/core/common/xclbin_parser.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. * Copyright (C) 2019-2022 Xilinx, Inc * * Licensed under the Apache License, Version 2.0 (the "License"). You may @@ -835,13 +836,28 @@ get_softkernels(const axlf* top) pSection != nullptr; pSection = ::xclbin::get_axlf_section_next(top, pSection, SOFT_KERNEL)) { auto begin = reinterpret_cast(top) + pSection->m_sectionOffset; + auto section_size = pSection->m_sectionSize; + + if (section_size < sizeof(soft_kernel)) + continue; + auto soft = reinterpret_cast(begin); + if (soft->mpo_symbol_name >= section_size || + soft->mpo_name >= section_size || + soft->mpo_version >= section_size || + soft->m_image_offset >= section_size || + (soft->m_image_offset + soft->m_image_size) > section_size) + continue; + softkernel_object sko; sko.ninst = soft->m_num_instances; - sko.symbol_name = std::string(begin + soft->mpo_symbol_name); - sko.mpo_name = std::string(begin + soft->mpo_name); - sko.mpo_version = std::string(begin + soft->mpo_version); + sko.symbol_name = std::string(begin + soft->mpo_symbol_name, + strnlen(begin + soft->mpo_symbol_name, section_size - soft->mpo_symbol_name)); + sko.mpo_name = std::string(begin + soft->mpo_name, + strnlen(begin + soft->mpo_name, section_size - soft->mpo_name)); + sko.mpo_version = std::string(begin + soft->mpo_version, + strnlen(begin + soft->mpo_version, section_size - soft->mpo_version)); sko.size = soft->m_image_size; sko.sk_buf = const_cast(begin + soft->m_image_offset); // NOLINT sks.emplace_back(std::move(sko)); @@ -858,29 +874,77 @@ get_aie_partition(const axlf* top) return {}; auto topbase = reinterpret_cast(top) + pSection->m_sectionOffset; + auto section_size = pSection->m_sectionSize; + + if (section_size < sizeof(aie_partition)) + return {}; + auto aiep = reinterpret_cast(topbase); - auto scp = reinterpret_cast(topbase + aiep->info.start_columns.offset); - aie_partition_obj obj{aiep->info.column_width, {scp, scp + aiep->info.start_columns.size}, topbase + aiep->mpo_name, aiep->operations_per_cycle}; + if (aiep->mpo_name >= section_size) + return {}; + if (aiep->info.start_columns.offset >= section_size) + return {}; + size_t start_cols_bytes = static_cast(aiep->info.start_columns.size) * sizeof(uint16_t); + if (start_cols_bytes > section_size || + aiep->info.start_columns.offset > section_size - start_cols_bytes) + return {}; + if (aiep->aie_pdi.offset >= section_size) + return {}; + size_t aie_pdi_bytes = static_cast(aiep->aie_pdi.size) * sizeof(aie_pdi); + if (aie_pdi_bytes > section_size || aiep->aie_pdi.offset > section_size - aie_pdi_bytes) + return {}; + + auto scp = reinterpret_cast(topbase + aiep->info.start_columns.offset); + aie_partition_obj obj{aiep->info.column_width, {scp, scp + aiep->info.start_columns.size}, + std::string(topbase + aiep->mpo_name, strnlen(topbase + aiep->mpo_name, section_size - aiep->mpo_name)), + aiep->operations_per_cycle}; for (uint32_t i = 0; i < aiep->aie_pdi.size; i++) { - aie_pdi_obj pdiobj; - auto aiepdip = reinterpret_cast(topbase + aiep->aie_pdi.offset + i * sizeof(aie_pdi)); + size_t pdi_offset = aiep->aie_pdi.offset + i * sizeof(aie_pdi); + if (pdi_offset + sizeof(aie_pdi) > section_size) + continue; + + auto aiepdip = reinterpret_cast(topbase + pdi_offset); + + if (aiepdip->pdi_image.offset >= section_size || + (aiepdip->pdi_image.offset + aiepdip->pdi_image.size) > section_size || + aiepdip->cdo_groups.offset >= section_size) + continue; + size_t cdo_groups_bytes = static_cast(aiepdip->cdo_groups.size) * sizeof(cdo_group); + if (cdo_groups_bytes > section_size || + aiepdip->cdo_groups.offset > section_size - cdo_groups_bytes) + continue; if (aiepdip->pdi_image.size > PDI_IMAGE_MAX_SIZE) throw std::runtime_error("PDI image size too big"); + aie_pdi_obj pdiobj; pdiobj.uuid = aiepdip->uuid; pdiobj.pdi.resize(aiepdip->pdi_image.size); memcpy(pdiobj.pdi.data(), topbase + aiepdip->pdi_image.offset, pdiobj.pdi.size()); + for (uint32_t j = 0; j < aiepdip->cdo_groups.size; j++) { + size_t cdo_offset = aiepdip->cdo_groups.offset + j * sizeof(cdo_group); + if (cdo_offset + sizeof(cdo_group) > section_size) + continue; + + auto cdop = reinterpret_cast(topbase + cdo_offset); + if (cdop->mpo_name >= section_size || + cdop->dpu_kernel_ids.offset >= section_size) + continue; + size_t ids_bytes = static_cast(cdop->dpu_kernel_ids.size) * sizeof(uint64_t); + if (ids_bytes > section_size || cdop->dpu_kernel_ids.offset > section_size - ids_bytes) + continue; + std::vector dpu_kernel_ids; - auto cdop = reinterpret_cast(topbase + aiepdip->cdo_groups.offset + j * sizeof(cdo_group)); auto kernel_idp = reinterpret_cast(topbase + cdop->dpu_kernel_ids.offset); for (uint32_t k = 0; k < cdop->dpu_kernel_ids.size; ++k) dpu_kernel_ids.push_back(kernel_idp[k]); - pdiobj.cdo_groups.emplace_back({topbase + cdop->mpo_name, cdop->cdo_type, cdop->pdi_id, std::move(dpu_kernel_ids)}); + std::string cdo_name(topbase + cdop->mpo_name, + strnlen(topbase + cdop->mpo_name, section_size - cdop->mpo_name)); + pdiobj.cdo_groups.emplace_back({cdo_name, cdop->cdo_type, cdop->pdi_id, std::move(dpu_kernel_ids)}); } obj.pdis.emplace_back(std::move(pdiobj)); diff --git a/src/runtime_src/core/tools/common/xball b/src/runtime_src/core/tools/common/xball index e27740aeda4..ea9a2b8a0fb 100755 --- a/src/runtime_src/core/tools/common/xball +++ b/src/runtime_src/core/tools/common/xball @@ -148,6 +148,8 @@ exit $python_exit_code import json import os import re +import subprocess +import shlex import sys temp_python_status = sys.argv[1] @@ -198,11 +200,17 @@ for device in working_devices: print("\n") print("=====================================================================") print("%d / %d [%s] : %s" % (device_count, len(working_devices), device["bdf"], device["vbnv"])) - cmd = xrt_bin_dir + "/" + xrt_app + " --device " + device["bdf"] + " " + prog_args + cmd_list = [os.path.join(xrt_bin_dir, xrt_app), "--device", device["bdf"]] + if prog_args: + cmd_list.extend(shlex.split(prog_args)) print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") - print("Command: %s\n" % cmd) - exit_code = os.system(cmd) - + print("Command: %s\n" % " ".join(shlex.quote(a) for a in cmd_list)) + try: + exit_code = subprocess.run(cmd_list).returncode + except OSError as e: + print("Error: %s" % e) + exit_code = 1 + if exit_code == 0: print("\nCommand Return Value: 0 [Operation successful]"); passed_devices += 1 diff --git a/src/runtime_src/tools/xclbinutil/SectionAIEResourcesBin.cxx b/src/runtime_src/tools/xclbinutil/SectionAIEResourcesBin.cxx index 8d01e9f23f5..2c1b090f34c 100644 --- a/src/runtime_src/tools/xclbinutil/SectionAIEResourcesBin.cxx +++ b/src/runtime_src/tools/xclbinutil/SectionAIEResourcesBin.cxx @@ -1,6 +1,5 @@ - /** - * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved. + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may * not use this file except in compliance with the License. A copy of the @@ -22,6 +21,7 @@ #include #include #include +#include namespace XUtil = XclBinUtilities; @@ -37,9 +37,8 @@ SectionAIEResourcesBin::init::init() { auto sectionInfo = std::make_unique(AIE_RESOURCES_BIN, "AIE_RESOURCES_BIN", boost::factory()); sectionInfo->supportsSubSections = true; - sectionInfo->subSections.push_back(getSubSectionName(SubSection::obj)); - sectionInfo->subSections.push_back(getSubSectionName(SubSection::metadata)); - + sectionInfo->subSections.push_back(std::string(getSubSectionName(SubSection::obj))); + sectionInfo->subSections.push_back(std::string(getSubSectionName(SubSection::metadata))); sectionInfo->supportsIndexing = true; // Add format support empty (no support) @@ -166,6 +165,13 @@ SectionAIEResourcesBin::copyBufferUpdateMetadata(const char* _pOrigDataSection, auto pHdr = reinterpret_cast(_pOrigDataSection); + if (pHdr->mpo_name >= _origSectionSize || + pHdr->mpo_version >= _origSectionSize || + pHdr->m_image_offset >= _origSectionSize || + (pHdr->m_image_offset + pHdr->m_image_size) > _origSectionSize) { + throw std::runtime_error("ERROR: Invalid offsets in aie_resources_bin structure"); + } + XUtil::TRACE_BUF("aie_resources_bin-original", reinterpret_cast(pHdr), sizeof(aie_resources_bin)); XUtil::TRACE(boost::format("Original: \n" " mpo_name (0x%lx): '%s'\n" @@ -388,16 +394,19 @@ SectionAIEResourcesBin::writeObjImage(std::ostream& _oStream) const { XUtil::TRACE("SectionAIEResourcesBin::writeObjImage"); - // Overlay the structure - // Do we have enough room to overlay the header structure if (m_bufferSize < sizeof(aie_resources_bin)) { auto errMsg = boost::format("ERROR: Segment size (%d) is smaller than the size of the bmc structure (%d)") % m_bufferSize % sizeof(aie_resources_bin); throw std::runtime_error(errMsg.str()); } - // No look at the data auto pHdr = reinterpret_cast(m_pBuffer); + if (pHdr->m_image_offset > m_bufferSize || + pHdr->m_image_size > m_bufferSize || + pHdr->m_image_offset > m_bufferSize - pHdr->m_image_size) { + throw std::runtime_error("ERROR: Invalid m_image_offset/m_image_size in aie_resources_bin"); + } + auto pFWBuffer = reinterpret_cast(pHdr) + pHdr->m_image_offset; _oStream.write(pFWBuffer, pHdr->m_image_size); } @@ -409,8 +418,6 @@ SectionAIEResourcesBin::writeMetadata(std::ostream& _oStream) const { XUtil::TRACE("AIE_RESOURCES_BIN-METADATA"); - // Overlay the structure - // Do we have enough room to overlay the header structure if (m_bufferSize < sizeof(aie_resources_bin)) { auto errMsg = boost::format("ERROR: Segment size (%d) is smaller than the size of the aie_resources_bin structure (%d)") % m_bufferSize % sizeof(aie_resources_bin); throw std::runtime_error(errMsg.str()); @@ -418,29 +425,33 @@ SectionAIEResourcesBin::writeMetadata(std::ostream& _oStream) const auto pHdr = reinterpret_cast(m_pBuffer); + auto safe_str = [this, pHdr](uint32_t off) -> std::string { + if (off >= m_bufferSize) + return ""; + return std::string(reinterpret_cast(pHdr) + off, + strnlen(reinterpret_cast(pHdr) + off, m_bufferSize - off)); + }; + XUtil::TRACE(boost::format("Original: \n" " mpo_name (0x%lx): '%s'\n" " m_image_offset: 0x%lx, m_image_size: 0x%lx\n" " mpo_version (0x%lx): '%s'\n" " m_start_column (0x%lx): '%s'\n" " m_num_columns (0x%lx): '%s'") - % pHdr->mpo_name % (reinterpret_cast(pHdr) + pHdr->mpo_name) + % pHdr->mpo_name % safe_str(pHdr->mpo_name) % pHdr->m_image_offset % pHdr->m_image_size - % pHdr->mpo_version % (reinterpret_cast(pHdr) + pHdr->mpo_version) - % pHdr->m_start_column % (reinterpret_cast(pHdr) + pHdr->m_start_column) - % pHdr->m_num_columns % (reinterpret_cast(pHdr) + pHdr->m_num_columns)); + % pHdr->mpo_version % safe_str(pHdr->mpo_version) + % pHdr->m_start_column % safe_str(pHdr->m_start_column) + % pHdr->m_num_columns % safe_str(pHdr->m_num_columns)); - // Convert the data from the binary format to JSON boost::property_tree::ptree ptAieResourcesBin; - - ptAieResourcesBin.put("name", reinterpret_cast(pHdr) + pHdr->mpo_name); - ptAieResourcesBin.put("version", reinterpret_cast(pHdr) + pHdr->mpo_version); - ptAieResourcesBin.put("start_column", reinterpret_cast(pHdr) + pHdr->m_start_column); - ptAieResourcesBin.put("num_columns", reinterpret_cast(pHdr) + pHdr->m_num_columns); + ptAieResourcesBin.put("name", safe_str(pHdr->mpo_name)); + ptAieResourcesBin.put("version", safe_str(pHdr->mpo_version)); + ptAieResourcesBin.put("start_column", safe_str(pHdr->m_start_column)); + ptAieResourcesBin.put("num_columns", safe_str(pHdr->m_num_columns)); boost::property_tree::ptree root; root.put_child("aie_resources_bin_metadata", ptAieResourcesBin); - boost::property_tree::write_json(_oStream, root); }