感谢提交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.


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


方案更新(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 是宿主必然持有的通道。


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


方案更新(以此为准,关联 PR:!32402)
issue 描述中的方案有两处已过期,最终落地的修改方案如下:
-
授权表(
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双向清理)释放。
-
授权 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 均已登记放行。 -
校验收紧: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 前完成授权;同进程场景与系统进程调用路径不受影响。


问题背景
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,缺少宿主对客进程的显式授权机制。
修改方案
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双向清理)释放。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 均已登记放行。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 前先完成授权。同进程场景与系统进程调用路径不受影响。