已关闭
UIExtension跨进程渲染:SurfaceNode创建与command改为宿主显式授权模型 #25967
huaixu-y创建于  8月19日关闭于  8月22日
huaixu-y
huaixu-y
8月19日 创建

问题背景

UIExtension 跨进程渲染场景:宿主进程(UEA)生成 NodeId 后传递给 UEC 进程(Guest),UEC 通过该 NodeId 调用 CREATE_NODE_AND_SURFACE IPC 创建 SurfaceNode,此时 ExtractPid(NodeId) = hostPid ≠ callingPid = UEC pid。

现有实现为"无条件放行":

  • rs_client_to_render_connection_stub.cpp 中 CREATE_NODE_AND_SURFACE 对 UI_EXTENSION_COMMON_NODE/UI_EXTENSION_SECURE_NODE 类型跳过 IsValidCallingPid 校验,任何非系统进程可用任意 NodeId 创建 UIExtension SurfaceNode;
  • RSTransactionData::CheckNonSystemCommand 及各 command 校验点(proxy node、animation、node showing)对命中 IsUIExtensionSurfaceNode(nodeId) 的节点放行任意 caller。

即任何进程可冒用他人 NodeId 创建 UIExtension 节点并下发 command,缺少宿主对客进程的显式授权机制。

修改方案

  1. 授权表(rs_render_node_map.h/.cpp):RSRenderNodeMap::uiExtensionSurfaceNodes_ 由 std::unordered_set<NodeId> 改为 std::unordered_map<NodeId, pid_t>,value 记录被授权的 UEC pid;删除 IsUIExtensionSurfaceNode 与注册时的 AddUIExtensionSurfaceNode 登记(注册不再登记,授权是唯一写入口),新增:
    • AuthorizeUIExtensionPid(NodeId, guestPid, enforcePerHostQuota):宿主授权客进程(允许节点注册前的预授权;拒绝 guestPid<=0 或等于 hostPid;enforcePerHostQuota=true 时同一 hostPid 限 500 条,防恶意应用刷表拒绝服务);
    • RevokeUIExtensionPid(NodeId, guestPid):撤销授权;
    • IsUIExtensionAuthorized(NodeId, callingPid):权限校验查询(替换原 IsUIExtensionSurfaceNode);
    • GetUIExtensionGuestPid(NodeId):获取被授权的客进程 pid(hostPid 恒等于 ExtractPid(nodeId),不单独存储)。
      配额计数表 uiExtensionHostEntryCounts_ 与授权表同锁同步维护,配额检查 O(1);授权项随节点注销(UnregisterRenderNode→RemoveUIExtensionSurfaceNode)、宿主/客进程死亡(FilterNodeByPid 双向清理)释放。
  2. 授权 IPC 链路:客户端入口 RSInterfaces::AuthorizeUIExtensionPid(定义在 RSInterface 而非 RSRenderInterface,UEC 调 CreateNodeAndSurface 前 UEA 无需获取 renderPipelineClient)→ RSRenderServiceClient → client_to_service 连接(新增枚举 AUTHORIZE_UIEXTENSION_PID = 0x014005,同步 TF_SYNC,返回值代表 render process 已实际接受并应用)→ render_service 侧 RSClientToServiceConnection 校验仅 NodeId 属主进程可授权/撤销(ExtractPid(nodeId)==callingPid,≤0 回退连接级 remotePid_),并经 GetAccessType 判定调用方是否非系统应用(token 不可识别时保守按非系统处理),随转发下发 enforceQuota 标志 → 经 renderProcessManagerAgent_->GetServiceToRenderConns() 转发(与 RegisterUIExtensionCallback 同一模式)→ service_to_render 连接(新增枚举 AUTHORIZE_UIEXTENSION_PID = 0x00F018,TF_SYNC)→ RSServiceToRenderConnection 复核宿主 pid → RSRenderPipelineAgent 写入 NodeMap 授权表——仅当 guest pid 在该 render process 已建立 client-to-render 连接时才插入(FindClientToRenderConnection 门控),其余 render process 跳过,避免授权条目在无连接进程中残留;因此 UEA 须在 UEC 建立连接之后再授权、在 UEC 调 CreateNodeAndSurface 之前完成授权。两条通道的 verifier 均已登记放行。
  3. 校验收紧:CREATE_NODE_AND_SURFACE 对 UI_EXTENSION 类型跨 pid 创建要求预先授权;rs_transaction_data.cpp、rs_proxy_node_command.cpp、rs_animation_command.cpp、rs_node_showing_command.cpp 各 command 校验点同步切换为 IsUIExtensionAuthorized(nodeId, callingPid)。

兼容性影响

行为收紧:改动后 UEA 必须先调用授权 IPC(且在 UEC 建立 client-to-render 连接之后),UEC 才能 CREATE_NODE_AND_SURFACE 及下发 command,需要 UEA 侧(UIExtension 框架)配套在分发 NodeId 前先完成授权。同进程场景与系统进程调用路径不受影响。

likedislike
openharmony_ci
openharmony_ci成员
8月19日 评论:

感谢提交Issue!关于Issue的交互操作,请访问OpenHarmony社区支持命令清单。如果有问题,请联系 [@liumingxiang1](https://gitcode.com/liumingxiang1) [@comicchang](https://gitcode.com/comicchang) [@aslklw](https://gitcode.com/aslklw) [@wang-luyu4](https://gitcode.com/wang-luyu4) [@lijj01](https://gitcode.com/lijj01) [@chensiyi_CE](https://gitcode.com/chensiyi_CE) [@stonesxd](https://gitcode.com/stonesxd) [@xuyuqiong](https://gitcode.com/xuyuqiong) [@kroswang](https://gitcode.com/kroswang) [@djnash](https://gitcode.com/djnash) [@gmiao522](https://gitcode.com/gmiao522) [@wh_qwe](https://gitcode.com/wh_qwe) [@liuchao-huawei](https://gitcode.com/liuchao-huawei) [@BruceXu](https://gitcode.com/BruceXu) [@liuchuan666](https://gitcode.com/liuchuan666) [@gaoweihua](https://gitcode.com/gaoweihua) 。如果需要调整订阅PR、Issue的变更状态,请访问链接。


Thanks for submitting the issue. For more commands, please visit OpenHarmony Command List. If you have any questions, please refer to committer gitcode for help. If you need to change the subscription of a Pull Request or Issue, please visit the link.

likedislike
openharmony_ciopenharmony_ci成员
8月19日 添加了label:waiting_for_assign
huaixu-yhuaixu-y
8月19日 关联了pull request:UIExtension跨进程渲染:SurfaceNode创建与command改为宿主显式授权模型
huaixu-y
huaixu-y
8月19日 评论:

方案更新:客户端授权入口由 RSRenderInterface 调整为 RSInterfaces::AuthorizeUIExtensionPid——RSInterfaces 单例内部持有基于默认 token 的 client_to_render 连接(RSRenderPipelineClient),UEA 无需等待 UIContext/renderPipelineClient 就绪,可在 UEC 调用 CreateNodeAndSurface 之前完成授权。已在关联 PR !32402 中更新。

likedislike
huaixu-y
huaixu-y
8月19日 评论:

方案更新(PR !32402 已同步):授权 IPC 不再挂在 client_to_render 连接上,改为 client_to_service → service_to_render 转发链路——客户端 RSInterfaces::AuthorizeUIExtensionPid 经 RSRenderServiceClient 走 client_to_service 连接(异步);render_service 侧 RSClientToServiceConnection 做 NodeId 属主校验后经 GetServiceToRenderConns() 转发;render_process 侧 RSServiceToRenderConnection 复核宿主 pid 后写入 NodeMap 授权表。原因是 UEA 在 UEC 调 CreateNodeAndSurface 前拿不到 render 侧连接,client_to_service 是宿主必然持有的通道。

likedislike
huaixu-y
huaixu-y
8月19日 评论:

方案更新(PR !32402 已同步):NodeMap 查询接口定为 GetUIExtensionHostPid 的替代命名 GetUIExtensionGuestPid,返回授权表中的 guest(UEC)pid(未授权返回 0);hostPid 恒等于 ExtractPid(nodeId),不单独提供访问器。

likedislike
huaixu-y
huaixu-y
8月20日 评论:

方案更新(以此为准,关联 PR:!32402)

issue 描述中的方案有两处已过期,最终落地的修改方案如下:

  1. 授权表(rs_render_node_map.h/.cpp):RSRenderNodeMap::uiExtensionSurfaceNodes_ 由 std::unordered_set<NodeId> 改为 std::unordered_map<NodeId, pid_t>,value 记录被授权的 UEC pid;删除 IsUIExtensionSurfaceNode 与注册时的 AddUIExtensionSurfaceNode 登记(注册不再登记,授权是唯一写入口),新增:

    • AuthorizeUIExtensionPid(NodeId, guestPid):宿主授权客进程(允许节点注册前的预授权;拒绝 guestPid<=0 或等于 hostPid;表项上限 1024 防恶意刷表);
    • RevokeUIExtensionPid(NodeId, guestPid):撤销授权;
    • IsUIExtensionAuthorized(NodeId, callingPid):权限校验查询(替换原 IsUIExtensionSurfaceNode);
    • GetUIExtensionGuestPid(NodeId):获取被授权的客进程 pid(注意是 Guest 不是 Host;hostPid 恒等于 ExtractPid(nodeId),不单独存储)。
      授权项随节点注销、宿主/客进程死亡(FilterNodeByPid 双向清理)释放。
  2. 授权 IPC 链路:客户端入口为 RSInterfaces::AuthorizeUIExtensionPid(定义在 RSInterface 而非 RSRenderInterface,UEC 调 CreateNodeAndSurface 前 UEA 无需获取 renderPipelineClient)→ RSRenderServiceClient → client_to_service 连接(新增枚举 AUTHORIZE_UIEXTENSION_PID = 0x014005,异步 TF_ASYNC)→ render_service 侧 RSClientToServiceConnection 校验仅 NodeId 属主进程可授权/撤销(ExtractPid(nodeId)==callingPid,≤0 回退连接级 remotePid_)→ 经 renderProcessManagerAgent_->GetServiceToRenderConns() 转发(与 RegisterUIExtensionCallback 同一模式)→ service_to_render 连接(新增枚举 AUTHORIZE_UIEXTENSION_PID = 0x00F018,TF_SYNC)→ RSServiceToRenderConnection 复核宿主 pid → RSRenderPipelineAgent 写入 NodeMap 授权表。两条通道的 verifier 均已登记放行。

  3. 校验收紧:CREATE_NODE_AND_SURFACE 对 UI_EXTENSION 类型跨 pid 创建要求预先授权;rs_transaction_data.cpp、rs_proxy_node_command.cpp、rs_animation_command.cpp、rs_node_showing_command.cpp 各 command 校验点同步切换为 IsUIExtensionAuthorized(nodeId, callingPid)。

兼容性影响不变:行为收紧,UEA 必须先调授权 IPC,UEC 才能 CREATE_NODE_AND_SURFACE 及下发 command,需 UEA 侧(UIExtension 框架)配套在分发 NodeId 前完成授权;同进程场景与系统进程调用路径不受影响。

likedislike
huaixu-yhuaixu-y
8月20日 修改了issue 的描述
huaixu-yhuaixu-y
8月21日 修改了issue 的描述
huaixu-yhuaixu-y
8月21日 修改了issue 的描述
openharmony_ciopenharmony_ci成员
8月22日 关闭了 issue
openharmony_ciopenharmony_ci成员
8月22日 issue状态由 待办的 改变为 已完成