Skip to content

Commit

Permalink
x86/vm86/32: Remove VM86_SCREEN_BITMAP support
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Acked-by: Stas Sergeev <[email protected]>
Link: https://lkml.kernel.org/r/f3086de0babcab36f69949b5780bde851f719bc8.1611078018.git.luto@kernel.org
  • Loading branch information
amluto authored and suryasaimadhu committed Jan 21, 2021
1 parent b86cb29 commit 8ece53e
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 81 deletions.
1 change: 0 additions & 1 deletion arch/x86/include/asm/vm86.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/include/uapi/asm/vm86.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
62 changes: 14 additions & 48 deletions arch/x86/kernel/vm86_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -160,49 +164,6 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
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);

Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down
30 changes: 0 additions & 30 deletions arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1416,8 +1388,6 @@ void do_user_addr_fault(struct pt_regs *regs,
mm_fault_error(regs, hw_error_code, address, fault);
return;
}

check_v8086_mode(regs, address, tsk);
}
NOKPROBE_SYMBOL(do_user_addr_fault);

Expand Down

0 comments on commit 8ece53e

Please sign in to comment.