I forget to mention: I agree with you on #2 - (2) The comparison is not appropriate here (after the patch); it is too strict.
BASE_4GB is an exclusive limit, hence the pre-patch status is good. But MAX_ADDRESS is an inclusive limit, so the condition should be CpuStart + PhysicalSize - 1 <= MAX_ADDRESS Because CpuStart and PhysicalSize are UINT64, it may cause problem when the source is CpuStart+PhysicalSize==0x10000000000000000, theoretically. So I think we should update DxeCore and PeiCore as well - to use Start+Size - 1 <= MAX_ADDRESS. Thank you Yao Jiewen From: Yao, Jiewen Sent: Wednesday, June 29, 2016 9:02 PM To: Laszlo Ersek <[email protected]>; [email protected] Cc: Kinney, Michael D <[email protected]>; Fan, Jeff <[email protected]>; Yao, Jiewen <[email protected]> Subject: RE: [edk2] [PATCH] MdeModulePkg/PiSmmCore: Replace BASE_4GB with MAX_ADDRESS check. HI Laszlo I appreciate your careful review. I would like to clarify why we did not consider adding check for integer overflow. The EDKII security model is that: 1) We trust any internal data communication before EndOfDxe. We have to, because the SMM core has to trust the component runs before SMM, and construct SMM. 2) We do not trust any external data communication after EndOfDxe. We should not, external data might be from an untrusted source. That is why we need lots of check in PE/COFF library, SMM communication buffer, UEFI authenticated variable, etc. Based upon above assumption, SmramRanges is from a trusted source. There is *no need* to add security check, we just need add function check. You can refer to how DxeCore parse resource description hob: if (PhitHob->EfiFreeMemoryTop > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) { continue; } if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (EFI_PHYSICAL_ADDRESS)MAX_ADDRESS) { continue; } You can refer to how PeiCore parse the resource description hob: if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) { continue; } if (NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) { continue; } if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS && ResourceHob->ResourceLength > TotalReservedMemorySize && PeiLoadFixAddressIsMemoryRangeAvailable(PrivateData, ResourceHob)) { Go back to your suggestion. I have no problem to adopt you suggestion on using below format. It is not harmful. if (PhysicalSize <= MAX_ADDRESS && CpuStart - 1 <= MAX_ADDRESS - PhysicalSize) { But one thing I have to mention is that: If we do not trust CpuStart and PhysicalSize, we will have big problem, because CPU driver need use these data to set SMRR, which is the basic of SMM security. We have assume CpuStart and PhysicalSize is set correctly. Thank you Yao Jiewen From: edk2-devel [mailto:[email protected]] On Behalf Of Laszlo Ersek Sent: Wednesday, June 29, 2016 8:30 PM To: Yao, Jiewen <[email protected]<mailto:[email protected]>>; [email protected]<mailto:[email protected]> Cc: Kinney, Michael D <[email protected]<mailto:[email protected]>>; Fan, Jeff <[email protected]<mailto:[email protected]>> Subject: Re: [edk2] [PATCH] MdeModulePkg/PiSmmCore: Replace BASE_4GB with MAX_ADDRESS check. On 06/29/16 04:29, Jiewen Yao wrote: > PI specification Vol 4 - SMM does not have any limitation of BASE_4GB for SMM. > So we should replace BASE_4GB check with MAX_ADDRESS check to make sure > the SMM memory is accessible by SMM Core. > > Cc: Jeff Fan <[email protected]<mailto:[email protected]>> > Cc: Michael D Kinney > <[email protected]<mailto:[email protected]>> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiewen Yao <[email protected]<mailto:[email protected]>> > --- > MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c | 2 +- > MdeModulePkg/Core/PiSmmCore/Pool.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c > b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c > index acfcc83..3788bd5 100644 > --- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c > +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c > @@ -1556,7 +1556,7 @@ SmmIplEntry ( > } > > if (gSmmCorePrivate->SmramRanges[Index].CpuStart >= BASE_1MB) { > - if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + > gSmmCorePrivate->SmramRanges[Index].PhysicalSize) <= BASE_4GB) { > + if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + > gSmmCorePrivate->SmramRanges[Index].PhysicalSize) <= MAX_ADDRESS) { > if (gSmmCorePrivate->SmramRanges[Index].PhysicalSize >= MaxSize) { > MaxSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize; > mCurrentSmramRange = &gSmmCorePrivate->SmramRanges[Index]; > diff --git a/MdeModulePkg/Core/PiSmmCore/Pool.c > b/MdeModulePkg/Core/PiSmmCore/Pool.c > index 761988e..e493fd2 100644 > --- a/MdeModulePkg/Core/PiSmmCore/Pool.c > +++ b/MdeModulePkg/Core/PiSmmCore/Pool.c > @@ -67,7 +67,7 @@ SmmInitializeMemoryServices ( > } > > if (SmramRanges[Index].CpuStart >= BASE_1MB) { > - if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) > <= BASE_4GB) { > + if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) > <= MAX_ADDRESS) { > if (SmramRanges[Index].PhysicalSize >= MaxSize) { > MaxSize = SmramRanges[Index].PhysicalSize; > CurrentSmramRangesIndex = Index; > I have one question and two suggestions: (1) These checks refer to the SMRAM ranges that are reported by EFI_SMM_ACCESS2_PROTOCOL.GetCapabilities() member function, correct? So whatever worked before should continue to work. (2) The comparison is not appropriate here (after the patch); it is too strict. BASE_4GB is an exclusive limit, hence the pre-patch status is good. But MAX_ADDRESS is an inclusive limit, so the condition should be CpuStart + PhysicalSize - 1 <= MAX_ADDRESS (3) The addition in (2) can easily overflow (wrap around) before the comparison. Therefore I recommend the following steps instead: * First, reorder the LHS of the formula in (2): (CpuStart - 1) + PhysicalSize <= MAX_ADDRESS The subtraction is safe, because we have an outermost condition that ensures (CpuStart >= BASE_1MB). * Second, subtract PhysicalSize from both sides: CpuStart - 1 <= MAX_ADDRESS - PhysicalSize Considering X64 only, this could be the final form: MAX_ADDRESS is MAX_UINT64, so the subtraction on the right hand side is safe too. * However, that is not the case on Ia32. There we must compare MAX_ADDRESS vs. PhysicalSize explicitly. Which leaves us with: if (PhysicalSize <= MAX_ADDRESS && CpuStart - 1 <= MAX_ADDRESS - PhysicalSize) { /* ... */ } This is the final form that I'm proposing for the patch. The first condition is always true on X64, but it has "teeth" on Ia32. Then, once the first condition is true, the RHS of the second condition will not underflow, and we can safely do the comparison. (The LHS of the second condition will not underflow due to the argument about CpuStart above.) Thanks Laszlo _______________________________________________ edk2-devel mailing list [email protected]<mailto:[email protected]> https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

