Skip to content

Commit

Permalink
StandaloneMmPkg: Arm: Call TextUpdate after ReadwriteUpdater
Browse files Browse the repository at this point in the history
The StandaloneMm implementation for Arm sets up the stack in
the early startup code using the data section reserved in the
assembly code.

When TF-A loads the StandaloneMM binary in the DRAM it maps
the entire StandaloneMM memory region as Read Only.

Therefore, the initial startup assembly code updates the mem
permissions of the stack region to Read Write.

However, when the StandaloneMmCore is loaded the function
UpdateMmFoundationPeCoffPermissions() starts applying the
memory permissions based on the PE COFF sections as below:

A. If the section is not executable, it first removes the
executable permission of the section by calling TextUpdate().
TextUpdate() is the StandaloneMM MMU library function
ArmSetMemoryRegionNoExec().

B. It then checks if the section is writable, and if it is
it calls ReadWriteUpdater(), which invokes the StandaloneMM
MMU library function ArmClearMemoryRegionReadOnly() to make
the section writable.

However, this results in the stack being made read-only
between A and B. To understand this please see the following
flow.

1. TF-A sets the entire StandaloneMM region as Read Only.
2. The stack is reserved in the data section by the early
   assembly entry point code.
    +--------------------+   <--- Start of Data Section
    |                    |
    |  Data Section      |
    |                    |
    | +----------------+ |   <--- Stack region
    | |   Stack        | |
    | +----------------+ |
    |                    |
    +--------------------+

3. The StanaloneMM early entry point code updates the
   attributes of the stack to Read Write.
4. When UpdateMmFoundationPeCoffPermissions() sets the
   permission of the data section to remove the Execute
   attribute, it calls ArmSetMemoryRegionNoExec().
5. The ArmSetMemoryRegionNoExec() implementation gets the
   attributes of the first granule which is at the start
   of the data section, then clears the execute permission
   and applies the attribute for the entire data section.
6. Since TF-A has mapped the entire section as read only
   the first granule of the data section is read only and
   therefore the stack region attributes are changed to
   Read Only no execute.
7. Since the stack is read only after point A any updates
   to the stack result in an exception.
To resolve this issue, reverse the order of the PE COFF
section permission initialisation (i.e. step A and B) so
that the Read Write attribute is first set for the data
section, and then the execute permission is removed.

By doing this the write permission for the stack region
is preserved.

Signed-off-by: Levi Yun <[email protected]>
  • Loading branch information
LeviYeoReum committed Sep 25, 2024
1 parent 1cd5b84 commit 4ccfe5b
Showing 1 changed file with 2 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ UpdateMmFoundationPeCoffPermissions (
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
Base = ImageBase + SectionHeader.VirtualAddress;

TextUpdater (Base, SectionHeader.Misc.VirtualSize);

if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_WRITE) != 0) {
ReadWriteUpdater (Base, SectionHeader.Misc.VirtualSize);
DEBUG ((
Expand All @@ -146,6 +144,8 @@ UpdateMmFoundationPeCoffPermissions (
ImageContext->ImageAddress
));
}

TextUpdater (Base, SectionHeader.Misc.VirtualSize);
} else {
DEBUG ((
DEBUG_INFO,
Expand Down

0 comments on commit 4ccfe5b

Please sign in to comment.