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++; |
