[Android N]KeyStore mBinder成员空指针引起system process不断重启
来源:互联网 发布:嵌入式linux开发前景 编辑:程序博客网 时间:2024/05/29 17:53
本地编译Android N项目得Rom刷机后,发现重启回到值SYSTEM_PROCESS无法启动,一直重启停留再开机动画阶段。
经查,发现android.security.keystore对应的service binder对象为NULL,报了空指针异常(LOG如下所示)。
--------- beginning of crash01-01 00:54:27.593 1102 1102 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main01-01 00:54:27.593 1102 1102 E AndroidRuntime: java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.USER_STARTED flg=0x50000010 (has extras) } in com.android.server.ConnectivityService$3@26aa3ad01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1174)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:836)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:103)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.os.Looper.loop(Looper.java:203)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.server.SystemServer.run(SystemServer.java:432)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.server.SystemServer.main(SystemServer.java:286)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1084)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:945)01-01 00:54:27.593 1102 1102 E AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int android.security.IKeystoreService.exist(java.lang.String, int)' on a null object reference01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.security.KeyStore.contains(KeyStore.java:210)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.security.KeyStore.contains(KeyStore.java:218)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.server.net.LockdownVpnTracker.isEnabled(LockdownVpnTracker.java:98)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.server.ConnectivityService.onUserStart(ConnectivityService.java:4060)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.server.ConnectivityService.-wrap27(ConnectivityService.java)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at com.android.server.ConnectivityService$3.onReceive(ConnectivityService.java:4114)01-01 00:54:27.593 1102 1102 E AndroidRuntime: at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1164)01-01 00:54:27.593 1102 1102 E AndroidRuntime: ... 8 more01-01 00:54:27.643 1102 1102 D AMEventHook: onEvent: AM_EndOfErrorDumpThread
经此LOG跟踪,发现是ConncetivityService在收到android.intent.action.USER_STARTED广播后,进行响应处理时调用了KeyStore的mBinder成员为空,导致系统进程无法正常地运行。
/frameworks/base/keystore/java/android/security/KeyStore.java
public boolean contains(String key, int uid) { try { return mBinder.exist(key, uid) == NO_ERROR;//mBinder == NULL } catch (RemoteException e) { Log.w(TAG, "Cannot connect to keystore", e); return false; } } public boolean contains(String key) { return contains(key, UID_SELF); }
ConnectivityService响应广播时,通过LockdownVpnTracker.isEnabled(),间接地使用KeyStore的getInstance()方法和contains()方法。
/frameworks/base/services/core/java/com/android/server/ConnectivityService.java
public static boolean isEnabled() { return KeyStore.getInstance().contains(Credentials.LOCKDOWN_VPN); }
经此,调用关系很清晰简单,问题也很明显,现在需要确定的是时序问题,看看是android.security.keystore这个服务启动绑定失败还是时序上的小偏差,前者的可能性更大,下面进行验证。
首先,看看KeyStore的mBinder怎么来的。
/frameworks/base/keystore/java/android/security/KeyStore.java
private KeyStore(IKeystoreService binder) { mBinder = binder; mContext = getApplicationContext(); } public static KeyStore getInstance() { IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager .getService("android.security.keystore"));// Log.i(TAG, "---->KeyStore getInstance on keystore file-- xdy ----->"); return new KeyStore(keystore); }
是从ServiceManager中根据android.security.keystore去获取对应的服务,这就需要看是谁往ServiceManager中注册了此服务。
经过一番搜寻,发现是keystore_main.cpp中有个main方法,往SM中addService。
/system/security/keystore/keystore_main.cpp
int main(int argc, char* argv[]) { ALOGE("------------> system --> security --> xdy1--->"); if (argc < 2) { ALOGE("A directory must be specified!"); return 1; } ALOGE("------------> system --> security --> xdy2--->"); if (chdir(argv[1]) == -1) { ALOGE("chdir: %s: %s", argv[1], strerror(errno)); return 1; } ALOGE("------------> system --> security --> xdy3--->"); Entropy entropy; if (!entropy.open()) { return 1; } ALOGE("------------> system --> security --> xdy4--->"); keymaster2_device_t* dev; if (keymaster_device_initialize(&dev)) { ALOGE("keystore keymaster could not be initialized; exiting"); return 1; } ALOGE("------------> system --> security --> xdy5--->"); keymaster2_device_t* fallback; if (fallback_keymaster_device_initialize(&fallback)) { ALOGE("software keymaster could not be initialized; exiting"); return 1; } ALOGE("------------> system --> security --> xdy6--->"); if (configure_keymaster_devices(dev, fallback)) { ALOGE("Keymaster devices could not be configured; exiting"); return 1; } ALOGE("------------> system --> security --> xdy7--->"); if (configure_selinux() == -1) { return -1; } ALOGE("------------> system --> security --> xdy8--->"); KeyStore keyStore(&entropy, dev, fallback); keyStore.initialize(); android::sp<android::IServiceManager> sm = android::defaultServiceManager(); android::sp<android::KeyStoreService> service = new android::KeyStoreService(&keyStore); android::status_t ret = sm->addService(android::String16("android.security.keystore"), service); ///核心代码 if (ret != android::OK) { ALOGE("Couldn't register binder service!"); ALOGE("------------> system --> security --> xdy9--->"); return -1; } ALOGE("------------> system --> security --> xdy10--->"); /* * We're the only thread in existence, so we're just going to process * Binder transaction as a single-threaded program. */ android::IPCThreadState::self()->joinThreadPool(); keymaster_device_release(dev); return 1;}
上方自添加了一些ALOGE LOG。
经过重新编译,重新刷机,发现reboot不再复现该问题,但二者时序可以从下方log看出。
1.keystore
2.USER_STARTED
3.ConnectivityService启动
1579: 01-01 03:30:54.638540 1100 1100 I SystemServer: StartConnectivityService 1580: 01-01 03:30:54.683255 1100 1100 D ConnectivityService: ConnectivityService starting up
综合上述LOG,最先addService,然后ConnectivityService被实例化启动,AMS发送USER_STARTED广播,ConnectivityService响应。
所以结论是,在keystore_main.cpp的main方法执行时,addService注册binder service不成功,应该会有如下log输出才对。
android::status_t ret = sm->addService(android::String16("android.security.keystore"), service); if (ret != android::OK) { ALOGE("Couldn't register binder service!");//LOG输出 return -1; }
其实从addService出现的地方就应该能够基本确定了,keystore是要在ConnectivityService之前的。
遗憾的是复现的版本,只是从终端logcat一部分log,未抓取到keystore部分的log,且暂记录之。
- [Android N]KeyStore mBinder成员空指针引起system process不断重启
- Android Keystore System
- Android Keystore System
- 空指针 引起的死机
- Android System.exit(code) and android.os.Process.killProcess(pid)或者发生RunTimeException 导致应用重启
- Android System.exit(code) and android.os.Process.killProcess(pid)或者发生RunTimeException 导致应用重启
- VS2003不断重启
- 网卡不断重启
- Android M原生BUG,手机使用过程中SystemServer空指针异常导致手机重启
- 空指针调用成员函数
- 空指针调用成员函数
- Android---相册getContentResolver().query结果为空指针(因为android版本引起)
- 空指针引起的程序崩溃
- 由动态代理引起的空指针
- android system services startup process
- android 应用异常可以引起android系统崩溃重启
- android.os.Process.killProcess(android.os.Process.myPid());重启应用的原理
- cookies空值情况下引起System.NullReferenceException错误解决方法
- URL编码
- 机器学习实战-logistic回归随机梯度上升浅见
- 初涉selenium+phantomjs
- Oracle之SQL语句性能优化(34条优化方法)
- 关于使用xpath的疑惑
- [Android N]KeyStore mBinder成员空指针引起system process不断重启
- 通过Synplify Pro查看FSM状态机
- SQL语句大全
- VS IntelliSense不识别新安装的Python库解决方法
- IDEA 热部署 Tomcat
- COOP绕过微软最新CFG(Control Flow Guard)
- Object-c学习笔记
- malloc
- 多线程的那些事