Service Contexts
本文面向已经读过 安全上下文、TE规则语法、File Contexts、Property Contexts 和 Binder 系列基础文章的读者。前文说明路径、属性名如何映射到 Context;本篇聚焦系统 Binder 的名字空间:service_contexts 如何把 activity、android.hardware.power.IPower/default 这样的服务名映射到 service_manager 对象类的 target Context,servicemanager 如何据此检查 add/find/list,服务表何时更新,以及 lazy service、VINTF accessor 和死亡回调如何改变结束路径。
本文不讨论 hwservice_contexts 或 vndservice_contexts 的完整实现,它们分别属于后续专题。也不把 service_manager add/find 和服务对象真正执行 Binder transaction 的 binder call 混为一谈:前者由 servicemanager 使用 service_contexts 授权名字空间操作,后者由 Binder 驱动和目标进程的 process/domain policy 消费。读完后,读者应能从一个服务名追到文本条目、分区 module、selabel_lookup()、Access::actionAllowed()、ServiceManager 的状态表和错误返回,并能定位“服务未注册”“注册被拒绝”“查找被拒绝”“找到服务但调用被拒绝”四种不同故障。
1. 名字与对象
1.1 服务名
service_contexts 的 key 是 servicemanager 接口使用的字符串。Framework 服务通常使用短名;AIDL/HAL 服务使用接口全名加实例名。两者在 lookup 层没有不同的安全机制,都会作为同一个 service_manager backend 的 key。
源码文件:system/sepolicy/private/service_contexts
activity u:object_r:activity_service:s0
window u:object_r:window_service:s0
android.hardware.power.IPower/default u:object_r:hal_power_service:s0
android.hardware.camera.provider.ICameraProvider/internal/0 \
u:object_r:hal_camera_service:s0
* u:object_r:default_android_service:s0最后的 * 是服务 backend 的默认 Context;它不自动给予任何域 add 或 find 权限。target type 仍必须在 policy 中具有 service_manager_type attribute,调用者还必须满足相应 access vector。
1.2 三种权限
servicemanager 对名字空间暴露三种与本篇直接相关的权限:
| 权限 | 消费者 | 作用 |
|---|---|---|
add | ServiceManager::addService() | 将 binder 对象写入名字到服务的表 |
find | getService()、checkService()、通知/连接信息查询 | 读取名字对应的 binder 对象或请求 lazy 启动 |
list | listServices()、debug info | 列出服务名或服务调试信息 |
这三个权限的 target object class 都是 service_manager,target Context 来自 service_contexts。获得 binder 引用之后,客户端再发起 transaction 时还会经过 binder 类的 call 检查;service_contexts 不替代该检查。
1.3 Service表
ServiceManager 的 owner 是 mNameToService,键是服务名,值保存 binder、allowIsolated、dump priority、client 状态和注册者 CallingContext。注册回调和 client 回调分别保存在两个 map 中。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.h
using ServiceCallbackMap =
std::map<std::string, std::vector<RegistrationCallback>>;
using ClientCallbackMap =
std::map<std::string, std::vector<sp<IClientCallback>>>;
using ServiceMap = std::map<std::string, Service>;
ServiceMap mNameToService;
ServiceCallbackMap mNameToRegistrationCallback;
ClientCallbackMap mNameToClientCallback;
std::unique_ptr<Access> mAccess;2. 文本条目
2.1 平台服务
Android 17 平台文件包含大量 framework 服务名和 AIDL 服务名。下面只取能说明命名层级的条目,不是服务清单。
源码文件:system/sepolicy/private/service_contexts
android.frameworks.stats.IStats/default u:object_r:fwk_stats_service:s0
android.frameworks.sensorservice.ISensorManager/default \
u:object_r:fwk_sensor_service:s0
android.system.keystore2.IKeystoreService/default \
u:object_r:keystore_service:s0
android.system.net.netd.INetd/default u:object_r:system_net_netd_service:s0
android.os.UpdateEngineService u:object_r:update_engine_service:s0
android.security.keystore u:object_r:keystore_service:s0服务名是否带 /instance 是接口注册约定;SELinux 只按最终字符串查找 Context。相同 target type 可以被多个服务名共享,但每个调用者仍需要对该 target type 的 add 或 find 权限。
2.2 条件条目
Contexts 文件经过 M4,因此 release flag 可以控制条目是否进入当前输出。条件没有满足时,源码中存在的名字不会出现在产物中。
源码文件:system/sepolicy/private/service_contexts
is_flag_enabled(RELEASE_HARDWARE_BLUETOOTH_RANGING_SERVICE, `
android.hardware.bluetooth.ranging.IBluetoothChannelSounding/default \
u:object_r:hal_bluetooth_service:s0
')
is_flag_enabled(RELEASE_AISEAL_FRAMEWORK, `
aiseal_host u:object_r:aiseal_host_service:s0
aiseal_internal u:object_r:aiseal_internal_service:s0
')2.3 默认Context
平台文件通常用 * 提供 default Android service Context。lookup 是否使用它由 selabel backend 决定;如果 backend 没有 handle,servicemanager 不会用任意字符串继续完成 MAC 检查。
源码文件:system/sepolicy/private/service_contexts
* u:object_r:default_android_service:s03. 分区构建
3.1 输入Module
Soong 为 platform、system_ext、product、vendor 和 odm 分别注册 service_contexts module。分区属性决定输入 filegroup 和安装变体;运行时 system/vendor ServiceManager 再选择对应 handle。
源码文件:system/sepolicy/contexts/Android.bp
service_contexts {
name: "plat_service_contexts",
defaults: ["contexts_flags_defaults"],
srcs: [":service_contexts_files{.plat_private}"],
}
service_contexts {
name: "system_ext_service_contexts",
defaults: ["contexts_flags_defaults"],
srcs: [":service_contexts_files{.system_ext_private}"],
system_ext_specific: true,
}
service_contexts {
name: "vendor_service_contexts",
defaults: ["contexts_flags_defaults"],
srcs: [
":service_contexts_files{.plat_vendor}",
":service_contexts_files{.vendor}",
":service_contexts_files{.reqd_mask}",
],
soc_specific: true,
}3.2 通用生成
service_contexts 使用 buildServiceContexts(),默认把 Remove_comment 设为 true,再复用 buildGeneralContexts() 的 newline、M4、release flag 和注释清理。service contexts 不使用 file contexts 的 fc_sort 分支。
源码文件:system/sepolicy/build/soong/selinux_contexts.go
func (m *selinuxContextsModule) buildServiceContexts(
ctx android.ModuleContext, inputs android.Paths) android.Path {
if m.properties.Remove_comment == nil {
m.properties.Remove_comment = proptools.BoolPtr(true)
}
return m.buildGeneralContexts(ctx, inputs)
}
func serviceFactory() android.Module {
m := newModule()
m.build = m.buildServiceContexts
return m
}3.3 测试Module
service contexts 测试使用 checkfc -s,而不是 file contexts 的默认 backend。-s 表示 binder service backend;测试加载编译 policy,验证 target type 属于 service_manager_type。
源码文件:system/sepolicy/build/soong/selinux_contexts.go
case ServiceContext:
flags = []string{"-s" /* binder services */}
case HwServiceContext:
flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */}
case VndServiceContext:
flags = []string{"-e" /* allow empty */, "-v" /* vnd service */}4. Libselinux加载
4.1 路径选择
libselinux 为 service contexts 定义正式路径。Android 17 的实现按分区选择存在的文件,再交给 Android service label backend;vendor ServiceManager 使用 vendor 变体。
源码文件:external/selinux/libselinux/src/android/android.c
static const path_alts_t service_context_paths = { .paths = {
{ "/system/etc/selinux/plat_service_contexts", "/plat_service_contexts" },
{ "/system_ext/etc/selinux/system_ext_service_contexts", "/system_ext_service_contexts" },
{ "/product/etc/selinux/product_service_contexts", "/product_service_contexts" },
{ "/vendor/etc/selinux/vendor_service_contexts", "/vendor_service_contexts" },
{ "/odm/etc/selinux/odm_service_contexts", "/odm_service_contexts" },
}};4.2 Handle缓存
Access 缓存一个 selabel_handle。SELinux 状态更新后,旧 handle 被关闭,下一次操作重新打开;服务表中的已有 binder 不会因为 handle 刷新而自动重注册。
源码文件:frameworks/native/cmds/servicemanager/Access.cpp
static struct selabel_handle* getSehandle() {
static struct selabel_handle* gSehandle = nullptr;
if (gSehandle != nullptr && selinux_status_updated()) {
selabel_close(gSehandle);
gSehandle = nullptr;
}
if (gSehandle == nullptr) {
gSehandle = kIsVendor
? selinux_android_vendor_service_context_handle()
: selinux_android_service_context_handle();
}
CHECK(gSehandle != nullptr);
return gSehandle;
}4.3 Lookup失败
服务名 lookup 失败时,Access 记录 No match for ... in service_contexts 并返回 false;它不会把未匹配的名字当作允许。
源码文件:frameworks/native/cmds/servicemanager/Access.cpp
bool Access::actionAllowedFromLookup(const CallingContext& sctx,
const std::string& name,
const char* perm) {
char* tctx = nullptr;
if (selabel_lookup(getSehandle(), &tctx, name.c_str(),
SELABEL_CTX_ANDROID_SERVICE) != 0) {
LOG(ERROR) << "SELinux: No match for " << name
<< " in service_contexts.\n";
return false;
}
bool allowed = actionAllowed(sctx, tctx, perm, name);
freecon(tctx);
return allowed;
}5. Access判定
5.1 Caller Context
source SID 来自 Binder 调用者,优先从 IPCThreadState 读取;target Context 来自服务名 lookup。这两个来源在代码中分别由 getCallingContext() 和 selabel_lookup() 表达。
源码文件:frameworks/native/cmds/servicemanager/Access.cpp
Access::CallingContext Access::getCallingContext() {
IPCThreadState* ipc = IPCThreadState::self();
const char* callingSid = ipc->getCallingSid();
pid_t callingPid = ipc->getCallingPid();
return CallingContext{
.debugPid = callingPid,
.uid = ipc->getCallingUid(),
.sid = callingSid ? std::string(callingSid)
: getPidcon(callingPid),
};
}5.2 MAC调用
actionAllowed() 固定使用 service_manager class,把 add、find 或 list 作为 permission 传入 selinux_check_access()。
源码文件:frameworks/native/cmds/servicemanager/Access.cpp
bool Access::actionAllowed(const CallingContext& sctx,
const char* tctx,
const char* perm,
const std::string& tname) {
#ifdef __ANDROID__
const char* tclass = "service_manager";
AuditCallbackData data{.context = &sctx, .tname = &tname};
return 0 == selinux_check_access(
sctx.sid.c_str(), tctx, tclass, perm,
reinterpret_cast<void*>(&data));
#else
return true;
#endif
}5.3 三个入口
canAdd()、canFind() 都按服务名 lookup;canList() 使用 servicemanager 自身 Context 作为 target,因此 list 不是逐服务 find。
源码文件:frameworks/native/cmds/servicemanager/Access.cpp
bool Access::canFind(const CallingContext& ctx,
const std::string& name) {
return actionAllowedFromLookup(ctx, name, "find");
}
bool Access::canAdd(const CallingContext& ctx,
const std::string& name) {
return actionAllowedFromLookup(ctx, name, "add");
}
bool Access::canList(const CallingContext& ctx) {
return actionAllowed(ctx, mThisProcessContext,
"list", "service_manager");
}5.4 Target属性
服务 Context 的 type 必须拥有 service_manager_type attribute;API attribute 决定 app domain 的可见范围。
源码文件:system/sepolicy/public/service.te
type activity_service, app_api_service, ephemeral_app_api_service,
system_server_service, service_manager_type;
type window_service, system_api_service,
system_server_service, service_manager_type;
type hal_power_service, protected_service,
hal_service_type, service_manager_type;源码文件:system/sepolicy/private/service.te
neverallow domain ~{ service_manager_type vndservice_manager_type }:
service_manager { add find };6. 注册路径
6.1 UID检查
普通 App UID 在进入 SELinux canAddService() 前就被 ServiceManager 拒绝。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
auto ctx = mAccess->getCallingContext();
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
return Status::fromExceptionCode(
Status::EX_SECURITY,
"App UIDs cannot add services.");
}6.2 权限与名称
通过 canAddService() 后,ServiceManager 仍检查 binder 非空和名称合法性;名称允许 /,所以 AIDL instance 名可以保留接口/实例结构。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
if (binder == nullptr) {
return Status::fromExceptionCode(
Status::EX_ILLEGAL_ARGUMENT, "Null binder.");
}
if (!isValidServiceName(name)) {
ALOGE("%s Invalid service name: %s",
ctx.toDebugString().c_str(), name.c_str());
return Status::fromExceptionCode(
Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
}6.3 表项提交
注册成功后把 binder、allowIsolated、dump priority 和 server Context 写入名字表。同名注册覆盖旧表项并保留 client 状态。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
auto it = mNameToService.find(name);
bool prevClients = false;
if (it != mNameToService.end()) {
const Service& existing = it->second;
prevClients = existing.hasClients;
if (existing.ctx.sid != ctx.sid) {
ALOGW("Service '%s' originally registered from SID %s "
"but it is now being registered from SID %s.",
name.c_str(), existing.ctx.sid.c_str(), ctx.sid.c_str());
}
}
mNameToService[name] = Service{
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.hasClients = prevClients,
.guaranteeClient = false,
.ctx = ctx,
};6.4 死亡清理
远程 binder 在写表前 linkToDeath;死亡回调删除服务表和关联 callback。清理后名字仍可由新 server 重新 add。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
if (binder->remoteBinder() != nullptr &&
binder->linkToDeath(
sp<ServiceManager>::fromExisting(this)) != OK) {
return Status::fromExceptionCode(
Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
}7. 查找路径
7.1 get与check
getService() 允许启动 lazy service,checkService() 不启动;两者的 Binder 状态通过输出参数表达,Status 出于历史兼容可能仍为 ok。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::getService(const std::string& name,
sp<IBinder>* outBinder) {
*outBinder = tryGetBinder(name, true).service;
return Status::ok();
}
Status ServiceManager::checkService(const std::string& name,
sp<IBinder>* outBinder) {
*outBinder = tryGetBinder(name, false).service;
return Status::ok();
}7.2 Isolated状态
allowIsolated 是注册者写入的 Service 状态,不是 SELinux target attribute。isolated caller 即使拥有 find,也可能被该字段返回空。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
if (!service->allowIsolated &&
is_multiuser_uid_isolated(ctx.uid)) {
LOG(WARNING) << "Isolated app with UID " << ctx.uid
<< " requested '" << name
<< "', but the service is not allowed for isolated apps.";
return os::ServiceWithMetadata();
}7.3 Find与Lazy
服务表有无 binder 不决定权限;canFind() 先决定 caller 是否可以观察该名字。只有 find 通过且 getService() 发现 binder 缺失时,才异步设置 ctl.interface_start。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
if (!mAccess->canFind(ctx, name)) {
return os::ServiceWithMetadata();
}
if (!out && startIfNotFound) {
tryStartService(ctx, name);
}源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
std::thread([=] {
if (!base::SetProperty("ctl.interface_start",
"aidl/" + name)) {
ALOGI("Tried to start aidl service %s as a lazy service, "
"but was unable to.", name.c_str());
}
}).detach();7.4 Accessor
平台 ServiceManager 对 VINTF accessor 服务先检查原名 find,再查 accessor binder;vendor 构建排除此路径。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
if (accessorName.has_value()) {
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
return os::Service::make<os::Service::Tag::accessor>(nullptr);
}
return os::Service::make<os::Service::Tag::accessor>(
tryGetBinder(*accessorName, startIfNotFound).service);
}8. 列举与通知
8.1 List权限
listServices() 只执行一次 canList(),然后按 dump priority 遍历表。具体服务的 find 不会自动授予 list。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::listServices(
int32_t dumpPriority,
std::vector<std::string>* outList) {
if (!mAccess->canList(mAccess->getCallingContext())) {
return Status::fromExceptionCode(
Status::EX_SECURITY, "SELinux denied.");
}
for (auto const& [name, service] : mNameToService) {
if (service.dumpPriority & dumpPriority) {
outList->push_back(name);
}
}
return Status::ok();
}8.2 注册通知
registerForNotifications() 需要 find 权限。callback 保存于 mNameToRegistrationCallback,服务后来 add 时才 dispatch;已存在服务则立即通知。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::registerForNotifications(
const std::string& name,
const sp<IServiceCallback>& callback) {
auto ctx = mAccess->getCallingContext();
std::optional<std::string> accessorName;
if (auto status = canFindService(ctx, name, &accessorName);
!status.isOk()) {
return status;
}
mNameToRegistrationCallback[name].push_back(
RegistrationCallback{.callback = callback, .ctx = ctx});
return Status::ok();
}8.3 Client回调
client callback 只允许服务自身注册。ServiceManager 比较调用 PID 和表中 server PID,再比较 binder 对象,避免任意 find 客户端伪造服务 client 状态。
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
if (serviceIt->second.ctx.debugPid !=
IPCThreadState::self()->getCallingPid()) {
return Status::fromExceptionCode(
Status::EX_UNSUPPORTED_OPERATION,
"Only service can register client callback for itself.");
}
if (serviceIt->second.binder != service) {
return Status::fromExceptionCode(
Status::EX_ILLEGAL_ARGUMENT, "Service mismatch.");
}9. 自注册与实例
9.1 manager服务
servicemanager 启动后把自身注册为 manager,再成为 Binder context manager。自注册同样经过 add 权限和 service contexts lookup。
源码文件:frameworks/native/cmds/servicemanager/main.cpp
sp<ServiceManager> manager =
sp<ServiceManager>::make(std::make_unique<Access>());
manager->setRequestingSid(true);
if (!manager->addService(
"manager", manager, false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
IPCThreadState::self()->setTheContextObject(manager);
if (!ps->becomeContextManager()) {
LOG(FATAL) << "Could not become context manager";
}9.2 Ready属性
系统 servicemanager 完成 Binder polling 和自注册后设置 servicemanager.ready=true。这是 property service 事件,不是 service_contexts 的注册完成标志。
源码文件:frameworks/native/cmds/servicemanager/main.cpp
#ifndef VENDORSERVICEMANAGER
if (!SetProperty("servicemanager.ready", "true")) {
LOG(ERROR) << "Failed to set servicemanager ready property";
}
#endif9.3 Vendor实例
vndservicemanager 复用 Access/ServiceManager,但定义 VENDORSERVICEMANAGER=1,通常使用 /dev/vndbinder,并选择 vendor service Context handle。
源码文件:frameworks/native/cmds/servicemanager/Android.bp
cc_binary {
name: "vndservicemanager",
defaults: ["servicemanager_defaults"],
init_rc: ["vndservicemanager.rc"],
vendor: true,
cflags: ["-DVENDORSERVICEMANAGER=1"],
required: ["vndservice"],
srcs: ["main.cpp"],
}10. Policy配套
10.1 服务类型
target type 必须带 service_manager_type。Framework type 还使用 app/system API 和 system server attribute 描述可见范围。
源码文件:system/sepolicy/public/service.te
type activity_service, app_api_service,
ephemeral_app_api_service, system_server_service,
service_manager_type;
type window_service, system_api_service,
system_server_service, service_manager_type;
type hal_power_service, protected_service,
hal_service_type, service_manager_type;10.2 Add规则
服务端需要对 target type 拥有 service_manager add。
源码文件:system/sepolicy/private/system_server.te
add_service(system_server, system_server_service);
allow system_server artd_service:service_manager find;
allow system_server audioserver_service:service_manager find;
allow system_server cameraserver_service:service_manager find;
allow system_server drmserver_service:service_manager find;
allow system_server fingerprintd_service:service_manager find;add_service(system_server, system_server_service) 展开为 system_server 对该 target 的 add/find,并生成“其他 domain 不得 add”的 neverallow;system_server 对具体服务的许多操作则是 find 规则,因为这些服务由其他进程提供。
10.3 Find规则
客户端 find 与 server add 独立。拥有 find 不意味着能 add,也不意味着可以调用接口。
源码文件:system/sepolicy/private/isolated_app_all.te
allow isolated_app_all activity_service:service_manager find;
allow isolated_app_all activity_structured_service:service_manager find;
allow isolated_app_all display_service:service_manager find;10.4 Binder调用
取得 binder 后,transaction 继续由 binder class 的 call/transfer 权限和接口业务权限控制。
源码文件:system/sepolicy/public/te_macros
define(`binder_call', `
allow $1 $2:binder { call transfer };
allow $2 $1:binder transfer;
')11. 失败定位
11.1 注册失败
| 现象 | 代码位置 | 先检查 |
|---|---|---|
| App UIDs cannot add services | addService() | caller UID |
| SELinux denied for service | canAddService() | key、target type、add rule |
| No match in service_contexts | Access::actionAllowedFromLookup() | flag、分区产物、名字 |
| Invalid service name | isValidServiceName() | 长度和字符集 |
| VINTF declaration error | meetsDeclarationRequirements() | accessor/manifest |
| Couldn't linkToDeath | addService() | remote binder 生命周期 |
11.2 查找失败
查找为空时分别检查表项是否存在、isolated 是否不允许、find 是否被拒绝、lazy property 是否设置、服务是否最终重新注册。getService() 的 Status 可能为 ok,真正结果是输出 binder。
11.3 调用失败
服务已 find 但 transaction 被拒绝,应检查目标服务进程 domain、Binder call/transfer policy 和接口 permission;修改 service_contexts 不会授予 call。
11.4 Handle刷新
SELinux status 更新会触发 handle 重载。新 contexts 文件缺失或损坏可能使 CHECK(gSehandle != nullptr) 致命退出,区别于一次性的 access deny。
12. 测试与验证
12.1 Checkfc断言
service contexts 的静态测试选择 checkfc -s,使用 service_manager_type attribute。它只证明文本和 policy 的静态契约,不证明 caller 权限。
源码文件:system/sepolicy/tools/checkfc.c
static const char * const CHECK_SC_ASSERT_ATTRS[] = {
"service_manager_type", NULL
};
case filemode_service_contexts:
return CHECK_SC_ASSERT_ATTRS;12.2 SM测试
构建文件声明 host/device 测试,覆盖 ServiceManager 的状态、API、回调和死亡处理。
源码文件:frameworks/native/cmds/servicemanager/Android.bp
cc_test {
name: "servicemanager_test",
host_supported: true,
test_suites: ["device-tests"],
defaults: ["servicemanager_defaults"],
srcs: ["test_sm.cpp"],
static_libs: ["libgmock"],
}
cc_test_host {
name: "servicemanager_unittest",
test_suites: ["general-tests"],
defaults: ["servicemanager_defaults"],
srcs: ["ServiceManagerUnittest.cpp"],
static_libs: ["libgmock"],
}12.3 构建命令
# 初始化构建环境并选择实际产品。
source build/envsetup.sh
lunch PRODUCT-userdebug
# 构建 contexts、静态检查和 ServiceManager 测试。
m plat_service_contexts plat_service_contexts_test \
vendor_service_contexts vendor_service_contexts_test \
servicemanager_unittest servicemanager_test构建成功表示当前输入能生成文本并通过静态规则;还需设备运行时证据。
12.4 设备命令
# 查看名字表;该命令自身需要 servicemanager:list。
adb shell service list | rg 'activity|window|power'
# 查看调用者 domain。
adb shell id -Z
# 查看服务进程 domain;它不是 service_contexts target type。
adb shell ps -AZ | rg 'system_server|servicemanager'
# 筛选名字空间拒绝与服务名。
adb shell dmesg | rg 'service_manager|activity|window|denied'service list 只证明名字表可列举;ps -AZ 只证明进程 domain;transaction 失败仍需检查 Binder call 和接口权限。
12.5 复述任务
给定 activity,应能复述:system_server 调用 add,Access 以 calling SID 为 source、从 service_contexts 取 activity_service 为 target,执行 service_manager:add;通过名称、binder 和死亡链接后写入表;App 查找时重新执行 target lookup 和 find,拿到引用后再经过 Binder call 和 ActivityManager 业务权限。服务死亡会删除表项,lazy 启动还要经过 ctl.interface_start,不能从一行 service_contexts 推断全部生命周期。
13. 源码导航
| 问题 | 首选源码 | 关键符号 |
|---|---|---|
| 服务名映射 | system/sepolicy/private/service_contexts | 条目、flag、默认项 |
| 分区生成 | system/sepolicy/contexts/Android.bp | plat/vendor/odm_service_contexts |
| M4与去注释 | system/sepolicy/build/soong/selinux_contexts.go | buildServiceContexts |
| 静态检查 | system/sepolicy/tools/checkfc.c | service backend、attribute断言 |
| target type | system/sepolicy/public/service.te | service_manager_type |
| add/find/list | frameworks/native/cmds/servicemanager/Access.cpp | actionAllowedFromLookup、actionAllowed |
| handle刷新 | 同上 | getSehandle |
| 注册状态 | frameworks/native/cmds/servicemanager/ServiceManager.cpp | addService、mNameToService |
| 查找与lazy | 同上 | tryGetBinder、tryStartService |
| VINTF accessor | 同上 | canAddService、canFindService |
| 死亡清理 | 同上 | binderDied |
| 自注册 | frameworks/native/cmds/servicemanager/main.cpp | addService("manager")、becomeContextManager |
| Binder下一层 | system/sepolicy/public/te_macros | binder_call |
