Files
go-obfuscation/pkg/pageman/guard.go
T
2026-05-31 01:09:34 +01:00

115 lines
1.7 KiB
Go

package pageman
import (
"os"
"runtime"
"sync"
"time"
)
type Guard struct {
mu sync.Mutex
buffers []*SecureBuffer
interval time.Duration
stop chan struct{}
stopped bool
}
func NewGuard(interval time.Duration) *Guard {
return &Guard{
interval: interval,
stop: make(chan struct{}),
}
}
func (g *Guard) Watch(buf *SecureBuffer) {
g.mu.Lock()
defer g.mu.Unlock()
g.buffers = append(g.buffers, buf)
}
func (g *Guard) Start() {
go g.loop()
}
func (g *Guard) Stop() {
g.mu.Lock()
defer g.mu.Unlock()
if g.stopped {
return
}
g.stopped = true
close(g.stop)
}
func (g *Guard) loop() {
ticker := time.NewTicker(g.interval)
defer ticker.Stop()
var prevMaps []byte
for {
select {
case <-g.stop:
return
case <-ticker.C:
g.enforceAutoLock()
if runtime.GOOS == "linux" {
prevMaps = g.checkMapsTampering(prevMaps)
}
}
}
}
func (g *Guard) enforceAutoLock() {
g.mu.Lock()
bufs := make([]*SecureBuffer, len(g.buffers))
copy(bufs, g.buffers)
g.mu.Unlock()
now := time.Now()
for _, buf := range bufs {
if buf.IsClosed() || buf.IsLocked() {
continue
}
if now.Sub(buf.LastAccess()) > buf.AutoLockDuration() {
buf.forceLock()
}
}
}
func (g *Guard) checkMapsTampering(prev []byte) []byte {
current, err := os.ReadFile("/proc/self/maps")
if err != nil {
return prev
}
if prev != nil && !equalBytes(prev, current) {
g.mu.Lock()
for _, buf := range g.buffers {
if !buf.IsClosed() && !buf.IsLocked() {
buf.forceLock()
}
}
g.mu.Unlock()
}
result := make([]byte, len(current))
copy(result, current)
return result
}
func equalBytes(a, b []byte) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}