* Re: Using Linux+dosemu to install Windows
@ 2002-07-26 16:47 Stas Sergeev
[not found] ` <mit.lcs.mail.linux-msdos/3D417D1E.50902@yahoo.com>
0 siblings, 1 reply; 8+ messages in thread
From: Stas Sergeev @ 2002-07-26 16:47 UTC (permalink / raw)
To: linux-msdos
Hello.
Patrick J. LoPresti wrote:
>> /usr/src/linux/arch/i386/kernel/vm86.c The attached patch must be a
>> good start for fixing the problem.
> Ah, so the problem is that the kernel's emulation does not account for
> multiple prefix bytes?
Yep, that was the problem.
> Will you submit your patch to Alan Cox? It would be nice to get this
> fixed in the long run.
Yes, I'll try to submit this one.
> One more thing. How precise should the emuluation be?
Hmm, 100%? :)
> The popfd instruction should not modify the VM or RF bits. (Not to
> mention any bits which are reserved in the current revision of the
> CPU.) Or does the kernel already take care of these concerns?
Yes, see how the thread.v86mask gets
initialised in do_sys_vm86().
> I believe clearing those flags is a bad idea. They are both used
> routinely to detect the CPU version:
I agree:(
The only good thing here is that the
amount of progs that works on 486 but
not on 386 is very minor...
> I suggest removing the BUG: stuff from the dosemu source code, then
> figuring out what the real problem is and fixing it properly.
This was suggested several times before
but still noone figured out the real
problem so all that suggestions failed.
> What do you think?
Currently the "BUG" cannot be removed.
Just set the $_cpu=(80486) and try to
run FoxPro after removing the "BUG" from
dpmi.c and sigsegv.c (there are 3 places
where the AC gets cleared) and it will
crash.
Furthermore somehow it happens that if the
signal was received while AC is set,
dosemu itself executes with AC set and
crashs somewhere in glibc functions due
to exception 0x11.
If you can find the roots of the problem,
the "BUG" will be removed, thats for sure...
My guess is that the problem is somewhere
in the kernel/vm86() because when CPU-emu
is used, the "BUG" doesn't occure.
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: Using Linux+dosemu to install Windows
@ 2002-07-28 7:09 Stas Sergeev
0 siblings, 0 replies; 8+ messages in thread
From: Stas Sergeev @ 2002-07-28 7:09 UTC (permalink / raw)
To: linux-msdos; +Cc: Bart Oldeman
[-- Attachment #1: Type: text/plain, Size: 793 bytes --]
Hello.
Bart Oldeman wrote:
>> functionality. Then you can safely
>> remove the "BUG" stuff I think.
> Yes, that looks like the proper fix to me.
We probably have to contact
Alberto to find out if his tests
are passed with that patches
because my testcase for the
"BUG" includes only FoxPro...
>> > Would you accept such a patch?
> That would be me. Well together with Stas' patch I would accept it.
But that was:
> But I do have time to
> create a patch to allow people to enable the BUG: code from
> dosemu.conf.
and this patch we don't need anymore.
The attached patch removes the "BUG"
stuff leaving it only for the dosemu
flags. It is always a good idea to
have dosemu flags protected I think.
How they got infected is still unclear
however this doesn't seem to happen
with my patches.
[-- Attachment #2: remove_bug.diff --]
[-- Type: text/plain, Size: 1184 bytes --]
--- src/arch/linux/async/sigsegv.c Sun Jul 28 10:51:57 2002
+++ src/arch/linux/async/sigsegv.c Sun Jul 28 10:52:23 2002
@@ -99,8 +99,10 @@
pushl %%eax\n \
popfl" \
: : "i"(~(AC|ID)) : "%eax");
+#if 0
_eflags &= ~(AC|ID);
REG(eflags) &= ~(AC|ID);
+#endif
if (in_vm86) {
in_vm86 = 0;
--- src/dosext/dpmi/dpmi.c Sun Jul 28 10:51:02 2002
+++ src/dosext/dpmi/dpmi.c Sun Jul 28 10:51:30 2002
@@ -2172,12 +2172,14 @@
retval=DO_VM86(&vm86s);
in_vm86=0;
+#if 0
/* This will let foxpro run with cpu>=486 */
if (_EFLAGS & (AC|ID)) {
_EFLAGS &= ~(AC|ID);
if (debug_level('M')>3)
D_printf("BUG: AC,ID set; flags changed to %08x\n",_EFLAGS);
}
+#endif
if (
#ifdef TRACE_DPMI
--- src/emu-i386/do_vm86.c Sun Jul 28 10:49:48 2002
+++ src/emu-i386/do_vm86.c Sun Jul 28 10:50:23 2002
@@ -474,12 +474,15 @@
}
#endif /* USE_NEW_INT */
+#if 0
/* This will protect us from Mr.Norton's bugs */
if (_EFLAGS & (AC|ID)) {
_EFLAGS &= ~(AC|ID);
if (debug_level('g')>3)
dbug_printf("BUG: AC,ID set; flags changed to %08x\n",_EFLAGS);
}
+#endif
+
if (
#ifdef X86_EMULATOR
(debug_level('e')>1)||
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: Using Linux+dosemu to install Windows
@ 2002-07-27 21:10 Stas Sergeev
2002-07-27 22:11 ` Bart Oldeman
0 siblings, 1 reply; 8+ messages in thread
From: Stas Sergeev @ 2002-07-27 21:10 UTC (permalink / raw)
To: linux-msdos
[-- Attachment #1: Type: text/plain, Size: 1977 bytes --]
Hello.
Patrick J. LoPresti wrote:
>> The only good thing here is that the amount of progs that works on
>> 486 but not on 386 is very minor...
> But how annoying when you run into one :-).
I really don't think it is a major
advantage to have an ability to
pass the first stage of NT install... :)
OKey, I have found the bug.
According to this:
http://support.intel.com/design/intarch/techinfo/Pentium/instrefi.htm#89126
AC is cleared by an INT instruction
executed in real mode. As this flag
resides in the higher word of eflags,
it is not saved on stack so it gets
lost.
Two attached patches implements that
functionality. Then you can safely
remove the "BUG" stuff I think.
I have failed to find any docs on
how the hardware interrupts affects
the AC flag but I guess they don't,
otherwise it can be used only when
IF is not set.
ID flag is not affected so I guess
it gets cleared together with AC by
mistake.
> Couldn't you just tell people to use $_cpu=(80386) as a workaround?
> That would have the side-effect of protecting the AC bit, wouldn't it?
Yes, it would. And not, it is not a
side-effect, this is the main and
almost only difference with 80486
in dosemu.
>> Furthermore somehow it happens that if the signal was received while
>> AC is set, dosemu itself executes with AC set and crashs somewhere
>> in glibc functions due to exception 0x11.
> Is that not a bug in the emulator design? I mean, shouldn't *all* of
> the emulator's state be isolated from the emulated machine's?
Right, this is a main design problem
of dosemu which is that the DPMI code
is executed in the same address space
with dosemu. vm86 is separated however.
So DPMI code can do everything and if
dosemu have root privs, it can be easily
exploited by DPMI code.
> Would you accept such a patch?
It is not me who accepting patches
here, this is what the project
coordinators/maintainers does.
Visit
dosemu.sourceforge.net
and
www.sf.net/projects/dosemu
to find out who is responsible.
[-- Attachment #2: int_ac.diff --]
[-- Type: text/plain, Size: 1618 bytes --]
--- src/include/cpu.h Wed Jun 26 21:58:32 2002
+++ src/include/cpu.h Sat Jul 27 23:12:23 2002
@@ -198,6 +198,10 @@
#define set_TF() (_EFLAGS |= TF)
#define clear_TF() (_EFLAGS &= ~TF)
#define isset_TF() ((_EFLAGS & TF) != 0)
+ /* alignment flag */
+#define set_AC() (_EFLAGS |= AC)
+#define clear_AC() (_EFLAGS &= ~AC)
+#define isset_AC() ((_EFLAGS & AC) != 0)
/* Virtual Interrupt Pending flag */
#define set_VIP() (_EFLAGS |= VIP)
#define clear_VIP() (_EFLAGS &= ~VIP)
--- src/emu-i386/do_vm86.c Fri Jul 26 21:16:46 2002
+++ src/emu-i386/do_vm86.c Sun Jul 28 00:06:46 2002
@@ -506,6 +506,14 @@
pic_iret();
break;
case VM86_INTx:
+ /*
+ * AC flag gets cleared by the INT instruction and is not restored
+ * by IRET because it resides in the higher word of eflags and
+ * hence not saved in the stack.
+ * However we can't clear it in real_run_int() et al because
+ * it is not cleared by hardware interrupts (???)
+ */
+ clear_AC();
#ifdef USE_MHPDBG
mhp_debug(DBG_INTx + (VM86_ARG(retval) << 8), 0, 0);
#endif
--- src/dosext/dpmi/dpmi.c Sun Jun 23 23:42:23 2002
+++ src/dosext/dpmi/dpmi.c Sun Jul 28 00:07:35 2002
@@ -2240,6 +2227,14 @@
pic_iret();
break;
case VM86_INTx:
+ /*
+ * AC flag gets cleared by the INT instruction and is not restored
+ * by IRET because it resides in the higher word of eflags and
+ * hence not saved in the stack.
+ * However we can't clear it in real_run_int() et al because
+ * it is not cleared by hardware interrupts (???)
+ */
+ clear_AC();
#ifdef X86_EMULATOR
D_printf("DPMI: Return from vm86() for interrupt\n");
#endif
[-- Attachment #3: vm86_ac.diff --]
[-- Type: text/plain, Size: 550 bytes --]
--- linux/arch/i386/kernel/vm86.c Sat Jul 27 13:12:38 2002
+++ linux/arch/i386/kernel/vm86.c Sat Jul 27 23:56:27 2002
@@ -317,6 +317,11 @@
regs->eflags &= ~TF_MASK;
}
+static inline void clear_AC(struct kernel_vm86_regs * regs)
+{
+ regs->eflags &= ~AC_MASK;
+}
+
/* It is correct to call set_IF(regs) from the set_vflags_*
* functions. However someone forgot to call clear_IF(regs)
* in the opposite case.
@@ -471,6 +476,7 @@
IP(regs) = segoffs & 0xffff;
clear_TF(regs);
clear_IF(regs);
+ clear_AC(regs);
return;
cannot_handle:
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: Using Linux+dosemu to install Windows
2002-07-27 21:10 Stas Sergeev
@ 2002-07-27 22:11 ` Bart Oldeman
0 siblings, 0 replies; 8+ messages in thread
From: Bart Oldeman @ 2002-07-27 22:11 UTC (permalink / raw)
To: linux-msdos
On Sun, 28 Jul 2002, Stas Sergeev wrote:
> Two attached patches implements that
> functionality. Then you can safely
> remove the "BUG" stuff I think.
Yes, that looks like the proper fix to me.
> Right, this is a main design problem
> of dosemu which is that the DPMI code
> is executed in the same address space
> with dosemu. vm86 is separated however.
> So DPMI code can do everything and if
> dosemu have root privs, it can be easily
> exploited by DPMI code.
yes, see section three of README.txt:
* Never allow DPMI programms to run, when dosemu is suid root.
(in /etc/dosemu.conf set 'dpmi off' to disable)
It is possible to overwrite sensitive parts of the emulator code,
and this makes it possible for a intruder program under DOS, who
knows about dosemu internals (which is easy as you have the
source) to get root access also on non dosemu processes. Because a
lot of games won't work without, we allow creation of
LDT-descriptor that span the whole user space.
There is a 'secure' option in /etc/dosemu.conf, that allows to
turn off creation of above mentioned descriptors, but those
currently protect only the dosemu code and the stack, and may be
some diabolical person finds a way to use the (unprotected) heap.
Anyway, better 'secure on' than nothing.
> > Would you accept such a patch?
That would be me. Well together with Stas' patch I would accept it.
Bart
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: Using Linux+dosemu to install Windows
@ 2002-07-26 14:02 Stas Sergeev
[not found] ` <mit.lcs.mail.linux-msdos/3D41566B.5030903@yahoo.com>
0 siblings, 1 reply; 8+ messages in thread
From: Stas Sergeev @ 2002-07-26 14:02 UTC (permalink / raw)
To: linux-msdos
[-- Attachment #1: Type: text/plain, Size: 1369 bytes --]
Hello.
Patrick J. LoPresti wrote:
> By instrumenting the code a bit, I learned
> that winnt.exe is attempting to invoke the pushfd and popfd
> instructions (opcodes 0x9c and 0x9d, respectively), which
> dosemu does not support.
Good investigation but actually
you are hacking the wrong place.
These instructions are handled in
handle_vm86_fault() which is in
/usr/src/linux/arch/i386/kernel/vm86.c
The attached patch must be a good
start for fixing the problem. It is
against the latest 2.4.19-pre-ac
kernels and probably can't be applied
to 2.4.18 because -ac tree have a lot
of changes in vm86.
> All winnt.exe is really doing is trying to determine whether the
> processor is a 486 or higher. It does this by using pushfd and popfd
> to attempt to alter the next-to-highest bit of the EFLAGS register.
No, it tries to alter the AC flag which
is a bit 2 of the higher word of eflags.
But dosemu explicitly clears this flag
because due to some unknown bugs it
sometimes sets spuriously.
grep the do_vm86.c for the string "BUG:"
and comment the relevant code, then
winnt.exe will work.
> So, my question boils down to this: How can I modify the EFLAGS
> register from within vm86_GP_fault()? If someone will tell me this, I
> will submit a patch to add support for emulating the pushf/pushfd and
> popf/popfd opcodes.
Well, but this won't solve the AC
problem...
[-- Attachment #2: vm86_pref.diff --]
[-- Type: text/plain, Size: 3995 bytes --]
--- linux/arch/i386/kernel/vm86.c Sat Jun 15 19:46:46 2002
+++ linux/arch/i386/kernel/vm86.c Fri Jul 26 14:25:35 2002
@@ -502,8 +502,9 @@
void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
{
- unsigned char *csp, *ssp;
+ unsigned char *csp, *ssp, opcode;
unsigned short ip, sp;
+ int prefix66, pref_done;
#define CHECK_IF_IN_TRAP \
if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \
@@ -518,63 +519,61 @@
sp = SP(regs);
ip = IP(regs);
- switch (popb(csp, ip, simulate_sigsegv)) {
-
- /* operand size override */
- case 0x66:
- switch (popb(csp, ip, simulate_sigsegv)) {
+ prefix66 = 0;
+ pref_done = 0;
+ do {
+ switch (opcode = popb(csp, ip, simulate_sigsegv)) {
+ case 0x66: /* operand prefix */ prefix66=1; break;
+ case 0x67: /* address prefix */ break;
+ case 0x2e: /* CS */ break;
+ case 0x3e: /* DS */ break;
+ case 0x26: /* ES */ break;
+ case 0x36: /* SS */ break;
+ case 0x65: /* GS */ break;
+ case 0x64: /* FS */ break;
+ case 0xf2: /* repnz */ break;
+ case 0xf3: /* rep */ break;
+ default: pref_done = 1;
+ }
- /* pushfd */
- case 0x9c:
- pushl(ssp, sp, get_vflags(regs), simulate_sigsegv);
- SP(regs) -= 4;
- IP(regs) += 2;
- VM86_FAULT_RETURN;
+ if (!pref_done)
+ IP(regs)++; /* prefix found, adjust IP */
+ else
+ break; /* no more prefixes */
+ } while (1);
- /* popfd */
- case 0x9d:
- {
- unsigned long newflags=popl(ssp, sp, simulate_sigsegv);
- SP(regs) += 4;
- IP(regs) += 2;
- CHECK_IF_IN_TRAP;
- set_vflags_long(newflags, regs);
- VM86_FAULT_RETURN;
- }
-
- /* iretd */
- case 0xcf:
- {
- unsigned long newip=popl(ssp, sp, simulate_sigsegv);
- unsigned long newcs=popl(ssp, sp, simulate_sigsegv);
- unsigned long newflags=popl(ssp, sp, simulate_sigsegv);
- SP(regs) += 12;
- IP(regs) = (unsigned short)newip;
- regs->cs = (unsigned short)newcs;
- CHECK_IF_IN_TRAP;
- set_vflags_long(newflags, regs);
- VM86_FAULT_RETURN;
- }
- /* need this to avoid a fallthrough */
- default:
- return_to_32bit(regs, VM86_UNKNOWN);
- }
+ switch (opcode) {
/* pushf */
case 0x9c:
- pushw(ssp, sp, get_vflags(regs), simulate_sigsegv);
- SP(regs) -= 2;
+ if (prefix66) {
+ pushl(ssp, sp, get_vflags(regs), simulate_sigsegv);
+ SP(regs) -= 4;
+ } else {
+ pushw(ssp, sp, get_vflags(regs), simulate_sigsegv);
+ SP(regs) -= 2;
+ }
IP(regs)++;
VM86_FAULT_RETURN;
/* popf */
case 0x9d:
{
- unsigned short newflags=popw(ssp, sp, simulate_sigsegv);
- SP(regs) += 2;
+ unsigned long newflags;
+ if (prefix66) {
+ newflags=popl(ssp, sp, simulate_sigsegv);
+ SP(regs) += 4;
+ } else {
+ newflags = popw(ssp, sp, simulate_sigsegv);
+ SP(regs) += 2;
+ }
IP(regs)++;
CHECK_IF_IN_TRAP;
- set_vflags_short(newflags, regs);
+ if (prefix66) {
+ set_vflags_long(newflags, regs);
+ } else {
+ set_vflags_short(newflags, regs);
+ }
VM86_FAULT_RETURN;
}
@@ -593,14 +592,28 @@
/* iret */
case 0xcf:
{
- unsigned short newip=popw(ssp, sp, simulate_sigsegv);
- unsigned short newcs=popw(ssp, sp, simulate_sigsegv);
- unsigned short newflags=popw(ssp, sp, simulate_sigsegv);
- SP(regs) += 6;
+ unsigned long newip;
+ unsigned long newcs;
+ unsigned long newflags;
+ if (prefix66) {
+ newip=popl(ssp, sp, simulate_sigsegv);
+ newcs=popl(ssp, sp, simulate_sigsegv);
+ newflags=popl(ssp, sp, simulate_sigsegv);
+ SP(regs) += 12;
+ } else {
+ newip = popw(ssp, sp, simulate_sigsegv);
+ newcs = popw(ssp, sp, simulate_sigsegv);
+ newflags = popw(ssp, sp, simulate_sigsegv);
+ SP(regs) += 6;
+ }
IP(regs) = newip;
regs->cs = newcs;
CHECK_IF_IN_TRAP;
- set_vflags_short(newflags, regs);
+ if (prefix66) {
+ set_vflags_long(newflags, regs);
+ } else {
+ set_vflags_short(newflags, regs);
+ }
VM86_FAULT_RETURN;
}
^ permalink raw reply [flat|nested] 8+ messages in thread* Using Linux+dosemu to install Windows
@ 2002-07-26 3:50 Patrick J. LoPresti
0 siblings, 0 replies; 8+ messages in thread
From: Patrick J. LoPresti @ 2002-07-26 3:50 UTC (permalink / raw)
To: linux-msdos
I am sorry this is so long. Executive summary: I would like some
guidance to produce a patch to improve dosemu. Skip to the end for my
actual question.
As you may (or may not) know, Windows NT/2000/XP installation CDs
include a 16-bit DOS application i386\winnt.exe which starts the
installation of the operating system. All this application does is
copy a bunch of stuff to the hard drive and reboot the machine.
I want to perform unattendend installations of Windows over the
network. But instead of mucking about with DOS network drivers, I
thought it might be fun to try using a bootable Linux CD and dosemu to
run the winnt.exe installer.
But I hit a snag. Running winnt.exe causes dosemu 1.1.3 to abort like
this:
ERROR: general protection at 0xbbca: 67
ERROR: SIGSEGV, protected insn...exiting!
This error comes from the vm86_GP_fault() function in
src/i386-emu/do_vm86.c. By instrumenting the code a bit, I learned
that winnt.exe is attempting to invoke the pushfd and popfd
instructions (opcodes 0x9c and 0x9d, respectively), which dosemu does
not support.
All winnt.exe is really doing is trying to determine whether the
processor is a 486 or higher. It does this by using pushfd and popfd
to attempt to alter the next-to-highest bit of the EFLAGS register.
On the 386 and earlier, this attempt fails, because the bit was
reserved back then and was always zero.
I figured this out after I wrote stub handlers for opcodes 0x9c and
0x9d, which allowed dosemu to run winnt.exe until the latter explained
that "Windows 2000 requires a 486 or higher; setup will exit now".
I have tried to figure out how to modify EFLAGS from within
vm86_GP_fault(), but so far I am finding this difficult. Assigning to
REG(eflags) does not appear to work. I have hacked my stub handlers
to simply return what winnt.exe expects, and this actually allowed
winnt.exe to proceed to the end and "reboot" the dosemu box (i.e., it
worked). But I would like to do this right and get it into the stock
dosemu distribution.
So, my question boils down to this: How can I modify the EFLAGS
register from within vm86_GP_fault()? If someone will tell me this, I
will submit a patch to add support for emulating the pushf/pushfd and
popf/popfd opcodes.
Thanks!
- Pat
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2002-07-28 7:09 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-07-26 16:47 Using Linux+dosemu to install Windows Stas Sergeev
[not found] ` <mit.lcs.mail.linux-msdos/3D417D1E.50902@yahoo.com>
2002-07-27 15:02 ` Patrick J. LoPresti
-- strict thread matches above, loose matches on Subject: below --
2002-07-28 7:09 Stas Sergeev
2002-07-27 21:10 Stas Sergeev
2002-07-27 22:11 ` Bart Oldeman
2002-07-26 14:02 Stas Sergeev
[not found] ` <mit.lcs.mail.linux-msdos/3D41566B.5030903@yahoo.com>
2002-07-26 16:06 ` Patrick J. LoPresti
2002-07-26 3:50 Patrick J. LoPresti
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox