feat(go): advance validation sidecar toward production
This commit is contained in:
parent
6a06eba255
commit
f85c2e831a
92 changed files with 8881 additions and 91 deletions
86
go-agent/internal/system/suid.go
Normal file
86
go-agent/internal/system/suid.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ScanSUIDBinaries mirrors Python's deliberately conservative SUID/SGID walk.
|
||||
// The primary root never crosses a filesystem boundary, while explicitly
|
||||
// configured writable mounts are walked separately because tmpfs-backed paths
|
||||
// are exactly where an attacker is likely to drop a privileged binary.
|
||||
//
|
||||
// Individual unreadable entries are ignored. Host filesystems are inherently
|
||||
// racy and permission-sensitive, so one denied subtree must not discard the
|
||||
// useful portion of a scan.
|
||||
func ScanSUIDBinaries(root string, extraDirs []string) []string {
|
||||
if root == "" {
|
||||
root = "/"
|
||||
}
|
||||
result := make(map[string]bool)
|
||||
rootInfo, err := os.Lstat(root)
|
||||
if err == nil {
|
||||
device, ok := deviceID(rootInfo)
|
||||
if ok {
|
||||
walkSUID(root, &device, result)
|
||||
}
|
||||
}
|
||||
for _, directory := range extraDirs {
|
||||
info, err := os.Lstat(directory)
|
||||
if err != nil || !info.IsDir() {
|
||||
continue
|
||||
}
|
||||
walkSUID(directory, nil, result)
|
||||
}
|
||||
paths := make([]string, 0, len(result))
|
||||
for path := range result {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
sort.Strings(paths)
|
||||
return paths
|
||||
}
|
||||
|
||||
func walkSUID(root string, requiredDevice *uint64, result map[string]bool) {
|
||||
stack := []string{root}
|
||||
for len(stack) > 0 {
|
||||
directory := stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
entries, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, entry := range entries {
|
||||
path := filepath.Join(directory, entry.Name())
|
||||
info, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if info.IsDir() {
|
||||
if requiredDevice != nil {
|
||||
device, ok := deviceID(info)
|
||||
if !ok || device != *requiredDevice {
|
||||
continue
|
||||
}
|
||||
}
|
||||
stack = append(stack, path)
|
||||
continue
|
||||
}
|
||||
mode := info.Mode()
|
||||
if mode.IsRegular() && (mode&os.ModeSetuid != 0 || mode&os.ModeSetgid != 0) {
|
||||
result[path] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func deviceID(info os.FileInfo) (uint64, bool) {
|
||||
stat, ok := info.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
return 0, false
|
||||
}
|
||||
return uint64(stat.Dev), true
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue