1.市场上手机分身的情况
如今市场上的手机厂商都逐渐增加了应用双开的功能,如小米,华为,OPPO。
而在一个Android手机设备实现多个系统空间,即系统分身,系统之间互相隔离。有该功能的厂商有小米和华为。
下面三张图是小米的系统分身和应用双开的截图。图2中的红框分别是应用双开和系统分身入口图标,图3是通过切换分身图标进入新系统中,没有任何原系统中的应用及数据。
系统层虚拟化方案主要有Linux内核层和Android framework层两种方案。小米和OPPO都在Linux内核层做的。其中,小米用的应该是加拿大软件公司Graphite Software的Secure Spaces技术,以下是官网截图。小米,酷派,联想,blackphone等手机都使用了Graphite的产品。
接下来介绍Linux内核层和Android framework层两种方案的具体实现。
2.2. Linux内核层解决方案
《Cells: A Virtual Mobile Smartphone Architecture》
SOSP 2011 (ACM Symposium on Operating Systems Principles)
哥伦比亚大学 Jeremy Andrus, Christoffer Dall, Alexander Van’t Hof
应用场景:
哥伦比亚大学虚拟化研究室的这篇论文DEMO后来被以色列公司cellrox在2014年进行了商业化
哥伦比亚论文地址
Cellrox官网
2016年电子科技大学的一篇硕士毕业论文和这篇文章很相像,《基于安全容器的Android虚拟化技术研究》孙超群&杨霞
Background
关于namespace:
Linux Namespace是一种Linux Kernel提供的资源隔离方案,提供PID,Network,IPC,UTS,Mount,User六种资源的隔离,每个Namespace下的这些资源对于其他Namespace是不可见的。
一个进程可以同时属于多个Namespace。Linux Kernel、Namespace、Process之间的关系可以用下图描述。
Design
在Linux kernel层利用namespace + device proxy来实现虚拟android系统(VP)
每个VP都有私有的虚拟namespace
虚拟化标识符、内核接口和硬件资源,并将OS资源标识符映射到虚拟标识符上
虚拟化 文件系统路径、PID、IPC、网络接口和UID等,保证VP隔离
foreground VP独占屏幕资源
background VP依然在后方运行,能够接受系统事件,并执行任务。
VP在电脑端生成和配置,通过USB线下载到手机上
三种访问配置:
(1)no access:VP可限制某些权限,即使用户同意使用
(2)shared access:foreground VP和background VP可共享
(3)exclusive access:当foreground VP运行时,它独占所有资源,可防止信息泄露
1.共享可读的系统文件,减少内存使用
2.隔离VP以及root namespace
(1)利用UID namespace虚拟化用户凭证
(2)在内核层用namespace隔离VP及其数据
(3)使用mount namespace隔离VP文件
(4)去除VP内创建设备节点的能力
1. Kernel-level Device Virtualization
提供 隔离+硬件资源多样化
kernel device namespace:在驱动层表示数据结构并注册回调函数。当device namespace状态转变的时候回调函数被调用
每个VP都有一个device namespace
(1)虚拟化内核接口
创建device driver wrapper,用于接收foreground VP的请求,并更新设备状态。如屏幕显示的Framebuffer
(2)修改设备子系统使其能感知device namespace,如图7的输入子系统
(3)修改设备驱动使其能感知device namespace,如Binder driver
2. User-level Device Virtualization
user device namespace proxy:虚拟化设备配置,比如wifi和电话配置。
root namespace用于管理VP及两种namespace,可访问整个文件系统。
VP的启动:
CellD将挂载VP文件系统,将自己克隆到一个具有单独namespace的新进程中,并启动VP的init进程以启动用户空间环境。
CellD设置了一组IPC套接字,供VP中的进程与root namespace通信。
Cells利用LXC进行资源控制,以防止单个VP的资源不足。
A. Graphics
Android的屏幕显示依赖于Linux framebuffer (FB)来实现
进程和GPU硬件可以读写屏幕内存
- Framebuffer
创建新的FB device driver mux_fb
进程通过ioctl控制FB硬件状态
foreground VP可访问屏幕内存和显示硬件,而background VP维持着虚拟硬件状态,并将输出保存到内存中的backing buffer中。
当foreground VP mmap一个打开的FB device,mux_fb驱动时,mux_fb驱动会将相关的屏幕内存映射到进程内存中
当background VP mmap一个打开的FB device,mux_fb驱动时,mux_fb驱动会将backing buffer映射到进程内存中
foreground VP与background VP的切换过程:
交换屏幕内存和backing buffer,将backing buffer中的信息重新映射到FB,同步硬件状态,并将内存地址转换通知给GPU,以便它能更新内部图像内存映射。
2.GPU
GPU独立图像内容+ FB屏幕内存虚拟化
当foreground VP使用GPU时,会导致屏幕内存的直接变化
当background VP使用GPU时,会导致backing buffer的变化
B. Power Management
Cells通过namespace来虚拟化这个子系统
Android有三种电池管理的接口
(1)early suspend:允许驱动在设备suspend之前和resume之后接收通知
Cells通过禁止background VP初始化suspend操作来虚拟化这个子系统。
(2)frame buffer early suspend:将设备的suspend和resume状态展示到用户空间
Cells通过namespace来虚拟化这个子系统。background VP会一直认为设备在睡眠。当转换VP时,原来的background VP会感知到设备苏醒。降低电池使用度
(3)wake locks:有两种状态active和inactive,当inactive时,系统进入低电量模式或暂停。
C. Telephony
虚拟化radio stack(射频协议栈),实现VP的电话隔离
由于Vendor RIL是闭源库,无法直接修改源码加入namespace,因此利用user device namespace proxy在原来的Radio Interface Layer上加了一个RIL Proxy,包括Cells RIL和CellD。
用于控制拨打和接收电话,使得可以接收background VP的来电
利用VoIP服务实现SIM卡复用
D. Networking
内核层+用户层虚拟化
(1)核心网络资源虚拟化 network namespace
如IP地址,网络适配器,路由表和端口号
VP的虚拟标识符被转换成物理标识符
内核层实现网络和VP端Ethernet对的NAT转换,实现VP之间的网络隔离
(2)无线配置管理虚拟化
和Telephony一样,利用user device namespace proxy加入了一层代理,代替原有的无线网络配置库和RIL库。
3.Android framework层解决方案
《Condroid: A Container-based Virtualization Solution Adapted for Android Devices》
MobileCloud 2015
浙江大学 Lei Xu, Guoxi Li, Chuan Li, Weijie Sun, Wenzhi Chen, Zonghui Wang
项⽬本来有源码的后来取消掉了,剩下⽂档了。文档地址:http://condroid.github.io/
两种应用场景:
(1)公司监控员工设备,但是员工想保护隐私
(2)攻击需要支持员工的工作环境,在工作后Destroy,下一个工作日又进行恢复
方式
(1)修改Android framework层,构建独立、安全、隔离的一个Android手机设备的多系统
(2)替代了Boionic库(Android的内核库)中不支持的函数
(3)由于安卓系统版本的不同替代了一些系统调用
(4)使用Android NDK toochain交叉编译
(5)重编译内核,融入namespace和cgroup
4个特征
(1)基于namespace特征的资源隔离
namespace的目的:将一个特定的全局系统资源包装在一个抽象中,使命名空间中的进程觉得它们拥有自己的全局资源的独立实例。每个容器都感知不到其他容器。
(2)基于cgroup特征的资源控制
限制、说明和隔离流程组的资源使用
每个容器都有自己的资源区,不会被其他容器访问
(3)系统服务共享机制
/proc 文件系统
(4)文件系统共享机制
/system分区
与Cells的不同
Cells修改linux kernel层,Condroid主要修改Android framework层,更多虚拟化Binder子系统
Design
基于容器的结构
内核层和用户层设备虚拟化结合
(1)每个容器都是一个独立的安卓系统
(2)Linux容器技术(Linux Container, LXC)是一种操作系统层的轻量级虚拟化技术,LXC的实现依赖Linux 内核中的NameSpace和Cgroups 机制, NameSpace机制为不同容器间提供了隔离性,Cgroups实现了对容器的资源进行配额。
(3)虚拟化 标识符和硬件资源
(4)host android是控制中心,不会安装任何下载的app
Implementation Details
A. Binder System Virtualization
一个Android手机设备的多系统 Binder driver是ServiceManager, Service和apps的桥梁,他们通过在/dev/binder上使用syscall来传递request和response。
Condroid在内核初始化阶段注册一系列的virtual Binder devices。如Figure 2所示,Host提供主要的IPC组件(Binder Driver, ServiceManager),而在容器中的app通过virtual Binder Device与host的Binder进行通信。
Virtual Binder Driver主要有两个功能:
(1)将app在virtual binder driver上做的操作转给real binder driver
(2)如果操作是注册或请求服务,virtual driver会将service名改为Hash值,解决了命名冲突的问题
B. Display System Virtualization
Foreground container独占显示屏,但是background container的显示图像需要被及时更新和保存,以便切换系统时能及时显示实时图像。
Cells:在Linux kernel层虚拟化framebuffer device
ConDroid:在Android framework层修改WindowManager(控制window生命周期、输入时间、位置等参数的系统服务),WindowManager会将所有的window元数据发送给SurfaceFlinger,由SurfaceFlinger进行图形显示。
WindowManager的window stack决定了SurfaceFlinger会将哪个window显示在屏幕上。ConDroid通过修改container的偏移来进行屏幕切换。
C. Input System Virtualization
拦截非当前系统的event事件,只有foreground container才能感知到用户输入
input manager有两个对象:mInputDisaptcher和mInputReader(修改对象)。mInputDisaptcher负责将输入事件分配到现在激活的窗口中,mInputReader负责监控输入事件。
D. Service Sharing Mechanism
有些服务是可以在多个container之间共享的,比如电池、wifi等,Condroid允许用户通过/proc文件系统定制共享服务。
E. Filesystem Sharing Mechanism
host共享只读文件及目录给各个container