|
29 | 29 | #include <asm/mmu_context.h>
|
30 | 30 | #include <asm/pgtable_areas.h>
|
31 | 31 |
|
| 32 | +#include <xen/xen.h> |
| 33 | + |
32 | 34 | /* This is a multiple of PAGE_SIZE. */
|
33 | 35 | #define LDT_SLOT_STRIDE (LDT_ENTRIES * LDT_ENTRY_SIZE)
|
34 | 36 |
|
@@ -543,6 +545,37 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
|
543 | 545 | return bytecount;
|
544 | 546 | }
|
545 | 547 |
|
| 548 | +static bool allow_16bit_segments(void) |
| 549 | +{ |
| 550 | + if (!IS_ENABLED(CONFIG_X86_16BIT)) |
| 551 | + return false; |
| 552 | + |
| 553 | +#ifdef CONFIG_XEN_PV |
| 554 | + /* |
| 555 | + * Xen PV does not implement ESPFIX64, which means that 16-bit |
| 556 | + * segments will not work correctly. Until either Xen PV implements |
| 557 | + * ESPFIX64 and can signal this fact to the guest or unless someone |
| 558 | + * provides compelling evidence that allowing broken 16-bit segments |
| 559 | + * is worthwhile, disallow 16-bit segments under Xen PV. |
| 560 | + */ |
| 561 | + if (xen_pv_domain()) { |
| 562 | + static DEFINE_MUTEX(xen_warning); |
| 563 | + static bool warned; |
| 564 | + |
| 565 | + mutex_lock(&xen_warning); |
| 566 | + if (!warned) { |
| 567 | + pr_info("Warning: 16-bit segments do not work correctly in a Xen PV guest\n"); |
| 568 | + warned = true; |
| 569 | + } |
| 570 | + mutex_unlock(&xen_warning); |
| 571 | + |
| 572 | + return false; |
| 573 | + } |
| 574 | +#endif |
| 575 | + |
| 576 | + return true; |
| 577 | +} |
| 578 | + |
546 | 579 | static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
|
547 | 580 | {
|
548 | 581 | struct mm_struct *mm = current->mm;
|
@@ -574,7 +607,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
|
574 | 607 | /* The user wants to clear the entry. */
|
575 | 608 | memset(&ldt, 0, sizeof(ldt));
|
576 | 609 | } else {
|
577 |
| - if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) { |
| 610 | + if (!ldt_info.seg_32bit && !allow_16bit_segments()) { |
578 | 611 | error = -EINVAL;
|
579 | 612 | goto out;
|
580 | 613 | }
|
|
0 commit comments