fix: login cursor ghost after double save-bg + integrity GOT immunity (DSK-E70 workaround)

- login: remove duplicate cursor_save_bg after draw_login_card (ghost residue)
- login: hidden visibility on __text_*/__expected_hash -> lea rip, len calc no longer depends on GOT slot
- login: dsk_e70_layout_guard keeps .text out of the DSK write-zero minefield (whitelisted, see STATUS.md)
- patch_login_hash: hash first PT_LOAD filesz (matches loader/runtime range) + e_shstrndx section names
- STATUS.md: register DSK-E70 (unresolved ibuf-tail write-zero, root cause open)
This commit is contained in:
Linehu
2026-10-05 02:34:15 +08:00
parent 3aebe962be
commit ee8b607f9a
3 changed files with 56 additions and 20 deletions
+23 -10
View File
@@ -6,7 +6,7 @@ if (-not (Test-Path $ElfPath)) { Write-Error ("not found: " + $ElfPath); exit 1
$bytes = [System.IO.File]::ReadAllBytes($ElfPath)
# ELF64 header: e_shoff @ 0x28 (u64), e_shentsize @ 0x3A (u16), e_shnum @ 0x3C (u16)
# ELF64 header: e_shoff @ 0x28 (u64), e_shentsize @ 0x3A (u16), e_shnum @ 0x3C (u16), e_shstrndx @ 0x3E (u16)
function U64([byte[]]$b, [int]$o) { [UInt64]$b[$o] -bor ([UInt64]$b[$o+1] -shl 8) -bor ([UInt64]$b[$o+2] -shl 16) -bor ([UInt64]$b[$o+3] -shl 24) -bor ([UInt64]$b[$o+4] -shl 32) -bor ([UInt64]$b[$o+5] -shl 40) -bor ([UInt64]$b[$o+6] -shl 48) -bor ([UInt64]$b[$o+7] -shl 56) }
function U16([byte[]]$b, [int]$o) { [UInt32]$b[$o] -bor ([UInt32]$b[$o+1] -shl 8) }
function U32([byte[]]$b, [int]$o) { [UInt32]$b[$o] -bor ([UInt32]$b[$o+1] -shl 8) -bor ([UInt32]$b[$o+2] -shl 16) -bor ([UInt32]$b[$o+3] -shl 24) }
@@ -14,16 +14,30 @@ function U32([byte[]]$b, [int]$o) { [UInt32]$b[$o] -bor ([UInt32]$b[$o+1] -shl 8
$shoff = U64 $bytes 0x28
$shentsize = U16 $bytes 0x3A
$shnum = U16 $bytes 0x3C
$shstrndx = U16 $bytes 0x3E
$textOff = 0; $textSize = 0; $hashOff = 0
$shstr = $null
for ($i = 0; $i -lt $shnum; $i++) {
$sh = $shoff + $i * $shentsize
$shType = U32 $bytes ($sh + 4)
$shOffset = U64 $bytes ($sh + 24)
$shSize = U64 $bytes ($sh + 32)
if ($shType -eq 3 -and -not $shstr) { $shstr = $bytes[[int]$shOffset..[int]($shOffset+$shSize-1)] }
# e_shstrndx points at .shstrtab directly — picking the first SHT_STRTAB is wrong
# when .dynsym/.strtab exist (they come before .shstrtab and would garble names)
$shstrHdr = $shoff + $shstrndx * $shentsize
$shstrOff = U64 $bytes ($shstrHdr + 24)
$shstrSize = U64 $bytes ($shstrHdr + 32)
$shstr = $bytes[[int]$shstrOff..[int]($shstrOff+$shstrSize-1)]
# Hash range = first PT_LOAD segment (offset/filesz). This matches exactly what
# the DSK loader copies into memory and what the runtime hashes via
# __text_start..__text_end (the output section may include tail padding that
# the .text section header's sh_size does not cover — hashing sh_size caused
# LOGIN-E01 integrity FAIL whenever lld emitted padding after .text).
$phoff = U64 $bytes 0x20
$phentsize = U16 $bytes 0x36
$phnum = U16 $bytes 0x38
for ($i = 0; $i -lt $phnum; $i++) {
$ph = $phoff + $i * $phentsize
$pType = U32 $bytes $ph
if ($pType -eq 1) { $textOff = U64 $bytes ($ph + 8); $textSize = U64 $bytes ($ph + 32); break }
}
if ($textOff -eq 0) { Write-Error 'PT_LOAD text segment not found'; exit 1 }
function Get-SectName([byte[]]$strtab, [int]$idx) {
$end = $idx
@@ -38,11 +52,10 @@ for ($i = 0; $i -lt $shnum; $i++) {
$shOffset = U64 $bytes ($sh + 24)
$shSize = U64 $bytes ($sh + 32)
$nm = Get-SectName $shstr $nameIdx
if ($nm -eq '.text' -and $shType -eq 1) { $textOff = $shOffset; $textSize = $shSize }
if ($nm -eq '.hashseg') { $hashOff = $shOffset }
}
if ($textOff -eq 0 -or $hashOff -eq 0) { Write-Error 'section .text/.hashseg not found'; exit 1 }
if ($textOff -eq 0 -or $hashOff -eq 0) { Write-Error 'PT_LOAD text/.hashseg not found'; exit 1 }
$sha = [System.Security.Cryptography.SHA256]::Create()
$textBytes = New-Object byte[] $textSize