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會檢測該應用請求的權限,根據該應用的簽名或者提示用戶來分配相應的權限。www.aiwalls.com
在程序運行期間是不檢測權限的。如果安裝時權限獲取失敗,那執行就會出錯,不會提示用戶權限不夠。
大多數情況下,權限不足導致的失敗會引發一個 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級不得而知,知道的朋友勞煩告知,感激不盡  

摘自 jerry_2015
 

發佈留言