From b34eed580db3d6c7458078048baaac54beb24ba1 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 29 Sep 2026 11:42:59 -0400 Subject: [PATCH] [Docs] (P11): HSPIKE - an app_process helper with no Context gets connected sockets to the server app over Binder under the shell uid and another app uid, token-checked; ruling ID-P11-13 on the single broker mechanism and the ROM caveat --- docs/Disaggregated/notes/p11/HSPIKE.md | 23 +++++++++++++++++++ .../notes/p11/INTEGRATOR-DECISIONS-P11.md | 1 + 2 files changed, 24 insertions(+) create mode 100644 docs/Disaggregated/notes/p11/HSPIKE.md diff --git a/docs/Disaggregated/notes/p11/HSPIKE.md b/docs/Disaggregated/notes/p11/HSPIKE.md new file mode 100644 index 00000000..8572d66c --- /dev/null +++ b/docs/Disaggregated/notes/p11/HSPIKE.md @@ -0,0 +1,23 @@ +# P11 B1 预探针:无 Context 的 `app_process` helper 能否经 Binder 拿到连 server 的套接字(真机) + +2026-09-29,Redmi `2f7cbe2e`(Android 16 / HyperOS),代码 `2fcde6eb`(PAIR 之前)。报告 `~/w7/notes/p11/hspike-report.md`,证据 `~/w7/notes/p11/evidence/hspike/`,工具提交 `59a5ceeb`(`p11/hspike`,保留到 B 落地),未提交的 `fd:` 端点补丁 `evidence/hspike/fd-endpoint.diff`。 + +## 结论:两条路都通,原生路线可行 + +| 路线 | helper 所在上下文 | 结果 | +|---|---|---| +| (a) | `adb shell app_process`(`u:r:shell:s0`) | 通;openra ssim 1.0,rd12 0.99988(Espryt)/ 0.999884(Magma) | +| (b) | 从 APK #2 的进程 exec `app_process`(`untrusted_app:c84`,代表 Termux 一类) | 通;同上 | +| 令牌错或缺 | 两条路 | 按名拒绝("token mismatch" / "no expected token configured"),不给 fd、不起会话 | + +**链路**:helper 自建 Binder → 经隐藏接口 `IActivityManager.broadcastIntentWithFeature`(与 `am` 同路,参数按类型填)发**显式广播** → server app 里导出的 broker 核对 IPC 令牌 → 连两次自己的 `@mglb0`(同 app 允许)→ 两个 client 端作为 `ParcelFileDescriptor` 回给 helper → helper 清 `FD_CLOEXEC`、带 `MOBILEGL_IPC_CONTROL=fd:,` `execve` 原生 retrace client。跨类别把 c83 建的套接字交给 c84 使用,无任何 avc 拒绝(补上 B0 §6 #1 未验证的一项)。 + +**依赖 ROM 的前提**:直接跑的 `app_process` 不是 zygote fork 出来的,不受 app 的隐藏 API 黑名单约束,所以 `IActivityManager` 可用;若某个 ROM 对它也强制执行,原生路线就断——`am broadcast` 这类命令带不了 Binder,没有替代。 + +## 顺带查出(B1 要处理) + +| # | 现象 | 对 B1 的意义 | +|---|---|---| +| 1 | 从 app uid 调 `pm path` 查 server APK 被包可见性过滤;但 c84 的 `app_process` 用 APK #1 的 `base.apk` 作 `CLASSPATH` 能正常加载,显式组件广播也不需要可见性 | 无 Context 的 client 缺的只是"发现";由 server 界面生成可复制的启动命令(APK 路径、组件、令牌) | +| 2 | HyperOS 熄屏约 7 s 后冻结 server uid,在飞会话 120 s 后 `Fatal{BarrierTimeout}`;helper 的 Binder 在 `execve` 之后就没了,保不住 server。冻结也会落到 client app 上,路线 (b) 的 rd12 要靠 root 解冻才跑完 | 防冻结要另想办法(前台服务 + 文档化的每 app 电池设置),并且门要在用户能达到的拓扑下量 | +| 3 | 路线 (a) 默认落位 23.5 fps → 手工定核 118.5(与 B0 的 26 → 118 一致,helper 与 `fd:` 在数据面上零成本);路线 (b) 两种落位都约 49:退到后台的 client app 被 HyperOS 关进小核 `/background` cpuset,调用方的 `taskset` 无效 | server 侧的亲和 / 自旋策略是最大的杠杆;client 在前台时才有大核可用 | diff --git a/docs/Disaggregated/notes/p11/INTEGRATOR-DECISIONS-P11.md b/docs/Disaggregated/notes/p11/INTEGRATOR-DECISIONS-P11.md index 20327c29..6784a681 100644 --- a/docs/Disaggregated/notes/p11/INTEGRATOR-DECISIONS-P11.md +++ b/docs/Disaggregated/notes/p11/INTEGRATOR-DECISIONS-P11.md @@ -16,3 +16,4 @@ | ID-P11-10 | 2026-09-29 | 推送前发现 origin 已前进到 `86dc38a0`(另一个会话把 Magma `eglSwapInterval` 的移植直接推到了本线)。它与已合并的 dev `c60639db` 在 9 个文件上逐字相同,另加 split 专属的 `ForgetRequestedSwapInterval`(`MOBILEGL_BUILD_DISAGGREGATED` 下;传输模式下 `~BackendObject_DirectVulkan` 调用它,结束的 server 会话不把交换间隔带给下一个,与 DirectGLES 同规则)。以合并吸收(`9176dcff`,净增 16 行),不改写 origin。 | origin 不能强推;两份实现只差这一处,取并集。 | `DirectVulkan.{h,cpp}`、`BackendObject_DirectVulkan.cpp` | | ID-P11-11 | 2026-09-29 | B0 的结论(`B0-CROSS-APP.md`):跨安全上下文连 server 的 unix 端点被 SELinux `connectto` 拒(shell 与另一个 app 都是),连上之后现有代码走共享段、7 个 fd 跨类别可用,数据面与协议不用改;B1 = 跨上下文的连接中介(导出的 bound Service 经 Binder 交出已连接的套接字)+ `fd:` 端点 + 按身份配对 + 防冻结 + 外部 client 的亲和 / 自旋策略 + 调用方认证。原生程序(Termux 一类)的引导方式交用户裁定。`AcceptPair` 按到达顺序配对(F2)是现有 server 的缺陷(unix 端点与非 `--serve` 的一次性 TCP server;产品 TCP 路径本已按身份配对),独立于 B1 先修(ID-P11-12)。`p11/b0` 保留到 B 落地(证据引用 `72926a88`)。 | 用户点名的消费者是原生程序,而跨上下文只有 Binder 能带 fd;原生进程没有 `Context`。 | `B0-CROSS-APP.md`、`DEBTS.md` | | ID-P11-12 | 2026-09-29 | **PAIR**:socket client 的控制与辅助连接按 nonce 配对。client 在两条连接上各先发一条 `PairBind{nonce, aux}`(控制连接上 Hello 紧随其后);server 用 `PairAcceptor` 取代 `SocketTransport::AcceptPair`(已删):跨调用保留未配对的连接,不读 `PairBind` 之后的字节,同 nonce、角色相反才配对;什么都不发就关的连接(就绪探测)静默关闭,2 s 内没有 `PairBind` 或没等到另一半的具名拒绝后关闭,最多 16 条待配对。`protocol.fbs` 追加一张表与联合末位成员,控制协议修订 **3 → 4**(按 pin 脚本的程序);rev-3 client 连新 server 得 `Refuse{WireFingerprint}`,不会被配对。门:`PairAcceptorTest` 8 例 × unix / tcp(探测后接真 client、四条连接交错、孤立辅助连接过期后下一个 client 正常、Hello 在前的旧 client 具名拒绝)加一个真 server 的端到端用例;按到达顺序配对放回后 8 例全红、端到端 rc=6(与设备上一致)。B1 注意:代 client 建连接的 Service 必须自己写这两条 `PairBind`。 | 就绪探测与并发连接会让会话配错;B1 的 broker 更会同时代多个 client 建连接。 | `MG_Remote/Transport/*`、`Server/PairAcceptor.*`、`ServerMain.cpp`、`protocol.fbs`、`CONTRACT-P11.md` | +| ID-P11-13 | 2026-09-29 | B1 的原生路线按用户裁定(app_process helper + IPC 令牌)可行(`HSPIKE.md`):helper 经隐藏 `IActivityManager` 发显式广播交出自己的 Binder,server app 的 broker 核令牌、连自己的端点两次、以 `ParcelFileDescriptor` 交回,client 走 `fd:,`;shell 与另一 app 的 uid 下都通,令牌错按名拒绝。B1 只做这一种 broker(广播 + helper Binder,Java client 同样可用),`bindService` 等有消费者再加。依赖 ROM:直接跑的 `app_process` 不受隐藏 API 黑名单约束,若某 ROM 强制则原生路线断。`p11/hspike` 保留到 B 落地。 | 用户点名的消费者是原生程序;探针证明了唯一未验证的一环。 | `HSPIKE.md` |