安卓namespace隔离机制

安卓namespace隔离机制

  • 引言
  • 概念
  • 加载流程
  • 思考闭环

引言

Android从8.0推出Treble计划后,提供了namespace机制。了解容器的同学,便会想到容器的隔离机制就是利用Linux的namepsace,但是此namespace是非彼namespace。Android的namepace是其系统加载so的一种隔离机制,它属于其Linker功能的一个特性。今天抽空总结下Android的namepace相关技术,本次技术分享只涉及到版本10.0及之前的namespace功能。

概念

Namespace:安卓每个加载的so都所属于一个namespace,默认的android_dlopen函数加载的so是属于名称为“default”这个namespace。每个namespace除了有name,还有关键的path属性。path属性决定了该namespace在加载so的过程中可以搜寻的路径。
Link-Namespace:为让一个namespace可以访问另一个namespace加载的库,可以将另一个namespace配置为它的link-namespace。
Shared-Libs:当配置了link-namespace后,我们可以配置这个namespace希望哪些so由link-namespace提供共享。

加载流程

整个namespace加载机制如下图
安卓namespace隔离机制_第1张图片
1 查询自己所属的namespace是否可以加载,如果已经加载,则直接返回该句柄;
2 反之,查询自己的Link-Namespace是否已经加载(注:这里的Link-Namespace是配置该so为Shared-Libs一员的Link-Namespace),如果已经加载,则直接返回该句柄;
3 反之,查询自己所属的namespace是否能够加载,即是否在其指定的搜索路径中,如果能够加载,则加载到自己所属的namespace中,然后返回句柄;
4 反之,查询自己的Link-Namespace是否能够加载(注:这里的Link-Namespace是指定该so为Shared-Libs的Link-Namespace),如果能够加载,则加载到该Link-Namespace中,然后返回句柄;
5反之,都不能加载,返回空句柄。

思考闭环

通过上述的加载流程,不难分析出一些结论(后面我也通过看linker源码和编写测试代码均已验证):
1 如果两个namespace x和y,x将a.so链接共享给y(即将x配置为y的Link-Namespace, a.so是它们可以共享加载的库),且a.so在x和y都可以访问的路径。如果y先加载a.so;后面x再加载a.so,那么就没法共享a.so。这时,在进程中将有两个a.so的映射,其代码段、全局变量等都不会共享。
2 如果两个namespace x和y以及z,x将a.so链接共享给y(即将x配置为y的Link-Namespace, a.so是它们可以共享加载的库),y将a.so链接共享给z(即将y配置为z的Link-Namespace, a.so是它们可以共享加载的库),如果a.so不在y和z的搜索路径中, 那么即使x可以加载a.so,z也无法加载到a.so。即链接共享无法传递

你可能感兴趣的:(开源解读)