Android 安全机制(1)uid 、 gid 与 pid

Posted by JackPeng on December 31, 2016

1、概述 

      Android 安全机制来源于Linux,并且以Linux权限管理为基础,要了解Android的安全机制,需要从linux中的安全机制了解开始,而用户的权限管理又是linux安全机制的最基本的一个组成

2、linux中的用户(UID)、组(GID)、进程(PID)

      在 Linux 中,一个用户 UID 标示一个给定用户。Linux系统中的用户(UID)分为3类,即普通用户、根用户、系统用户。

      普通用户是指所有使用Linux系统的真实用户,这类用户可以使用用户名及密码登录系统。Linux有着极为详细的权限设置,所以一般来说普通用户只能在其家目录、系统临时目录或其他经过授权的目录中操作,以及操作属于该用户的文件。通常普通用户的UID大于500,因为在添加普通用户时,系统默认用户ID从500开始编号。
      根用户也就是root用户,它的ID是0,也被称为超级用户,root账户拥有对系统的完全控制权:可以修改、删除任何文件,运行任何命令。所以root用户也是系统里面最具危险性的用户,root用户甚至可以在系统正常运行时删除所有文件系统,造成无法挽回的灾难。所以一般情况下,使用root用户登录系统时需要十分小心。
      系统用户是指系统运行时必须有的用户,但并不是指真实的使用者。比如在RedHat或CentOS下运行网站服务时,需要使用系统用户apache来运行httpd进程,而运行MySQL数据库服务时,需要使用系统用户mysql来运行mysqld进程。在RedHat或CentOS下,系统用户的ID范围是1~499。下面给出的示例显示的是目前系统运行的进程,第一列是运行该进程的用户。

       组(GID)又是什么呢?事实上,在Linux下每个用户都至少属于一个组。举个例子:每个学生在学校使用学号来作为标识,而每个学生又都属于某一个班级,这里的学号就相当于UID,而班级就相当于GID。当然了,每个学生可能还会同时参加一些兴趣班,而每个兴趣班也是不同的组。也就是说,每个学生至少属于一个组,也可以同时属于多个组。在Linux下也是一样的道理。

3、linux中进程的用户管理 (PID与UID、GID的关系)

      每个进程都拥有真实的用户、组(uid、gid),有效的用户、组(euid、egid),保存的设置用户、组(suid、sgid),还有linux中专门用于文件存储存取的用户、组id(fsuid、fsgid对于unix系统没有这两个fields)。现说明进程中每种类型用户的功能:

      (1)真实的用户、组(uid、gid):进程的真正所有者。每当用户在shell终端登录时,都会将登录用户作为登录进程的真正所有者。通过getuid来获得进程的真正用户所有者,修改进程的真正用户所有者可以通过setuid、seteuid、setresuid、setreuid。

      (2)有效的用户、组(euid、egid):进程的有效用户、组。进程所执行各种操作所允许的权限(process credentials)是依据进程的有效用户来判断的,(在linux系统中(内核2.4以上)又引入了一个新的进程权限管理模型process capabilities,通过process capabilities来确定进程所允许的各种操作[可参看《深入理解linux内核》table 20-3])。通过geteuid来获得进程的有效用户,修改进程的有效用户可以通过setuid、seteuid、setresuid、setreuid、seteuid。

      (3)文件系统的用户、组(fsuid、fsgid):用于进行文件访问的用户、组,这是linux系统中新引入的一类用户、组,对于unix系统文件的访问是通过euid来判断,没有函数获得进程的fsuid,用于修改有效用户的函数都会同时修改fsuid,如果要单独修改fsuid,而不修改euid,可以调用setfsuid。

      (4)保存的设置用户、组(suid、sgid):保存的设置用户、组。进程中该类型的用户、组主要的用处是用于还原有效用户,观察到对于非超级用户用于修改有效用户的各个函数setuid、seteuid、setresuid、setreuid、seteuid普遍有一个前提条件就是如果修改后的有效用户是原先的suid则允许修改,利用这一点,进程可以修改有效用户到一个新用户,然后还原到原来的值(原来的值保存在保存设置的用户)。通过getresuid来获得进程的真实用户、有效用户、保存的设置用户。


4、Android 系统中的UID、GID、GIDS与PID

        在 Android 上,一个用户 UID 标示一个应用程序。应用程序在安装时被分配用户 UID,应用程序在设备上的存续期间内,用户 UID 保持不变。对于普通的应用程序,GID即等于UID。

        GIDS 是由框架在 Application 安装过程中生成,与 Application 申请的具体权限相关。 如果 Application 申请的相应的 permission 被 granted ,而且有对应的GIDS, 那么 这个Application 的 gids 中将 包含这个 gids。记住权限(GIDS)是关于允许或限制应用程序(而不是用户)访问设备资源。

        Android 使用沙箱的概念来实现应用程序之间的分离和权限,以允许或拒绝一个应用程序访问设备的资源,比如说文件和目录、网络、传感器和 API。为此,Android 使用一些 Linux 实用工具(比如说进程级别的安全性、与应用程序相关的用户和组 ID,以及权限),来实现应用程序被允许执行的操作。

图 1. 两个 Android 应用程序,各自在其自己的基本沙箱或进程上

图:两个 Android 应用程序,各自在其自己的基本沙箱或进程上(具有不同的用户 ID)


        Android 应用程序运行在它们自己的 Linux 进程上,并被分配一个惟一的用户 ID。默认情况下,运行在基本沙箱进程中的应用程序没有被分配权限,因而此类应用程序访问系统或资源受到限制,Android 应用程序只能通过应用程序的 manifest 文件请求权限。

        不同的应用程序可以运行在相同的进程中。对于此方法,首先必须使用相同的私钥签署这些应用程序,然后必须使用 manifest 文件给它们分配相同的 Linux 用户 ID,这通过用相同的值/名定义 manifest 属性 android:sharedUserId 来做到,从而共享对其数据和代码的访问,如图2所示

图 2. 两个 Android 应用程序,运行在同一进程上

图:两个 Android 应用程序,运行在同一进程上(具有相同的数字签名和相同的 Linux 用户 ID)



5、总结

在 Android 上,一个应用程序只有一个UID,当然多个应用程序也可以共享一个UID。

对 于普通应用程序来说, gid 等于 uid 。由于每个应用程序之间的 uid 和 gid 都不相同, 因此不管是 native 层还是 Java 层都能够达到保护私有数据的作用 。

一个GIDS相当于一个权限的集合,一个UID可以关联GIDS,表明该UID拥有多种权限

一个进程就是host应用程序的沙箱,里面一般有一个UID和多个GIDS,每个进程只能访问UID的权限范围内的文件和GIDs所允许访问的接口,构成了Android最基本的安全基础。

后续还会介绍 Android Permission权限控制机制、Android 签名机制、Selinux Android 。


6、参考文献

1、http://blog.csdn.NET/nuoline/article/details/8610811

2、http://book.51cto.com/art/201401/427710.htm

3、http://www.educity.cn/wenda/174474.html

4、http://www.cnblogs.com/zhiyinjixu/articles/2252371.html