Binderの権限制御です。
AOSPには以下のコードが大量にあります:
final long origId = Binder.clearCallingIdentity();
...
Binder.restoreCallingIdentity(origId);
この暗号、実際はどうなっているの?いつも2つ1組で影のように現れる、その謎の内側を探るために今日も。まず、このコードの正体はバインダーのパーミッション・コントロール・メカニズムです。
//frameworks/base/core/java/android/os/Binder.java
/**
* Reset the identity of the incoming IPC on the current thread. This can
* be useful if, while handling an incoming call, you will be calling
* on interfaces of other objects that may be local to your process and
* need to do permission checks on the calls coming into them (so they
* will check the permission of your own local process, and not whatever
* process originally called you).
*
* @return Returns an opaque token that can be used to restore the
* original calling identity by passing it to
* {@link #restoreCallingIdentity(long)}.
*
* @see #getCallingPid()
* @see #getCallingUid()
* @see #restoreCallingIdentity(long)
*/
public static final native long clearCallingIdentity();
/**
 * Restore the identity of the incoming IPC on the current thread
 * back to a previously identity that was returned by {@link
 * #clearCallingIdentity}.
 *
 * @param token The opaque token that was previously returned by
 * {@link #clearCallingIdentity}.
 *
 * @see #clearCallingIdentity
 */
public static final native void restoreCallingIdentity(long token);
- clearCallingIdentityは、現在のスレッドで到着したIPC識別子をリセットし、呼び出しが処理されようとするとき、呼び出し元は、プロセス内の他のオブジェクトのインターフェースを呼び出す必要があるかもしれません。これらのオブジェクトはすべて、呼び出しのパーミッション・チェックを再度行う必要があります。
上記のノートを見ると、非常に理解できないかもしれませんが、それを平易に置くこと以外には、おそらく意味:AプロセスとBプロセスのIPCコールは、BのバインダースレッドへのIPCコールを介してAのバインダースレッドが、この時点でBのバインダースレッドは、スレッド内の他のコンポーネントまたはオブジェクトにアクセスするバインダを使用する場合、これらのコンポーネントまたはオブジェクトは、訪問者のIPCマークをチェックする必要がある場合は、この時点で、あなたは、コンポーネントまたはオブジェクトは、アクセス許可をチェックするためのBであるように、独自のプロセスのIPCマークにBのスレッド保存バインダIPCマークにする必要があります。これらのコンポーネントやオブジェクトが訪問者のIPCトークンをチェックする必要がある場合は、Bのバインダースレッドによって保存されたバインダIPCトークンを自プロセスのIPCトークンに変更し、コンポーネントやオブジェクトが許可チェックのためにBを対象とするようにする必要があります。この場合、clearCallingIdentityによってBinderスレッドのIPCタグを現在のプロセスのpidとuidに設定し、呼び出し元Aのpidとuidを一時的に保存し、Bが呼び出しを終了した後にrestoreCallingIdentityによってIPCタグを復元する必要があります。
もし、一般的な考え方が理解できないのであれば、以下のソースコードを見てください。
//frameworks/base/core/jni/android_util_Binder.cpp
static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz)
{
 return IPCThreadState::self()->clearCallingIdentity();
}
static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
{
 // XXX temporary sanity check to debug crashes.
 int uid = (int)(token>>32);
 if (uid > 0 && uid < 999) {
 // In Android currently there are no uids in this range.
 char buf;
 sprintf(buf, "Restoring bad calling ident: 0x%Lx", token);
 jniThrowException(env, "java/lang/IllegalStateException", buf);
 return;
 }
 IPCThreadState::self()->restoreCallingIdentity(token);
}
class IPCThreadState
{
 ...
 int getCallingPid() const;
 int getCallingUid() const;
 ...
 int64_t clearCallingIdentity();
 void restoreCallingIdentity(int64_t token);
 ...
 pid_t mCallingPid;
 uid_t mCallingUid;
 ...
};
status_t IPCThreadState::executeCommand(int32_t cmd)
{
 switch (cmd) {
 ...
 case BR_TRANSACTION:
 {
 binder_transaction_data tr;
 result = mIn.read(&tr, sizeof(tr));//データをtrに読み込む
 ...
 const pid_t origPid = mCallingPid;
 const uid_t origUid = mCallingUid;
 
 mCallingPid = tr.sender_pid;
 mCallingUid = tr.sender_euid;
 ...
 if (tr.target.ptr) {
 sp<BBinder> b((BBinder*)tr.cookie);
 const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
 }
 ...
 mCallingPid = origPid;
 mCallingUid = origUid;
 ...
 }
 }
}
IPCThreadState::executeCommandでは、Binderプロセスは、からドライバの内容を読み取ります、データはbinder_transaction_dataに読み込まれ、これはBinderのIPCで最も一般的なケースです、ほとんどのIPCコールはBC_TRANSACTIONとBR_に行きます。TRANSACTION、ここであなたは、フェッチされたデータがBBinderのTRANSACTIONによって取られることがわかります、今、最初に、読み取られたコンテンツがBBinderによってどのように処理されるかに関係なく、呼び出しの前後に、それは一時的にorigPidとorigUidにmCallingPidとmCalingUidを保存することを参照してください、そして、trは、mCallingPidとmCalingUidをorigPidとorigUidに保存します。sender_pidとsender_euidは、それぞれこのデータを送信するプロセスのpidとuidを表し、Binderリクエストを開始したプロセスのpidとuidとしても理解できます。これらはBinderドライバによって埋められます。Binderが呼び出し元によって実行された後、呼び出し元プロセスのpidとuidを呼び出し元のpidとuidに最終的に復元します。BBinderの実行中に、呼び出しの実行を完了するように、BinderのgetCallingPidとgetCallingUid、つまり、ここでmCallingPidとmCallingUidを介して呼び出し元のpidとuidを取得することができます。mCallingUidは、必要な権限チェックを行うため。
int64_t IPCThreadState::clearCallingIdentity()
{
 int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid;
 clearCaller();
 return token;
}
void IPCThreadState::clearCaller()
{
 mCallingPid = getpid();
 mCallingUid = getuid();
}
void IPCThreadState::restoreCallingIdentity(int64_t token)
{
 mCallingUid = (int)(token>>32);
 mCallingPid = (int)token;
}
要約すると
Binderのパーミッション制御は見かけほど複雑ではありません。 実際、Binder Serverがパーミッションをチェックするための認証情報を提供するだけで、すべてのパーミッション作業がBinderによって処理されるとは言い切れません。これは非現実的で、Binderの各プロセスはリソースにアクセスするための異なるパーミッション制御戦略を持つことになり、Binderは制御できませんし、制御すべきではありません。Binderができることは、パーミッションのチェックプロセスに認証情報を提供することだけですが、全体から見れば、これは本当にパーミッションのコントロール戦略です。





