Android系統是運行在Linux核心上的,Android與Linux分別有自己的一套嚴格的安全及許可權機制,
很多像我這樣的新手,尤其是習慣了windows低安全限制的使用者,很容易在這方面弄混淆,下面是我總結的Android系統許可權相關的內容,
作為這段時間對android許可權學習的總結,也希望能對大家有所協助,不正確之處請指出。
首先分清兩個概念:
要區分apk運行時的擁有的許可權與在檔案系統上被訪問(讀寫執行)的許可權兩個概念。
apk程式是運行在虛擬機器上的,對應的是Android獨特的許可權機制,只有體現到檔案系統上時才使用linux的使用權限設定。
(一)linux檔案系統上的許可權
-rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
代表的是相應的使用者/使用者組及其他人對此檔案的存取權限,與此檔案運行起來具有的許可權完全不相關。
比如上面的例子只能說明system使用者擁有對此檔案的讀寫執行許可權;system組的使用者對此檔案擁有讀、執行許可權;其他人對此檔案只具有執行許可權。
而test.apk運行起來後可以幹哪些事情,跟這個就不相關了。
千萬不要看apk檔案系統上屬於system/system使用者及使用者組,或者root/root使用者及使用者組,就認為apk具有system或root許可權。
(二)Android的許可權規則
(1)Android中的apk必須簽名
這種簽名不是基於權威認證的,不會決定某個應用允不允許安裝,而是一種自我簽署憑證。
重要的是,android系統有的許可權是基於簽名的。比如:system等級的許可權有專門對應的簽名,簽名不對,許可權也就擷取不到。
預設產生的APK檔案是debug簽名的。
擷取system許可權時用到的簽名,見:如何使Android應用程式擷取系統許可權
(2)基於UserID的進程層級的安全機制
大家都知道,進程有獨立的地址空間,進程與進程間預設是不能互相訪問的,是一種很可靠的保護機制。
Android通過為每一個安裝在裝置上的包(apk)分配唯一的linux userID來實現,名稱為"app_"加一個數字,比如app_43
不同的UserID,運行在不同的進程,所以apk之間預設便不能相互訪問。
Android提供了如下的一種機制,可以使兩個apk打破前面講的這種壁壘。
在AndroidManifest.xml中利用sharedUserId屬性給不同的package分配相同的userID,通過這樣做,兩個package可以被當做同一個程式,
系統會分配給兩個程式相同的UserID。當然,基於安全考慮,兩個package需要有相同的簽名,否則沒有驗證也就沒有意義了。
(這裡補充一點:並不是說分配了同樣的UserID,兩程式就運行在同一進程, 下面為PS指令摘取的,
顯然,system、app_2分別對應的兩個進程的PID都不同,不知Android到底是怎樣實現它的機制的)
User PID PPID
system 953 883 187340 55052 ffffffff afe0cbcc S system_server
app_2 1072 883 100264 19564 ffffffff afe0dcc4 S com.android.inputmethod.
system 1083 883 111808 23192 ffffffff afe0dcc4 S android.process.omsservi
app_2 1088 883 156464 45720 ffffffff afe0dcc4 S android.process.acore
(3)預設apk產生的資料對外是不可見的
實現方法是:Android會為程式儲存的資料分配該程式的UserID。
藉助於Linux嚴格的檔案系統存取權限,便實現了apk之間不能相互訪問似有資料的機制。
例:我的應用程式建立的一個檔案,預設許可權如下,可以看到只有UserID為app_21的程式才能讀寫該檔案。
-rw------- app_21 app_21 87650 2000-01-01 09:48 test.txt
如何對外開放?
<1> 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE 標記。
When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.
(4)AndroidManifest.xml中的明確權限聲明
Android預設應用是沒有任何許可權去操作其他應用或系統相關特性的,應用在進行某些操作時都需要顯式地去申請相應的許可權。
一般以下動作時都需要申請相應的許可權:
A particular permission may be enforced at a number of places during your program's operation:
- At the time of a call into the system, to prevent an application from executing certain functions.
- When starting an activity, to prevent applications from launching activities of other applications.
- Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
- When accessing and operating on a content provider.
- Binding or starting a service.
在應用安裝的時候,package installer會檢測該應用請求的許可權,根據該應用的簽名或者提示使用者來分配相應的許可權。
在程式運行期間是不檢測許可權的。如果安裝時許可權擷取失敗,那執行就會出錯,不會提示使用者權限不夠。
大多數情況下,許可權不足導致的失敗會引發一個 SecurityException, 會在系統log(system log)中有相關記錄。
(5)許可權繼承/UserID繼承
當我們遇到apk許可權不足時,我們有時會考慮寫一個linux程式,然後由apk調用它去完成某個它沒有許可權完成的事情,很遺憾,這種方法是行不通的。
前面講過,android許可權是經營在進程層面的,也就是說一個apk應用啟動的子進程的許可權不可能超越其父進程的許可權(即apk的許可權),
即使單獨運行某個應用有許可權做某事,但如果它是由一個apk調用的,那許可權就會被限制。
實際上,android是通過給子進程分配父進程的UserID實現這一機制的。
(三)常見許可權不足問題分析
首先要知道,普通apk程式是運行在非root、非system層級的,也就是說看要訪問的檔案的許可權時,看的是最後三位。
另外,通過system/app安裝的apk的許可權一般比直接安裝或adb install安裝的apk的許可權要高一些。
言歸正傳,運行一個android應用程式過程中遇到許可權不足,一般分為兩種情況:
(1)Log中可明顯看到許可權不足的提示。
此種情況一般是AndroidManifest.xml中缺少相應的使用權限設定,好好尋找一番許可權列表,應該就可解決,是最易處理的情況。
有時許可權都加上了,但還是報許可權不足,是什麼情況呢?
Android系統有一些API及許可權是需要apk具有一定的等級才能啟動並執行。
比如 SystemClock.setCurrentTimeMillis()修改系統時間,WRITE_SECURE_SETTINGS許可權 好像都是需要有system級的許可權才行。
也就是說UserID是system.
(2)Log裡沒有報許可權不足,而是一些其他Exception的提示,這也有可能是許可權不足造成的。
比如:我們常會想讀/寫一個設定檔或其他一些不是自己建立的檔案,常會報java.io.FileNotFoundException錯誤。
系統認為比較重要的檔案一般使用權限設定的也會比較嚴格,特別是一些很重要的(配置)檔案或目錄。
如
-r--r----- bluetooth bluetooth 935 2010-07-09 20:21 dbus.conf
drwxrwx--x system system 2010-07-07 02:05 data
dbus.conf好像是藍芽的設定檔,從許可權上來看,根本就不可能改動,非bluetooth使用者連讀的權利都沒有。
/data目錄下存的是所有程式的私人資料,預設情況下android是不允許普通apk訪問/data目錄下內容的,通過data目錄的使用權限設定可知,其他使用者沒有讀的許可權。
所以adb普通許可權下在data目錄下敲ls命令,會得到opendir failed, Permission denied的錯誤,通過代碼file.listfiles()也無法獲得data目錄下的內容。
上面兩種情況,一般都需要提升apk的許可權,目前我所知的apk能提升到的許可權就是system(具體方法見:如何使Android應用程式擷取系統許可權),
至於是否有root級的,如何提升至root級不得而知,知道的朋友勞煩告知,感激不盡。
轉載自
狐狸浩浩技術空間http://hi.baidu.com/donghaozheng/blog/item/23ca75ec0028bbdc2e2e21c5.html