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). |