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 Bander设计与实现 - 设计篇

Android Binder设计与实现 - 实现篇

ANDROID BINDER机制浅析的更多相关文章

  1. Android 进阶8:进程通信之 Binder 机制浅析

    读完本文你将了解: IBinder Binder Binder 通信机制 Binder 驱动 Service Manager Binder 机制跨进程通信流程 Binder 机制的优点 总结 Than ...

  2. 【转】Android - Binder机制

    以下几篇文章是分析binder机制里讲得还算清楚的 目录 1. Android - Binder机制 - ServiceManager 2. Android - Binder机制 - 普通servic ...

  3. Android Binder机制彻底梳理二

    根据AIDL了解整体调用流程[重点分析AIDL流程]: 在上一次https://www.cnblogs.com/webor2006/p/11741743.html中我们已经对Android Binde ...

  4. 浅谈android binder机制

    binder机制 是谷歌优化在android上更适合终端的IPC(多进程通信方式),满足系统对通信方式,传输性能和安全性的要求. 特性: 1. 用驱动程序来推进进程间的通信.2. 通过共享内存来提高性 ...

  5. Android Binder机制简单了解

    Binder -- 一种进程间通信(IPC)机制, 基于OpenBinder来实现 毫无疑问, 老罗的文章是不得不看的 Android进程间通信(IPC)机制Binder简要介绍和学习计划 浅谈Ser ...

  6. android binder机制之——(创建binder服务)

      Binder机制编程 前面的几篇文章具体介绍了android中binder机制的方方面面,相信你对binder机制已经有了较深刻的理解.俗话说得好"学以致用",以下我们就通过在 ...

  7. Android Binder机制详解:手写IPC通信

    想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...

  8. Android binder机制---概述

    1.进程间通讯的原因 目前操作系统都使用虚拟存储技术,管理内存. 假设是32位机器,0-3G是用户空间,3-4G是系统使用.虚拟内存和逻辑内存都按4K分页.这样虚拟内存和逻辑内存就存在对应关系. 一个 ...

  9. android binder机制详解

    摘要 Binder是android中一个很重要且很复杂的概念,它在系统的整体运作中发挥着极其重要的作用,不过本文并不打算从深层次分析Binder机制,有两点原因:1是目前网上已经有2篇很好的文章了,2 ...

随机推荐

  1. MySQL的SQL语句

    一. MySQL概念 程序 =数据+指令构成,如果下载1个程序需要连带该程序所有代码+数据下载到本地,那这个程序运行起来势必造成本机内存压力暴涨,所以我们需要1个在远程server端帮我们管理数据的软 ...

  2. linux文件软链接、硬链接

    在linux ext2文件系统中,一个文件的属性存放在inode中,而数据存放在block中.每个文件占用一个inode,inode中记录了文件的权限和block地址,通过inode可以定位到bloc ...

  3. cpu占用过高排查

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器 内容解释: PID:进程的ID USER:进程所有者 PR:进程的优先级别,越小 ...

  4. win7 忘记密码

    你可以找个PE来修改密码,用光盘或U盘做PE都行,现在很多PE都支持密码修改的!不过下面这个方法还是要用到PE:1. 进入pe2.进入c:\windows\system32下 更改magnify.ex ...

  5. vs 编译库文件

    vs编译的库文件 静态库  debug和release版本 需要分开编译,我编译和实践的结果. 但是我也发现有的debug release都用同一个(搞不清楚). 然后添加到工程应用. 静态库  附件 ...

  6. 怎么样才是设计功能函数的好思路(javascript)?

    在js里面,对于函数的调用,实际上也是也是面向对象的思路,于是写好js函数,也是考核面向对象设计的能力,同时也必须考虑到如何实现高内聚和低耦合,拿一个例子来说,现在的需求是这样的,实现个投资进度框,就 ...

  7. CSS3 的box-shadow进阶之 - 动画篇 - 制作辐射动画

    本篇文章是上一篇讲box-shadow基础知识的延伸,建议先花几分钟阅读那篇文章,点击阅读,再来看这篇. 除了box-shadow属性知识外,制作动画,还需要对CSS3的animation, @key ...

  8. new_images

    /home/westward/Pictures/Screenshot from 2017-03-19 20:23:55.png

  9. .net core 在扩展中使用接口实例之IServiceProvider

    在.net core 2.0中,我们使用的对象实例大多数都是通过构造函数依赖注入进来的,但那是在一般的类中使用. 如果需要在静态/扩展类中使用某些服务类的对象实例,可以使用如下方式: 1.新建一个Se ...

  10. bind配置文件

    options{} - 整个bind使用的全局配置选项 bind监听的端口,数据文件存储位置,缓存的存储位置,权限加密的控制 logging{}- 服务日志选项 日志输出的位置,以及输出的级别 zon ...