From 505d5131ca977447ebd2e1249d8fea17131e2f9b Mon Sep 17 00:00:00 2001 From: Andrew Bradford Date: Mon, 6 Jul 2026 12:08:27 -0400 Subject: [PATCH] zynqmp: Fix release-then-use segfault on bootimage import The v2026.1 smart-pointer migration replaced raw pointers with unique_ptr, but two spots kept dereferencing a unique_ptr after calling release() on it to hand ownership to a std::list. release() nulls the unique_ptr, so the subsequent field reads deref a null pointer and crash. This regressed `bootgen -arch zynqmp -image ` when the BIF contains a [bootimage] partition (e.g. presigned-FSBL flows using -generate_hashes), which worked in v2025.1 with raw pointers. Signed-off-by: Andrew Bradford --- zynqmp/src/bootimage-zynqmp.cpp | 6 +++--- zynqmp/src/imageheadertable-zynqmp.cpp | 21 ++++++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/zynqmp/src/bootimage-zynqmp.cpp b/zynqmp/src/bootimage-zynqmp.cpp index 5c23f63..5730811 100755 --- a/zynqmp/src/bootimage-zynqmp.cpp +++ b/zynqmp/src/bootimage-zynqmp.cpp @@ -329,7 +329,7 @@ void ZynqMpBootImage::ParseBootImage(PartitionBifOptions* it) { PartitionHeader* ph = (*partHdr); uint32_t encrPartLen = ph->GetEncryptedPartitionLength(); - size_t imageAuthBlock = image->GetAuthBlock(); + size_t imageAuthBlock = newImage->GetAuthBlock(); int acSize = 1; if (imageAuthBlock != 0) { @@ -342,7 +342,7 @@ void ZynqMpBootImage::ParseBootImage(PartitionBifOptions* it) if (ph->IsAuthCertPresent()) { LOG_INFO("Loading AC context for section %s ", ph->section->Name.c_str()); - image->SetAuthenticationType(Authentication::RSA); + newImage->SetAuthenticationType(Authentication::RSA); options.bifOptions->SetHeaderAC(true); /* load in previous certificate data */ for (int i = 0; i < acSize; i++) @@ -360,7 +360,7 @@ void ZynqMpBootImage::ParseBootImage(PartitionBifOptions* it) } } } - offset = image->GetNextImageHeaderOffset(); + offset = newImage->GetNextImageHeaderOffset(); } while (offset != 0); } diff --git a/zynqmp/src/imageheadertable-zynqmp.cpp b/zynqmp/src/imageheadertable-zynqmp.cpp index 0877f22..0c2cfd8 100755 --- a/zynqmp/src/imageheadertable-zynqmp.cpp +++ b/zynqmp/src/imageheadertable-zynqmp.cpp @@ -113,6 +113,9 @@ ZynqMpImageHeader::ZynqMpImageHeader(std::ifstream& ifs) hdr->ReadHeader(ifs); hdr->ReadData(ifs); + /* Ownership transfers to partitionHeaderList; keep a non-owning pointer + to read the header fields below, since release() nulls the unique_ptr */ + ZynqMpPartitionHeader* hdrPtr = hdr.get(); partitionHeaderList.push_back(hdr.release()); Bootloader = false; @@ -120,14 +123,14 @@ ZynqMpImageHeader::ZynqMpImageHeader(std::ifstream& ifs) Offset = 0; Reserve = 0; - destCpu = (DestinationCPU::Type)hdr->GetDestinationCpu(); - exceptionLevel = (ExceptionLevel::Type)hdr->GetExceptionLevel(); - trustzone = (TrustZone::Type)hdr->GetTrustZone(); - early_handoff = hdr->GetEarlyHandoff(); - hivec = hdr->GetHivec(); - authBlock = hdr->GetAuthblock(); + destCpu = (DestinationCPU::Type)hdrPtr->GetDestinationCpu(); + exceptionLevel = (ExceptionLevel::Type)hdrPtr->GetExceptionLevel(); + trustzone = (TrustZone::Type)hdrPtr->GetTrustZone(); + early_handoff = hdrPtr->GetEarlyHandoff(); + hivec = hdrPtr->GetHivec(); + authBlock = hdrPtr->GetAuthblock(); - switch (hdr->GetDestinationDevice()) + switch (hdrPtr->GetDestinationDevice()) { case DestinationDevice::DEST_DEV_PS: SetDomain(Domain::PS); @@ -145,10 +148,10 @@ ZynqMpImageHeader::ZynqMpImageHeader(std::ifstream& ifs) break; case DestinationDevice::DEST_DEV_NONE: - LOG_DEBUG(DEBUG_STAMP, "Bad destination field in imported partition header - %s", hdr->section->Name.c_str()); + LOG_DEBUG(DEBUG_STAMP, "Bad destination field in imported partition header - %s", hdrPtr->section->Name.c_str()); LOG_ERROR("Failure parsing imported bootimage"); } - offset += hdr->GetPartitionHeaderSize(); + offset += hdrPtr->GetPartitionHeaderSize(); } }