当前位置:   article > 正文

IBinder获取手机服务信息异常_ex_transaction_failed

ex_transaction_failed

 

小米8 利用IBinder transact获取服务的接口名字,结果出现以下异常:

  1. W/System.err: java.lang.SecurityException
  2. W/System.err:     at android.os.BinderProxy.transactNative(Native Method)
  3. W/System.err:     at android.os.BinderProxy.transact(BinderProxy.java:482)
  4. W/System.err:     at com.gamesec.essential.Essential.getInterfaceName(Essential.java:182)
  5. W/System.err:     at com.gamesec.essential.Essential.getRunningServiceInfo(Essential.java:204)
  6. W/System.err:     at com.gamesec.essential.Essential.getEssential(Essential.java:134)
  7. W/System.err:     at com.gamesec.DataCollector.collectDeviceInfo(DataCollector.java:373)
  8. W/System.err:     at com.gamesec.DataCollectorThread.run(DataCollectorThread.java:12)

 

手机系统为android9.0,所以查看源码 /.core/jni/android_util_Binder.cpp文件

 

android_os_BinderProxy_transact

[ android_util_Binder.cpp]

  1. static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
  2. jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
  3. {
  4. if (dataObj == NULL) {
  5. jniThrowNullPointerException(env, NULL);
  6. return JNI_FALSE;
  7. }
  8. Parcel* data = parcelForJavaObject(env, dataObj);
  9. if (data == NULL) {
  10. return JNI_FALSE;
  11. }
  12. Parcel* reply = parcelForJavaObject(env, replyObj);
  13. if (reply == NULL && replyObj != NULL) {
  14. return JNI_FALSE;
  15. }
  16. IBinder* target = getBPNativeData(env, obj)->mObject.get();
  17. if (target == NULL) {
  18. jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
  19. return JNI_FALSE;
  20. }
  21. ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
  22. target, obj, code);
  23. bool time_binder_calls;
  24. int64_t start_millis;
  25. if (kEnableBinderSample) {
  26. // Only log the binder call duration for things on the Java-level main thread.
  27. // But if we don't
  28. time_binder_calls = should_time_binder_calls();
  29. if (time_binder_calls) {
  30. start_millis = uptimeMillis();
  31. }
  32. }
  33. //printf("Transact from Java code to %p sending: ", target); data->print();
  34. status_t err = target->transact(code, *data, reply, flags);
  35. //if (reply) printf("Transact from Java code to %p received: ", target); reply->print();
  36. if (kEnableBinderSample) {
  37. if (time_binder_calls) {
  38. conditionally_log_binder_call(start_millis, target, code);
  39. }
  40. }
  41. if (err == NO_ERROR) {
  42. return JNI_TRUE;
  43. } else if (err == UNKNOWN_TRANSACTION) {
  44. return JNI_FALSE;
  45. }
  46. signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
  47. return JNI_FALSE;
  48. }

这里会有异常抛出:

  1. 当抛出异常NullPointerException: 代表dataObj为空,意味着java层传递下来的parcel data数据为空
  2. 当抛出异常IllegalStateException: 代表BpBinder为空,意味着Native层的BpBinder已经被释放
  3. 当进入signalExceptionForError(): 根据transact执行具体情况抛出相应的异常,具体看signalExceptionForError内部实现
  1. void signalExceptionForError(JNIEnv* env, jobject obj, status_t err, bool canThrowRemoteException, int parcelSize) {
  2. switch (err) {
  3. case UNKNOWN_ERROR:
  4. jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
  5. break;
  6. case NO_MEMORY:
  7. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  8. break;
  9. case INVALID_OPERATION:
  10. jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
  11. break;
  12. case BAD_VALUE:
  13. jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
  14. break;
  15. case BAD_INDEX:
  16. jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
  17. break;
  18. case BAD_TYPE:
  19. jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
  20. break;
  21. case NAME_NOT_FOUND:
  22. jniThrowException(env, "java/util/NoSuchElementException", NULL);
  23. break;
  24. case PERMISSION_DENIED:
  25. jniThrowException(env, "java/lang/SecurityException", NULL);
  26. break;
  27. case NOT_ENOUGH_DATA:
  28. jniThrowException(env, "android/os/ParcelFormatException", "Not enough data");
  29. break;
  30. case NO_INIT:
  31. jniThrowException(env, "java/lang/RuntimeException", "Not initialized");
  32. break;
  33. case ALREADY_EXISTS:
  34. jniThrowException(env, "java/lang/RuntimeException", "Item already exists");
  35. break;
  36. case DEAD_OBJECT:
  37. jniThrowException(env, canThrowRemoteException
  38. ? "android/os/DeadObjectException"
  39. : "java/lang/RuntimeException", NULL);
  40. break;
  41. case UNKNOWN_TRANSACTION:
  42. jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code");
  43. break;
  44. case FAILED_TRANSACTION: {
  45. ALOGE("!!! FAILED BINDER TRANSACTION !!! (parcel size = %d)", parcelSize);
  46. const char* exceptionToThrow;
  47. char msg[128];
  48. //transaction失败的底层原因有可能很多种,这里无法确定是那种,后续binder driver会进一步完善
  49. if (canThrowRemoteException && parcelSize > 200*1024) {
  50. exceptionToThrow = "android/os/TransactionTooLargeException";
  51. snprintf(msg, sizeof(msg)-1, "data parcel size %d bytes", parcelSize);
  52. } else {
  53. exceptionToThrow = (canThrowRemoteException)
  54. ? "android/os/DeadObjectException"
  55. : "java/lang/RuntimeException";
  56. snprintf(msg, sizeof(msg)-1,
  57. "Transaction failed on small parcel; remote process probably died");
  58. }
  59. jniThrowException(env, exceptionToThrow, msg);
  60. } break;
  61. case FDS_NOT_ALLOWED:
  62. jniThrowException(env, "java/lang/RuntimeException",
  63. "Not allowed to write file descriptors here");
  64. break;
  65. case UNEXPECTED_NULL:
  66. jniThrowNullPointerException(env, NULL);
  67. break;
  68. case -EBADF:
  69. jniThrowException(env, "java/lang/RuntimeException",
  70. "Bad file descriptor");
  71. break;
  72. case -ENFILE:
  73. jniThrowException(env, "java/lang/RuntimeException",
  74. "File table overflow");
  75. break;
  76. case -EMFILE:
  77. jniThrowException(env, "java/lang/RuntimeException",
  78. "Too many open files");
  79. break;
  80. case -EFBIG:
  81. jniThrowException(env, "java/lang/RuntimeException",
  82. "File too large");
  83. break;
  84. case -ENOSPC:
  85. jniThrowException(env, "java/lang/RuntimeException",
  86. "No space left on device");
  87. break;
  88. case -ESPIPE:
  89. jniThrowException(env, "java/lang/RuntimeException",
  90. "Illegal seek");
  91. break;
  92. case -EROFS:
  93. jniThrowException(env, "java/lang/RuntimeException",
  94. "Read-only file system");
  95. break;
  96. case -EMLINK:
  97. jniThrowException(env, "java/lang/RuntimeException",
  98. "Too many links");
  99. break;
  100. default:
  101. ALOGE("Unknown binder error code. 0x%" PRIx32, err);
  102. String8 msg;
  103. msg.appendFormat("Unknown binder error code. 0x%" PRIx32, err);
  104. jniThrowException(env, canThrowRemoteException
  105. ? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());
  106. break;
  107. }
  108. }
  1. struct BinderProxyNativeData {
  2. // Both fields are constant and not null once javaObjectForIBinder returns this as
  3. // part of a BinderProxy.
  4. // The native IBinder proxied by this BinderProxy.
  5. sp<IBinder> mObject;
  6. // Death recipients for mObject. Reference counted only because DeathRecipients
  7. // hold a weak reference that can be temporarily promoted.
  8. sp<DeathRecipientList> mOrgue; // Death recipients for mObject.
  9. };
  10. ...
  11. BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
  12. return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
  13. }
  14. ...
  15. IBinder* target = getBPNativeData(env, obj)->mObject.get();
  16. status_t err = target->transact(code, *data, reply, flags);

从上述代码可以看到,返回通过IBinder->transact接口返回err结果,IBinder->transact的接口可继续查看:BpBinder.transact和IPC.transact里面的实现,关于BpBinder.transact和IPC.transact的详细信息下面继续介绍:

BpBinder.transact

[ BpBinder.cpp]

  1. status_t BpBinder::transact(
  2. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  3. {
  4. if (mAlive) {
  5. //[见小节2.6]
  6. status_t status = IPCThreadState::self()->transact(
  7. mHandle, code, data, reply, flags);
  8. if (status == DEAD_OBJECT) mAlive = 0;
  9. return status;
  10. }
  11. return DEAD_OBJECT;
  12. }

当binder死亡,则返回err=DEAD_OBJECT,所对应的抛出的异常为DeadObjectException

 

IPC.transact

[IPCThreadState.cpp]

  1. status_t IPCThreadState::transact(int32_t handle,
  2. uint32_t code, const Parcel& data,
  3. Parcel* reply, uint32_t flags)
  4. {
  5. status_t err = data.errorCheck(); //错误检查
  6. flags |= TF_ACCEPT_FDS;
  7. if (err == NO_ERROR) {
  8. err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
  9. }
  10. if (err != NO_ERROR) {
  11. if (reply) reply->setError(err);
  12. return (mLastError = err); //返回writeTransactionData的执行结果err
  13. }
  14. if ((flags & TF_ONE_WAY) == 0) {
  15. if (reply) {
  16. err = waitForResponse(reply); //
  17. } else {
  18. Parcel fakeReply;
  19. err = waitForResponse(&fakeReply);
  20. }
  21. } else {
  22. err = waitForResponse(NULL, NULL);
  23. }
  24. return err; //返回waitForResponse的执行结果err
  25. }

返回值err的来源:

  1. 返回err=DEAD_OBJECT
  2. 返回writeTransactionData的执行结果err
  3. 返回waitForResponse的执行结果err

 

IPC.waitForResponse

[IPCThreadState.cpp]

  1. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
  2. {
  3. uint32_t cmd;
  4. int32_t err;
  5. while (1) {
  6. // 向Binder驱动写入交互
  7. if ((err=talkWithDriver()) < NO_ERROR) break;
  8. err = mIn.errorCheck();
  9. ...
  10. switch (cmd) {
  11. case BR_DEAD_REPLY:
  12. err = DEAD_OBJECT;
  13. goto finish;
  14. case BR_FAILED_REPLY:
  15. err = FAILED_TRANSACTION;
  16. goto finish;
  17. default:
  18. err = executeCommand(cmd); //[见小节2.7.1]
  19. if (err != NO_ERROR) goto finish;
  20. break;
  21. }
  22. }
  23. ...
  24. return err;
  25. }

当收到BR_DEAD_REPLY,则抛出err=DEAD_OBJECT

当收到BR_FAILED_REPLY, 则抛出err=FAILED_TRANSACTION

否则返回的是executeCommand的err

 

IPC.executeCommand

  1. status_t IPCThreadState::executeCommand(int32_t cmd)
  2. {
  3. BBinder* obj;
  4. RefBase::weakref_type* refs;
  5. status_t result = NO_ERROR;
  6. switch ((uint32_t)cmd) {
  7. case BR_ERROR:
  8. //从mIn中读取出错误码
  9. result = mIn.readInt32();
  10. break;
  11. ...
  12. default:
  13. result = UNKNOWN_ERROR;
  14. break;
  15. }
  16. return result;
  17. }

talkWithDriver过程便会跟Binder驱动交互

当服务端收到bind请求,则此时进入execTransact()过程。

 

Binder.execTransact

[Binder.java]

  1. private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
  2. Parcel data = Parcel.obtain(dataObj);
  3. Parcel reply = Parcel.obtain(replyObj);
  4. boolean res;
  5. try {
  6. //执行onTransact方法[见小节3.1.1]
  7. res = onTransact(code, data, reply, flags);
  8. } catch (RemoteException e) {
  9. if ((flags & FLAG_ONEWAY) != 0) {
  10. Log.w(TAG, "Binder call failed.", e);
  11. } else {
  12. reply.setDataPosition(0);
  13. reply.writeException(e); //[见后续]
  14. }
  15. res = true;
  16. } catch (RuntimeException e) {
  17. if ((flags & FLAG_ONEWAY) != 0) {
  18. Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
  19. } else {
  20. reply.setDataPosition(0);
  21. reply.writeException(e); //[见后续]
  22. }
  23. res = true;
  24. } catch (OutOfMemoryError e) {
  25. Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
  26. RuntimeException re = new RuntimeException("Out of memory", e);
  27. reply.setDataPosition(0);
  28. reply.writeException(re); //[见后续]
  29. res = true;
  30. }
  31. //[见小节3.3]
  32. checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
  33. reply.recycle();
  34. data.recycle();
  35. return res;
  36. }

可以看到服务端发送异常有3大类:

  1. RemoteException
  2. RuntimeException
  3. OutOfMemoryError

还有一类见writeException

writeException

  1. public final void writeException(Exception e) {
  2. int code = 0;
  3. if (e instanceof SecurityException) {
  4. code = EX_SECURITY;
  5. } else if (e instanceof BadParcelableException) {
  6. code = EX_BAD_PARCELABLE;
  7. } else if (e instanceof IllegalArgumentException) {
  8. code = EX_ILLEGAL_ARGUMENT;
  9. } else if (e instanceof NullPointerException) {
  10. code = EX_NULL_POINTER;
  11. } else if (e instanceof IllegalStateException) {
  12. code = EX_ILLEGAL_STATE;
  13. } else if (e instanceof NetworkOnMainThreadException) {
  14. code = EX_NETWORK_MAIN_THREAD;
  15. } else if (e instanceof UnsupportedOperationException) {
  16. code = EX_UNSUPPORTED_OPERATION;
  17. }
  18. writeInt(code); //写入异常码
  19. StrictMode.clearGatheredViolations();
  20. if (code == 0) {
  21. if (e instanceof RuntimeException) {
  22. throw (RuntimeException) e;
  23. }
  24. throw new RuntimeException(e);
  25. }
  26. writeString(e.getMessage());
  27. }

此处写入的异常类型:

  1. NullPointerException
  2. SecurityException
  3. BadParcelableException
  4. IllegalArgumentException
  5. IllegalStateException
  6. NetworkOnMainThreadException
  7. UnsupportedOperationException

 

checkParcel

  1. static void checkParcel(IBinder obj, int code, Parcel parcel, String msg) {
  2. // 检查parcel数据是否大于800KB
  3. if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) {
  4. StringBuilder sb = new StringBuilder();
  5. sb.append(msg);
  6. sb.append(": on ");
  7. sb.append(obj);
  8. sb.append(" calling ");
  9. sb.append(code);
  10. sb.append(" size ");
  11. sb.append(parcel.dataSize());
  12. sb.append(" (data: ");
  13. parcel.setDataPosition(0);
  14. sb.append(parcel.readInt());
  15. sb.append(", ");
  16. sb.append(parcel.readInt());
  17. sb.append(", ");
  18. sb.append(parcel.readInt());
  19. sb.append(")");
  20. Slog.wtfStack(TAG, sb.toString());
  21. }
  22. }

 

总结异常数据传输流程如下图:

 

结论:小米手机发出安全异常是binder服务端发出的,厂商设置了权限无法访问。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/235568
推荐阅读
相关标签
  

闽ICP备14008679号