|
46 | 46 | #define PAGE_OFFSET 0xfff0000000000000ul |
47 | 47 | #define PHYS_OFFSET 0ul |
48 | 48 |
|
49 | | -// VA_BITS candidates for Q_VA_BITS (finite-set lattice). 48 and 52 are the two |
50 | | -// configurations whose PAGE_OFFSET the directmap-range rule discriminates. |
51 | | -#define VA_BITS_CANDIDATES {48ul, 52ul} |
| 49 | +// VA_BITS candidates for Q_VA_BITS (finite-set lattice), smallest first. Each |
| 50 | +// arm64 paging config has its own VA_BITS (hence its own PAGE_OFFSET / |
| 51 | +// KIMAGE_VADDR geometry): 4K 3-level=39 (common on Android), 64K 2-level=42, |
| 52 | +// 16K 3-level=47, 4K/16K 4-level=48, and 52-bit LVA (VA_BITS_MIN still 48). |
| 53 | +#define VA_BITS_CANDIDATES {39ul, 42ul, 47ul, 48ul, 52ul} |
| 54 | +// Smallest supported VA_BITS — gives the highest (widest-accepting) linear-map |
| 55 | +// ceiling for region validation. |
| 56 | +#define ARM64_VA_BITS_MIN_SUPPORTED 39ul |
| 57 | + |
| 58 | +// VA_BITS-derived geometry, kept in one place so the layout math is not |
| 59 | +// duplicated across mmap_arm64_va_bits, arm64_coupling_validate, and |
| 60 | +// arm64_va_bits_from_directmap. arm64 PAGE_OFFSET = -(1<<VA_BITS); the linear |
| 61 | +// map occupies [PAGE_OFFSET, _PAGE_END), _PAGE_END = -(1<<(VA_BITS-1)). Pure |
| 62 | +// functions of VA_BITS, not randomized. |
| 63 | +static inline unsigned long arm64_page_offset_for(unsigned long va_bits) { |
| 64 | + return -(1UL << va_bits); |
| 65 | +} |
| 66 | +static inline unsigned long arm64_page_end_for(unsigned long va_bits) { |
| 67 | + return -(1UL << (va_bits - 1)); |
| 68 | +} |
52 | 69 |
|
53 | 70 | // On arm64, PHYS_OFFSET is runtime (= memstart_addr, randomized at boot), so |
54 | 71 | // the compile-time formula is NOT a sound runtime directmap projection; |
|
151 | 168 | // https://elixir.bootlin.com/linux/v6.12/source/arch/arm64/include/asm/memory.h#L46 |
152 | 169 | // Use v6.2+ value (2G module region, current default). |
153 | 170 | #define KIMAGE_VADDR 0xffff800080000000ul |
| 171 | +// Module-region size (KIMAGE_VADDR = _PAGE_END(VA_BITS_MIN) + this). v6.2+ uses |
| 172 | +// SZ_2G; older kernels used 128M/256M. rule_arm64_text_base derives |
| 173 | +// KIMAGE_VADDR for the resolved VA_BITS_MIN as arm64_page_end_for(VA_BITS_MIN) |
| 174 | +// + this — for VA_BITS_MIN=48 that reproduces KIMAGE_VADDR above. The version |
| 175 | +// spread is the pin's residual imprecision (inferred confidence; a real leak |
| 176 | +// overrides). |
| 177 | +#define ARM64_MODULE_REGION_SIZE (2ul * GB) |
154 | 178 |
|
155 | 179 | // See docs/kaslr.md "Default text base and KASLR alignment" for all |
156 | 180 | // architectures. Kernel source: arch/arm64/kernel/vmlinux.lds.S, |
157 | 181 | // arch/arm64/include/asm/memory.h |
158 | 182 | #define KERNEL_VIRT_TEXT_DEFAULT (KIMAGE_VADDR + IMAGE_BASE_OFFSET) |
159 | 183 |
|
160 | | -/* KASLR-off ⇒ pin contract. |
161 | | - * |
162 | | - * SCOPE: KASLD models arm64 only for VA_BITS_MIN == 48 — the {48, 52} configs |
163 | | - * (4K/16K 4-level, plus 52-bit LVA, whose VA_BITS_MIN is still 48). On those, |
164 | | - * no-KASLR text sits at KIMAGE_VADDR + IMAGE_BASE_OFFSET = the 48-bit default |
165 | | - * below, independent of the runtime VA_BITS (which only moves PAGE_OFFSET / the |
166 | | - * linear map), so this pin is correct. |
167 | | - * |
168 | | - * Sub-48 builds land at a DIFFERENT KIMAGE_VADDR and are NOT supported: |
169 | | - * 4K 3-level → VA_BITS 39 (common on Android), KIMAGE_VADDR |
170 | | - * 0xffffffc080000000 64K 2-level → VA_BITS 42 16K 3-level → VA_BITS 47, |
171 | | - * KIMAGE_VADDR 0xffffc00080000000 KASLD cannot even detect them: |
172 | | - * mmap_arm64_va_bits probes only 1<<48 (so every VA_BITS <= 48 reads as 48) and |
173 | | - * Q_VA_BITS models only {48, 52}. And the pin's window-containment backstop |
174 | | - * does NOT catch the mismatch — the 48-bit default coincides with the |
175 | | - * honest-top floor (KASLR_VIRT_TEXT_MIN_WIDE == KIMAGE_VADDR), so it is always |
176 | | - * "in window." A sub-48 no-KASLR kernel therefore mis-pins (and its window is |
177 | | - * wrong regardless of KASLR). Real support is a VA_BITS overhaul: see |
178 | | - * dev/research/arm64-va-bits-min.md. */ |
179 | | -#define KASLR_DISABLED_PINS_VIRT_TEXT 1 |
| 184 | +/* KASLR-off pin is LAYOUT-DEPENDENT on arm64: KIMAGE_VADDR varies with |
| 185 | + * VA_BITS_MIN (= min(VA_BITS, 48)), so the no-KASLR text base is not a single |
| 186 | + * compile-time constant. The generic virt_kaslr_disabled_pin (one fixed |
| 187 | + * default) is therefore opted OUT; rule_arm64_text_base owns the text base, |
| 188 | + * deriving VA_BITS_MIN from the resolved PAGE_OFFSET and narrowing/pinning to |
| 189 | + * KIMAGE_VADDR(VA_BITS_MIN) — correct for VA_BITS 39/42/47/48/52, not just 48. |
| 190 | + * Same shape as rule_riscv64_text_base. When PAGE_OFFSET is unresolved (no |
| 191 | + * probe result, no leak) it does not pin — the honest window stays wide |
| 192 | + * (sound). */ |
| 193 | +#define KASLR_DISABLED_PINS_VIRT_TEXT 0 |
180 | 194 | #define KASLD_ARCH_DEFAULT_TEXT_BASE_DEFINED 1 |
181 | 195 | static inline unsigned long arch_default_text_base(void) { |
182 | 196 | return KERNEL_VIRT_TEXT_DEFAULT; |
@@ -219,6 +233,14 @@ static inline unsigned long arch_default_text_base(void) { |
219 | 233 | * the v6.6 upper edge (96 TiB) and the v6.12+ upper edge (~94.5 TiB). */ |
220 | 234 | #define KASLR_VIRT_TEXT_MIN_WIDE KIMAGE_VADDR |
221 | 235 |
|
| 236 | +/* Honest-top CEILING for Q_VIRT_IMAGE_BASE. KASLR_VIRT_TEXT_MAX is the 48-bit |
| 237 | + * formula's window top (kept for entropy/slot reporting); it is too low for |
| 238 | + * sub-48 configs, whose KIMAGE_VADDR is HIGHER (39-bit → 0xffffffc080000000). |
| 239 | + * Widen the honest top to the validation ceiling KERNEL_VIRT_TEXT_MAX, which |
| 240 | + * admits every supported VA_BITS_MIN's text base, so a sub-48 text leak is not |
| 241 | + * falsely excluded. Widen-only, never-narrow — same discipline as the floor. */ |
| 242 | +#define KASLR_VIRT_TEXT_MAX_WIDE KERNEL_VIRT_TEXT_MAX |
| 243 | + |
222 | 244 | #define KASLR_SUPPORTED 1 |
223 | 245 |
|
224 | 246 | #endif /* KASLD_ARM64_H */ |
0 commit comments