Files
HomeAgent/internal
JianFeeeee ecde8dd515 fix(update): 补上内核升级缺失的四道安全闸(H1–H4)
四条缺陷的共同点都是「静默产出一个看起来成功的升级」,而失败的表现
是机器进崩溃循环且没人知道原因。

H1 dataDir 为空必须拒绝升级
  Apply 此前只在 dataDir 非空时写 pending,空值仅跳过标记、后照常替换
  二进制 ⇒ 产出「无回滚能力」的升级。现改为在动任何文件之前直接失败。
  另新增导出 update.ResolveDataDir(env → <exe>/data 兜底)。

H2 备份目录不能写 /root
  backup 原为 /root/homed-upgrade-backup-<ts>,服务在 ProtectSystem=strict
  + ReadWritePaths=/var/lib/hologram 下运行,非 root 对 /root 无写权限
  ⇒ MkdirAll 必 EACCES ⇒ 首次升级必挂。改为落在 dataDir 下。
  rollback 的 homed-broken-<ts> 同样从(通常只读的)二进制目录挪到 dataDir。

H3 备份目录要有 GC
  旧注释写「确认稳定后可删」,但全仓无任何删除逻辑。新增
  PruneOldBackups:保留最近 3 个 homed-upgrade-backup-* 与最近 1 个
  homed-broken-*,其余 RemoveAll,在 Apply 成功返回前调用。
  只处理名字精确为「前缀 + NowStamp 形态」的目录,不误删 pending 标记
  或前缀相近的第三方目录。

H4 结果事件吞错误 + 成功不发 result
  publishResult 里 `if errMsg != "" { _ = errMsg }` 把失败原因丢弃,payload
  也没有 error 字段 ⇒ 订阅方只看到 ok=false。现在 error 字段恒定存在。
  Apply 成功路径此前从不发 result,现补发 ok=true。

测试:kernel_apply_test.go 新增 5 个用例(含题目要求的四个函数名)。
2026-10-28 17:20:35 +08:00
..