patch-1.3.2 linux/arch/i386/kernel/vm86.c

Next file: linux/arch/i386/lib/Makefile
Previous file: linux/arch/i386/kernel/sys_i386.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.1/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
@@ -217,6 +217,8 @@
 
 static inline int is_revectored(int nr, struct revectored_struct * bitmap)
 {
+	if (verify_area(VERIFY_READ, bitmap, 256/8) < 0)
+		return 1;
 	__asm__ __volatile__("btl %2,%%fs:%1\n\tsbbl %0,%0"
 		:"=r" (nr)
 		:"m" (*bitmap),"r" (nr));
@@ -298,22 +300,32 @@
 
 static void do_int(struct vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp)
 {
-	unsigned short seg = get_fs_word((void *) ((i<<2)+2));
+	unsigned short *intr_ptr, seg;
 
-	if (seg == BIOSSEG || regs->cs == BIOSSEG ||
-	    is_revectored(i, &current->tss.vm86_info->int_revectored))
-		return_to_32bit(regs, VM86_INTx + (i << 8));
+	if (regs->cs == BIOSSEG)
+		goto cannot_handle;
+	if (is_revectored(i, &current->tss.vm86_info->int_revectored))
+		goto cannot_handle;
 	if (i==0x21 && is_revectored(AH(regs),&current->tss.vm86_info->int21_revectored))
-		return_to_32bit(regs, VM86_INTx + (i << 8));
+		goto cannot_handle;
+	intr_ptr = (unsigned short *) (i << 2);
+	if (verify_area(VERIFY_READ, intr_ptr, 4) < 0)
+		goto cannot_handle;
+	seg = get_fs_word(intr_ptr+1);
+	if (seg == BIOSSEG)
+		goto cannot_handle;
 	pushw(ssp, sp, get_vflags(regs));
 	pushw(ssp, sp, regs->cs);
 	pushw(ssp, sp, IP(regs));
 	regs->cs = seg;
 	SP(regs) -= 6;
-	IP(regs) = get_fs_word((void *) (i<<2));
+	IP(regs) = get_fs_word(intr_ptr+0);
 	clear_TF(regs);
 	clear_IF(regs);
 	return;
+
+cannot_handle:
+	return_to_32bit(regs, VM86_INTx + (i << 8));
 }
 
 void handle_vm86_debug(struct vm86_regs * regs, long error_code)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this