本地用户空间层在 Android 操作系统的安全配置中起到重要作用。 不理解在该层上发生了什么,就不可能理解在系统中如何实施安全架构决策。 在本章中,我们的主题是 Android 引导过程和文件系统特性的,并且描述了如何在本地用户空间层上保证安全性。
要了解在本地用户空间层上提供安全性的过程,首先应考虑 Android 设备的引导顺序。 要注意,在第一步中,这个顺序可能会因不同的设备而异,但是在 Linux 内核加载之后,过程通常是相同的。 引导过程的流程如图 3.1 所示。
图 3.1:Android 启动顺序
当用户打开智能手机时,设备的 CPU 处于未初始化状态。在这种情况下,处理器从硬连线地址开始执行命令。该地址指向 Boot ROM 所在的 CPU 的写保护存储器中的一段代码(参见图 3.1 中的步骤 1)。代码驻留在 Boot ROM 上的主要目的是检测 Boot Loader(引导加载程序)所在的介质[17]。检测完成后,Boot ROM 将引导加载程序加载到内存中(仅在设备通电后可用),并跳转到引导 Boot Loader 的加载代码。反过来,Boot Loader 建立了外部 RAM,文件系统和网络的支持。之后,它将 Linux 内核加载到内存中,并将控制权交给它。 Linux 内核初始化环境来运行 C 代码,激活中断控制器,设置内存管理单元,定义调度,加载驱动程序和挂载根文件系统。当内存管理单元初始化时,系统为使用虚拟内存以及运行用户空间进程[17]做准备。实际上,从这一步开始,该过程就和运行 Linux 的台式计算机上发生的过程没什么区别了。
第一个用户空间进程是init
,它是 Android 中所有进程的祖先。 该程序的可执行文件位于 Android 文件系统的根目录中。 清单 3.1 包含此可执行文件的主要部分。 可以看出,init
二进制负责创建文件系统基本条目(7 到 16 行)。 之后(第 18 行),程序解析init.rc
配置文件并执行其中的命令。
int main( int argc, char **argv )
{
...
if (!strcmp (basename( argv[0] ), "ueventd") )
return ueventd_main ( argc, argv ) ;
...
mkdir("/dev", 0755) ;
mkdir("/proc", 0755) ;
mkdir("/sys", 0755) ;
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755") ;
mkdir("/dev/pts", 0755) ;
mkdir("/dev/socket", 0755) ;
mount("devpts", "/dev/pts", "devpts", 0, NULL) ;
mount("proc", "/proc", "proc", 0, NULL) ;
mount("sysfs", "/sys", "sysfs", 0, NULL) ;
...
init_parseconfig_file("/init.rc") ;
...
}
代码 3.1:init
程序源码
init.rc
配置文件使用一种称为 Android Init Language 的语言编写,位于根目录下。 这个配置文件可以被想象为一个动作列表(命令序列),其执行由预定义的事件触发。 例如,在清单 3.2 中,fs
(行 1)是一个触发器,而第 4 - 7 行代表动作。 在init.rc
配置文件中编写的命令定义系统全局变量,为内存管理设置基本内核参数,配置文件系统等。从安全角度来看,更重要的是它还负责基本文件系统结构的创建,并为创建的节点分配所有者和文件系统权限。
1 on fs
2 # mount mtd partitions
3 # Mount /system rw first to give the filesystem a chance to save a checkpoint
4 mount yaffs2 mtd@system /system
5 mount yaffs2 mtd@system /system ro remount
6 mount yaffs2 mtd@userdata /data nosuid nodev
7 mount yaffs2 mtd@cache /cache nosuid nodev
代码 3.2:模拟器中的fs
触发器上执行的动作列表
此外,init
程序负责在 Android 中启动几个基本的守护进程和进程(参见图 3.1 中的步骤 5),其参数也在init.rc
文件中定义。 默认情况下,在 Linux 中执行的进程以与祖先相同的权限(在相同的 UID下)运行。 在 Android 中,init
以 root 权限(UID == 0
)启动。 这意味着所有后代进程应该使用相同的 UID 运行。 幸运的是,特权进程可以将其 UID 改变为较少特权的进程。 因此,init
进程的所有后代可以使用该功能来指定派生进程的 UID 和 GID(所有者和组也在init.rc
文件中定义)。
第一个守护进程派生于init
进程,它是ueventd
守护进程。 这个服务运行自己的main
函数(参见清单 3.1 中的第 5 行),它读取ueventd.rc
和ueventd.[device name].rc
配置文件,并重放指定的内核uevent_hotplug
事件。 这些事件设置了不同设备的所有者和权限(参见清单 3.3)。 例如,第 5 行显示了如何设置文件系统对/ dev/cam
设备的权限,2.2 节中会涉及这个例子。 之后,守护进程等待监听所有未来的热插拔事件。
ueventd.rc
1 ...
2 /dev/ashmem 0666 root root
3 /dev/binder 0666 root root
4 ...
5 /dev/cam 0660 root camera
6 ...
代码 3.3:ueventd.rc
文件
由init
程序启动的核心服务之一是servicemanager
(请参阅图 3.1 中的步骤 5)。 此服务充当在 Android 中运行的所有服务的索引。 它必须在早期阶段可用,因为以后启动的所有系统服务都应该有可能注册自己,从而对操作系统的其余部分可见[19]。
init
进程启动的另一个核心进程是 Zygote。 Zygote 是一个热身完毕的特殊进程。 这意味着该进程已经被初始化并且链接到核心库。 Zygote 是所有进程的祖先。 当一个新的应用启动时,Zygote 会派生自己。 之后,为派生子进程设置对应于新应用的参数,例如 UID,GID,nice-name
等。 它能够加速新进程的创建,因为不需要将核心库复制到新进程中。 新进程的内存具有“写时复制"(COW)保护,这意味着只有当后者尝试写入受保护的内存时,数据才会从 zygote 进程复制到新进程。 从而,核心库不会改变,它们只保留在一个地方,减少内存消耗和应用启动时间。
使用 Zygote 运行的第一个进程是 System Server(图 3.1 中的步骤 6)。 这个进程首先运行本地服务,例如 SurfaceFlinger 和 SensorService。 在服务初始化之后,调用回调,启动剩余的服务。 所有这些服务之后使用 servicemanager 注册。
虽然 Android 基于 Linux 内核,它的文件系统层次不符合文件系统层次标准[10],它了定义类 Unix 系统的文件系统布局(见清单 3.4)。 Android 和 Linux 中的某些目录是相同的,例如/dev
,/proc
,/sys
,/etc
,/mnt
等。这些文件夹的用途与 Linux 中的相同。 同时,还有一些目录,如/system
,/data
和/cache
,它们不存在于 Linux 系统中。这些文件夹是 Android 的核心部分。 在 Android 操作系统的构建期间,会创建三个映像文件:system.img
,userdata.img
和cache.img
。 这些映像提供 Android 的核心功能,是在设备的闪存上存储的。 在系统引导期间,init
程序将这些映像安装到预定义的安装点,如/system
,/data
和/cache
(参见清单 3.2)。
drwxr−xr−x root root 2013−04−10 08 : 13 acct
drwxrwx−−− system cache 2013−04−10 08 : 13 cache
dr−x−−−−−− root root 2013−04−10 08 : 13 config
lrwxrwxrwx root root 2013−04−10 08 : 13 d −> /sys/kernel/debug
drwxrwx−−x system system 2013−04−10 08 : 14 data
−rw−r−−r−− root root 116 1970−01−01 00 : 00 default . prop
drwxr−xr−x root root 2013−04−10 08 : 13 dev
lrwxrwxrwx root root 2013−04−10 08 : 13 etc −> /system/etc
−rwxr−x−−− root root 244536 1970−01−01 00 : 00 init
−rwxr−x−−− root root 2487 1970−01−01 00 : 00 init . goldfish . rc
−rwxr−x−−− root root 18247 1970−01−01 00 : 00 init . rc
−rwxr−x−−− root root 1795 1970−01−01 00 : 00 init . trace . rc
−rwxr−x−−− root root 3915 1970−01−01 00 : 00 init . usb . rc
drwxrwxr−x root system 2013−04−10 08 : 13 mnt
dr−xr−xr−x root root 2013−04−10 08 : 13 proc
drwx−−−−−− root root 2012−11−15 05 : 31 root
drwxr−x−−− root root 1970−01−01 00 : 00 sbin
lrwxrwxrwx root root 2013−04−10 08 : 13 sdcard −> /mnt/sdcard
d−−−r−x−−− root sdcard r 2013−04−10 08 : 13 storage
drwxr−xr−x root root 2013−04−10 08 : 13 sys
drwxr−xr−x root root 2012−12−31 03 : 20 system
−rw−r−−r−− root root 272 1970−01−01 00 : 00 ueventd . goldfish . rc
−rw−r−−r−− root root 4024 1970−01−01 00 : 00 ueventd . rc
lrwxrwxrwx root root 2013−04−10 08 : 13 vendor −> /system/vendor
代码 3.4:Android 文件系统
/system
分区包含整个 Android 操作系统,除了 Linux 内核,它本身位于/boot
分区上。 此文件夹包含子目录/system/bin
和/system/lib
,它们相应包含核心本地可执行文件和共享库。 此外,此分区包含由系统映像预先构建的所有系统应用。 映像以只读模式安装(参见清单 3.2 中的第 5 行)。 因此,此分区的内容不能在运行时更改。
因此,/system
分区被挂载为只读,它不能用于存储数据。 为此,单独的分区/data
负责存储随时间改变的用户数据或信息。 例如,/data/app
目录包含已安装应用程序的所有 apk 文件,而/data/data
文件夹包含应用程序的home
目录。
/cache
分区负责存储经常访问的数据和应用程序组件。 此外,操作系统无线更新(卡刷)也在运行之前存储在此分区上。
因此,在 Android 的编译期间生成/system
,/data
和/cache
,这些映像上包含的文件和文件夹的默认权限和所有者必须在编译时定义。 这意味着在编译此操作系统期间,用户和组 UID 和 GID 应该可用。 Android 文件系统配置文件(见清单 3.5)包含预定义的用户和组的列表。 应该提到的是,一些行中的值(例如,参见第 10 行)对应于在 Linux 内核层上定义的值,如第 2.2 节所述。
此外,文件和文件夹的默认权限,所有者和所有者组定义在该文件中(见清单 3.6)。 这些规则由fs_config()
函数解析并应用,它在这个文件的末尾定义。 此函数在映像组装期间调用。
#define AID_ROOT 0 /* traditional unix root user */
#define AID_SYSTEM 1000 /* system server */
#define AID_RADIO 1001 /* telephony subsystem , RIL */
#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
#define AID_GRAPHICS 1003 /* graphics devices */
#define AID_INPUT 1004 /* input devices */
#define AID_AUDIO 1005 /* audio devices */
#define AID_CAMERA 1006 /* camera devices */
...
#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
...
#define AID_APP 10000 /* first app user */
...
static const struct android_id_info android_ids [ ] = {
{ "root" , AID_ROOT, },
{ "system" , AID_SYSTEM, },
{ "radio" , AID_RADIO, },
{ "bluetooth" , AID_BLUETOOTH, },
{ "graphics" , AID_GRAPHICS, },
{ "input" , AID_INPUT, },
{ "audio" , AID_AUDIO, },
{ "camera" , AID_CAMERA, },
...
{ "inet" , AID_INET, },
...
};
代码 3.5:Android 中硬编码的 UID 和 GID,以及它们到用户名称的映射
在清单 3.6 中可以看到一些二进制文件分配有setuid
和setgid
访问权限标志。例如,su
程序设置了它们。这个众所周知的工具允许用户运行具有指定的 UID 和 GID 的程序。在 Linux 中,此功能通常用于运行具有超级用户权限的程序。根据列表 3.6,二进制/system/xbin/su
的访问权限分配为“06755"(见第 21 行)。第一个非零数“6"意味着该二进制具有setuid
和setgid
(4 + 2
)访问权限标志集。通常,在Linux中,可执行文件以与启动它的进程相同的权限运行。这些标签允许用户使用可执行所有者或组的权限运行程序[11]。因此,在我们的例子中,binary/system/xbin/su
将以 root 用户身份运行。这些 root 权限允许程序将其 UID 和 GID 更改为用户指定的 UID 和 GID(见清单 3.7 中的第 15 行)。之后,su
可以使用指定的 UID 和 GID 启动提供的程序(例如,参见行 22)。因此,程序将以所需的 UID 和 GID 启动。
在特权程序的情况下,需要限制可访问这些工具的应用程序的范围。 在我们的这里,没有这样的限制,任何应用程序可以运行su
程序并获得 root 级别的权限。 在 Android 中,通过将调用程序的 UID 与允许运行它的 UID 列表进行比较,来对本地用户空间层实现这种限制。 因此,在第 9 行中,su
可执行文件获得进程的当前 UID,它等于调用它的进程的 UID,在第10
行,它将这个 UID 与允许的 UID 的预定列表进行比较。 因此,只有在调用进程的 UID 等于AID_ROOT
或AID_SHELL
时,su
工具才会启动。 为了执行这样的检查,su
导入在 Android 中定义的 UID 常量(见第 1 行)。
/* Rules for directories .*/
static struct fs_path_config android_dirs [ ] = {
{ 00770 , AID_SYSTEM, AID_CACHE, "cache" } ,
{ 00771 , AID_SYSTEM, AID_SYSTEM, "data/app" } ,
...
{ 00777 , AID_ROOT, AID_ROOT, "sdcard" } ,
{ 00755 , AID_ROOT, AID_ROOT, 0 } ,
};
/* Rules for files .*/
static struct fs_path_config android_files [ ] = {
...
{ 00644 , AID_SYSTEM, AID_SYSTEM, "data/app/*" } ,
{ 00644 , AID_MEDIA_RW, AID_MEDIA_RW, "data/media/*" } ,
{ 00644 , AID_SYSTEM, AID SYSTEM, "data/app−private /*" } ,
{ 00644 , AID_APP, AID_APP, "data/data/*" } ,
...
{ 02755 , AID_ROOT, AID_NET_RAW, "system/bin/ping" } ,
{ 02750 , AID_ROOT, AID_INET, "system/bin/netcfg" } ,
...
{ 06755 , AID_ROOT, AID_ROOT, "system/xbin/su" } ,
...
{ 06750 , AID_ROOT, AID_SHELL, "system/bin/run−as" } ,
{ 00755 , AID_ROOT, AID_SHELL, "system/bin/*" } ,
...
{ 00644 , AID_ROOT, AID_ROOT, 0 } ,
};
代码 3.6:默认权限和所有者
此外,在较新的版本(从 4.3 开始),Android 核心开发人员开始使用 Capabilities Linux 内核系统[4]。 这允许它们额外限制需要以 root 权限运行的程序的权限。 例如,对于su
程序来说,它不需要具有 root 用户的所有特权。 对于这个程序,它足以有能力修改当前的 UID 和 GID。 因此,此工具只需要CAP_SETUID
和CAP_SETGID
root 权限来正常运行。
#include <private/android_filesystem_config.h>
...
int main( int argc, char **argv )
{
struct passwd *pw;
int uid, gid, myuid ;
/* Until we have something better , only root and the shell can use su . */
myuid = getuid () ;
if (myuid != AID_ROOT && myuid != AID_SHELL) {
fprintf ( stderr, "su : uid %d not allowed to su\n", myuid) ;
return 1;
}
...
if ( setgid ( gid ) || setuid ( uid ) ) {
fprintf ( stderr, "su : permission denied\n") ;
return 1;
}
/* User specified command for exec . */
if ( argc == 3 ) {
if ( execlp ( argv[2], argv[2], NULL) < 0) {
fprintf ( stderr , "su : exec failed for %s Error:%s\n" , argv [2] ,
strerror ( errno ) ) ;
return −errno ;
}
...
}
代码 3.7:su
程序的源代码
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。