在系统启动时,会新增一些自定义的 System Service 以供第三方应用使用一些特权操作。
第三方应用可以通过ServiceManager.getService(...)
或Context.getService(...)
获取到对应的 Binder 对象。
在测试中发现 SELinux 阻止了普通应用获取
ELinux: avc: denied { find } for service=test_service_name pid=14827 uid=10144 scontext=u:r:untrusted_app_27:s0:c512,c768 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
我不希望直接关闭 SELinux,尝试添加规则:allow untrusted_app default_android_service service_manager { find }
依然被 SELinux 阻止,还是上述一样的日志,所以想请问一下各位,是不是我对 SELinux 理解有偏差导致我的规则写错了?
1
RikkaW 2021-04-25 21:07:10 +08:00 2
1. untrusted_app_27 和 untrusted_app 是两个东西
2. 正常的系统服务是通过 attachApplication/bindApplication 由系统服务发给应用进程的,不需要专门允许应用进程 find service_manager |
2
RikkaW 2021-04-25 21:08:03 +08:00
补充一下,从 ContextImpl.getService 往上找就能看到系统服务的 binder 们是怎么进来的
|
3
gam2046 OP @RikkaW #1 感谢大佬。
简单梳理了一下,也为了方便后人,整个流程大概是这样(以 Android 10 代码为例) 目标 APK 能够获取到的 Service 是在 ActivityThread.bindApplication 方法中获得,此方法中对于应用不应该访问的服务给出了警告,但是没有拒绝访问 ``` if (ServiceManager.getService(name) == null) { Log.wtf(TAG, "Service " + name + " should be accessible by this app"); } ``` 而该方法中的 services 参数是由 AMS 发过来的,继续往里跟,可以得到 ActivityManagerService.getCommonServicesLocked 方法,在源代码中也可以看到一些注释 // Add common services. // IMPORTANT: Before adding services here, make sure ephemeral apps can access them too. // Enable the check in ApplicationThread.bindApplication() to make sure. 最终方法落到 ActivityManagerService.addServiceToMap,此方法中调用了 ServiceManager.getService 综上,可以得到,一般应用程序获得的 Service 是由 AMS 获取后通过 Binder 发送给目标应用,此时由于 AMS 本身是有权限获得 Service 的(这也就对应了大佬说不需要专门允许应用进程 find service_manager ),而在目标应用内对获得的 Service 列表有一个权限检查(即 AMS 传递过来的 Service 应用本身是否可以获取),即通过 service name 再次通过 ServiceManager 获取,如果返回 NULL,则输出警告日志,是否影响后续使用需要等待我测试一下。 |