gomcp/internal/infrastructure/antitamper/antitamper_unix.go

47 lines
1.3 KiB
Go

//go:build !windows
package antitamper
import (
"os"
"strconv"
"strings"
"syscall"
)
// platformInit applies Linux-specific anti-tamper controls.
func (s *Shield) platformInit() {
// PR_SET_DUMPABLE = 0 prevents core dumps and ptrace attachment.
// This is the strongest anti-debug measure on Linux without eBPF.
if err := syscall.Prctl(syscall.PR_SET_DUMPABLE, 0, 0, 0, 0); err != nil {
s.logger.Warn("anti-tamper: PR_SET_DUMPABLE failed (non-Linux?)", "error", err)
} else {
s.logger.Info("anti-tamper: PR_SET_DUMPABLE=0 (core dumps disabled)")
}
// PR_SET_NO_NEW_PRIVS prevents privilege escalation.
if err := syscall.Prctl(38 /* PR_SET_NO_NEW_PRIVS */, 1, 0, 0, 0); err != nil {
s.logger.Warn("anti-tamper: PR_SET_NO_NEW_PRIVS failed", "error", err)
} else {
s.logger.Info("anti-tamper: PR_SET_NO_NEW_PRIVS=1")
}
}
// isDebuggerAttached checks for debugger attachment on Linux.
func (s *Shield) isDebuggerAttached() bool {
// Method 1: Check /proc/self/status for TracerPid.
data, err := os.ReadFile("/proc/self/status")
if err == nil {
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "TracerPid:") {
pidStr := strings.TrimSpace(strings.TrimPrefix(line, "TracerPid:"))
pid, _ := strconv.Atoi(pidStr)
if pid != 0 {
return true // A process is tracing us.
}
}
}
}
return false
}