Android 14 servicemanager的前世今生2
本博文在下边两个文章的基础上,增加新的不同知识点,主要是基于Andorid14。
servicemanger的前世今生--Android 12
Android 12 S ServiceManager原理 --闪闪的vlog
接上个未完博文Android 14 servicemanager的前世今生1介绍了servicemanager的启动时序,Access类的定义和实现,以及ServiceManager的定义和重要成员变量,本节详细介绍ServiceManager类的核心成员函数,以及servicemanager的启动时序,以及servicemanager SELinux的上下文servicemanager.re。
1 ServiceMangaer类的定义
1.1 核心成员函数
getService():根据name查找service,如果service存在则返回IBinder对象。如果service不存在,则调用tryStartService()启动它。
checkService():检查指定name的service是否存在。如果service存在则返回IBinder对象,如果service不存在,则不启动它。
addService():注册指定name的service,如果该name的service存在,则用最新的service覆盖。
listService():列出所有满足优先级条件的服务列表。
registerForNotifications():注册一个服务注册时间的监听。
registerClientCallback():注册一个客户端连接或者断连的监听。
binderDied():当某个Binder对象所在的进程crash或者exit时,该方法会被调用。
tryStartService():尝试启动一个未注册的服务(实现懒加载),主要是通过设置系统属性ctl.interface_start.<name>来启动对应服务。
tryGetService():遍历mNameToService,根据name获取对应的service。根据参数bool
startIfNotFound判断当服务不存在时是否要重启。
2 servicemanager的main入口
2.1 initWithDriver
为了与vndservicemanager区分,依据main函数的参数个数,如果是2个,则第二个参数即为driver,否则driver节点为/dev/binder,与rc文件相对应。
// vndservicemanager.rc, 是需要指定参数的
service vndservicemanager /vendor/bin/vndservicemanager /dev/vndbinder// servicemanager.rc
service servicemanager /system/bin/servicemanager
2.2 创建ServiceManager对象,并注册自己
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {LOG(ERROR) << "Could not self register servicemanager";
}
2.3 成为ContextManager
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
...
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager();
3 servicemanager的SELinux上下文
代码路径:android/system/sepolicy/public/servicemanager.te
3.1 类型定义
# servicemanager - the Binder context manager
type servicemanager, domain, mlstrustedsubject;
type servicemanager_exec, system_file_type, exec_type, file_type;
- type语法:type type_id [, attribute_id, ...]
type:关键字
type_id:类型名称,唯一
attribute_id:可选一个或者多个属性,用逗号分隔
;是结束符 - 定义一个类型叫servicemanager,并赋予它两个属性:domain和mlstrustedsubject(多级安全新人主体,允许servicemanager在不同安全级别的进程间转发Binder引用)。
- 定义一个类型叫servicemanager_exec,并赋予它多个文件相关属性:system_file_type(系统文件类型,是一个在system分区中的文件/system),exec_type(可执行文件属性),file_type(通用文件属性)。
3.2 授权Binder权限
allow servicemanager self:binder set_context_mgr;
allow servicemanager {domain-init-vendor_init-hwservicemanager-vndservicemanager
}:binder transfer;
- allow语法:allow source_type target_type: object_class permisstion
allow是关键字
source_type:源类型,发起操作的主体。
target_type:目标类型(被访问的课题,如文件、设备),如果是多个目标类型,则可以用{}包裹。
object_type:对象类别(file, binders, socked, process)
permission:具体权限(read, write, execute, transfer),如果是多个权限,则可以用{}包裹。 - 常见对象类别(object_class)和权限
对象类别 常见权限 说明 file
read
,write
,execute
,open
,getattr
普通文件 dir
read
,write
,add_name
,remove_name
目录 sock_file
read
,write
Unix 域套接字文件 chr_file
read
,write
,ioctl
字符设备(如 /dev/binder
)binder
call
,transfer
,set_context_mgr
Binder IPC fd
use
文件描述符使用 fifo_file
read
,write
命名管道 process
fork
,transition
,sigchld
进程控制 - 允许servicemanager调用BINDER_SET_CONTEXT_MGR,成为Binder的上下文管理者(ContextManager)。
- 允许servicemanager从大部分域中接受和转发(transfer) Binder引用,排除项:init/-vendor_init/-hsservicemanager/-vndservicemanager域。“-” 表示排除某些类型。
3.3 授予读取系统文件权限
allow servicemanager service_contexts_file:file r_file_perms;allow servicemanager vendor_service_contexts_file:file r_file_perms;# nonplat_service_contexts only accessible on non full-treble devices
not_full_treble(`allow servicemanager vendor_service_contexts_file:file r_file_perms;')
- 允许servicemanager读取service_contexts_file类型的文件
- 允许
servicemanager
读取厂商定义的服务的上下文文件。 - 只有在非 Treble 设备上(Android7及以前版本),才再次允许读取
vendor_service_contexts_file。Treble设备(Android8)引入system和vendor解耦,引入plat_service_contexts(Platform)和vendor_service_contexts(vendor))。
🗂️ 文件路径映射
类型 路径 分区 来源 service_contexts_file
/system/etc/selinux/plat_service_contexts
system AOSP vendor_service_contexts_file
/vendor/etc/selinux/vendor_service_contexts
vendor OEM - r_file_perms:对于只读配置文件,这是一个标准权限集合,等价于{open, read, getattr, lock, ioctl }。
权限 作用 open
打开文件 read
读取内容 getattr
获取文件属性(如大小、权限) lock
文件锁(通常可忽略) ioctl
设备控制(对普通文件意义不大) - SELinux允许多条allow规则同时存在,权限是“并集”关系。
3.3 授权servicemanager可以向dumpstate报告其管理的服务列表
add_service(servicemanager, service_manager_service)
allow servicemanager dumpstate:fd use;
allow servicemanager dumpstate:fifo_file write;
- 在servicemanager启动后,它会把自己注册为一个name=manager的服务。该名称用于查询当前已注册的所有服务列表。
- 允许servicemanager使用由dumpstate进程创建的fd(文件描述符)
- 允许servicemanager写入由dumpstate进程拥有的fifo文件。
- 该三行实现了servicemanager安全地向dumpstate报告其管理的服务列表,是dumpsys命令能够工作的基础之一。
3.4 启用SELinux访问控制检查
# Check SELinux permissions.
selinux_check_access(servicemanager)
- 这是一个 宏(macro),用于启用对
servicemanager
域的 SELinux 访问控制检查。 - 实现servicemanager想判断某个进程是否有注册某个服务的权限,可以实现运行时权限控制。
3.5 日志调试
allow servicemanager kmsg_device:chr_file rw_file_perms;recovery_only(`# Read VINTF files.r_dir_file(servicemanager, rootfs)
')
- 允许servicemanager读写/dev/kmsg日志设备的文件,可以使得logd启动前servicemanager可以输出关键错误到内核日志。
- 仅在recovery模式下,允许servicemanager读取rootfs文件系统的目录和文件。
4 servicemanager的Android.bp
主要源文件是Access.cpp和ServiceManager.cpp,代码入口为main.cpp
cc_binary {name: "servicemanager",defaults: ["servicemanager_defaults"],init_rc: ["servicemanager.rc"],srcs: ["main.cpp"],bootstrap: true,
}
cc_defaults {name: "servicemanager_defaults",...srcs: ["Access.cpp","ServiceManager.cpp",],shared_libs: ["libbase","libbinder", // also contains servicemanager_interface"libvintf","libcutils","liblog","libutils","libselinux",],target: {vendor: {exclude_shared_libs: ["libvintf"],},},
}
- target: { vendor: { ...}}:用于在vendor分区构建时排除libvintf库。
- cc_defaults:定义一组可复用的编译配置(即把公共部分提取出来),供多个模块通过defaults指定复用。