Memory layout: Difference between revisions

No edit summary
Line 18: Line 18:
On version [[1.0.0]], the initial binaries loaded into memory by the kernel always have the upper 32-bits as all-zero, so there are 6 fewer bits of layout randomization.  
On version [[1.0.0]], the initial binaries loaded into memory by the kernel always have the upper 32-bits as all-zero, so there are 6 fewer bits of layout randomization.  


= Kernel Implementation of Userland ASLR =
== ASLR Implementation ==


== 1.0.0 ==
=== 1.0.0 ===


  if (AddressSpaceType == 2) {
  if (AddressSpaceType == 2) {
Line 52: Line 52:


= Kernel =
= Kernel =
  Granule size for TTBR0*_EL1 is 4KB.
For more details, see [[#Notes]]. Here comes a summary.
  TTBR0_EL1 vmem starts at vaddr 0x0.
 
  vmem end-addr for TTBR1_EL1 is 0xffffffffffffffff. vmem start-addr for TTBR1_EL1 is 0xFFFFFFF000000000.
PXN bit is set in the MMU descriptor for userland code pages. This means that userland code pages are not executable in kernel mode (equivalent to SMEP on x86).
  T0SZ = 31. Hence, bit-size of the TTBR0*_EL1 vmem region is 33. (0x0000000200000000)
 
  T1SZ = 28. Hence, bit-size of the TTBR1*_EL1 vmem region is 36. (0x0000001000000000)
For userland pages, the kernel has same access as userland (either both are read-only or both are read-write). This rule has one exception: pages that are mapped unreadable in usermode are still forced readable from kernelmode.
 
  Note: ARM config for TTBR0 is presumably configured for userland later.
 
  See arm-doc for "Table D4-25 Translation table entry addresses when using the 4KB translation granule".
 
  See arm-doc for "Overview of VMSAv8-64 address translation using the 4KB translation granule".
 
  See arm-doc for "Table D4-11 TCR.TnSZ values and IA ranges, 4K granule with no concatenation of tables".
  Both TTBR*_EL1 use "Initial lookup level" 1. Therefore, the TTBR*_EL1 tables are level1.
 
  Due to T*SZ, Stage1/Stage2 translation for the initial table(level1) are the same, except Stage2 uses hard-coded T0SZ.
  Basically, the table is accessed as: ((u64*)tablebase)[<IA[y:30]>], where y = (37-T*SZ)+26. That is, starting at bit "y" ending(inclusive) at bit30. For TTBR0*_EL1, y = 32, while for TTBR1_EL1 y = 35.
  Hence, for TTBR0, index=((vaddr>>30) & 0x7), and for TTBR1, index=((vaddr>>30) & 0x3f).


As of [[2.0.0]] KASLR is not used.
As of [[2.0.0]] KASLR is not used.


== [[2.0.0]] ==
== [[2.0.0]] ==
"Vector Base Address Register (EL1)" = 0xfffffff7ffc50800.
The table for TTBR0 only contains the following:
* Vmem 0x80000000 is mapped to physmem 0x80000000, using a size loaded from a register. This is only done when: "endaddr = 0x7fffffff + size; if(endaddr >= 0x80000001){...}"
** The size is loaded from: "(u32 *0x70019050 & 0x3fff) << 20;"
** The value written to the MMU-table descriptor is: "physaddr | val | 0x709;". val is 1<<52 when "tmp>>34" is non-zero and when "if((physaddr & 0x3c0000000) == 0)", otherwise val=0. tmp=size at the start and increased by 0xffffffffc0000000 each loop iteration. physaddr is increased by 0x40000000 each loop iteration.
TTBR1:
* vmem 0xFFFFFFF800000000 is mapped to physmem 0x80000000. Similar to above, except tmp=0 due to wrap-around, etc. The chunksize used when increasing addr is 0xfffffff840000000, with another +=0x40000000 separate from the addr cmp for the loop.
** "endaddr = 0x3fffffff + (<size from above> | 0xfffffff800000000); enaddr = (endaddr & 0xffffffffc0000000)-1; if(endaddr >= 0xfffffff800000001){<map mem>}"
* Initializes level2 pagetable descriptor for vmem 0xFFFFFFF7C0000000. descriptor = 0x3 | physaddr. physaddr is core-specific.
* Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FFC00000. descriptor = 0x3 | physaddr. physaddr is core-specific.
* The content of the pagetable for the following level3 mmutables are not initialized in the main mmutable-init func. descriptor = 0x8007c003(0x3 | <physaddr tablebase>). tablebase=0x8007c000.
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FEE00000. physaddr = tablebase + (0x1<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF000000. physaddr = tablebase + (0x2<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF200000. physaddr = tablebase + (0x3<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FFA00000. physaddr = tablebase + (0x7<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FEC00000. physaddr = tablebase.
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF400000. physaddr = tablebase + (0x4<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF600000. physaddr = tablebase + (0x5<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF800000. physaddr = tablebase + (0x6<<12).
{| class="wikitable" border="1"
{| class="wikitable" border="1"
|-
|-
! Cores
! Virtual
! Virtual
! Physical
! Physical
Line 107: Line 71:
! Description
! Description
|-
|-
| 0xFFFFFFF800000000-... || 0x80000000 || ... || ? || ? || Raw DRAM access
| All || 0xFFFFFFF800000000-... || 0x80000000 || ... || ? || ? || Raw DRAM access
|-
|-
| 0xFFFFFFF7FFC00000-0xFFFFFFF7FFC62FFF || 0x800A0000 || 0x63000 || 0x78B || R-X || Kernel .text
| All || 0xFFFFFFF7FFC00000-0xFFFFFFF7FFC62FFF || 0x800A0000 || 0x63000 || 0x78B || R-X || Kernel .text
|-
|-
| 0xFFFFFFF7FFC63000-0xFFFFFFF7FFC65FFF || 0x80103000 || 0x3000 || 0x6000000000078B || R-- || Kernel .rodata
| All || 0xFFFFFFF7FFC63000-0xFFFFFFF7FFC65FFF || 0x80103000 || 0x3000 || 0x6000000000078B || R-- || Kernel .rodata
|-
|-
| 0xFFFFFFF7FFC66000-0xFFFFFFF7FFC6EFFF || 0x80106000 || 0x9000 || 0x6000000000070B || RW- || Kernel .data+.bss
| All || 0xFFFFFFF7FFC66000-0xFFFFFFF7FFC6EFFF || 0x80106000 || 0x9000 || 0x6000000000070B || RW- || Kernel .data+.bss
|-
|-
| 0xFFFFFFF7FFDCA000-0xFFFFFFF7FFDCAFFF || 0x80060000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDCA000-0xFFFFFFF7FFDCAFFF || 0x80060000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDCB000-0xFFFFFFF7FFDCBFFF || 0x80061000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDCB000-0xFFFFFFF7FFDCBFFF || 0x80061000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDCE000-0xFFFFFFF7FFDCEFFF || 0x80068000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDCE000-0xFFFFFFF7FFDCEFFF || 0x80068000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDD4000-0xFFFFFFF7FFDD4FFF || 0x80062000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDD4000-0xFFFFFFF7FFDD4FFF || 0x80062000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDD5000-0xFFFFFFF7FFDD5FFF || 0x80063000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDD5000-0xFFFFFFF7FFDD5FFF || 0x80063000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDD8000-0xFFFFFFF7FFDD8FFF || 0x8006A000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDD8000-0xFFFFFFF7FFDD8FFF || 0x8006A000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDD9000-0xFFFFFFF7FFDD9FFF || 0x8006B000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDD9000-0xFFFFFFF7FFDD9FFF || 0x8006B000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDDE000-0xFFFFFFF7FFDDEFFF || 0x80064000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDDE000-0xFFFFFFF7FFDDEFFF || 0x80064000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDDF000-0xFFFFFFF7FFDDFFFF || 0x80065000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDDF000-0xFFFFFFF7FFDDFFFF || 0x80065000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDE2000-0xFFFFFFF7FFDE2FFF || 0x8006C000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDE2000-0xFFFFFFF7FFDE2FFF || 0x8006C000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDE3000-0xFFFFFFF7FFDE3FFF || 0x8006D000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDE3000-0xFFFFFFF7FFDE3FFF || 0x8006D000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDE8000-0xFFFFFFF7FFDE8FFF || 0x80066000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDE8000-0xFFFFFFF7FFDE8FFF || 0x80066000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDE9000-0xFFFFFFF7FFDE9FFF || 0x80067000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDE9000-0xFFFFFFF7FFDE9FFF || 0x80067000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDCF000-0xFFFFFFF7FFDCFFFF || 0x80069000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDCF000-0xFFFFFFF7FFDCFFFF || 0x80069000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDEC000-0xFFFFFFF7FFDECFFF || 0x8006E000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDEC000-0xFFFFFFF7FFDECFFF || 0x8006E000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDED000-0xFFFFFFF7FFDEDFFF || 0x8006F000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDED000-0xFFFFFFF7FFDEDFFF || 0x8006F000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDD2000-0xFFFFFFF7FFDD2FFF || 0x80070000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDD2000-0xFFFFFFF7FFDD2FFF || 0x80070000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDDC000-0xFFFFFFF7FFDDCFFF || 0x80071000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDDC000-0xFFFFFFF7FFDDCFFF || 0x80071000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDE6000-0xFFFFFFF7FFDE6FFF || 0x80072000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDE6000-0xFFFFFFF7FFDE6FFF || 0x80072000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDF0000-0xFFFFFFF7FFDF0FFF || 0x80073000 || 0x1000 || 0x6000000000070B || RW- ||
| All || 0xFFFFFFF7FFDF0000-0xFFFFFFF7FFDF0FFF || 0x80073000 || 0x1000 || 0x6000000000070B || RW- ||
|-
|-
| 0xFFFFFFF7FFDC6000-0xFFFFFFF7FFDC6FFF || 0x70019000 || 0x1000 || 0x60000000000607 || RW- || MC IO
| All || 0xFFFFFFF7FFDC6000-0xFFFFFFF7FFDC6FFF || 0x70019000 || 0x1000 || 0x60000000000607 || RW- || MC IO
|-
|-
| 0xFFFFFFF7FFDC4000-0xFFFFFFF7FFDC4FFF || 0x7001C000 || 0x1000 || 0x60000000000607 || RW- || MC0 IO
| All || 0xFFFFFFF7FFDC4000-0xFFFFFFF7FFDC4FFF || 0x7001C000 || 0x1000 || 0x60000000000607 || RW- || MC0 IO
|-
|-
| 0xFFFFFFF7FFDC2000-0xFFFFFFF7FFDC2FFF || 0x7001D000 || 0x1000 || 0x60000000000607 || RW- || MC1 IO
| All || 0xFFFFFFF7FFDC2000-0xFFFFFFF7FFDC2FFF || 0x7001D000 || 0x1000 || 0x60000000000607 || RW- || MC1 IO
|-
|-
| 0xFFFFFFF7FFDC0000-0xFFFFFFF7FFDC0FFF || 0x60006000 || 0x1000 || 0x60000000000607 || RW- || CLK IO
| All || 0xFFFFFFF7FFDC0000-0xFFFFFFF7FFDC0FFF || 0x60006000 || 0x1000 || 0x60000000000607 || RW- || CLK IO
|-
|-
| 0xFFFFFFF7FFDC8000-0xFFFFFFF7FFDC8FFF || 0x70006000 || 0x1000 || 0x60000000000607 || RW- || UART-A IO
| All || 0xFFFFFFF7FFDC8000-0xFFFFFFF7FFDC8FFF || 0x70006000 || 0x1000 || 0x60000000000607 || RW- || UART-A IO
|-
|-
| 0xFFFFFFF7FFDFB000-0xFFFFFFF7FFDFBFFF || 0x50041000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Distributor IO
| All || 0xFFFFFFF7FFDFB000-0xFFFFFFF7FFDFBFFF || 0x50041000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Distributor IO
|-
|-
| 0xFFFFFFF7FFDFD000-0xFFFFFFF7FFDFDFFF || 0x50042000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Controller IO
| All || 0xFFFFFFF7FFDFD000-0xFFFFFFF7FFDFDFFF || 0x50042000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Controller IO
|}
|}


Line 433: Line 397:
| TZRAM
| TZRAM
|}
|}
= Notes =
== 2.0.0 ==
  Granule size for TTBR0*_EL1 is 4KB.
  TTBR0_EL1 vmem starts at vaddr 0x0.
  vmem end-addr for TTBR1_EL1 is 0xffffffffffffffff. vmem start-addr for TTBR1_EL1 is 0xFFFFFFF000000000.
  T0SZ = 31. Hence, bit-size of the TTBR0*_EL1 vmem region is 33. (0x0000000200000000)
  T1SZ = 28. Hence, bit-size of the TTBR1*_EL1 vmem region is 36. (0x0000001000000000)
 
  Note: ARM config for TTBR0 is presumably configured for userland later.
 
  See arm-doc for "Table D4-25 Translation table entry addresses when using the 4KB translation granule".
 
  See arm-doc for "Overview of VMSAv8-64 address translation using the 4KB translation granule".
 
  See arm-doc for "Table D4-11 TCR.TnSZ values and IA ranges, 4K granule with no concatenation of tables".
  Both TTBR*_EL1 use "Initial lookup level" 1. Therefore, the TTBR*_EL1 tables are level1.
 
  Due to T*SZ, Stage1/Stage2 translation for the initial table(level1) are the same, except Stage2 uses hard-coded T0SZ.
  Basically, the table is accessed as: ((u64*)tablebase)[<IA[y:30]>], where y = (37-T*SZ)+26. That is, starting at bit "y" ending(inclusive) at bit30. For TTBR0*_EL1, y = 32, while for TTBR1_EL1 y = 35.
  Hence, for TTBR0, index=((vaddr>>30) & 0x7), and for TTBR1, index=((vaddr>>30) & 0x3f).
"Vector Base Address Register (EL1)" = 0xfffffff7ffc50800.
The table for TTBR0 only contains the following:
* Vmem 0x80000000 is mapped to physmem 0x80000000, using a size loaded from a register. This is only done when: "endaddr = 0x7fffffff + size; if(endaddr >= 0x80000001){...}"
** The size is loaded from: "(u32 *0x70019050 & 0x3fff) << 20;"
** The value written to the MMU-table descriptor is: "physaddr | val | 0x709;". val is 1<<52 when "tmp>>34" is non-zero and when "if((physaddr & 0x3c0000000) == 0)", otherwise val=0. tmp=size at the start and increased by 0xffffffffc0000000 each loop iteration. physaddr is increased by 0x40000000 each loop iteration.
TTBR1:
* vmem 0xFFFFFFF800000000 is mapped to physmem 0x80000000. Similar to above, except tmp=0 due to wrap-around, etc. The chunksize used when increasing addr is 0xfffffff840000000, with another +=0x40000000 separate from the addr cmp for the loop.
** "endaddr = 0x3fffffff + (<size from above> | 0xfffffff800000000); enaddr = (endaddr & 0xffffffffc0000000)-1; if(endaddr >= 0xfffffff800000001){<map mem>}"
* Initializes level2 pagetable descriptor for vmem 0xFFFFFFF7C0000000. descriptor = 0x3 | physaddr. physaddr is core-specific.
* Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FFC00000. descriptor = 0x3 | physaddr. physaddr is core-specific.
* The content of the pagetable for the following level3 mmutables are not initialized in the main mmutable-init func. descriptor = 0x8007c003(0x3 | <physaddr tablebase>). tablebase=0x8007c000.
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FEE00000. physaddr = tablebase + (0x1<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF000000. physaddr = tablebase + (0x2<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF200000. physaddr = tablebase + (0x3<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FFA00000. physaddr = tablebase + (0x7<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FEC00000. physaddr = tablebase.
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF400000. physaddr = tablebase + (0x4<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF600000. physaddr = tablebase + (0x5<<12).
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF800000. physaddr = tablebase + (0x6<<12).