Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getCallingUid/getCallingPid return current uid and pid in Handler.handleMessage

Tags:

android

I have a class extending android.os.Handler. An instance of this handler is passed to the constructor of a Messenger. The Messenger's IBinder from getBinder is passed as the result of onBind events in my service. Messages sent via the binder from remote applications do go to the handler's handleMessage method, however calls to Binder.getCallingUid and Binder.getCallingPid within handleMessage always return the uid and pid of the service's process (which is definitely not the same process as the remote application). handleMessage is definitely part of an IPC transaction, isn't it? So where have I gone wrong? I need this to work for authentication of connecting applications.

Thanks in advance.

Edit

OK. I have this horrible feeling that handleMessage is not part of the IPC transaction, because that happens in separate threads for AIDL which puts messages in a queue for the Messenger. Is there any other way of getting the User ID and Process ID of the caller?

like image 248
Dylan Avatar asked Sep 05 '11 15:09

Dylan


2 Answers

Make a custom Handler class and override sendMessageAtTime (this is the only overridable posting method in the Handler class ), and then use it to create a Messenger returned from onBind.

In the sendMessageAtTime method, you can get the pid/uid of the calling remote application by getCallingPid and getCallingUid.

But, in IPC using Messenger, as opposed to using AIDL, getCallingPid will always return 0 because the message sending by remote apps is asynchronous; transactions with IBinder.FLAG_ONEWAY. Therefore the uid is the only information available.

like image 63
eins Avatar answered Oct 24 '22 04:10

eins


I have come up with what I feel is quite a neat way to fix this. All messages that come through IPC get reconstructed from a parcel using Message.CREATOR.createFromParcel. So I have created a Java Dynamic Proxy Class (code pulled straight from the docs) that detects calls to createFromParcel and adds the process id and user id as additional items in the message's bundle before returning the result. The message is guaranteed to be created within a transaction, looking at the source for Messenger, so the IDs are correct. I then use reflection to replace the static final variable Message.CREATOR with a proxy of itself. IDs are then pulled out of messages later outside of transactions when authentication is required.

So far this is working exactly as intended.

Previously I was trying to create an alternative version of Messenger, and using reflection to access IMessenger, but even Messenger does not handle Messages before transactions end. A proxy is a lot less work and less prone to errors involved in casting different implementations of IMessenger.

like image 1
Dylan Avatar answered Oct 24 '22 05:10

Dylan