public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Manfred Spraul <manfred@colorfullife.com>
To: linux-kernel@vger.kernel.org
Cc: stas.orel@mailcity.com
Subject: [CFT] error checking for VM86 instruction emulation
Date: Tue, 25 Dec 2001 19:43:17 +0100	[thread overview]
Message-ID: <3C28C8C5.29C433ED@colorfullife.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 458 bytes --]

The emulation code for the instructions that cannot be executed in vm86
mode directly (iretd, pushf and a few others) accesses user space memory
without an exception handler. This can cause a kernel oops if the stack
pointer points to non-present or read-only memory areas.

The attached patch adds these handlers, but I can't test them properly.
Under 2.5.2-pre1, dosemu still runs.

The patch applies to both 2.4.17 and 2.2.20. Please test it.

--
	Manfred

[-- Attachment #2: patch-vm86 --]
[-- Type: text/plain, Size: 9012 bytes --]

--- 2.5/arch/i386/kernel/vm86.c	Fri Dec 21 21:28:52 2001
+++ build-2.5/arch/i386/kernel/vm86.c	Tue Dec 25 18:44:25 2001
@@ -326,74 +326,176 @@
  * Boy are these ugly, but we need to do the correct 16-bit arithmetic.
  * Gcc makes a mess of it, so we do it inline and use non-obvious calling
  * conventions..
+ * FIXME: is VM86_UNKNOWN really the correct return code?
  */
-#define pushb(base, ptr, val) \
-__asm__ __volatile__( \
-	"decw %w0\n\t" \
-	"movb %2,0(%1,%0)" \
-	: "=r" (ptr) \
-	: "r" (base), "q" (val), "0" (ptr))
-
-#define pushw(base, ptr, val) \
-__asm__ __volatile__( \
-	"decw %w0\n\t" \
-	"movb %h2,0(%1,%0)\n\t" \
-	"decw %w0\n\t" \
-	"movb %b2,0(%1,%0)" \
-	: "=r" (ptr) \
-	: "r" (base), "q" (val), "0" (ptr))
-
-#define pushl(base, ptr, val) \
-__asm__ __volatile__( \
-	"decw %w0\n\t" \
-	"rorl $16,%2\n\t" \
-	"movb %h2,0(%1,%0)\n\t" \
-	"decw %w0\n\t" \
-	"movb %b2,0(%1,%0)\n\t" \
-	"decw %w0\n\t" \
-	"rorl $16,%2\n\t" \
-	"movb %h2,0(%1,%0)\n\t" \
-	"decw %w0\n\t" \
-	"movb %b2,0(%1,%0)" \
-	: "=r" (ptr) \
-	: "r" (base), "q" (val), "0" (ptr))
-
-#define popb(base, ptr) \
-({ unsigned long __res; \
-__asm__ __volatile__( \
-	"movb 0(%1,%0),%b2\n\t" \
-	"incw %w0" \
-	: "=r" (ptr), "=r" (base), "=q" (__res) \
-	: "0" (ptr), "1" (base), "2" (0)); \
-__res; })
-
-#define popw(base, ptr) \
-({ unsigned long __res; \
-__asm__ __volatile__( \
-	"movb 0(%1,%0),%b2\n\t" \
-	"incw %w0\n\t" \
-	"movb 0(%1,%0),%h2\n\t" \
-	"incw %w0" \
-	: "=r" (ptr), "=r" (base), "=q" (__res) \
-	: "0" (ptr), "1" (base), "2" (0)); \
-__res; })
-
-#define popl(base, ptr) \
-({ unsigned long __res; \
-__asm__ __volatile__( \
-	"movb 0(%1,%0),%b2\n\t" \
-	"incw %w0\n\t" \
-	"movb 0(%1,%0),%h2\n\t" \
-	"incw %w0\n\t" \
-	"rorl $16,%2\n\t" \
-	"movb 0(%1,%0),%b2\n\t" \
-	"incw %w0\n\t" \
-	"movb 0(%1,%0),%h2\n\t" \
-	"incw %w0\n\t" \
-	"rorl $16,%2" \
-	: "=r" (ptr), "=r" (base), "=q" (__res) \
-	: "0" (ptr), "1" (base)); \
-__res; })
+#define pushb(base, ptr, val, regs) \
+	do { \
+		int err; \
+		__asm__ __volatile__(				\
+			"decw %w0\n\t"				\
+			"1: movb %3,0(%2,%0)\n\t"		\
+			"xor %1,%1\n\t"				\
+			"2:\n"					\
+			".section .fixup,\"ax\"\n\t"		\
+			"3:	movl $1,%1\n\t"			\
+			"	jmp 2b\n\t"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 1b,3b\n"			\
+			".previous"				\
+			: "=r" (ptr), "=r" (err)		\
+			: "r" (base), "q" (val), "0" (ptr));	\
+		if (err) \
+			return_to_32bit(regs, VM86_UNKNOWN); \
+	} while(0)
+
+#define pushw(base, ptr, val, regs) \
+	do { \
+		int err; \
+		__asm__ __volatile__(				\
+			"decw %w0\n\t"				\
+			"1: movb %h3,0(%2,%0)\n\t"		\
+			"decw %w0\n\t"				\
+			"2: movb %b3,0(%2,%0)\n\t"		\
+			"xor %1,%1\n\t"				\
+			"3:\n"					\
+			".section .fixup,\"ax\"\n\t"		\
+			"4:	movl $1,%1\n\t"			\
+			"	jmp 3b\n\t"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 1b,4b\n"			\
+			"	.long 2b,4b\n"			\
+			".previous"				\
+			: "=r" (ptr), "=r" (err)		\
+			: "r" (base), "q" (val), "0" (ptr));	\
+		if (err) \
+			return_to_32bit(regs, VM86_UNKNOWN); \
+	} while(0)
+
+#define pushl(base, ptr, val, regs) \
+	do { \
+		int err; \
+		__asm__ __volatile__(				\
+			"decw %w0\n\t"				\
+			"rorl $16,%3\n\t"			\
+			"1: movb %h3,0(%2,%0)\n\t"		\
+			"decw %w0\n\t"				\
+			"2: movb %b3,0(%2,%0)\n\t"		\
+			"decw %w0\n\t"				\
+			"rorl $16,%3\n\t"			\
+			"3: movb %h3,0(%2,%0)\n\t"		\
+			"decw %w0\n\t"				\
+			"4: movb %b3,0(%2,%0)\n\t"		\
+			"xor %1,%1\n\t"				\
+			"5:\n"					\
+			".section .fixup,\"ax\"\n\t"		\
+			"6:	movl $1,%1\n\t"			\
+			"	jmp 5b\n\t"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 1b,6b\n"			\
+			"	.long 2b,6b\n"			\
+			"	.long 3b,6b\n"			\
+			"	.long 4b,6b\n"			\
+			".previous"				\
+			: "=r" (ptr), "=r" (err)		\
+			: "r" (base), "q" (val), "0" (ptr));	\
+		if (err) \
+			return_to_32bit(regs, VM86_UNKNOWN); \
+	} while(0)
+
+#define popb(base, ptr, regs) \
+	({ \
+	 	unsigned long __res; \
+	 	unsigned int err; \
+		__asm__ __volatile__( \
+			"1:movb 0(%1,%0),%b2\n\t"		\
+			"incw %w0\n\t"				\
+			"xor %3,%3\n\t"				\
+			"2:\n"					\
+			".section .fixup,\"ax\"\n\t"		\
+			"3:	movl $1,%1\n\t"			\
+			"	jmp 2b\n\t"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 1b,3b\n"			\
+			".previous"				\
+			: "=r" (ptr), "=r" (base), "=q" (__res), \
+				"=r" (err) \
+			: "0" (ptr), "1" (base), "2" (0)); \
+		if (err) \
+			return_to_32bit(regs, VM86_UNKNOWN); \
+		__res; \
+	})
+
+#define popw(base, ptr, regs) \
+	({ \
+	 	unsigned long __res; \
+	 	unsigned int err; \
+		__asm__ __volatile__( \
+			"1:movb 0(%1,%0),%b2\n\t"		\
+			"incw %w0\n\t"				\
+			"2:movb 0(%1,%0),%h2\n\t"		\
+			"incw %w0\n\t"				\
+			"xor %3,%3\n\t"				\
+			"3:\n"					\
+			".section .fixup,\"ax\"\n\t"		\
+			"4:	movl $1,%1\n\t"			\
+			"	jmp 3b\n\t"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 1b,4b\n"			\
+			"	.long 2b,4b\n"			\
+			".previous"				\
+			: "=r" (ptr), "=r" (base), "=q" (__res), \
+				"=r" (err) \
+			: "0" (ptr), "1" (base), "2" (0)); \
+		if (err) \
+			return_to_32bit(regs, VM86_UNKNOWN); \
+		__res; \
+	})
+
+#define popl(base, ptr, regs) \
+	({ \
+	 	unsigned long __res; \
+	 	unsigned int err; \
+		__asm__ __volatile__( \
+			"1:movb 0(%1,%0),%b2\n\t"		\
+			"incw %w0\n\t"				\
+			"2:movb 0(%1,%0),%h2\n\t"		\
+			"incw %w0\n\t"				\
+			"rorl $16,%2\n\t"			\
+			"3:movb 0(%1,%0),%b2\n\t"		\
+			"incw %w0\n\t"				\
+			"4:movb 0(%1,%0),%h2\n\t"		\
+			"incw %w0\n\t"				\
+			"rorl $16,%2\n\t"			\
+			"xor %3,%3\n\t"				\
+			"5:\n"					\
+			".section .fixup,\"ax\"\n\t"		\
+			"6:	movl $1,%1\n\t"			\
+			"	jmp 5b\n\t"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 1b,6b\n"			\
+			"	.long 2b,6b\n"			\
+			"	.long 3b,6b\n"			\
+			"	.long 4b,6b\n"			\
+			".previous"				\
+			: "=r" (ptr), "=r" (base), "=q" (__res), \
+				"=r" (err) \
+			: "0" (ptr), "1" (base), "2" (0)); \
+		if (err) \
+			return_to_32bit(regs, VM86_UNKNOWN); \
+		__res; \
+	})
 
 static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp)
 {
@@ -410,9 +512,9 @@
 		goto cannot_handle;
 	if ((segoffs >> 16) == BIOSSEG)
 		goto cannot_handle;
-	pushw(ssp, sp, get_vflags(regs));
-	pushw(ssp, sp, regs->cs);
-	pushw(ssp, sp, IP(regs));
+	pushw(ssp, sp, get_vflags(regs), regs);
+	pushw(ssp, sp, regs->cs, regs);
+	pushw(ssp, sp, IP(regs), regs);
 	regs->cs = segoffs >> 16;
 	SP(regs) -= 6;
 	IP(regs) = segoffs & 0xffff;
@@ -454,7 +556,7 @@
 
 #define CHECK_IF_IN_TRAP \
 	if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
-		pushw(ssp,sp,popw(ssp,sp) | TF_MASK);
+		pushw(ssp,sp,popw(ssp,sp, regs) | TF_MASK, regs);
 #define VM86_FAULT_RETURN \
 	if (VMPI.force_return_for_pic  && (VEFLAGS & (IF_MASK | VIF_MASK))) \
 		return_to_32bit(regs, VM86_PICRETURN); \
@@ -465,17 +567,17 @@
 	sp = SP(regs);
 	ip = IP(regs);
 
-	switch (popb(csp, ip)) {
+	switch (popb(csp, ip, regs)) {
 
 	/* operand size override */
 	case 0x66:
-		switch (popb(csp, ip)) {
+		switch (popb(csp, ip, regs)) {
 
 		/* pushfd */
 		case 0x9c:
 			SP(regs) -= 4;
 			IP(regs) += 2;
-			pushl(ssp, sp, get_vflags(regs));
+			pushl(ssp, sp, get_vflags(regs), regs);
 			VM86_FAULT_RETURN;
 
 		/* popfd */
@@ -483,16 +585,16 @@
 			SP(regs) += 4;
 			IP(regs) += 2;
 			CHECK_IF_IN_TRAP
-			set_vflags_long(popl(ssp, sp), regs);
+			set_vflags_long(popl(ssp, sp, regs), regs);
 			VM86_FAULT_RETURN;
 
 		/* iretd */
 		case 0xcf:
 			SP(regs) += 12;
-			IP(regs) = (unsigned short)popl(ssp, sp);
-			regs->cs = (unsigned short)popl(ssp, sp);
+			IP(regs) = (unsigned short)popl(ssp, sp, regs);
+			regs->cs = (unsigned short)popl(ssp, sp, regs);
 			CHECK_IF_IN_TRAP
-			set_vflags_long(popl(ssp, sp), regs);
+			set_vflags_long(popl(ssp, sp, regs), regs);
 			VM86_FAULT_RETURN;
 		/* need this to avoid a fallthrough */
 		default:
@@ -503,7 +605,7 @@
 	case 0x9c:
 		SP(regs) -= 2;
 		IP(regs)++;
-		pushw(ssp, sp, get_vflags(regs));
+		pushw(ssp, sp, get_vflags(regs), regs);
 		VM86_FAULT_RETURN;
 
 	/* popf */
@@ -511,12 +613,12 @@
 		SP(regs) += 2;
 		IP(regs)++;
 		CHECK_IF_IN_TRAP
-		set_vflags_short(popw(ssp, sp), regs);
+		set_vflags_short(popw(ssp, sp, regs), regs);
 		VM86_FAULT_RETURN;
 
 	/* int xx */
 	case 0xcd: {
-	        int intno=popb(csp, ip);
+	        int intno=popb(csp, ip, regs);
 		IP(regs) += 2;
 		if (VMPI.vm86dbg_active) {
 			if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] )
@@ -529,10 +631,10 @@
 	/* iret */
 	case 0xcf:
 		SP(regs) += 6;
-		IP(regs) = popw(ssp, sp);
-		regs->cs = popw(ssp, sp);
+		IP(regs) = popw(ssp, sp, regs);
+		regs->cs = popw(ssp, sp, regs);
 		CHECK_IF_IN_TRAP
-		set_vflags_short(popw(ssp, sp), regs);
+		set_vflags_short(popw(ssp, sp, regs), regs);
 		VM86_FAULT_RETURN;
 
 	/* cli */

             reply	other threads:[~2001-12-25 18:43 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-12-25 18:43 Manfred Spraul [this message]
2001-12-25 22:58 ` [CFT] error checking for VM86 instruction emulation Stas Sergeev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3C28C8C5.29C433ED@colorfullife.com \
    --to=manfred@colorfullife.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stas.orel@mailcity.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox