diff options
-rw-r--r-- | arch/x86/include/asm/desc.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/ldt.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/tls.c | 11 | ||||
-rw-r--r-- | tools/testing/selftests/x86/ldt_gdt.c | 3 |
4 files changed, 11 insertions, 12 deletions
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index bc359dd2f7f6..85e23bb7b34e 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h | |||
@@ -21,6 +21,8 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in | |||
21 | 21 | ||
22 | desc->type = (info->read_exec_only ^ 1) << 1; | 22 | desc->type = (info->read_exec_only ^ 1) << 1; |
23 | desc->type |= info->contents << 2; | 23 | desc->type |= info->contents << 2; |
24 | /* Set the ACCESS bit so it can be mapped RO */ | ||
25 | desc->type |= 1; | ||
24 | 26 | ||
25 | desc->s = 1; | 27 | desc->s = 1; |
26 | desc->dpl = 0x3; | 28 | desc->dpl = 0x3; |
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c index 9629c5d8267a..579cc4a66fdf 100644 --- a/arch/x86/kernel/ldt.c +++ b/arch/x86/kernel/ldt.c | |||
@@ -158,7 +158,12 @@ map_ldt_struct(struct mm_struct *mm, struct ldt_struct *ldt, int slot) | |||
158 | ptep = get_locked_pte(mm, va, &ptl); | 158 | ptep = get_locked_pte(mm, va, &ptl); |
159 | if (!ptep) | 159 | if (!ptep) |
160 | return -ENOMEM; | 160 | return -ENOMEM; |
161 | pte = pfn_pte(pfn, __pgprot(__PAGE_KERNEL & ~_PAGE_GLOBAL)); | 161 | /* |
162 | * Map it RO so the easy to find address is not a primary | ||
163 | * target via some kernel interface which misses a | ||
164 | * permission check. | ||
165 | */ | ||
166 | pte = pfn_pte(pfn, __pgprot(__PAGE_KERNEL_RO & ~_PAGE_GLOBAL)); | ||
162 | set_pte_at(mm, va, ptep, pte); | 167 | set_pte_at(mm, va, ptep, pte); |
163 | pte_unmap_unlock(ptep, ptl); | 168 | pte_unmap_unlock(ptep, ptl); |
164 | } | 169 | } |
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index 9a9c9b076955..a5b802a12212 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c | |||
@@ -93,17 +93,10 @@ static void set_tls_desc(struct task_struct *p, int idx, | |||
93 | cpu = get_cpu(); | 93 | cpu = get_cpu(); |
94 | 94 | ||
95 | while (n-- > 0) { | 95 | while (n-- > 0) { |
96 | if (LDT_empty(info) || LDT_zero(info)) { | 96 | if (LDT_empty(info) || LDT_zero(info)) |
97 | memset(desc, 0, sizeof(*desc)); | 97 | memset(desc, 0, sizeof(*desc)); |
98 | } else { | 98 | else |
99 | fill_ldt(desc, info); | 99 | fill_ldt(desc, info); |
100 | |||
101 | /* | ||
102 | * Always set the accessed bit so that the CPU | ||
103 | * doesn't try to write to the (read-only) GDT. | ||
104 | */ | ||
105 | desc->type |= 1; | ||
106 | } | ||
107 | ++info; | 100 | ++info; |
108 | ++desc; | 101 | ++desc; |
109 | } | 102 | } |
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c index 0304ffb714f2..1aef72df20a1 100644 --- a/tools/testing/selftests/x86/ldt_gdt.c +++ b/tools/testing/selftests/x86/ldt_gdt.c | |||
@@ -122,8 +122,7 @@ static void check_valid_segment(uint16_t index, int ldt, | |||
122 | * NB: Different Linux versions do different things with the | 122 | * NB: Different Linux versions do different things with the |
123 | * accessed bit in set_thread_area(). | 123 | * accessed bit in set_thread_area(). |
124 | */ | 124 | */ |
125 | if (ar != expected_ar && | 125 | if (ar != expected_ar && ar != (expected_ar | AR_ACCESSED)) { |
126 | (ldt || ar != (expected_ar | AR_ACCESSED))) { | ||
127 | printf("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n", | 126 | printf("[FAIL]\t%s entry %hu has AR 0x%08X but expected 0x%08X\n", |
128 | (ldt ? "LDT" : "GDT"), index, ar, expected_ar); | 127 | (ldt ? "LDT" : "GDT"), index, ar, expected_ar); |
129 | nerrs++; | 128 | nerrs++; |