Parcel::remove() not yet implemented!

2020. 5. 23. 11:56Security ★ Development/시스템

반응형

Android hal binder 동작 시 발생하는 에러입니다.

Parcel::remove() not yet implemented!


Binder쪽 로그를 보면 EX_TRANSACTION_FAILED 및 WOULD_BLOCK 그리고

binder : ~ioctl ~ return -11 과 같은 에러도 같이 볼 수 있습니다.


먼저 Parcel::remove()에러는 libs/binder/Prcel.cpp에서 확인할 수 있습니다.  에러 내용 그대로의 log만 출력합니다.


HAL Library와 Kernel Driver에서 발생하는 에러입니다.


어떻게 저 부분으로 빠지게 되는데 동작을 보겠습니다.

HAL을 사용 시 내부적으로 /dev/hwbinder를 open하게 됩니다.  

HAL app쪽에서는 joinThraedPool()을 호출하면서 동작하게 되는데 talkWithDriver()를 통해 binder를 통해 처리해야 할 command들을 확인합니다.

tlakWithDriver()는 ioctl을 통해 binder read/write를처리합니다.  이 후 데이터의 처리 여부를 확인하여 Parcel의 remove를 호출하게 됩니다.  전체 데이터 사이즈보다 소비된 데이터가 적을 경우인데 이는 non blocking모드로 인해 데이터 sync가 제대로 되지 않은 경우를 뜻합니다.


Binder debug log를 enable시키고 보면

wirte 80 at -, read 6 a -

wrote 77 at 80, read 6 at 6 

이런 로그를 볼 수 있습니다.

위의 로그는 80의 데이터를 쓰도록 요청했지만 77밖에 쓰지 않았다는 것이고 이런 경우에 Parcel::remove에러가 발생합니다.

흔히 데이터를 80쓰기로 요청했지만 실제 들어온 데이터는 77로 되어있고 77만 쓰고 리턴할 때 이 구현이 별도로 되어있는 상태로 보면됩니다.


binder driver 단에서는 binder read/wirte인 경우 binder_ioctl_write_read() - binder_thread_read()를 호출합니다.  이 때 fd의 blocking 모드를 확인합니다.

if (non_block) {

if (!binder_has_work(thread, wait_for_proc_work))

ret = -EAGAIN;

} else {

ret = binder_wait_for_work(thread, wait_for_proc_work);

non_blocking인 경우 갖고 있는 데이터가 없으면 바로 에러를 설정합니다.

'wrote 77 at 80' 때와 달리 non blocking 모드로 인해 read에 문제가 생긴 경우입니다.

두 경우 모드 app이나 hal service가 에러 회복을 위한 방어 코드를 시도할 수 없게 되어있습니다.

App 혹은 service에서 에러 return 값을 확인하기전 framework 단에서 이미 crash가 발생한 후이기 때문입니다.


정리하면 linux binder 동작 시 non blocking 모드는 소켓 등과 같이 데이터가 없을 때 '데이터 없음'을 리턴하는 것 뿐만 아니라 error/abort를 발생시킴으로써 app이 crash가 나도록 되어있습니다.

non blocking의 큐에 데이터 없음을 허용하지 않습니다.


이러한 에러가 발생하는 이유는 /dev/hwbinder를 통해 얻은 fd가 non blocking으로 설정되었기 때문입니다.

fcntl을 통해 O_NONBLOCK로 설정하고 hal 호출을 하면 에러 발생을 재현할 수 있습니다.  

저 fd는 process내에 싱글톤으로 하나만 관리되기 때문에 다른 스레드 코드, thirdparty에서 fd를 얻고 non blocking 모드로 설정하게 되면 다른 코드에서 에러를 발생시키기 때문에 디버깅이 까다롭습니다.  

hwbinder의 fd를 blocking으로 설정하는 것으로 app에서는 에러가 발생하는 것을 막을 수 있습니다.