diff --git a/src/engine/win32/contract.h b/src/engine/win32/contract.h index 36cb0d9..ed0210c 100644 --- a/src/engine/win32/contract.h +++ b/src/engine/win32/contract.h @@ -1,13 +1,14 @@ -#ifndef CONTRACT_MAGIC0 -#define CONTRACT_MAGIC0 0x3A7C1E94B2D6F058ull +#ifndef CONTRACT_MAGIC +#define CONTRACT_MAGIC 0x3A7C1E94B2D6F058ull #endif -#ifndef CONTRACT_MAGIC1 -#define CONTRACT_MAGIC1 0x9F41D80E6BC57A23ull -#endif - -#ifndef CONTRACT_ACK -#define CONTRACT_ACK 0xACED5EEDACED5EEDull +/* Companion magic = byte-reversed primary, folded to an immediate at -O2 (no + * runtime bswap). One source of truth; in memory magic0 ++ magic1 forms a + * 16-byte palindrome. The host echoes this value into `ack` to acknowledge, so + * there is no separate ack constant. (CONTRACT_MAGIC must not be a byte + * palindrome, or magic1 would equal magic0.) */ +#ifndef CONTRACT_MAGIC_R +#define CONTRACT_MAGIC_R (__builtin_bswap64(CONTRACT_MAGIC)) #endif #ifndef VMIE_CONTRACT_H diff --git a/src/engine/win32/guest.c b/src/engine/win32/guest.c index 7b1851f..e593f61 100644 --- a/src/engine/win32/guest.c +++ b/src/engine/win32/guest.c @@ -5,13 +5,8 @@ #define ACK_POLL_MS 5u #endif -#ifndef ACK_TIMEOUT_MS -#define ACK_TIMEOUT_MS (120*1000u) -#endif - int main(void) { contract* c = VirtualAlloc(NULL, sizeof *c, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - uint32_t timeout = ACK_TIMEOUT_MS; if (c == NULL) { return 1; } @@ -20,22 +15,21 @@ int main(void) { c->va_self = (uint64_t)(uintptr_t)c; c->ack = 0; - c->magic1 = CONTRACT_MAGIC1; + c->magic1 = CONTRACT_MAGIC_R; MemoryBarrier(); - c->magic0 = CONTRACT_MAGIC0; + c->magic0 = CONTRACT_MAGIC; - do { - if (*(volatile uint64_t*)&c->ack == CONTRACT_ACK) { - c->magic0 = 0; - c->magic1 = 0; - VirtualUnlock(c, sizeof *c); - VirtualFree(c, 0, MEM_RELEASE); - break; - } + /* Live until acknowledged. A VMI host may attach at any moment - or only + * after the guest has idled for a long time - so there is no justified + * deadline: poll the ack flag forever, exit only once the host sets it. */ + while (*(volatile uint64_t*)&c->ack != CONTRACT_MAGIC_R) { + Sleep(ACK_POLL_MS); + } - Sleep(ACK_POLL_MS); - } while (timeout -= ACK_POLL_MS); - - return timeout > 0 ? 0 : 255; + c->magic0 = 0; + c->magic1 = 0; + VirtualUnlock(c, sizeof *c); + VirtualFree(c, 0, MEM_RELEASE); + return 0; } \ No newline at end of file diff --git a/src/engine/win32/host.c b/src/engine/win32/host.c index 34db062..2f7d02a 100644 --- a/src/engine/win32/host.c +++ b/src/engine/win32/host.c @@ -62,7 +62,7 @@ static int beacon_find(vmie_mem* m, uint64_t* pa, uint64_t* va) { do { const contract* c = (void*)ptr; - if (c->magic0 == CONTRACT_MAGIC0 && c->magic1 == CONTRACT_MAGIC1) { + if (c->magic0 == CONTRACT_MAGIC && c->magic1 == CONTRACT_MAGIC_R) { *pa = offset_gpa(m, ptr - m->pa); *va = c->va_self; return 0; @@ -204,7 +204,7 @@ static uint32_t ko_export_rva(vmie_mem* m, uintptr_t cr3, uint64_t kbase, const } static void beacon_ack(vmie_mem* m, uint64_t anchor_pa) { - uint64_t ack = CONTRACT_ACK; + uint64_t ack = CONTRACT_MAGIC_R; gpa_write(m, anchor_pa + offsetof(contract, ack), &ack, 8); }