從架構開始
對于Android架構的一般理解會是铅搓,”在Linux上的Java“瑟押。然而,不準確星掰,這樣的描述直接忽略掉整個平臺的復雜架構多望。
縱觀全局,架構由五部分組成氢烘,包括Android應用層怀偷,Android Framework,Dalvik虛擬機播玖,native code和Linux kernel椎工。如圖
職能簡介
- 應用層:允許開發(fā)者擴展與提升設備功能,無需關注底層實現細節(jié)蜀踏。
- Framework:提供豐富的API調用Android設備上的功能维蒙,包括管理UI元素,數據存儲與應用間傳遞數據果覆。是應用層與Dalvik虛擬機之間的粘合劑颅痊,
上述兩層都是使用Java開發(fā)并在Dalvik虛擬機上運行的。
- Dalvik:為操作系統特別設計的高性能抽象層局待,執(zhí)行Dalvik Executable(DEX)文件斑响,依賴于native層的libraries。
- Native:包括系統服務如vold钳榨,Dbus舰罚;網絡服務如dhcpd;其他庫如WebKit薛耻,OpenSSL营罢。其中的一些服務會與內核級服務,驅動程序通信饼齿,另一些則簡化了調用底層代碼饲漾。
Android基于Linux內核做出很多額外的改動瘟滨,例如獲取相機,WIFI能颁,網絡杂瘸,Binder和安全等。
安全模型
Android使用兩套分離伙菊,卻又互相配合的權限模型:沙箱和運行時權限败玉。
在低層級,Linux內核強制使用用戶和用戶組權限镜硕,限制獲取文件系統和Android特定資源的權限运翼。一般被稱為Android's sandBox(沙箱)。
在Android運行時兴枯,通過Dalvik虛擬機和Android Framework實現第二套模型血淌,在用戶安裝應用時啟用,限制了應用能獲取資源的權限财剖。一部分權限直接對應底層操作系統特定用戶和用戶組的權限悠夯。
Android‘s SandBox
Android基于Linux,而Linux繼承了Unix著名的進程獨立和最小特權法則躺坟。需要注意的是沦补,進程作為獨立的用戶運行時,既不能與其他用戶通信咪橙,又無法訪問其他用戶的內存區(qū)域夕膀。
所以沙箱可以理解為幾個概念:標準的Linux進程隔離,大多數應用都有單獨的用戶ID(UID)美侦,嚴格的文件系統權限产舞。
Andoird定義了一系列的AndroidIDs(AIDs)來代替?zhèn)鹘y的用戶和用戶組的密碼驗證,AIDs通過補充組獲取權限或共享資源菠剩,例如在sdcard_rw組的成員擁有讀寫/sdcard文件的權限易猫。
除了文件系統的權限,補充組也用于獲取其他權限赠叼。例如AID_INET組擦囊,允許用戶打開AF_INET和AF_INET6套接字违霞。
當應用運行時嘴办,UID,GID和補充組分配給一個新進程,操作系統不僅會在內核層級強制使用權限限制买鸽,還會在應用運行時進行控制涧郊,這就是Android沙箱。
在Android模擬器中眼五,通過ps
命令可以查看進程的PID妆艘。
通過cd /proc/1
進入PID為1的進程內彤灶,cat status
查看UID和GID。
Android權限
Android權限模型是多方面的批旺,有API權限幌陕,文件系統權限和IPC權限。正如前面所說汽煮,高層級的權限會對應底層OS的功能搏熄,包括打開套接字,藍牙設備暇赤,和特定的文件路徑心例。
Android高層級權限聲明在AndroidManifest內。應用安裝時鞋囊,PackageManager會將應用權限從Manifest中讀取出來止后,存儲在/data/system/packages.xml中。
通過cat /data/system/packages.xml
可以找到系統Phone的UID及權限溜腐。
<shared-user name="android.uid.phone" userId="1001">
<sigs count="1">
<cert index="1" />
</sigs>
<perms>
<item name="android.permission.WRITE_SETTINGS" />
<item name="android.permission.READ_SMS" />
<item name="android.permission.READ_CALL_LOG" />
<item name="android.permission.MODIFY_AUDIO_SETTINGS" />
<item name="android.permission.SYSTEM_ALERT_WINDOW" />
<item name="android.permission.SEND_RESPOND_VIA_MESSAGE" />
<item name="android.permission.SHUTDOWN" />
<item name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<item name="android.permission.BROADCAST_SMS" />
<item name="android.permission.CALL_PRIVILEGED" />
<item name="android.permission.CHANGE_NETWORK_STATE" />
<item name="android.permission.RECEIVE_BOOT_COMPLETED" />
<item name="android.permission.DEVICE_POWER" />
<item name="android.permission.RECEIVE_SMS" />
<item name="android.permission.SET_TIME_ZONE" />
<item name="android.permission.BLUETOOTH" />
...
</perms>
</shared-user>
這些權限會在應用進程實例化時(例如設置補充GIDs時)授予译株。
用戶組的權限存儲在/etc/permissions/platform.xml中,用于確定應用的補充組GIDs挺益。
通過cat /etc/permission/platform.xml
查看古戴。下面列舉存儲權限。
<permission name="android.permission.READ_EXTERNAL_STORAGE" >
<group gid="sdcard_r" />
</permission>
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
<group gid="sdcard_r" />
<group gid="sdcard_rw" />
</permission>
<permission name="android.permission.ACCESS_ALL_EXTERNAL_STORAGE" >
<group gid="sdcard_r" />
<group gid="sdcard_rw" />
<group gid="sdcard_all" />
</permission>
這些權限會以下列兩種方式之一強制執(zhí)行:運行時調用方法時進行判斷矩肩,底層操作系統或內核檢查现恼。
API權限
API權限包括用于控制在API/frameword中高層級的功能和第三方框架。例如公用API權限READ_PHONE_STATE黍檩,在文檔中定義為“僅允許讀取電話狀態(tài)”叉袍。需要該權限的應用要在調用任何與電話狀態(tài)相關的API之前獲取授權。相關方法在TelephoneManager
中getDeviceSoftwareVersion, getDeviceId等刽酱。
文件系統權限
Android應用沙箱由Unix嚴格的文件系統權限控制喳逛。UIDs和GIDs授予了訪問各自文件系統內的存儲空間。
通過ls -l /data/data
查看棵里,UIDs和GIDs(第二润文,第三列)在列表中是獨一無二的,而且再看權限只有特定UIDs和GIDs才能訪問其中內容殿怜。
正如前面提到的典蝌,補充組GIDs用于獲取共享資源,例如SD卡或外置存儲头谜。
通過ls -l /mnt/
查看sdcard讀寫權限骏掀。
總結
本文對Android權限在低層級和高層級的應用做了大致的介紹,通過兩個互相配合的安全模型,強制限制了應用最小需用權限截驮,獲取共享資源和應用間通信笑陈。
下一篇Android安全—深入理解各層級介紹Android架構里每個模塊為實現安全各自所做的努力。