Files
HomeAgent/internal/plugin/proc/shm_security_linux.go
JianFeeeee 7a328679da feat(proc): Cleaner 跨进程修复(tool/input/output) + 共享内存安全模式 + plan §13
- Cleaner 协议统一为 cleaner.invoke(scope,name,text),覆盖工具/输入/输出三类
- 新增 ShmSecurityMode (safe/debug/full),Linux 审计探针,Windows crypto nonce
- plan.md 追加 §13 步骤分组
2026-09-10 10:21:50 +08:00

63 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build linux
package proc
import (
"fmt"
"os"
"strings"
)
// countOurShmMappings 在 Linux 上审计本 Host 的共享段被多少进程映射。
//
// 原理memfd 是匿名对象,文件系统无名,但在每个映射它的进程的
// /proc/<pid>/maps 里会有一行形如:
//
// 7f.. 7f.. rw-s 00000000 00:00 7312 .../memfd:hastagectx (deleted)
//
// 我们遍历 Supervisor.List() 给出的全部子进程 PID统计它们的 maps 中
// 出现 "memfd:hastagectx" 的行数。
// homed 自身的映射不算(它本来就该有一份)。
//
// 局限:/proc/<pid>/maps 需要同 UID/同命名空间读。读不到的 PID 直接跳过,
// 返回 ok=true 但少计——审计是告警不是判据,宁缺毋滥。
func (h *Host) countOurShmMappings() (int, bool) {
if h.sup == nil {
return 0, false
}
procs := h.sup.List()
if len(procs) == 0 {
return 0, true
}
// memfd 的"文件名"在 shmalloc_linux.go 里是 "hastagectx"。
const memfdTag = "memfd:hastagectx"
total := 0
for _, p := range procs {
if !p.Alive {
continue
}
if n, err := countMemfdLinesForPID(p.PID, memfdTag); err == nil {
total += n
}
}
return total, true
}
// countMemfdLinesForPID 读 /proc/<pid>/maps统计含 tag 的行数。
//
// 一个进程对同一 memfd 多次 mmap 会产生多行;我们计数"行数"而非
// "是否出现",这样能发现一个插件进程泄漏了多余映射的情况。
func countMemfdLinesForPID(pid int, tag string) (int, error) {
data, err := os.ReadFile(procMapsPath(pid))
if err != nil {
return 0, fmt.Errorf("读 /proc/%d/maps: %w", pid, err)
}
return strings.Count(string(data), tag), nil
}
// procMapsPath 组装 /proc/<pid>/maps 路径。pid 是内核自己 spawn 的进程号,
// 无用户输入注入面。
func procMapsPath(pid int) string {
return fmt.Sprintf("/proc/%d/maps", pid)
}