diff --git a/MobileGL/MG_Remote/CONTRACT-P65.md b/MobileGL/MG_Remote/CONTRACT-P65.md index 29d191b4..4e3475b5 100644 --- a/MobileGL/MG_Remote/CONTRACT-P65.md +++ b/MobileGL/MG_Remote/CONTRACT-P65.md @@ -8,7 +8,7 @@ `MOBILEGL_TRANSPORT=spawn` 表示两进程拓扑。`MOBILEGL_IPC_CONTROL` 选择 `fork`(默认)、`unix:` 或 `tcp://host:port`,`MOBILEGL_IPC_DATA=auto|shm|stream` 选择数据面。本波 TCP 只接受 stream,fork/UNIX 只接受 shm;不支持的显式组合具名拒绝。Connect 不启动本地子进程,实际 server pid 来自 Welcome。 -TCP 两条连接依次为控制和数据。每条均设置 NODELAY、KEEPALIVE,Linux/Android 另设置 KEEPIDLE=2、KEEPINTVL=1、KEEPCNT=3、USER_TIMEOUT=5000。网络错误和 EOF 才触发 peer-hung-up;apply 超时不是 device loss。无 `MOBILEGL_IPC_TOKEN` 的 listener 仅能绑定 loopback;错令牌返回 Refuse,不打印令牌值。 +TCP 两条连接依次为控制和数据。每条均设置 NODELAY、KEEPALIVE,Linux/Android 另设置 KEEPIDLE=2、KEEPINTVL=1、KEEPCNT=3、USER_TIMEOUT=5000。网络错误和 EOF 才触发 peer-hung-up;apply 超时不是 device loss。无 `MOBILEGL_IPC_TOKEN` 的 listener 仅能绑定 loopback;错令牌返回 Refuse,不打印令牌值。(P7 包 f2-auth,PH-7 (5))`--serve` 的 TCP supervisor 在 fork 之前自己读每条连接的首帧、先验令牌:未认证对端只得到 `Refuse{Authentication}`,不带 wire 指纹与 build stamp,也不花一次 fork;首帧须在 `MOBILEGL_IPC_PREAUTH_MS`(默认 2000)内到齐;同时待认证的连接至多 `MOBILEGL_IPC_PREAUTH_MAX`(默认 8,上限 256),满时新连接顶掉占位最多的地址最老的一条(`Refuse{Busy}`),自己地址已占最多时才被拒;同一地址失败(错令牌、畸形首帧、超时、静默占位超过 250 ms)达 `MOBILEGL_IPC_AUTH_BACKOFF_AFTER`(默认 5,0 关)次后在 accept 处拒绝,窗口自 `MOBILEGL_IPC_AUTH_BACKOFF_MS`(默认 1000)起逐次翻倍、上限 60 s,一次认证成功清零。这四个旋钮只读环境变量(supervisor 不跑 ConfigLoader)。细节 `MG_Remote/Server/PreAuthGate.h`,记录债见 CONTRACT-P7 §12。 ## 握手与布局 diff --git a/MobileGL/MG_Remote/CONTRACT-P7.md b/MobileGL/MG_Remote/CONTRACT-P7.md index a04e89a4..e89bc7c3 100644 --- a/MobileGL/MG_Remote/CONTRACT-P7.md +++ b/MobileGL/MG_Remote/CONTRACT-P7.md @@ -177,14 +177,15 @@ verify **在 wave 3 之前**只在 monolith 臂注册(`MG_IntegrationTest/CMak - **B2 返工留下的记录债(`notes/p7/magma-b2.md` §6,ID-P7-35/37)**:(1) 多重采样颜色 resolve 的第二段 `vkCmdBlitImage` 不裁剪目的矩形(越界 = `VUID-vkCmdBlitImage-dstOffset-00248/00249`),与 monolith 臂共有,两臂一起裁是独立的活;(2) `MagmaWireFatal("multisample-resolve-region")` 对源矩形越出读缓冲的 blit 仍带走会话——GL 说那些像素未定义而非错误,应 decline 或钳制;(3) 1 → N 等矩形 decline 拒绝的是合法形状(18.3.1 样本复制),Vulkan 无对应命令、monolith 的可观测本身是 VU 违规;(4) tcp 车道带不了 server 端测试旋钮——六条 knob 条目只在 split + spawn,`spawn_lane_parity.py` 的 `MAGMA_SERVER_ENV_KNOB_NO_TCP` 具名;收回要 `tcp_server_fixture.py` 接受每用例 server 环境;(5) X 镜像与跨格式 Y 镜像的深 / 模板 resolve 以规则 I(a) 具名 decline(合法 blit);跨格式那条在 renderbuffer 与 texture 的 D24S8 映射到不同 `VkFormat` 的设备上会让 `MsFlip.` 变红;(6) **monolith `DirectVulkan` 臂的翻转 / 缩放多重采样深度 blit**:翻转被拒(目的地保持清屏值、无错误)、缩放被执行(GL 说 `INVALID_OPERATION`)——wire 与 monolith 的分歧,wire 臂是更正确的一方,monolith 修正归 P13 / G1;(7) **Espryt(DirectGLES)的翻转 / 缩放多重采样深度 resolve**:翻转什么也不写且不报错、缩放不报错——P3b / P4b 债;用例在这两类条目上以具名理由 `Skipped`。 - **B3 / B4 记录债(ID-P7-36/37/51)**:B3 指出的 WaitForFrameSerial 首 fence 假成功、pre-pass pending、FlushWirePendingCommandsForTextureUpdate 单 fence 假设、Present 槽回收前缺完整提交等待和 AdoptRun extent 覆盖,已由 B4 在 pipe b19297d5 修复并通过完整门;集成者 review land 见 notes/handoff/review-b4.md。 - **V1 留下的记录债(`notes/p7/verify-split.md` §6,ID-P7-37)**:verify 在 spawn 上需要一个跨进程的比对形状(server 把读到的字段值随回复带回、client 比),门 2 的文本是 `{monolith, split(inproc)}`;server `ReadPixels` 窗口里 pack 半边的字段级盲区很窄(只有恰等于中性 pack 的错推送不可见);DirectGLES × split 上四条 Magma decline 契约用例按名从 verify-split 车道减掉——Espryt 是否 decline 这些形状归 P3b / P4b。 -- **F 片 1–3 之后(`notes/p7/ph-f.md` §4,ID-P7-37)**:`wireFingerprint` 随 `Welcome.dataNonce` / `DataBind` 变更(`0x7d4470f241d23539` → `0x03c4c293a54b3e08`),新 server 对旧 client 回 `Refuse{WireFingerprint}`,旧 server 对新 client **没有 Refuse 帧**(旧 `AcceptPair` 等第二条连接 2000 ms 后关闭,client 只见 `no Welcome … (rc=6)`)——设备上的 server 必须随下一个 APK 重部署;D11 五处 + PH-2、PH-6、PH-1 (3)(4)、PH-7 (5)(fork 前认证)未做,前置是一个能向 spawn / TCP server 投递畸形记录的对端字节驱动(fuzz 臂 2 的第一块),包 **F2**。 -- **F 修复轮之后的两条小债(集成者审查,ID-P7-44)**:`ServerMain.cpp` `RunSession` 在 `Accept()` 返回到 `close(sourceFd)` 之间,supervisor 已转发的一条 DataBind 随 child 队列关闭而得不到具名拒绝(微秒级窗口);`protocol_revision_pin.py` 对 `protocol.fbs` 的注释 / 空白改动同样要求 bump(严格、有意)。 +- **F 片 1–3 之后(`notes/p7/ph-f.md` §4,ID-P7-37)**:`wireFingerprint` 随 `Welcome.dataNonce` / `DataBind` 变更(`0x7d4470f241d23539` → `0x03c4c293a54b3e08`),新 server 对旧 client 回 `Refuse{WireFingerprint}`,旧 server 对新 client **没有 Refuse 帧**(旧 `AcceptPair` 等第二条连接 2000 ms 后关闭,client 只见 `no Welcome … (rc=6)`)——设备上的 server 必须随下一个 APK 重部署;D11 五处 + PH-2、PH-6、PH-1 (3)(4)、PH-7 (5)(fork 前认证;**已由包 f2-auth 做,见本节末条**)未做,前置是一个能向 spawn / TCP server 投递畸形记录的对端字节驱动(fuzz 臂 2 的第一块),包 **F2**。 +- **F 修复轮之后的两条小债(集成者审查,ID-P7-44)**:`ServerMain.cpp` `RunSession` 在 `Accept()` 返回到 `close(sourceFd)` 之间,supervisor 已转发的一条 DataBind 随 child 队列关闭而得不到具名拒绝(微秒级窗口;**已关,包 f2-auth**:child 先 `shutdown(SHUT_RD)` 再收尽已排队的描述符逐条具名拒绝,Accept 之前的每条退出路径经 `ExitBeforeAccept` 同样处理,只剩 child 崩溃仍会丢);`protocol_revision_pin.py` 对 `protocol.fbs` 的注释 / 空白改动同样要求 bump(严格、有意)。 - **M2 r2 的代价(集成者审查,ID-P7-46)**:wire store 的 destroy epoch 进了 `UniformManager` 的两个 descriptor memo,所以每次销毁事件之后同 program 的第一笔 draw 多一次 descriptor set 分配 + 写(bsl 整跑 ~2.6 万次销毁 / 130 万次调用),并把 §6.1 的长帧内 descriptor set 增长每事件多推一个 set——这是 M3 的分母,不是新债;`ServerSpawn.cpp` 放行名单(`WIRE_DEFERRED_MB` / `SPIN_US` / `SERVER_AFFINITY` / `AUDIT`)之外的 `MOBILEGL_IPC_*` 仍被清洗,都是协议形状(双方必须一致)或 client 读的值,不记债。 - **M3 长帧 descriptor 游标(ID-P7-50)**:M2 r2 上述额外 descriptor 写入的增长已由 M3 的 2048 Acquire 边界回卷约束;证明在 graphics queue idle 后才重写 set,避免依赖 B4 尚未修的单 fence 退休。主机 bsl 确有一次回卷(缓存总数 3555 是多个 layout 的历史集合,2048 是单 epoch Acquire 上限,不是进程全局缓存上限)。queue idle stall 是性能记录项;M3 后 APK 的真机回归仍待取。 -- **Ph 簇 F 的两处预认证暴露**(wave 2-F 之前就在树上,F 修复轮审查核实,归 PH-7 (5)「有界的预认证工作 + 失败退避」,P7 之后):(a) TCP supervisor 对每条连接**先 fork 再读 Hello**(`ServerMain.cpp` `RunSession`),未认证对端每连接可让 server 付出一次 fork + 最长 10 s 的 Hello 等待;(b) `ValidatePeerHandshake` 在 `AuthenticatePeerToken` **之前**跑,`Refuse{ProtocolVersion|WireFingerprint|BuildFingerprint}` 把本端 wire 指纹与 build stamp 送给了未认证的对端。同一轮记下的本地对端债:unix 端点仍按到达顺序配对(`AcceptPair` 250 ms / 2000 ms 窗口),抽象命名空间套接字没有 mode bits,「只有本 app 能连」靠 SELinux 域隔离而非传输层。**指纹不对称**(§10 第 3 条的 `wireFingerprint` 变化):新 server 对旧 client 回 `Refuse{WireFingerprint}`;旧 server 对新 client **没有任何 Refuse 帧**——旧 `AcceptPair` 等第二条连接 2000 ms 后关掉两条,client 只看到 `no Welcome ... (rc=6)`,即设备上的 server 未随本次构建重装。细节 `notes/p7/ph-f.md` §2.2 / §6.4。 +- **Ph 簇 F 的两处预认证暴露**(**(a)(b) 已由包 f2-auth 关,见本节末条;本地对端债与指纹不对称仍在**)(wave 2-F 之前就在树上,F 修复轮审查核实,归 PH-7 (5)「有界的预认证工作 + 失败退避」,P7 之后):(a) TCP supervisor 对每条连接**先 fork 再读 Hello**(`ServerMain.cpp` `RunSession`),未认证对端每连接可让 server 付出一次 fork + 最长 10 s 的 Hello 等待;(b) `ValidatePeerHandshake` 在 `AuthenticatePeerToken` **之前**跑,`Refuse{ProtocolVersion|WireFingerprint|BuildFingerprint}` 把本端 wire 指纹与 build stamp 送给了未认证的对端。同一轮记下的本地对端债:unix 端点仍按到达顺序配对(`AcceptPair` 250 ms / 2000 ms 窗口),抽象命名空间套接字没有 mode bits,「只有本 app 能连」靠 SELinux 域隔离而非传输层。**指纹不对称**(§10 第 3 条的 `wireFingerprint` 变化):新 server 对旧 client 回 `Refuse{WireFingerprint}`;旧 server 对新 client **没有任何 Refuse 帧**——旧 `AcceptPair` 等第二条连接 2000 ms 后关掉两条,client 只看到 `no Welcome ... (rc=6)`,即设备上的 server 未随本次构建重装。细节 `notes/p7/ph-f.md` §2.2 / §6.4。 - **门 4 的 `p7-magma` 余 86 = `# P13`(ratchet88,§4.1)**:全在 disaggregated 构建的缺省传输 monolith 臂上(CI monolith-control 与门 3 参照臂在用),不动那条臂就消不掉;P13 删 `MGB_CTX`、建 server 镜像边界时随 monolith 臂离开 server 对象。四组: - 占位纹理 62(`UniformManager.cpp.o`):`TextureObject{1D,2D,2DCube,3D}` ctor、`TextureObjectBase` ctor/dtor、`TextureObjectWithOneMipmap` vtable/typeinfo、`TextureObjectBase::*` 32 + `TextureObjectWithOneMipmap::*` 20 个虚函数、`MGPipeNoteAggregate` / `TextureObjectBase::PipePublishParams`;唯一不等 P13 的路是让 monolith 臂改用 wire 原生占位(`WirePlaceholderImages.inc`),但那会改参照臂的可观测(未绑 1D/3D/立方/数组采样器由丢 draw 变成画、shadow 占位 RGBA8 → D16、MS 占位由未定义变成 (0,0,0,1)),须单独裁定 + 设备窗口。 - 采样器 14:`SamplerObject::Get{BorderColor,BorderColorI,BorderColorUI,CompareMode,MagFilter,MaxAnisotropy,MaxLod,MinFilter,MinLod,MipmapMode,SamplerCompareFunc,WrapR,WrapS,WrapT}`(`VkSamplerManager` 的 `` 实例化;5 个另由 `UniformManager::ProgramSamplesOnlySingleLevelTextures`)。 - 对象读 6:`FramebufferAttachmentObject::{GetSize,IsComplete,IsValid}`、`RenderbufferObject::IsAllocated`、`VertexArrayObject::GetIndexBufferBindingSlot`、`BufferObject::EnsureGpuResidentStorage`(monolith render pass / clear / blit / 回读 / 索引 / SSBO 与 XFB)。 - `MGB_CTX` 访问 4:`PipeInputs::{GetTextureObject,HasOpenTransformFeedbackSpan,InvalidateCompileEnv}`、`GLImpl::CopyTextureImageToClientOrPBO_State`。 - **PH-6 / fuzz 臂 3 的记录债(包 f2-event,ID-P7-2;细节 `~/w7/logs/f2-event/NOTE.md` §5)**:(1) **被丢事件所属的那条记录照常完成**:它仍贴 `kStatusOk` 回复并推进 `appliedSeq`(`ServerLoop.cpp` `DrainRing` 在该记录之后才停),而 `Client/` 里没有任何代码读 `eventDropped`(`EventRingConsumer::DroppedEvents()` 只有测试在读)——一个先发不等的 readback、事后才等其回复的 client,可能在看到 EOF 之前读到缺那次 writeback 的影子。只有不等待的 client 走得到(等待中的 client 在等待里就排空了)。修法候选是让触发 forfeit 的记录回复失败,或 client 在 `eventDropped != 0` 时闩 device-lost;两者都动 client 的等待 / 回复契约,未做。(2) **inproc 不被告知**:forfeit 停掉 apply 线程,同进程的 client 收不到任何信号。这不是「只有测试能到达」(初版 NOTE 的说法不对):(3) 的场景在 inproc 上同样可达,之后 client 的下一次等待在 120 s 后以 `Fatal{BarrierTimeout}` 死——诊断名字是错的,真因是 forfeit(审查指出,本包未测)。(3) **默认 2000 ms 未在设备上测过**:合法 client 停调 GL 超过旋钮(如 Android 退后台)且队里有一环以上未等待的事件(XFB writeback)会丢会话;此前是 30 s 后 Fatal。(4) **lockstep 臂不变**:无 `kCapRunAheadApply` 的 server(Magma)满环仍是 P5C 的 `Fatal{EventRingOverflow}`,不排空的对端让会话 SIGABRT(计入 `sessionsFaulted`,下一连接照常服务);fuzz 臂 3 没有 Magma 臂。(5) **对端不被告知原因**:没有 forfeit 的 wire 词,client 只见 EOF → device-lost;加 `Refuse` / `Fatal` 码会改 `wireFingerprint`。(6) **shm 的 `eventRingFull` 在对端可写的页上**:持续写 0 的对端让保留循环不 park 地自旋,直到旋钮耗尽后以 `TooSlow` forfeit 或会话被 Stop(有界,只记)。(7) **stream 面的阻塞 `sendmsg`**(`StreamLink.cpp:158`,apply 线程经 `StreamLink::Flush` 同步 `SendEvents`)**不是无界的**:数据套接字带 `TCP_USER_TIMEOUT=5000`(`SocketTransport.cpp:99-112`)。实测(临时探针,未入库):对端 SIGSTOP、旋钮 8000,stream 面 5327 ms 时链路被内核判死 → `ReverseChannelForfeit{PeerGone}`、exit 0;shm 面等满 8006 ms → `NotDraining`、exit 0。即 stream 面上一个冻住(活着但不 ACK)的对端约 5 s 被叫作 PeerGone,与旋钮无关;apply 线程恰好卡在 send 里时控制流又结束,`Stop()` 的 5000 ms join 与这 5 s 赛跑——未构造出,记录。(8) forfeit 后队列里剩下的记录不再应用(有意);`RunSession` 每会话每 250 ms 轮询一次控制套接字,且每一轮都查 apply 线程(记录,不是门)。(9) 排在 PH-6 等待后面的 surface op:server 的控制线程阻塞在 apply 线程的邮箱里(P5e 的等待谓词不含控制请求,本包未改),对端活着但只是不排空时,这个 op 要等旋钮耗尽才被回答;对端死亡则由数据 bell 报告(shm 面靠 server bell 挂在控制套接字上的死亡见证,镜像 CONTRACT-P6 D5c)。(10) **server bell 的死亡见证改变了 shm 会话的正常收尾顺序**:client 的 `ShutdownSend`(`ClientSession::Stop` 第 2 步)现在可能先让 apply 线程从 park 里以 dead bell 退出、再由控制循环读到 EOF;两条路走同一个退出块,每次 shm 会话正常收尾 server 日志多一行 INFO `the peer hung up (witness fd …, revents=0x2000)`(其措辞是为 client 侧写的)。 +- **PH-7 (5) + fuzz 臂 1 + ID-P7-44(包 f2-auth,分支 `p7/f2-auth`,含 fix round)关掉的与留下的**。关掉:TCP `--serve` supervisor 在 fork 前读首帧、先验令牌(未认证对端只得 `Refuse{Authentication}`,无指纹 / stamp,无 fork);首帧期限 `MOBILEGL_IPC_PREAUTH_MS`(默认 2000);待认证连接上限 `MOBILEGL_IPC_PREAUTH_MAX`(默认 8,钳到 256),满时按地址公平让位(新连接顶掉占位最多地址的最老一条,`Refuse{Busy}` "displaced ...");失败退避 `MOBILEGL_IPC_AUTH_BACKOFF_AFTER`(默认 5,0 关)/ `MOBILEGL_IPC_AUTH_BACKOFF_MS`(默认 1000,逐次翻倍,上限 60 s,认证成功清零,10 分钟遗忘,最多跟踪 256 个地址),失败 = 错令牌、畸形首帧、超时、静默占位超过 250 ms 后关闭或被顶掉;accept 遇 EMFILE/ENFILE/ENOBUFS/ENOMEM 暂停 100 ms 而非退出 73;`RunSession` 自读首帧(单会话 TCP、unix 端点)每条出路具名,令牌先于 `ValidatePeerHandshake`;ID-P7-44 见上。无 schema 变化,`MOBILEGL_PROTOCOL_CONTROL_REVISION` 与 pin 不动;**对端可见的行为变化要设备 server 随下一个 APK 重部署**:未认证的错指纹 Hello 得 Authentication 而非 WireFingerprint;静默连接 2 s 后得 Authentication(原来是 fork + 10 s 后 exit 67 且计入 faulted);会话忙时静默的第二条连接得期限拒绝而非 Busy;满队时的让位拒绝。**留下的记录债**:(1) unix 端点仍对每个 `AcceptPair` 先 fork 再读 Hello(本地对端债,不在远端威胁模型内;只补了具名拒绝);(2) 退避按对端地址计,NAT / `adb forward` 回环后的对端共用一个键,同址合法 client 会被连坐;轮换地址(如 IPv6)只受上限、期限与按地址让位约束;(3) nonce 不符的 DataBind(child 内比较)与找不到活会话的 DataBind 不计入退避(后者可能是合法的陈旧连接),两者都不花 fork;(4) 会话建立后的畸形控制帧只以日志行结束会话(child exit 0),握手之后没有给对端的帧;(5) 四个旋钮只读环境变量,不在任何配置表或 Android service extra 里;(6) ID-P7-44 的控制依赖 Linux af_unix dgram 语义(接收端 `SHUT_RD` 后 `sendmsg` 得 EPIPE),child 崩溃时已排队的 DataBind 仍被内核丢弃;(7) 测试专用杠杆 `MOBILEGL_TEST_DELAY_SESSION_HANDSHAKE_MS`(与 `MOBILEGL_TEST_DELAY_FIRST_CAPS_MS` 同类,未设不生效)。 diff --git a/docs/Disaggregated/notes/p7/ph-f.md b/docs/Disaggregated/notes/p7/ph-f.md index 6ff19b51..76c643f2 100644 --- a/docs/Disaggregated/notes/p7/ph-f.md +++ b/docs/Disaggregated/notes/p7/ph-f.md @@ -297,7 +297,9 @@ GREEN 还原: protocol revision pin: revision 1 holds (sha256 7fc859f7fa756818.. - **两处 wave 2-F 之前就存在的预认证暴露**(审查核实、归 PH-7 (5)):(a) supervisor 对每条 TCP 连接**先 fork 再读 Hello**,未认证对端每连接可让 server 付出一次 fork + 最长 10 s 的 Hello 等待;(b) `ValidatePeerHandshake` 在 `AuthenticatePeerToken` **之前**跑,`Refuse{ProtocolVersion|WireFingerprint|BuildFingerprint}` 把本端 - wire 指纹与 build stamp 送给了未认证的对端。 + wire 指纹与 build stamp 送给了未认证的对端。**(P7 F2 包 f2-auth 已关 (a)(b)**:supervisor 在 fork 前自己读首帧、 + 先验令牌,待认证工作有期限、有上限、按地址公平让位,失败按地址退避;unix 端点的「先 fork 再读 Hello」仍在, + 归本地对端债。旋钮与留下的债见 CONTRACT-P7 §12 末条、`MG_Remote/Server/PreAuthGate.h`。**)** - 令牌最小长度只在 TCP 监听处检查(§1.1)。 ---