ANDROID BINDER机制浅析
Binder是Android上一种IPC机制,重要且较难理解。由于Linux上标准IPC在灵活和可靠性存在一定不足,Google基于OpenBinder的设计和构想实现了Binder。
本文只简单介绍其实现,并重点讨论Binder安全相关的内容。详细的Binder设计与实现分析,参考附录4篇文章。
一、Binder 实现
Android Binder由Client、Server、Service Manager和Binder驱动4个部件组成,下图引自网络。
在类UNIX系统中,进程是相互独立的,一个进程不能访问另一个进程的内存空间。然而内核控制着所有进程,因此可以暴露一个接口用作IPC。在Binder中这个接口就是/dev/binder设备,该设备由Binder内核驱动程序实现。
Binder驱动是整个Binder架构的核心,所有IPC都通过它来实现。
上图的Client与Server可以看作2个进程,其IPC通过对/dev/binder的ioctl实现。从Android源码可以看到,ioctl使用binder_write_read的结构体收发数据。
其中write_buffer包含驱动要执行的命令,read_buffer包含用户层需要执行的命令:
binder_write实现对bs->fd的ioctl()操作:
bs->fd是打开/dev/binder得到的文件描述符:
实际数据如何在进程间传输呢?
Binder驱动管理着每个进程的一部分地址空间。Binder管理的内存,对于进程是只读的,其写操作由内核模块实施。当一个进程向另一个进程发送消息时,内核在目标进程的内存空间申请一部分空间,接着直接将数据从发送进程复制进去。然后它将接收消息的具体位置,通过一个短消息通知给接收进程。因为消息在接收者的内存空间,接收者可以直接访问到消息。当进程不再需要这个数据时,它通知Binder驱动来释放这一内存块。
可以发现,数据经过了一次复制,所以Binder的效率不如共享内存。
Android中更高层次的IPC抽象,如Intent(跨进程组件间传递带有关联数据的命令),Messenger(支持跨进程消息通信的对象),ContentProvider(暴露跨进程数据管理接口的组件),均是基于Binder实现的。
二、Binder 安全
下图展示Binder IPC架构的一个简单例子。
每个通过Binder框架实现IBinder接口,允许被访问调用的对象都可被称作Binder对象。对Binder对象的调用在一个Binder事务处理(transaction)内部实现,其中包括一个对目标对象的引用、需执行方法的ID和一个数据缓冲区。
Binder驱动会将调用进程的ID(PID)和有效用户ID(EUID)自动添加到事务处理数据。被调用进程可以检查PID和EUID,然后基于内部实现逻辑来决定是否执行所请求的方法。
因为PID和EUID是由内核填写的,所以调用者进程不能通过伪造身份标识来获取超出系统允许的权限。这是Android安全模型的核心之一,所有更高层次抽象,比如权限,均是建立在它之上。调用者的PID和EUID通过类android.os.Binder的getCallingPid()和getCallingUid()来访问,他们是Android公开API的一部分。
三、Binder 令牌
Binder对象的一个重要属性是它具有跨进程、独一无二的身份标识。因此如果进程A创建了一个Binder对象,然后将之传递给进程B,进程B再将之传递给进程C,那么对这3个进程的调用,均由同一个Binder对象处理。实际上,进程A会通过内存地址直接引用Binder对象,而进程B和C使用Binder对象的句柄。
内核负责维护活动的Binder对象与它们在其他进程中的句柄之间的映射关系。因为一个Binder的标志符是独一无二的,并且由内核负责维护,所以用户空间进程除非通过IPC机制处理,否则不可能创建一个Binder对象的副本或获取相关引用(后面介绍如何获得Binder对象引用)。因此Binder对象是唯一的、不可伪造的、可通信的对象,可以作为安全令牌使用。
这也使得Android可以使用基于权能的安全模型(capability-based security)。
基于权能的安全模型中,通过赋予程序一个不可伪造的权能,授权程序对特定资源的访问权限。在Android中,Binder对象可以表示权能。
在这种使用方式下,Binder对象又被称作Binder令牌(Binder Token)。一个Binder令牌可以是一种权能,也可以是一个目标资源。一个进程拥有一个Binder令牌,授权该进程对Binder对象的完全访问控制权限,从而使其能够在目标对象上执行Binder事务处理操作。如果Binder对象实现了多个动作(基于Binder事务处理的code参数,选择要执行的动作),只要调用者拥有一个Binder对象的引用,就可以执行任意操作。如果需要更细粒度的访问控制,那么每个操作需要相应实现必要的权限检查,这通常利用调用者进程的PID和EUID来实现。
以上看到,获取了Binder对象引用(Binder令牌)后,就获取了目标Binder对象的完全访问权限,如果Binder事务处理操作涉及敏感动作,这是危险的。
在Android中,通常对于system(UID 10000)或root(UID 0)权限下运行的调用进程,允许执行所有操作,而对于其他进程要执行额外的权限检查。因此控制对一个重要Binder对象的访问,有2种方式:一是通过限制谁可以获得Binder对象的引用,另一个是执行该Binder对象动作前,检查调用者的身份标志(需要Binder对象自己实现)。
Binder对象可以没有其他功能实现,只被作为权能使用。这种模式下,多个协作进程可同时拥有同一个Binder对象,而作为服务端的进程(处理客户端请求)使用Binder令牌来验证它的客户端,就像Web服务器使用会话Cookie一样。
四、Binder 对象访问
出于安全考虑,Android控制着对Binder对象的访问,与Binder对象通信的唯一方法是使用该对象的引用。但很多Binder对象需要被全局访问的(尤其是系统服务)。分发所有Binder对象到每个进程是不切实际的,所以需要一种机制,来允许进程主动发现和获取这些Binder对象的引用。
Android使用servicemanger原生守护进程实现了这种发现机制。
servicemanger先于系统服务启动,因此系统服务在启动时,传递服务名和一个Binder对象引用到servicemanger进行注册。一旦注册成功,任何客户端都可以通过服务名获取它的Binder对象引用。然而大部分系统服务有额外的权限检查,所以获得引用不能自动确保对它所有功能的访问。
同时因为在servicemanger上注册后,任何人都可以访问该Binder对象引用,所以出于安全考虑,只有一部分在白名单内的系统进程才可以注册为系统服务。
可以通过service list命令查看已注册系统服务列表,该命令返回每个已注册服务的名称和实现的IBinder接口。
五、附录
Android进程间通信(IPC)机制Binder简要介绍和学习计划
ANDROID BINDER机制浅析的更多相关文章
- Android 进阶8:进程通信之 Binder 机制浅析
读完本文你将了解: IBinder Binder Binder 通信机制 Binder 驱动 Service Manager Binder 机制跨进程通信流程 Binder 机制的优点 总结 Than ...
- 【转】Android - Binder机制
以下几篇文章是分析binder机制里讲得还算清楚的 目录 1. Android - Binder机制 - ServiceManager 2. Android - Binder机制 - 普通servic ...
- Android Binder机制彻底梳理二
根据AIDL了解整体调用流程[重点分析AIDL流程]: 在上一次https://www.cnblogs.com/webor2006/p/11741743.html中我们已经对Android Binde ...
- 浅谈android binder机制
binder机制 是谷歌优化在android上更适合终端的IPC(多进程通信方式),满足系统对通信方式,传输性能和安全性的要求. 特性: 1. 用驱动程序来推进进程间的通信.2. 通过共享内存来提高性 ...
- Android Binder机制简单了解
Binder -- 一种进程间通信(IPC)机制, 基于OpenBinder来实现 毫无疑问, 老罗的文章是不得不看的 Android进程间通信(IPC)机制Binder简要介绍和学习计划 浅谈Ser ...
- android binder机制之——(创建binder服务)
Binder机制编程 前面的几篇文章具体介绍了android中binder机制的方方面面,相信你对binder机制已经有了较深刻的理解.俗话说得好"学以致用",以下我们就通过在 ...
- Android Binder机制详解:手写IPC通信
想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...
- Android binder机制---概述
1.进程间通讯的原因 目前操作系统都使用虚拟存储技术,管理内存. 假设是32位机器,0-3G是用户空间,3-4G是系统使用.虚拟内存和逻辑内存都按4K分页.这样虚拟内存和逻辑内存就存在对应关系. 一个 ...
- android binder机制详解
摘要 Binder是android中一个很重要且很复杂的概念,它在系统的整体运作中发挥着极其重要的作用,不过本文并不打算从深层次分析Binder机制,有两点原因:1是目前网上已经有2篇很好的文章了,2 ...
随机推荐
- ajax请求二进制流图片并渲染到html中img标签
日常显示图片都诸如这种形式:直接使用img的src属性 <img src="图片路径.地址" alt="" /> 以上方法无法在获取图片请求中设置请 ...
- E - Let's Go Rolling!
题目描述:数轴上有nn个质点,第ii个质点的坐标为xixi,花费为cici,现在要选择其中一些点固定,代价为这些点的花费,固定的点不动,不固定的点会向左移动直至遇到固定的点,代价是这两点的距离,如果左 ...
- docker 安装nginx、php-fpm
运行环境: 创建目录: mkdir -p /Users/sui/docker/nginx/conf.d && mkdir /Users/sui/www && cd /U ...
- redis的文件事件
redis的文件事件:即与io相关的事件. /* File event structure */ typedef struct aeFileEvent { int mask; /* one of AE ...
- wps去除首字母自动大写
首字母大写功能在不是进行英文编写时是个“自作聪明”的功能,我们可能会想把它关掉.
- ueditor自定义额外参数
<script>ue.ready(function () { ue.setContent('123456');//设置富文本编辑器初始化数据 ue.execCommand('serverp ...
- win7 php nginx 启动命令
1 php 启动命令 @echo off e: cd E:/php-/ echo "php is starting on port 9007, php_version is 7.0.6&qu ...
- 搭建Hadoop2.7.1的分布式集群
Hadoop 2.7.1 (2015-7-6更新),hadoop的环境配置不是特别的复杂,但是确实有很多细节需要注意,不然会造成许多配置错误的情况.尽量保证一次配置正确防止反复修改. 网上教程有很多关 ...
- 深入理解java虚拟机---虚拟机工具jinfo(十五)
作用: 实时查看和调整虚拟机参数. jinfo 是jdk自带的一个工具,它可以用来查看正在运行的java应用程序的扩展参数(JVM中-X标示的参数):甚至支持在运行时修改部分参数. 1.通过以下的命令 ...
- 4.5 C++重载、覆盖和遮蔽
参考:http://www.weixueyuan.net/view/6375.html 总结: 函数签名包括函数名和函数参数的个数.顺序以及参数数据类型. 需要注意的是函数签名并不包含函数返回值部分, ...