mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
x86/vm86/32: Remove VM86_SCREEN_BITMAP support
The implementation was rather buggy. It unconditionally marked PTEs read-only, even for VM_SHARED mappings. I'm not sure whether this is actually a problem, but it certainly seems unwise. More importantly, it released the mmap lock before flushing the TLB, which could allow a racing CoW operation to falsely believe that the underlying memory was not writable. I can't find any users at all of this mechanism, so just remove it. Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Borislav Petkov <bp@suse.de> Acked-by: Stas Sergeev <stsp2@yandex.ru> Link: https://lkml.kernel.org/r/f3086de0babcab36f69949b5780bde851f719bc8.1611078018.git.luto@kernel.org
This commit is contained in:
parent
b86cb29287
commit
8ece53ef7f
@ -36,7 +36,6 @@ struct vm86 {
|
||||
unsigned long saved_sp0;
|
||||
|
||||
unsigned long flags;
|
||||
unsigned long screen_bitmap;
|
||||
unsigned long cpu_type;
|
||||
struct revectored_struct int_revectored;
|
||||
struct revectored_struct int21_revectored;
|
||||
|
@ -97,7 +97,7 @@ struct revectored_struct {
|
||||
struct vm86_struct {
|
||||
struct vm86_regs regs;
|
||||
unsigned long flags;
|
||||
unsigned long screen_bitmap;
|
||||
unsigned long screen_bitmap; /* unused, preserved by vm86() */
|
||||
unsigned long cpu_type;
|
||||
struct revectored_struct int_revectored;
|
||||
struct revectored_struct int21_revectored;
|
||||
@ -106,7 +106,7 @@ struct vm86_struct {
|
||||
/*
|
||||
* flags masks
|
||||
*/
|
||||
#define VM86_SCREEN_BITMAP 0x0001
|
||||
#define VM86_SCREEN_BITMAP 0x0001 /* no longer supported */
|
||||
|
||||
struct vm86plus_info_struct {
|
||||
unsigned long force_return_for_pic:1;
|
||||
|
@ -134,7 +134,11 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
|
||||
unsafe_put_user(regs->ds, &user->regs.ds, Efault_end);
|
||||
unsafe_put_user(regs->fs, &user->regs.fs, Efault_end);
|
||||
unsafe_put_user(regs->gs, &user->regs.gs, Efault_end);
|
||||
unsafe_put_user(vm86->screen_bitmap, &user->screen_bitmap, Efault_end);
|
||||
|
||||
/*
|
||||
* Don't write screen_bitmap in case some user had a value there
|
||||
* and expected it to remain unchanged.
|
||||
*/
|
||||
|
||||
user_access_end();
|
||||
|
||||
@ -160,49 +164,6 @@ Efault:
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
static void mark_screen_rdonly(struct mm_struct *mm)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
spinlock_t *ptl;
|
||||
pgd_t *pgd;
|
||||
p4d_t *p4d;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
int i;
|
||||
|
||||
mmap_write_lock(mm);
|
||||
pgd = pgd_offset(mm, 0xA0000);
|
||||
if (pgd_none_or_clear_bad(pgd))
|
||||
goto out;
|
||||
p4d = p4d_offset(pgd, 0xA0000);
|
||||
if (p4d_none_or_clear_bad(p4d))
|
||||
goto out;
|
||||
pud = pud_offset(p4d, 0xA0000);
|
||||
if (pud_none_or_clear_bad(pud))
|
||||
goto out;
|
||||
pmd = pmd_offset(pud, 0xA0000);
|
||||
|
||||
if (pmd_trans_huge(*pmd)) {
|
||||
vma = find_vma(mm, 0xA0000);
|
||||
split_huge_pmd(vma, pmd, 0xA0000);
|
||||
}
|
||||
if (pmd_none_or_clear_bad(pmd))
|
||||
goto out;
|
||||
pte = pte_offset_map_lock(mm, pmd, 0xA0000, &ptl);
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (pte_present(*pte))
|
||||
set_pte(pte, pte_wrprotect(*pte));
|
||||
pte++;
|
||||
}
|
||||
pte_unmap_unlock(pte, ptl);
|
||||
out:
|
||||
mmap_write_unlock(mm);
|
||||
flush_tlb_mm_range(mm, 0xA0000, 0xA0000 + 32*PAGE_SIZE, PAGE_SHIFT, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int do_vm86_irq_handling(int subfunction, int irqnumber);
|
||||
static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus);
|
||||
|
||||
@ -282,6 +243,15 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
|
||||
offsetof(struct vm86_struct, int_revectored)))
|
||||
return -EFAULT;
|
||||
|
||||
|
||||
/* VM86_SCREEN_BITMAP had numerous bugs and appears to have no users. */
|
||||
if (v.flags & VM86_SCREEN_BITMAP) {
|
||||
char comm[TASK_COMM_LEN];
|
||||
|
||||
pr_info_once("vm86: '%s' uses VM86_SCREEN_BITMAP, which is no longer supported\n", get_task_comm(comm, current));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&vm86regs, 0, sizeof(vm86regs));
|
||||
|
||||
vm86regs.pt.bx = v.regs.ebx;
|
||||
@ -302,7 +272,6 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
|
||||
vm86regs.gs = v.regs.gs;
|
||||
|
||||
vm86->flags = v.flags;
|
||||
vm86->screen_bitmap = v.screen_bitmap;
|
||||
vm86->cpu_type = v.cpu_type;
|
||||
|
||||
if (copy_from_user(&vm86->int_revectored,
|
||||
@ -370,9 +339,6 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
|
||||
update_task_stack(tsk);
|
||||
preempt_enable();
|
||||
|
||||
if (vm86->flags & VM86_SCREEN_BITMAP)
|
||||
mark_screen_rdonly(tsk->mm);
|
||||
|
||||
memcpy((struct kernel_vm86_regs *)regs, &vm86regs, sizeof(vm86regs));
|
||||
return regs->ax;
|
||||
}
|
||||
|
@ -262,25 +262,6 @@ void arch_sync_kernel_mappings(unsigned long start, unsigned long end)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Did it hit the DOS screen memory VA from vm86 mode?
|
||||
*/
|
||||
static inline void
|
||||
check_v8086_mode(struct pt_regs *regs, unsigned long address,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
#ifdef CONFIG_VM86
|
||||
unsigned long bit;
|
||||
|
||||
if (!v8086_mode(regs) || !tsk->thread.vm86)
|
||||
return;
|
||||
|
||||
bit = (address - 0xA0000) >> PAGE_SHIFT;
|
||||
if (bit < 32)
|
||||
tsk->thread.vm86->screen_bitmap |= 1 << bit;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool low_pfn(unsigned long pfn)
|
||||
{
|
||||
return pfn < max_low_pfn;
|
||||
@ -335,15 +316,6 @@ KERN_ERR
|
||||
"******* Disabling USB legacy in the BIOS may also help.\n";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* No vm86 mode in 64-bit mode:
|
||||
*/
|
||||
static inline void
|
||||
check_v8086_mode(struct pt_regs *regs, unsigned long address,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
static int bad_address(void *p)
|
||||
{
|
||||
unsigned long dummy;
|
||||
@ -1416,8 +1388,6 @@ good_area:
|
||||
mm_fault_error(regs, hw_error_code, address, fault);
|
||||
return;
|
||||
}
|
||||
|
||||
check_v8086_mode(regs, address, tsk);
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_user_addr_fault);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user