VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

Are there other testsuites like test386.asm? I know of xoreaxeaxeax's x86 fuzzer, but since I can't get a new enough linux to boot yet I can't use it?
The test386.asm testsuite already checks out.
CheckIt also doesn't tell me much.
The v7.1 version of Hiren's Boot CD also gives nothing weird.

Still, NT 4.o/2000 crash during starting the 2000(installer boot) and first full boot(4.0 starting phase 2 of setup from the HDD).
Debian Jessie hangs after telling me it's marked kernel and text readonly, with an infinite loop with HLT instructions in it? I do see lots of memory it's reading/writing to be zeroes 0nly?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

Intel has IPDT
The old version is also available for Linux and UEFI, and the source is also available (idk which license).
But it seems to only support cpus from P4 or so onwards, so maybe not that useful for you. Unless there's an older version for older hw somewhere, anyone know?

superfury wrote on 2021-06-27, 09:50:

... I can't get a new enough linux to boot yet ...

Since you put it that way, you mean that you got some older version of Linux booting?

In other news, baresifter made some changes a few months ago that made it possible to build a 32-bit version (NB: haven't tested this, I don't know if it actually runs)
EDIT: Yes it builds and starts (in qemu). They recommend installing Nix for some reason (reproducible builds?) but it seems to compile just fine with "scons -C src" (as long as you have clang, nasm etc. packages present).

Last edited by mr.cat on 2021-06-28, 18:36. Edited 2 times in total.

Reply 2 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++
mr.cat wrote on 2021-06-27, 15:57:
Intel has IPDT The old version is also available for Linux and UEFI, and the source is also available (idk which license). But i […]
Show full quote

Intel has IPDT
The old version is also available for Linux and UEFI, and the source is also available (idk which license).
But it seems to only support cpus from P4 or so onwards, so maybe not that useful for you. Unless there's an older version for older hw somewhere, anyone know?

superfury wrote on 2021-06-27, 09:50:

... I can't get a new enough linux to boot yet ...

Since you put it that way, you mean that you got some older version of Linux booting?

In other news, baresifter made some changes a few months ago that made it possible to build a 32-bit version (NB: haven't tested this, I don't know if it actually runs)

Yes, it was Debian Bo if I remember correctly.

But afaik Jessie is required for Sandsifter. It's currently hanging on some infinite loop after the message of the kernel text and data becoming marked readonly. The only thing that intervenes with said loop is the local APIC timer interrupt.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

OK, that's issue #61 on GitHub. So let's see, Bo came out July 1997 and Jessie is from 2015.
If you go by differential debugging methodology, Etch or Sarge would be the next ones to try 😁
These both have Python v2. But I guess sandsifter may have other issues besides python, on these old distros.
Obviously it'd take a lot of booting different versions, to work your way down to that one commit that holds the explanation to it all...

Reply 4 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++
mr.cat wrote on 2021-06-28, 17:20:
OK, that's issue #61 on GitHub. So let's see, Bo came out July 1997 and Jessie is from 2015. If you go by differential debugging […]
Show full quote

OK, that's issue #61 on GitHub. So let's see, Bo came out July 1997 and Jessie is from 2015.
If you go by differential debugging methodology, Etch or Sarge would be the next ones to try 😁
These both have Python v2. But I guess sandsifter may have other issues besides python, on these old distros.
Obviously it'd take a lot of booting different versions, to work your way down to that one commit that holds the explanation to it all...

Afaik Jessie is the bare minimum requirement for running Sandsifter, due to requiring a compiler that's new enough. But it runs an infinite loop (based on various 00000000h values read from memory apparently) directly after making kernel text and code read-only (according to text on the screen).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 5 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

OK that's good to know. Dev tools can be compiled from scratch, but that can be a real hassle (especially starting from 1997!)
The booting issue could perhaps be resolved by trying out those older ones.

OTOH baresifter sidesteps these issues altogether, so perhaps it'd be a better fit.
Here's a ready-made boot floppy if you want to give it a try. Do note that the output goes to serial port by default.
I renamed baresifter.x86_32.elf to bsifter, so that's the file to replace in case you need to customize.

EDIT: Changed the output device to 0xE9 (see superfury's explanation below).
EDIT2: OK found another stumbling block...
Instruction length tests fail because one of the tests uses the xbegin opcode, so I just removed that from main.cpp.
Strangely enough, that test does pass in qemu (with -cpu pentium2).
EDIT3: Added some DEBUG logging to self tests.
EDIT4: Added NX detection (from git issue).
EDIT5: If you can't boot from floppies (as seems to be the case with Bochs BIOS), you can convert the floppy image to bootable iso, e.g. something like this:

mkdir boot
mv -i /path/to/BSIFTER.IMG boot/.
genisoimage -o BSIFTER.ISO -b BSIFTER.IMG boot

Attachments

Last edited by mr.cat on 2021-07-06, 22:56. Edited 5 times in total.

Reply 6 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++
mr.cat wrote on 2021-06-29, 11:07:
OK that's good to know. Dev tools can be compiled from scratch, but that can be a real hassle (especially starting from 1997!) T […]
Show full quote

OK that's good to know. Dev tools can be compiled from scratch, but that can be a real hassle (especially starting from 1997!)
The booting issue could perhaps be resolved by trying out those older ones.

OTOH baresifter sidesteps these issues altogether, so perhaps it'd be a better fit.
Here's a ready-made boot floppy if you want to give it a try. Do note that the output goes to serial port by default.
I renamed baresifter.x86_32.elf to bsifter, so that's the file to replace in case you need to customize.

Well, I've looked at it and saw that essentially the only change to the Baresifter code would be to force the Bochs/Qemu port E9 hack to be active(stripping out the special CPUID requirement for that). UniPCemu doesn't support logging from a serial port, but fully supports the port E9 hack from Bochs (and apparently Qemu supports it as well, seeing as it's writing output ASCII to port E9 and nothing else from what I saw).
It should basically be commenting out that one line that checks bit 31 of some CPUID result?
Edit: It's checking if a hypervisor is running for it to use UniPCemu's/Bochs port E9 hack. Simple replace it's contents with "return 1;" (unquoted) on src/common/cpuid.cpp line 32.
UniPCemu can't set that bit because it's actually emulating everything and not a hypervisor itself.
With that change, UniPCemu should log everything it receives from the app to a log file (UniPCemu itself will take care of any line ending conversion).
Of course, Baresifter can also try to detect UniPCemu's port E9 hack by reading port E9 and check if it reads 0xE9 (that's supported on all emulators I know of (UniPCemu, Bochs, Qemu)).

Last edited by superfury on 2024-03-12, 01:24. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 7 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

Oh cool, thanks for pointing that out! You're right, it really is that simple. I've updated the image.

Btw, for Bochs you need to enable SMEP, so something like this in .bochsrc:
cpuid: smep=true

Reply 8 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++
mr.cat wrote on 2021-06-30, 09:39:

Oh cool, thanks for pointing that out! You're right, it really is that simple. I've updated the image.

Btw, for Bochs you need to enable SMEP, so something like this in .bochsrc:
cpuid: smep=true

I gave it a go. It didn't get very far:

00:10:24:93.03632:  |             _||       
00:10:24:93.05232: _ \ _|(_-< _| _| _|
00:10:24:93.05744: _.__/_| ___/_| \__|_|
00:10:24:93.06448: 32-bit version a0cf762-dirty
00:10:24:93.08432: >>> CPU is GenuineIntel 00000633.
00:10:24:93.09648: >>> Executing self test.
00:10:24:94.03296: Instruction length: b0rken!

Edit: Looking in the source code, it's probably that xbegin instruction that's unsupported by UniPCemu.
Edit: Are those tests even compatible with older 32-bit architectures (base Pentium II or lower without any extended instruction sets)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 9 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

Yeah that's the old version, I removed the xbegin test in a later update.
That b0rken announcement just means that the instruction length self test failed.

I could be mistaken but I think xbegin is Haswell stuff. Well not included in P2 in any case.

Reply 10 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, one of those instruction tests seem to somehow have been failing? Are there any other opcodes in that list that can cause issues with Pentium II CPUs (without any non-mandatory (besides FPU/MMX opcodes not being implemented) x86 extensions implemented)?

I do notice that it seems to not check for invalid opcodes in there? It just assumes the instruction is completely decoded, even if it's an #UD(which aborts early)?

I'd assume looking at user space execution can perhaps show the 'failing' opcode in said list, looking at the last fault raised in user space(CPL 3)?
Edit: It doesn't seem to take #UD into account, or does it?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 11 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

The tests are listed in main.cpp, function self_test_instruction_length().
Adding some DEBUG printing (using format()) there should reveal which one of these tests fail, but I spotted this:

    { 2, { 0x00, 0x00 } },      // add [rax], al

No 64-bit registers available in P2 I don't think...but I guess this just shows baresifter's heritage of being a x86_64 thing.
In a 32-bit context that translates to a similar kind of "add" opcode though (just using eax), so maybe it's not the one causing trouble.

I've updated the image now with some extra DEBUG. Should you want to make your own, you can use mtools to update the bsifter binary in the image (I used the virtual floppy disk inside of qemu myself though). The command line is a bit tricky to get right, but something like this seems to work:

mcopy -v -i baresifter_floppy.img /path/to/baresifter.x86_32.elf ::bsifter

About #UD, you're probably right about that, or at least I didn't spot any checks for that. There's only that one ef.vector test for Page Fault (decimal 14).

Last edited by mr.cat on 2021-07-01, 14:51. Edited 2 times in total.

Reply 12 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

It's now logging:

00:24:43:13.04336: DEBUG: attempt.length=1 test.length=1
00:24:43:14.02016: DEBUG: attempt.length=1 test.length=1
00:24:43:14.09056: DEBUG: attempt.length=1 test.length=2
00:24:43:15.06352: DEBUG: attempt.length=1 test.length=2
00:24:43:16.03008: DEBUG: attempt.length=1 test.length=2
00:24:43:17.00432: DEBUG: attempt.length=1 test.length=5
00:24:43:17.07472: DEBUG: attempt.length=1 test.length=4
00:24:43:18.04512: DEBUG: attempt.length=1 test.length=2
00:24:43:19.02320: DEBUG: attempt.length=1 test.length=1
00:24:43:19.09360: DEBUG: attempt.length=1 test.length=2
00:24:43:20.03456: Instruction length: b0rken!

Edit: hmmm... weird? All attempts always report a length of 1 even though I know some of them execute as multiple bytes?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 14 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Perhaps I should look into what's happening in CPL3 (mostly regarding faults etc.)?

Edit: OK, I see:
101FFF: OK(with that I mean single step exception). Return EIP=102000(the second page, so that looks correct?). The debugger interrupt it's firing is interrupt 01h? That should be correct? The opcode that was executed was 0x90. It transfers control to address 40212F for the single step interrupt handler.
101FFF: 1-byte instruction #GP(001B) for trying to violate IDT CPL rights for the interrupt handler.
101FFF: Page fault for 102000 for opcode CD only having been loaded.
And again?
Then for opcode 00 at 101FFF for address 102000?
Then for opcode EB at 101FFF for address 102000?
The nfor opcode E9 at 101FFF for address 102000?
(The PDE for address 102000h being 407025h and PTE being 0 for that page)

The flags pushed on the stack is 0x0004 for that.

Then 66h at 101FFFh on address 102000h.
Then single step at 102000h for instruction at 101FFF opcode FDh (CLD).
Then page fault at 102000h for opcode 8Eh at 101FFF.

That's all that's raised on faults from user mode during the Bareshifer self test.
So it's supposed to move the instruction 1 byte backwards to the previous page (at LA 101FFFE), but somehow never does that?

Edit: Just answered my own question: the code at main.cpp line 32 requires bit 4 of the error code to be set, but UniPCemu doesn't ever set that bit? Is it even set for instruction fetches on PSE 32-bit x86?
Edit: It's a x64 code remainder! (https://wiki.osdev.org/Exceptions#Page_Fault). Since the NX bit isn't supported, that bit is never set on pre-NX processors!
Just created an issue on the issue tracker of Baresifter ( https://github.com/blitz/baresifter/issues/4 )

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 15 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

👏Hey that's a great find man! The 32-bit port is quite recent, so I can't say it's wholly surprising...
It'd be great if the minimum platform could be lowered even further down to say, i386, but I guess it'll take a while to get there.

Reply 16 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++
mr.cat wrote on 2021-07-01, 21:27:

👏Hey that's a great find man! The 32-bit port is quite recent, so I can't say it's wholly surprising...
It'd be great if the minimum platform could be lowered even further down to say, i386, but I guess it'll take a while to get there.

Could y0u modify the line in your build&disk image to use the I bit in page faults being 0 for the check for the page after the fuzzed instruction's page?

That way it should at least be able to continue fuzzing?

Although it should be able to implement better by using CPUID to check for the NX bit being supported (like Sandsifter does in it's injector, although it uses a parameter instead of CPUID bits)? That's at leaf 80000001h(if the leaf is present), EDX bit 20.

So, the condition would be:

static bool nx_supported()
{
return !(get_cpuid(0x80000000U).eax&0x80000000U)?0: //Not possibly present?
(
(get_cpuid(0x80000000U).eax<0x80000001U)?0: //NX Leaf unsupported?
((get_cpuid(0x80000001U).edx&(1U<<20U))>>20U) //NX supported to bit 0!
);
}

nx_supported() giving a 1-bit value(0 or 1, 1 when supported). Might be precalculated or macro'd.

Then, the offending line(main.c:32 and 33) can change to:

bool has_nx = nx_supported(); //NX supported?
bool incomplete_instruction_fetch = (ef.vector == 14 and
(ef.error_code & (0b0101|(has_nx<<4U)) /* user space instruction fetch */) == (0b0100|(has_nx<<4U)) and

That should theoretically fix it on those older processors?
Edit: Put the code slightly optimized on the issue page.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 17 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Forcing the bit 4 to be set for instruction fetch page faults in UniPCemu causes all of them to give correct results, except the case with a length of 5?
Edit: That's opcode E9(short/long JMP rel16/32)?
Edit: It observes a length of 2?
Edit: OK. That's the ending byte of the instruction's 32-bit parameter that's faulting? But since it's supposed to be the first byte in the page to actually fault, it's misdetected by the injector! Thus CR2=102002 for the instruction at 101FFFE, which is incorrect! So 32-bit page faults need refining there!

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 18 of 58, by mr.cat

User metadata
Rank Member
Rank
Member

That's progress right there 😁
The image is now updated. I'm still wondering about the CPU models used in qemu and Bochs...
Namely, I think I had the model set to some sort of "Pentium II" (or Pentium Pro for Bochs) and they did pass the tests without this NX patch (well except for xbegin, which was subsequently removed).
AFAIK NX is a later development (P4 or so?). I guess that's something to test out.

EDIT: Yup, the minimum processor configuration for qemu that can run baresifter (the non-NX-patched version) is "-cpu 486,cmov"
Btw something I noticed while playing around with qemu: Linux (kernel 4.19) doesn't want to boot without FPU present. Didn't investigate it further, but perhaps that's related to your problem with Jessie.
EDIT2: Looks like it's simply because math emulation is disabled by default nowadays. Doesn't make sense to have it on modern platforms I suppose...

Last edited by mr.cat on 2021-07-02, 12:23. Edited 1 time in total.

Reply 19 of 58, by superfury

User metadata
Rank l33t++
Rank
l33t++

Having fixed the paging address for 32-bit operand sizes and instruction fetches, it now starts sifting (using the version from yesterday with UniPCemu temporarily patched to set bit 4 of page faults for instruction fetching, in source control with the test patch commented out (the PF_EXTRABITS define in cpu/paging.c).
Edit: The version without the patch in UniPCemu and with the github Sandsifter patched disk image properly starts sifting! 😁

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io