]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Ingo Molnar <mingo@elte.hu> |
2 | References: bnc#439348 | |
3 | Subject: x86: use the right protections for split-up pagetables | |
4 | Patch-mainline: yes | |
5 | Git: 07a66d7c53a538e1a9759954a82bb6c07365eff9 | |
6 | ||
7 | Steven Rostedt found a bug in where in his modified kernel | |
8 | ftrace was unable to modify the kernel text, due to the PMD | |
9 | itself having been marked read-only as well in | |
10 | split_large_page(). | |
11 | ||
12 | The fix, suggested by Linus, is to not try to 'clone' the | |
13 | reference protection of a huge-page, but to use the standard | |
14 | (and permissive) page protection bits of KERNPG_TABLE. | |
15 | ||
16 | The 'cloning' makes sense for the ptes but it's a confused and | |
17 | incorrect concept at the page table level - because the | |
18 | pagetable entry is a set of all ptes and hence cannot | |
19 | 'clone' any single protection attribute - the ptes can be any | |
20 | mixture of protections. | |
21 | ||
22 | With the permissive KERNPG_TABLE, even if the pte protections | |
23 | get changed after this point (due to ftrace doing code-patching | |
24 | or other similar activities like kprobes), the resulting combined | |
25 | protections will still be correct and the pte's restrictive | |
26 | (or permissive) protections will control it. | |
27 | ||
28 | Also update the comment. | |
29 | ||
30 | This bug was there for a long time but has not caused visible | |
31 | problems before as it needs a rather large read-only area to | |
32 | trigger. Steve possibly hacked his kernel with some really | |
33 | large arrays or so. Anyway, the bug is definitely worth fixing. | |
34 | ||
35 | [ Huang Ying also experienced problems in this area when writing | |
36 | the EFI code, but the real bug in split_large_page() was not | |
37 | realized back then. ] | |
38 | ||
39 | Reported-by: Steven Rostedt <rostedt@goodmis.org> | |
40 | Reported-by: Huang Ying <ying.huang@intel.com> | |
41 | Acked-by: Linus Torvalds <torvalds@linux-foundation.org> | |
42 | Signed-off-by: Ingo Molnar <mingo@elte.hu> | |
43 | ||
44 | Acked-by: Nick Piggin <npiggin@suse.de> | |
45 | ||
46 | Automatically created from "patches.arch/x86-pageattr-pmd-permission-fix.patch" by xen-port-patches.py | |
47 | ||
48 | --- sle11-2009-03-16.orig/arch/x86/mm/pageattr-xen.c 2009-03-16 16:39:50.000000000 +0100 | |
49 | +++ sle11-2009-03-16/arch/x86/mm/pageattr-xen.c 2009-03-16 16:46:27.000000000 +0100 | |
50 | @@ -573,22 +573,17 @@ static int split_large_page(pte_t *kpte, | |
51 | set_pte(&pbase[i], pfn_pte_ma(mfn, ref_prot)); | |
52 | ||
53 | /* | |
54 | - * Install the new, split up pagetable. Important details here: | |
55 | + * Install the new, split up pagetable. | |
56 | * | |
57 | - * On Intel the NX bit of all levels must be cleared to make a | |
58 | - * page executable. See section 4.13.2 of Intel 64 and IA-32 | |
59 | - * Architectures Software Developer's Manual). | |
60 | - * | |
61 | - * Mark the entry present. The current mapping might be | |
62 | - * set to not present, which we preserved above. | |
63 | + * We use the standard kernel pagetable protections for the new | |
64 | + * pagetable protections, the actual ptes set above control the | |
65 | + * primary protection behavior: | |
66 | */ | |
67 | if (!xen_feature(XENFEAT_writable_page_tables) && | |
68 | HYPERVISOR_update_va_mapping((unsigned long)pbase, | |
69 | mk_pte(base, PAGE_KERNEL_RO), 0)) | |
70 | BUG(); | |
71 | - ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte))); | |
72 | - pgprot_val(ref_prot) |= _PAGE_PRESENT; | |
73 | - __set_pmd_pte(kpte, address, level, mk_pte(base, ref_prot)); | |
74 | + __set_pmd_pte(kpte, address, level, mk_pte(base, __pgprot(_KERNPG_TABLE))); | |
75 | base = NULL; | |
76 | ||
77 | out_unlock: |