1. 程式人生 > >android IPC通訊中的UID和PID識別

android IPC通訊中的UID和PID識別

  IPCThreadState物件維護了2個變數

            pid_t               mCallingPid;

            uid_t               mCallingUid;

    從變數名稱來看,這2個變數儲存了程序的PID和UID,並且由於這兩個變數由IPCThreadState物件維護,可見它們是與IPC相關的。具體它們儲存的是IPC傳送方的PID和UID還是當前程序的IPD和UID,視情況而定。

    在IPC呼叫過程中,被呼叫方需要知道呼叫方的UID和PID,以便被呼叫方用於許可權檢測;所以需要一種方式來提供呼叫方的UID和PID,因此上述2個變數的主要作用就是用於許可權檢測。

    那麼我們想象一下,下面描述的情況下,mCallingPid和mCallingUid又應該儲存誰的UID和PID?假如有2個程序process A和process B,我們站在process B的角度來分析,process A IPC呼叫process B, 而process B 又呼叫同樣處於process B的Service的介面(儘管此時實際上不是遠端呼叫,並且開發者是知道的,但是對於Binder呼叫機制來說,它本身並不知道當前的呼叫是否為遠端呼叫,前幾篇文章中有分析系統如何確定是否為遠端呼叫,這個過程是在binder driver中實現的),那麼此時mCallingPid和mCallingUid是不是應該儲存process B的UID和PID?

1.       process B在被process A IPC呼叫時, process B需知道process A的UID和PID,來檢查process A的訪問許可權,此時mCallingUid和mCallingPid儲存的是process A的UID和PID。

2.       在IPC遠端呼叫process B的過程中,process B的方法呼叫了同進程中的service的介面,process B既是呼叫方也是被呼叫方,雖然這個過程比較無聊,但是鑑於IPC過程的不透明性,因此process B仍然需要進行許可權檢測。

 

    前面的文章中分析過,binder driver會判斷當前的Binder呼叫是否為遠端呼叫,如果是同進程呼叫的話,BD就不會再向應用提供程序的PID和UID。因此在process B中需要顯示的設定當前的PID和UID。

    為實現以上case, android提供了一組函式

    public static final native long clearCallingIdentity();

    public static final native void restoreCallingIdentity(long token);

    process B的方法呼叫了同進程中的service的介面前,clearCallingIdentity()方法會清除process A的UID和PID,重置為process B的UID和PID。

    process B的方法呼叫了同進程中的service的介面後,此時仍然處在process A遠端呼叫process B方法的過程中,此時需要restore  process A的UID和PID。

    本文描述的case,雖然在application 開發中並不常見,但是在system_server中很常見,比如client呼叫ActivityManagerService的方法,而ActivityManagerService又呼叫了PackageManagerService的方法,並且ActivityManagerService和PackageManagerService均會執行在system_server程序中。