199 lines
5.4 KiB
C++
199 lines
5.4 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: PEImage.cpp
|
|
//
|
|
// Note: Kernel Only
|
|
//
|
|
|
|
#include "hal.h"
|
|
|
|
//////////////////////////////////////////////////////////////// Image Loader.
|
|
//
|
|
#if PAGING
|
|
extern int syscallEntryTable[];
|
|
|
|
struct AbiStackHead
|
|
{
|
|
uintptr prevBegin;
|
|
uintptr prevLimit;
|
|
uintptr esp;
|
|
};
|
|
|
|
int FakeSyscallBegin(int abiIndex)
|
|
{
|
|
// TODO: validate abiIndex, set fs, etc.
|
|
return syscallEntryTable[abiIndex];
|
|
}
|
|
|
|
// TODO: these cannot be functions; we cannot trust the user stack
|
|
uintptr PushAbiStack(uintptr esp)
|
|
{
|
|
Struct_Microsoft_Singularity_ThreadContext * context =
|
|
Class_Microsoft_Singularity_Processor::g_GetCurrentThreadContext();
|
|
AbiStackHead *head = (AbiStackHead *)(context->abiStackHead);
|
|
head->prevBegin = context->stackBegin;
|
|
head->prevLimit = context->stackLimit;
|
|
head->esp = esp;
|
|
context->stackBegin = context->abiStackBegin;
|
|
context->stackLimit = context->abiStackLimit;
|
|
return uintptr(head);
|
|
}
|
|
|
|
uintptr PopAbiStack(AbiStackHead *head)
|
|
{
|
|
Struct_Microsoft_Singularity_ThreadContext * context =
|
|
Class_Microsoft_Singularity_Processor::g_GetCurrentThreadContext();
|
|
// HACK: if the ABI call changed stackBegin/stackLimit, keep the changes
|
|
// (otherwise, switch back to original stack)
|
|
if (context->stackBegin == context->abiStackBegin) {
|
|
context->stackBegin = head->prevBegin;
|
|
context->stackLimit = head->prevLimit;
|
|
}
|
|
return head->esp;
|
|
}
|
|
|
|
//#define SEGMENT_SELECTOR(s) \
|
|
// (uint16)(offsetof(Struct_Microsoft_Singularity_CpuInfo,s) \
|
|
// - offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtNull))
|
|
//const uint16 ourFs = SEGMENT_SELECTOR(GdtPF);
|
|
|
|
__declspec(naked) void FakeSyscall()
|
|
{
|
|
__asm
|
|
{
|
|
#if 0
|
|
push ecx
|
|
push edx
|
|
call AbiStackSegment
|
|
pop edx
|
|
pop ecx
|
|
mov esp, eax // TODO: must set stackBase, stackLimit
|
|
push edx
|
|
call FakeSyscallBegin
|
|
mov edx, eax
|
|
mov eax, [esp] // eax = pointer to arg1
|
|
call edx
|
|
pop ecx // ecx = pointer to arg1
|
|
sub ecx, 4 // ecx = pointer to return address
|
|
mov esp, ecx
|
|
ret 8
|
|
#else
|
|
// user stack = ret arg1 arg2 ret arg3 ... argn ...
|
|
// ecx = ABI index
|
|
// edx = pointer to arg1
|
|
push ecx
|
|
push edx
|
|
mov ecx, edx
|
|
sub ecx, 4 // 1 word for return address
|
|
call PushAbiStack
|
|
pop edx
|
|
pop ecx
|
|
mov esp, eax
|
|
|
|
/// mov eax, edx
|
|
/// sub eax, 4 // 1 word for return address
|
|
/// mov esp, eax
|
|
sti
|
|
mov ax, ss
|
|
mov ds, ax // Copy stack segment selector to DS so we can access memory!
|
|
mov es, ax // Copy stack segment selector to ES so we can access memory!
|
|
// push (offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtPF) - offsetof(Struct_Microsoft_Singularity_CpuInfo,GdtNull))
|
|
// push ourFs
|
|
// pop fs
|
|
mov ax, 0x38 // TODO: no more hexadecimal constants
|
|
mov fs, ax
|
|
// push fs;
|
|
// pop fs; // refresh fs (TODO: don't trust user's fs)
|
|
push edx
|
|
call FakeSyscallBegin
|
|
mov edx, eax
|
|
pop eax // pointer to arg1
|
|
// user stack = ret arg1 arg2 ret arg3 ... argn ...
|
|
call edx
|
|
call Class_Microsoft_Singularity_Isal_Isa::g_EnterUserMode
|
|
|
|
// Any changes here must be reflected in EnterRing0
|
|
mov ecx, esp
|
|
push eax
|
|
push edx
|
|
call PopAbiStack
|
|
mov ecx, eax
|
|
pop edx
|
|
pop eax
|
|
mov esp, ecx
|
|
|
|
ret 8
|
|
#endif
|
|
}
|
|
}
|
|
__declspec(naked) void EnterRing0()
|
|
{
|
|
__asm
|
|
{
|
|
add esp, 4 // discard return address (pointing to FakeSyscall)
|
|
|
|
// Copied from FakeSyscall epilog:
|
|
mov ecx, esp
|
|
push eax
|
|
push edx
|
|
call PopAbiStack
|
|
mov ecx, eax
|
|
pop edx
|
|
pop eax
|
|
mov esp, ecx
|
|
|
|
ret 8
|
|
}
|
|
}
|
|
#endif // PAGING
|
|
|
|
int32 Class_Microsoft_Singularity_Loader_PEImage::
|
|
g_HalCallEntryPoint(UIntPtr entry, int threadIndex, bool runAtRing3)
|
|
{
|
|
if (entry == 0) {
|
|
__debugbreak();
|
|
return -1;
|
|
}
|
|
|
|
#if PAGING
|
|
if (runAtRing3) {
|
|
Class_Microsoft_Singularity_Isal_Isa::g_EnterUserMode();
|
|
}
|
|
#else
|
|
Assert(!runAtRing3);
|
|
#endif
|
|
|
|
int32 retval = (( int32 (__fastcall *)(int32))entry)(threadIndex);
|
|
|
|
#if PAGING
|
|
if (runAtRing3) {
|
|
// We should still be running at ring-3 when the process unwinds
|
|
Assert(Class_Microsoft_Singularity_Isal_Isa::g_IsInUserMode());
|
|
|
|
// Call ABI zero, which drops us to ring-0. Why is this not
|
|
// a gaping security hole? The kernel should verify that this
|
|
// request only ever comes from its own (trusted) code (i.e.,
|
|
// right here).
|
|
__asm {
|
|
mov ecx, 0
|
|
push ecx
|
|
push ecx
|
|
mov edx, esp
|
|
push done
|
|
_emit 0x0f
|
|
_emit 0x34 //sysenter
|
|
done:
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return retval;
|
|
}
|
|
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|