Android系統權限及簽名
50
Android權限及簽名
引子
現象:系統中的一個定制Service,服務是對外開放的,使用系統簽名
LOCAL_CERTIFICATE := platform
應用層調用這個系統服務,獲取底層的一些信息。如果在IDE里進行開發,普通簽名,無法調用到該服務, 改成在系統編譯環境里編譯,並在Android.mk中加入如下語句:
LOCAL_CERTIFICATE := platformandroid:sharedUserId="android.uid.system“android:process="com.android.phone"
就可以順利的獲取到系統服務。其內在的原因是什么?
Linux權限
說起Android的權限和簽名,就要先從Linux的權限說起,我們都知道Linux的文件系統是有權限限制的,對於每一個文件或者目錄,我們執行 ls -l 指令都會看到類似如下的顯示: -rw-r–r– 1 xxxxx xxxxx 681 2013-05-24 09:16 Android.mk 分別代表:文件種類和權限;硬鏈接個數;User;Group;大小;最后訪問/修改時間;文件/目錄名 文件權限代表是否對對應用戶,用戶組,其他用戶開放讀或者寫權限。而User;Group則是代表了該文件是屬於誰的,比如用戶ABC創建的一個文件,該文件的User則為ABC。linux就是通過文件權限和用戶用戶組這種方式來保證安全的。 而文件權限是通過進程來體現的,用戶訪問一個文件,總是要通過進程來訪問,即便是打開一個終端界面,也是打開了一個bash進程來查看文件的。 就如下圖所示: 圖1
對於Android而言,啟動一個Application,一般同樣要啟動一個單獨的進程來運行,就像這樣:
drwxr-x--x u0_a49 u0_a49 2013-01-01 08:00 com.example.testdrwxr-x--x radio radio 2013-01-03 06:35 com.android.phone
上面的test應用啟動了一個單獨的進程,它的用戶的用戶組都是u0_a49。這樣如果沒有意外的話,其只能訪問到該應用自己的data數據。 問題來了,如果我想訪問其他不適自己data的文件及目錄該怎么辦呢?首先想到的就是能不能把自定義的應用的用戶組改成和其他某應用一樣呢?比如User改成radio。
答案是可以的。不過Android為了保證系統安全,還有個規定: 必須在AndroidManifest.xml具有相同簽名+相同shareUserId屬性的兩個App,才可以分配相同的用戶ID。因為com.android.phone是系統應用,其簽名是LOCAL_CERTIFICATE := platform 系統簽名,所以我必須同樣采用LOCAL_CERTIFICATE := platform系統簽名,並且android:sharedUserId=”android.uid.radio” 才可以讓這個自定義的App和phone應用具有相同的UID。(當然如果只是想訪問,android:sharedUserId可以設為更高權限的用戶也可以實現)。
AndroidManifest.xml中還有一個標簽android:process,比如:android:process=”com.android.phone”,它可以單獨應用於某個Activity或者Service,也可以直接應用於Application。作用就是將對應的Activity或者Service放在com.android.phone這個進程中運行。而使用這個標簽的前提就是前一段所說的:具有相同簽名+相同shareUserId屬性。 標簽android:process的作用比如phone應用中運行的某個動態庫或者持有的某個單例對象,如果另外一個app想要使用或者說調用的話,是沒法使用,或者拿到的是另外一個單例—因為是另一個進程了。這個時候通過android:process將對於的Activity讓其在phone進程中運行。這樣就可以很方便的使用phone應用中的資源了。 圖2
簽名和APK的關系:通常APK對於的是Linux中的User和Process。APK的運行,就代表一個獨特的進程的運行,而該進程又屬於某個User。具有相同簽名和相同shareUserId屬性的兩個APK,才會屬於同一個User.(APK安裝時,PackageManagerService會檢查) 簽名和權限的關系:簽名是為了讓系統識別是不是同一個作者,除了前面提到的系統簽名外,每個作者都可以自定義自己的簽名。對於簽名級的權限,比如一個作者的應用定義了一個權限。並設置權限的android:protectionLevel 為”signature”。那么只有該作者使用同樣簽名的另一個應用,才可以使用該權限。
Root后的手機呢
為什么root后就可以無視那些權限呢? 拿一個root過得手機,執行如下代碼:
Process process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream()); os.writeBytes(“echo 1500000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" + "/n");
su程序的權限如下所示:
System/bin/su-rwsr-xr-x root root
關鍵就是那個執行權限標志位S,代表當任何用戶執行該文件時,都擁有該文件所有者的權限—–root。 當然這里說的比較簡略,其實在應用執行root權限操作的時候,向Superuser.apk申請超級用戶請求, Superuser.apk利用系統漏洞,執行類似如下的操作。讓su程序居然這些功能。
cp /data/tmp/su /system/bin/chown root:root su chmod 4775 /system/bin/su
這樣上面修改cpu頻率的語句就可以順利執行。
Q&A
Q:android:sharedUserId和android:process的關系? A:sharedUserId是對整個apk而言, android:process則是對某一個activity或者servicce而言,很多時候sharedUserId是android:process的前提 Q:android:sharedUserId和android:process分別對應用來說有什么作用。 A:sharedUserId可以讓應用的uid變成類似system,phone,雖然沒有root用戶權限高,但是也可以做很多事了,具體要看其需求。具有phone的uid,然后才可以設定應用內的activity的android:process屬性。 使用android:process的原因很多: a)比如Stk應用,想要使用CatService(單例模式),於是它調用CatService.getInstance(),調用時如果已經存在CatService實例才會正確返回,該實例還沒有建立,是拿不到的。而這個CatService是在Phone應用中,使用CommandsInterface 對象(Ril)作為參數建立。這是就需要把Stk應用放在Phone進程里,才可以拿到CatService實例。 b)又或者想要設計一個系統應用,想要調用Phone phone = PhoneFactory.getDefaultPhone()獲得Phone對象,但是這個調用只能運行在phone進程中(原因見該函數源碼)。這就必須把調用該語句的activity設為android:process=“com.android.phone“——如Setting里的IccLockSettings。