Well, the time has come. So, here I am.
I need to get x286 binaries running (that is, iAPX286 Unix COFF binaries, both short and long memory models - well, technically compact mode, but the magic number says long - they're from Microport days, and their first two bytes magic numbers are 0x4a01 for the short and 0x5201 for the long). In particular, ones that ran in a previous life with the help of i286emul, an Intel variation of the Xenix x286emul. i286emul comes to me as a binary 80386 COFF executable. I know it ran on the Microport 386 version of UNIX. It may also have been able to run on Unixware 7.1.2.
No, I'm not running on ibcs-us, at the moment - I've gone back to ibcs-3.9.4 on an OpenSuSE 11.4, which is behaving pretty well.
Why am I bothering you with this? Well, because (a) you've got more history with this than anyone else I know, (2) you may be amused to look at the source in ibcs-us/per-svr4/sysi86.c for the case SI86DSCR and (3) know that it hasn't done anything but print the arguments received from the user space since at least ibcs_3_4 (2007).
And, yes, i286emul DOE call that system call, and abi_trace DOES print the arguments as the code calls for, and i286emul DOES get -EINVAL and so hork, just as the code says it should.
What this code APPEARS to SUPPOSED to be doing is actually adding a descriptor to the LDT for selector 0x2cb, which is the 89th (decimal) descriptor in the GDT for crying out loud, because it may be trying to create a gate, I guess.
But, for what ever reason, this case for this function has evidently not ever actually called anything to actually do anything.
If you've read this far, I can tell you I have trace file output in /var/log/messages that shows
1) the the entry to the sysi86/sys3b call from the i286emul, then
2) the parameters passed to sysi86 for the SI86DSCR(2cb, 3404, 17, ec, 0), and
3) the next line is the trace report of the retuned error from the call (return -22/22).
So - why has this case in sysi86 never actually done anything other than produce trace messages and return -EINVAL?
The "file i286emul" returns "80386 COFF executable". Its first two bytes are 0x4c01 (so, 0x01, 0x4c, bytewise).
I THINK I need the i286emul, because that's how folks got these 16-bit compilers to run on the Microport 386 and, I think, the UnixWare 7.1.2 (or OpenServer 5? I don't really know).
One question I have about the user space IBCS you're working with - how do you access the LDT and GDT of the process from outside the kernel? Does some code have to run in user space as root to be able to access the Intel instructions to get them? I've not gone through your code enough to see just where that magic occurs. I'm guessing SETTING (e.g., writing to) the LDT and GDT might require kernel ops to accomplish.
I know this doesn't make the most sense. But I thought I'd ping you to see if you're willing to help me sort through how to support writing to the GDT on behalf of a 286 helper. Thanks.
Okay, so according to http://docsrv.sco.com/cgi-bin/man?mansearchword=i286emul&mansection=C&lang=en , i286emul (and more importantly, SysVR2 and SysVR3 on i286) do, indeed, use GDT callgate 89:
"i286emul reads the 286 program's text and data into memory and maps them through the LDT (Local Descriptor Table) (via sysi86(S)) as 286 text and data segments. It also sets callgate 89 in the GDT (Global Descriptor Table) (which is used by 286 programs for system calls) to point to a routine in i286emul. i286emul starts the 286 program by jumping to its entry point."
So, I either need to do this via the "let them call the gate, trap, and handle the trap" approach. Interesting - I may very well need to do this with ibcs-us instead of the kernel mode.
Well, I was planning to port ibcs-us to GEMSOS (a fully segmented RTOS) anyway - and this might help solve the problem. Interestingly, we DO make extensive use of call gates, and that's what I do development on, but we have a similar problem there that we can't be guaranteed that the gates we need (7, 27, and evidently 89) aren't being used by the security kernel, so we need the trap handler mechanism, too.
And, like VMWare, you modify the executable in the lcall_sigsegv() handler, replacing lcall instructions with calls to your function. Okay - I actually know how to do that, but it's slow going, the first time, because we DON'T allow the code segment to be writable, but an inner domain / kernel-like module can "unmap" (well, un-makeknown) the segment, make it known writeable, modify it, unmakeknown it again, and then make it known executable - like I said, it won't be fast the first time through, but with a disassembler, we should be able to make most of those changes statically before running the application).
I'm sorry to clutter up your inbox with my ramblings, but I think I'm seeing a way forward ...
God lord, a fellow hacker who has read the Intel x86 Architecture documentation back in the 90's. They were such small books back then.
You can't. All the crap Intel stuffed into them notwithstanding, their primary use back in the 8086/286 days was to increase the the addressing space beyond 64k using segments. Extending the register size 32bit is a much saner way of going about that, and page tables are far easier to handle than segments if you are swapping. "The crap" like task gates, privilege level swaps and so it turned out to be far too slow so OS developers avoided them, and eventually AMD replaced the stuff they could not avoid with specialised instructions like SYSENTER / SYSEXIT. Now they are only used for interrupts - which user space has no interest in. Nonetheless it all still works. The amount of microcode AMD & Intel must carry around to support this legacy stuff must be huge.
The kernel does provide a modify_ldt(2) syscall, but it's so crippled it's useless. The 286 arch only lasted a few years, and is for all intents and purposes dead now. There are probably more Z80 users out there. The truck load of 286's Boeing keeps in temperature controlled storage so they can continue expanding 737 line while pretending that aren't changing anything doesn't really amount to much). As you say, your only hope is emulation now.
PS: This is the most entertaining stuff I've had in my inbox in years.
lol - yeah, that's what they say.
You'll be amused to know that
1) GEMSOS is a Class A1 (under TCSEC) real time secure operating system
that I work on for highly secure systems.
2) GEMSOS, as a security kernel together with the firmware and x86
architecture hardware, creates a security kernel whose design center is,
as they say, security, rather than performance or speed or nifty gadgets.
3) like ALL other secure systems built as reference monitors
implementing Mandatory Access Controls (MAC), GEMSOS makes extensive use
of segmentation and hardware protection rings, including hardware call
gates, interrupt gates, and of course normal every-day segment
descriptors (segments ranging in size of 0 bytes or from 2-2^30 or 32
bits - I forget which. 1GB? 2? not the full four.
4) in more than a decade of deployments on the internet by ICL for the
UK MoD CHoTS program, and the NSA's BLACKER program, as well as in the
Pentagon as the IBM Front End Processors to their main frame farm, there
was never a single security patch ever required for GEMSOS. No zero day
exploits. GEMSOS is able to protect itself.
5) GEMSOS runs in 286 16-bit mode, exporting a 32-bit interface for
application development. I got the 286 Pascal compiler running again
this past weekend on UnixWare 7.1.3 using the old i286emul code from
Intel used to enable SysVr2 on 386 to still run SysVr2 286 binaries.
That's what I'm working to support.
6) My ultimate goal in this line is to port the iBCS-US to run ON
GEMSOS, to provide a verifiably secure development platform for
ourselves and our customers.
7) Yes, I got past my issue. No the UnixWare kernel launches NEITHER
i286emul NOR x286emul any longer, so I'm having to wrap programs in
shell scripts or other programs that exec the emulator.
8) The secret to getting the emulator working for me was figuring out
that they APPEND the program to be executed at the END of the list of
command line arguments as a new argument. That keeps arg[0], etc. all
in their normal locations, but the execv call invokes the emulator, and
the emulator takes the final argument in the arg array as the command to
be loaded and run as a 286 binary.
9) On GEMSOS, I'll actually create the call gates for lcall 7, lcall 14?
I've forgotten the other one. I don't reasonably expect to actually
export a GDT 89 for the i286emul, but we'll see what we see...
Yup, fun times.
I see you closed the ticket, and that's fine, unless you want me to
document the resolution, which I've done above.
I'll let you know when I have a port of ibcs-us to GEMSOS for you to
wonder about. www.aesec.com
Ed
On 7/12/2021 6:39 PM, Russell Stuart wrote:
We’ll build a future in space one dogged step at a time,
and when asked how long humanity will struggle before
reaching the stars, we’ll respond,
“As long as it takes.”
Related
Tickets:
#8I closed the ticket because there is not much I personally will do. I don't have a i286emul to test it on, I don't have any spare time, and as the ibcs-us man page says I don't particularly like working on the thing. And I like to keep my open tickets manageable.
That's a remarkable feat.
Please do. And if you have patches to contribute raise a new ticket.