安卓架構以下圖 java
做爲一個unix系統,android內核能驅動運行硬件、網絡、文件系統、進程管理。可是不一樣於一般的Linux內核,android有着low memory killer, wakelocks, anonymous shared memory (ashmem), alarms, paranoid networking, Binder機制。其中最重要的是Binder和paranoid networking。linux
內核之上是本地用戶空間層,由_init_二進制文件(第一個啓動的進程,用於啓動全部其它進程),幾個本地守護進程以及在整個系統中使用的幾百個本地庫組成android
大部分Android都是用java實現的,而且由java虛擬機(JVM)執行。Android當前JVM實現被稱爲Dalvik。Dalvik不能直接運行Java字節碼(.class文件):其原生輸入格式稱爲Dalvik Executable(DEX),而且被打包在.dex文件中。反過來,dex文件被打包在系統Java庫(JAR文件)或者安裝在Android應用程序(APK文件)中。shell
Dalvik和Oracle的JVM有不一樣的體系結構——基於寄存器的Dalvik和基於堆棧的JVM,以及有着不一樣的指令集。JVM會使用x條指令將x個參數加載到堆棧,而Dalvik則是使用寄存器,用指令進行運算。通常來講,基於寄存器的Dalvik使用較少的指令,但代碼大於基於堆棧的虛擬機中相應的代碼。可是在大多數體系架構中,加載代碼比指令調度成本要小,所以基於寄存器的虛擬機效率更高。數據庫
在大多數生產設備中,系統庫和預安裝的應用程序不直接包含獨立於設備的DEX代碼。在性能優化上,DEX代碼被轉換爲設備相關格式並存儲在Optimized DEX(.odex)文件中,該文件一般位於與其父JAR或者APK文件相同目錄中。在安裝時爲用戶安裝的應用程序執行相似的優化過程。編程
Java語言的實現須要一組運行時庫(runtime libraries),主要定義在java.*和javax.*包中。Android的核心Java庫最初是從Apache Harmony project4中派生出來的。隨着Android的發展,原來的Harmony代碼已經發生的很大變化,在這個過程當中,一些功能已經徹底被替換(好比國際化支持,加密服務,和一些相關類),而其餘功能則獲得了擴展和改進。核心庫主要以Java開發,但它們也具備一些本機代碼依賴性。本機代碼使用標準Java Native Interface(JNI)連接到Android的Java庫中,該代碼容許Java代碼調用本機代碼,反之亦然。Java運行時庫直接從系統服務和應用程序訪問。瀏覽器
迄今爲止引入的各類層構成了實現Android系統服務核心所需的管道。系統服務(從4.4版本開始)實現了大部分基本的Android功能,包括顯示和觸摸屏支持、電話和網絡鏈接。大多數系統服務都是用Java實現的,一些基本的是用本機代碼編寫的。安全
除少數例外狀況,每一個系統服務都定義了能夠從其餘服務和應用程序調用的遠程接口。再加上Binder提供的服務發現、中介和IPC,系統服務在Linux之上有效地實現了一個面向對象操做系統。性能優化
如前所述,Binder是一個IPC機制。與任何類Unix系統同樣,Android中的進程是具備獨立的地址空間的,進程沒法直接訪問另外一進程的內存(進程隔離)。可是若是進程想爲其餘進程提供一些有用的服務,則須要提供一些機制,以容許其餘進程發現這些服務並與之交互,這個機制被稱爲IPC。對於標準IPC機制的需求並不新鮮,在Android以前就有好幾個選擇,包括文件、信號、套接字(sockets)、管道(pipes)、信號量(semaphores)、共享內存(shared memory)、消息隊列(message queues)等等。雖然Android使用了其中一些(如本地套接字),可是它不支持其餘(即系統V IPC,好比信號量、共享內存和消息隊列)服務器
因爲標準IPC機制不夠靈活可靠,所以爲Android開發了一種名爲Binder的新的IPC機制。雖然Android的Binder是一個新的實現,但它基於OpenBinder的體系結構和思想。
Binder實現了基於抽象接口的分佈式組件結構,它相似於Unix上的Windows通用對象模型(COM)和通用對象代理請求結構(CORBA),但與這些框架不一樣,它運行在單個設備上,不支持跨網絡的遠程調用(RPC)(儘管RPC支持能夠在Binder上實現)。下面簡要介紹Binder主要組件。
如前面所述,在類Unix系統上,進程沒法訪問另外一個進程的內存,可是內核能夠控制因此進程,所以能夠公開一個啓用IPC的接口。在Binder中,此接口是/dev/binder,由Binder內核驅動程序實現。Binder driver是框架的中心,全部的IPC調用都會經過它。進程間通訊經過一個ioctl()
調用實現,調用經過binder\_write\_read
結構(由包含驅動程序命令的write_buffer和包含用戶空間須要執行的命令的read_buffer組成)發送和接收數據。
可是數據如何在實際進程中傳遞的?Binder驅動程序管理每一個進程的部分地址空間。Binder驅動程序管理的內存塊對進程是隻讀的,而且全部的寫入都有內核模塊執行。當進程向另外一進程發送消息的時候,內核會在目標進程的內存中分配一些空間,而後直接從發送進程中複製消息數據。而後它將一條短消息排隊到接收過程,告訴它收到的消息在哪裏。接受者能夠直接訪問該消息,由於它在本身的內存空間中。當一個進程結束時,它會通知Binder驅動程序將內存標記爲空閒。下圖是Binder IPC體系結構簡化圖
Android中更高級別的IPC抽象,例如Intents(帶有相關數據的命令,這些數據經過進程傳遞給組件)、Messengers(支持跨進程的基於消息通訊的對象)和ContentProviders(公開跨進程數據管理接口的組件)創建在Binder之上。另外須要暴露給其它進程的服務接口可使用Android接口定義語言(AIDL)進行定義,AIDL使客戶端能夠調用遠程服務,就好像它們是本地Java對象同樣。關聯的AIDL工具自動生成stubs存根(客戶端表示的遠程對象),和將接口方法映射到較低級別的transact()
Binder方法並負責將參數轉換爲Binder能夠傳輸的格式的proxies代理(這稱爲parameter marshalling/unmarshalling參數的編組/解組)。由於Binder本質上仍是無類型的,因此AIDL生成的存根和代理還經過在每一個Binder事務(在代理中)包含目標接口名稱並在存根中驗證它來提供類型安全性。
在更高級別上,能夠經過Binder框架訪問每一個對象實現的IBinder接口而且這被稱爲Binder對象。對Binder對象的調用在Binder事務中執行,該事務包括對目標對象的引用、要執行的方法的ID以及數據緩衝區。Binder驅動程序會自動將調用進程的進程標識(PID)和有效用戶標識(EUID)添加到事務數據中。被調用進程(被調用者)能夠檢查PID和EUID,並根據其內部邏輯或關於調用應用程序的系統元數據來決定是否應該執行請求的方法。
因爲PID和EUID由內核填充,所以調用者進程不能僞造其身份以得到比系統容許的更多特權(Binder阻止提權)。這是Android安全模型的核心部分之一,全部更高級別的抽象(好比權限)都是基於它的。調用者的EUID和PID能夠經過android.os.Binder
類的getCallingPid()
和getCallingUid()
方法範圍,該類是Android的公有API一部分。
注意: 若是多個應用程序在同一個UID下執行,則調用進程的EUID可能沒法映射到單個應用程序,可是這不會影響安全決策,由於在相同的UID下運行的進程一般都會被授予相同的權限和特權(除非已定義特定於進程的SELinux規則)
Binder對象最重要的屬性之一是它們在流程中保持惟一的身份。所以,若是進程A建立一個Binder對象並將其傳遞給進程B,而進程B又將其傳遞給進程C,則來自全部三個進程的調用將由同一個Binder對象進行處理。實際上,進程A將直接經過其內存地址引用Binder對象(由於它在進程A的內存空間中),而進程B和C只會接收到Binder對象的句柄。
內核維護其餘進程中"實時"Binder對象及其句柄之間的映射。因爲Binder對象的身份是惟一的,而且由內核維護,因此用戶空間進程不可能建立Binder對象的副本或獲取對其的引用,除非已經過IPC交給IPC。所以,一個Binder對象是一個獨特的,不可僞造的,可傳播的對象,能夠充當安全令牌(token)。這使得在Android中使用Capability-Based Security(基於能力的安全性)成爲可能。
在基於能力的安全模型中,程序被授予對特定資源的訪問權限,爲其提供一種不可僞造的功能,該功能既引用目標對象又封裝一組訪問權限。因爲功能是不可僞造的,程序擁有一項功能的事實足以讓它可以訪問目標資源,不須要維護與實際資源相關聯的訪問控制列表(ACL)或相似結構。
在Android中,Binder對象能夠充當功能,並以這種方式使用時稱爲Binder token。Binder token既能夠是能力也能夠是目標資源。擁有一個Binder token賦予擁有進程徹底訪問一個Binder對象的權利,使它可以對目標對象執行Binder事務。若是Binder對象實現多個動做(經過根據Binder事務的代碼參數選擇要執行的動做),則調用者能夠在引用該Binder對象時執行任何動做。若是須要更細化的訪問控制,則每一個操做的實施須要執行必要的權限檢查,一般經過使用調用者進程的PID和EUID。
Android中的一種常見模式是運行對系統(UID 1000)和根(UID 0)運行的調用者執行全部操做。但對全部其餘進程執行額外的權限檢查。所以訪問重要的Binder對象(如系統服務)的方式有兩種:經過限制誰能夠獲取對該Binder對象的引用,以及在對Binder對象執行操做以前檢查調用者身份。(若是須要,這個檢查是可選的,而且由Binder對象自己實現)
另外,一個Binder對象只能做爲一個功能使用,而不須要實現任何其餘功能。在這種使用模式中,同一個Binder對象由兩個(或更多)合做進程持有,而充當服務器(處理某種客戶端請求)的Binder對象使用Binder token來驗證其客戶端,就像Web服務器使用session cookies同樣。這種使用模式由Android框架在內部使用,而且大多數應用程序不可見。在公有API中可見的Binder token的一個值得注意的用例是窗口 token。每一個活動的頂層窗口都與一個Binder token(稱爲一個窗口token)相關聯,該窗口token是Android的窗口管理器(負責管理應用程序窗口的系統服務)跟蹤的。應用程序能夠獲取本身的窗口token,但沒法訪問其餘應用程序的窗口token。一般您不但願其餘應用程序在您本身的頂部添加或者刪除窗口,每一個請求都必須提供與應用程序關聯的窗口標記,從而保證窗口請求來着您本身的應用程序或者系統。
雖然Android處於安全目的控制對Binder對象的訪問,而且與Binder對象進行通訊的惟一方法是引用它,可是某些Binder對象(最顯著的是系統服務),須要廣泛可訪問。然而,將全部系統服務的引用分發黑每一個進程是不切實際的,所以咱們須要一些機制來容許進程根據須要發現和獲取對系統服務的引用。
爲了啓動服務發現,Binder框架具備單個上下文管理器,該管理器維護對Binder對象的引用。Android的上下文管理器實現是服務管理器本地守護進程。它在引導過程的早期就開始了,以便系統服務能夠在啓動時註冊。經過將服務名稱和Binder引用傳遞給服務管理器來註冊服務。一旦註冊了服務,任何客戶端均可以使用其名稱獲取其Binder引用。可是,大多數系統服務都會執行額外的權限檢查,所以獲取引用不會自動保證訪問其全部功能。由於任何人在向服務管理器註冊時均可以訪問Binder引用,全部只有一小部分被列入白名單的系統進程能夠註冊系統服務。例如,只有以UID 1002(AID_BLUETOOTH)執行的進程才能夠註冊藍牙系統服務。
你可使用service list
命令查看已註冊服務的列表,該命令將返回每一個已註冊服務的名稱和已實現的Binder界面。
雖然和Android安全模型沒有直接關係,可是另外兩個著名的Binder功能是引用計數和死亡通知(也稱爲死亡連接)。引用計數可確保當沒有人引用它們時,Binder對象會自動釋放,並在內核驅動程序中使用BC_INCREFS,BC_ACQUIRE,BC_RELEASE和BC_DECREFS命令實現。引用計數集成在Android框架的各個級別,但不直接顯示給應用程序。
死亡通知容許使用由其餘進程託管的Binder對象的應用程序在內核終止這些進程並執行任何須要的清理時獲得的通知。死亡通知是經過內核驅動程序中的BC_REQUEST_DEATH_NOTIFICATION和BC_CLEAR_DEATH_NOTIFICATION命令以及框架中的IBinder接口的linkToDeath()
和unlinkToDeath()
方法實現的。(本地binder的死亡通知是不會發送的,由於沒有託管過程死亡,本地binder也不會死亡)
有時候簡稱爲"框架"(the framework)。框架包括全部不屬於標準Java運行時(java.* , javax.*等)的Java庫,而且適用於大多數部分託管在android頂層的包中。該框架包含構建Android應用程序的基本塊,例如 活動,服務和內容提供者(在android.app.*包中),GUI小部件(在android.view.*和android.widget包中),文件和數據庫訪問類(主要在android.database.*和android.content.*包中)。它還包括容許您與設備硬件交互的類以及利用系統提供的更高級別服務的類。
儘管內核級以上的幾乎全部Android操做系統功能都是做爲系統服務實現的,但它並不直接暴露在框架中,而是經過稱爲管理器的外觀類來訪問。一般每一個管理器都要相應的系統服務支持,例如BluetoothManager是BluetoothManagerService的表面。
最高層是應用程序(或app),它們是用戶直接與之交互的程序。雖然全部應用程序都具備相同的結構,並構建在Android框架之上,但咱們區分了系統應用程序和用戶安裝的應用程序。
系統應用程序包含在操做系統映像(image)中,該映像在生產設備上是隻讀的(一般以/system
身份登陸),而且不能由用戶卸載或更改。所以,這些應用程序被認爲是安全的,而且被賦予比用戶安裝的應用程序更多的特權。系統app能夠是核心Android操做系統的一部分,也能夠只是預先安裝的用戶應用程序,例如電子郵件客戶端或瀏覽器。雖然安裝在/system
下的全部應用程序在早期版本的Android中平等對待(除了經過檢查應用程序簽名證書的操做系統功能除外),Android 4.4和更高版本將安裝在/system/priv-app/
中的應用程序視爲特權應用程序,保護級別爲signatureOrSystem
的權限授予應用程序,而不是安裝在/system下的全部應用程序。使用平臺簽名密鑰簽名的應用能夠被授予具備簽名保護級別的系統權限,所以能夠得到操做系統級別的權限,即便它們未預安裝在/system
下。雖然沒法卸載或更改系統應用程序,但只要更新使用相同的私鑰簽名,用戶就能夠更新系統應用程序,有些能夠由用戶安裝應用。例如,用戶能夠選擇用第三方應用程序替換預安裝的應用程序啓動器或輸入法。
用戶安裝的應用程序安裝在專用的讀寫分區上(一般以/data的形式安裝),能夠託管用戶數據並能夠隨意卸載。 每一個應用程序都位於專用安全沙箱中,一般不會影響其餘應用程序或訪問其數據。 此外,應用程序只能訪問他們明確被授予使用權限的資源。 特權分離和最小特權原則是Android安全模型的核心。
Android應用程序與傳統應用程序不一樣,能夠有多個入口點。每一個組件均可以提供多個入口點,這些入口點能夠基於同一應用程序或另外一個應用程序中的用戶操做達到,或者由應用程序已註冊要通知的系統事件觸發。組件及其入口點以及其餘元數據在應用程序的清單文件中定義,稱爲AndroidManifest.xml。與大多數Android資源文件同樣,此文件在捆綁到應用程序包(APK)文件以前被編譯爲二進制XML格式(相似於ASN.1),以減少文件大小並加快解析速度。清單文件中定義的最重要的應用程序屬性是應用程序包名稱,它惟一標識系統中的每一個應用程序。包名稱與Java包名稱(反向域名錶示法;例如com.google.email)格式相同。
AndroidManifest.xml文件在應用程序安裝時解析,而且它定義的包和組件在系統中註冊。 Android須要使用開發人員控制的密鑰對每一個應用程序進行簽名。這保證已安裝的應用程序不能被聲稱具備相同程序包名稱的另外一個應用程序替代(除非它使用相同的密鑰簽名,在這種狀況下現有應用程序已更新)。下面列出了Android應用程序的主要組件。
activity是帶有用戶界面的單個屏幕。 activity是Android GUI應用程序的主要構建塊。 一個應用程序能夠有多個activity,雖然它們一般被設計爲以特定順序顯示,但每一個activity均可以獨立啓動,可能由不一樣的應用程序(若是容許)啓動。
service是一個在後臺運行而且沒有用戶界面的組件。service一般用於執行一些長時間運行的操做,例以下載文件或播放音樂,而不會阻止用戶界面。service還可使用AIDL定義遠程接口併爲其餘應用程序提供一些功能。 可是,與做爲操做系統一部分並始終運行的系統服務不一樣,應用程序的service是按需啓動和中止的。
content provider提供應用程序數據的接口,一般存儲在數據庫或文件中。 content provider能夠經過IPC訪問,主要用於與其餘應用程序共享應用程序的數據。 content provider對數據的哪些部分是可訪問的進行了細粒度的控制,容許應用程序僅共享其數據的一個子集。
broadcast receiver 是響應全系統事件的組件,稱爲廣播。 廣播能夠源自系統(例如,宣佈網絡鏈接性的變化),或來自用戶應用程序(例如,宣佈後臺數據更新已完成)。
與系統的其餘部分同樣,Android的安全模型也利用了Linux內核提供的安全功能。 Linux是一個多用戶操做系統,內核能夠隔離用戶資源,就像隔離進程同樣。 在Linux系統中,一個用戶不能訪問另外一個用戶的文件(除非明確授予權限),而且每一個進程都以啓動它的用戶的標識(用戶和組ID,一般稱爲UID和GID)運行,除非在相應的可執行文件上set-user-ID或者set-group-ID (SUID和SGID)。
Android利用了這種用戶隔離,但與傳統的Linux系統(桌面或服務器)對待用戶不一樣。 在傳統的系統中,UID被賦予一個物理用戶,該用戶能夠登陸系統並經過shell執行命令,或者在後臺執行系統服務(守護進程)(由於系統守護進程一般能夠經過網絡訪問 ,使用專用的UID運行每一個守護進程能夠在受到攻擊時限制其受到的損害)。 Android最初是爲智能手機設計的,並且因爲手機是我的設備,所以不須要在系統中註冊不一樣的物理用戶。 物理用戶是隱含的,UID用於區分應用程序。 這構成了Android應用沙盒的基礎。
Android會在安裝時自動爲每一個應用程序分配一個惟一的UID(一般稱爲應用程序ID),並在做爲該UID運行的專用進程中執行該應用程序。 此外,每一個應用程序都有一個專用的數據目錄,只有它有權讀取和寫入。 所以,應用程序在進程級別(經過使每一個進程在專用進程中運行)和在文件級別(經過具備專用數據目錄)都是隔離的或者沙箱化的。 這將建立一個內核級應用程序沙箱,該沙箱應用於全部應用程序,而無論它們是在本機仍是虛擬機進程中執行。
系統守護進程和應用程序在定義好的常量UID下運行,不多的守護進程以root用戶(UID 0)運行。 Android沒有傳統的/etc/password文件,它的系統UID是在android_filesystem_config.h頭文件中靜態定義的。系統服務的UID從1000開始,其中1000是系統(AID_SYSTEM)用戶,具備特殊(但仍然有限)的權限。自動生成的應用程序的UID從10000開始(AID_APP),相應的用戶名格式爲app_XXX或uY_aXXX(在支持多個物理用戶的Android版本上),其中XXX是來自AID_APP的偏移量,Y是Android用戶ID(不是與UID相同)。例如,10037 UID對應於u0_a37用戶名,可能會分配給Google電子郵件客戶端應用程序(com.google.android.email包)。
電子郵件應用程序的數據目錄以其包名稱命名,並在單用戶設備上的/data/data/下建立。數據目錄內的全部文件均歸專用Linux用戶u0_a37全部。 應用程序能夠選擇使用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE標誌建立文件,以容許其餘應用程序直接訪問文件,這些應用程序分別有效地設置文件上的S_IROTH和S_IWOTH訪問位。 可是,不鼓勵直接共享文件,而且這些標誌在Android 4.2及更高版本中已棄用。
應用程序UID與/data/system/packages.xml文件(規範源文件)中的其餘程序包元數據一塊兒管理,而且還寫入/data/system/packages.list文件。
在這裏,第一個字段是軟件包名稱,第二個是分配給應用程序的UID,第三個是可調試標誌(1:可調試),第四個是應用程序的數據目錄路徑,第五個是seinfo標籤(被SELinux使用的)。最後一個字段是應用程序啓動的補充GID列表。每一個GID一般都與Android權限相關聯,並根據授予應用程序的權限生成GID列表。
可使用相同的UID(稱爲共享用戶ID)安裝應用程序,在這種狀況下,它們能夠共享文件,甚至能夠在相同的進程中運行。 共享用戶標識被系統應用程序普遍使用,這些應用程序一般須要在不一樣的程序包中使用相同的資源以實現模塊化。例如,在Android 4.4中,系統UI和keyguard(鎖屏實現)共享UID 10012。
儘管不建議將非共享用戶標識設施用於非系統應用程序,但它也可用於第三方應用程序。 爲了共享相同的UID,應用程序須要使用相同的代碼簽名密鑰進行簽名。 此外,因爲將共享用戶ID添加到已安裝應用的新版本會致使其更改其UID,所以系統不容許這樣作。 所以,沒法追溯添加共享用戶標識,而且須要將應用程序設計爲從一開始就使用共享標識。
因爲Android應用程序是沙盒式的,所以它們只能訪問本身的文件和設備上的任何世界可訪問的資源。 這樣一個有限的應用程序雖然不會頗有趣,而且Android能夠爲應用程序授予額外的細粒度訪問權限,以便實現更豐富的功能。 這些訪問權被稱爲權限,而且它們能夠控制對硬件設備,互聯網鏈接,數據或操做系統服務的訪問。
應用程序能夠經過在AndroidManifest.xml文件中定義它們來請求權限。 在應用程序安裝時,Android會檢查請求的權限列表並決定是否授予它們。 一旦被授予,權限不能被撤銷,而且它們能夠在沒有任何額外確認的狀況下被應用程序使用。 此外,即便請求應用程序已被授予相應權限,對於諸如私鑰或用戶賬戶訪問等功能,每一個訪問對象都須要明確的用戶確認。 某些權限只能授予屬於Android操做系統的應用程序,或者是由於它們是預安裝的或使用與操做系統相同的密鑰簽名的。 第三方應用程序能夠定義自定義權限並定義稱爲權限保護級別的相似限制,從而限制對同一做者建立的應用程序訪問應用程序的服務和資源。
權限能夠在不一樣的級別執行。 請求更低級別的系統資源(如設備文件)由Linux內核經過檢查調用進程的UID或GID(針對資源的全部者和訪問位)來強制執行。 當訪問更高級別的Android組件時,強制執行由Android OS或每一個組件(或二者)執行。
Android使用內核驅動程序和用戶空間庫的組合來實現IPC。 「Binder」中所述,Binder內核驅動程序保證不能僞造調用者的UID和PID,而且許多系統服務依賴Binder提供的UID和PID來動態控制對經過IPC公開的敏感API的訪問。
更多粗粒度的權限影響經過IPC公開的服務的全部方法的粗粒度權限能夠經過在服務聲明中指定權限由系統自動執行。 與請求的權限同樣,所需的權限在AndroidManifest.xml文件中聲明。 與上例中的動態權限檢查同樣,每一個組件的權限也能夠經過查詢從Binder得到的調用者UID來實現。 系統使用包數據庫來肯定被調用者組件所需的權限,而後將調用者UID映射到包名稱並檢索授予調用者的權限集。 若是所需的權限在該組中,則調用成功。 若是不是,則失敗而且系統拋出SecurityException。
全部Android應用程序必須由其開發人員簽名,包括系統應用程序。因爲Android APK文件是Java JAR包格式的擴展,所以所使用的代碼簽名方法也基於JAR簽名。 Android使用APK簽名來確保應用程序的更新來自同一做者(這稱爲相同的來源策略),並在應用程序之間創建信任關係。這兩種安全功能都是經過將當前安裝的目標應用程序的簽名證書與更新證書或相關應用程序進行比較來實現的。系統應用程序由多個平臺密鑰簽名。不一樣的系統組件能夠共享資源,並在使用相同平臺密鑰簽名時在同一進程內運行。平臺密鑰由維護安裝在特定設備上的Android版本生成和控制:設備製造商,運營商,Google for Nexus設備或用戶自建的開源Android版本。
因爲Android最初是爲具備單個物理用戶的手機(智能手機)設備設計的,所以它爲每一個已安裝的應用程序分配不一樣的Linux UID,而且傳統上沒有物理用戶的概念。 Android在4.2版中得到了對多個物理用戶的支持,但只有平板電腦才支持多用戶支持,而平板電腦更有可能被共享。經過將用戶的最大數量設置爲1,手機設備上的多用戶支持被禁用。每一個用戶被分配惟一的用戶ID,從0開始,而且用戶被賦予其本身的專用數據目錄在/data/system/users/<用戶ID>/,這被稱爲用戶的系統目錄。此目錄託管用戶特定的設置,例如主屏幕參數,賬戶數據以及當前安裝的應用程序的列表。雖然應用程序二進制文件在用戶之間共享,但每一個用戶都會得到應用程序數據目錄的副本。爲了區分爲每一個用戶安裝的應用程序,安卓爲特定用戶安裝時,Android會爲每一個應用程序分配一個新的有效UID。這個有效的UID基於目標物理用戶的用戶ID和應用程序在單用戶系統中的UID(應用程序ID)。授予的UID的這種組合結構保證即便兩個不一樣用戶安裝了相同的應用程序,兩個應用程序實例也均可以得到他們本身的沙箱。此外,Android還爲每一個物理用戶保證專用的共享存儲(託管在舊設備的SD卡上),這些存儲是世界可讀的。 用戶首先初始化設備稱爲設備全部者,只有他們能夠管理其餘用戶或執行影響整個設備的管理任務(如出廠重置)。
傳統的Android安全模型在很大程度上依賴於授予應用程序的UID和GID。儘管這些內核是由內核保證的,而且默認狀況下每一個應用程序的文件都是私有的,可是沒有任何東西阻止應用程序授予世界對其文件的訪問權限(不管是有意仍是因爲編程錯誤)。一樣,沒有任何措施能夠防止惡意應用程序利用系統文件或本地套接字的過分寬容訪問位。實際上,分配給應用程序或系統文件的不適當權限已成爲多個Android漏洞的來源。這些漏洞在Linux使用的默認訪問控制模型中是不可避免的,稱爲自主訪問控制(DAC)。這裏的自由選擇意味着一旦用戶訪問特定的資源,他們能夠自行決定將其傳遞給另外一個用戶,例如經過將其中一個文件的訪問模式設置爲世界可讀。相反,強制訪問控制(MAC)確保對資源的訪問符合系統範圍內稱爲策略的一組受權規則。該策略只能由管理員進行更改,而且用戶沒法覆蓋或繞過該策略,例如,授予每一個人訪問本身的文件的權限。安全加強型Linux(SELinux)是Linux內核的MAC實現,已經在主線內核中集成了10多年。從版本4.3開始,Android集成了來自Android安全加強(SEAndroid)項目的一個修改過的SELinux版本,該版本已被加強以支持Android特定的功能,例如Binder。在Android中,SELinux用於隔離不一樣安全域中的核心繫統守護進程和用戶應用程序,併爲每一個域定義不一樣的訪問策略。從版本4.4開始,SELinux以強制模式進行部署(違反系統策略生成運行時錯誤),但策略強制只應用於核心系統守護進程。應用程序仍然以寬容模式運行,而且會記錄違規,但不會致使運行時錯誤。
Android設備能夠經過空中傳送(OTA)或經過將設備鏈接到PC並使用標準Android調試橋(ADB)客戶端或某些供應商提供的具備相似功能的應用程序推送更新映像來進行更新。因爲除系統文件以外,Android更新可能須要修改基帶(調制解調器)固件,引導加載程序以及沒法從Android直接訪問的設備的其餘部分,所以更新過程一般使用特殊用途的最小操做系統獨家訪問全部設備硬件。這被稱爲恢復操做系統或簡單恢復。 OTA更新經過下載OTA包文件(一般是帶有附加代碼簽名的ZIP文件)來執行,其中包含一個由恢復解釋的小腳本文件,並在恢復模式下從新啓動設備。或者,用戶能夠在引導設備時使用設備特定組合鍵進入恢復模式,並經過使用恢復的菜單界面手動應用更新,恢復菜單界面一般使用硬件按鈕(音量增大/減少,電源和等等)的設備。在生產設備上,恢復只接受設備製造商簽名的更新。更新文件經過擴展ZIP文件格式進行簽名,以在註釋部分的整個文件中包含簽名,在安裝更新以前,恢復將提取並驗證這些簽名。在某些設備(包括全部Nexus設備,專用開發人員設備和某些供應商設備)上,設備全部者能夠替換恢復操做系統並禁用系統更新簽名驗證,從而容許他們經過第三方安裝更新。將設備引導加載程序切換到容許替換恢復和系統映像的模式稱爲引導加載程序解鎖(不要與SIM解鎖混淆,它容許設備在任何移動網絡上使用),而且一般須要擦除全部用戶數據(工廠重置),以確保潛在的惡意第三方系統映像沒法訪問現有的用戶數據。在大多數消費設備上,解鎖引導加載程序會致使設備保修失效。
從版本4.4開始,Android支持使用Linux Device-Mapper的verity target進行驗證啓動。 Verity使用加密哈希樹提供對塊設備的透明完整性檢查。樹中的每一個節點都是加密哈希,葉節點包含物理數據塊的哈希值,中間節點包含其子節點的哈希值。因爲根節點中的散列基於全部其餘節點的值,所以只須要信任根散列以驗證樹的其他部分。使用引導分區中包含的RSA公鑰執行驗證。設備塊在運行時經過計算塊讀取時的散列值並將其與哈希樹中記錄的值進行比較來檢查。若是這些值不匹配,則讀取操做會致使I/O錯誤,指示文件系統已損壞。由於全部檢查都是由內核執行的,因此引導過程須要驗證內核的完整性,以便驗證的引導起做用。此過程是特定於設備的,一般經過使用不可更改的硬件特定的密鑰來實現,該密鑰被「燒」(寫入只寫存儲器)到設備中。該密鑰用於驗證每一個引導加載程序級別和最終內核的完整性。
Android是基於Linux內核的權限分離操做系統。 更高級別的系統功能是做爲一套協做系統服務實現的,它們使用稱爲Binder的IPC機制進行通訊。 Android經過運行具備不一樣系統標識(Linux UID)的應用程序來隔離彼此的應用程序。 默認狀況下,應用程序被賦予極少的權限,而且必須請求精細的權限才能與系統服務,硬件設備或其餘應用程序交互。 權限在每一個應用程序的清單文件中定義,並在安裝時授予。 系統使用每一個應用程序的UID來找出它已授予的權限並在運行時強制執行它們。 在最近的版本中,系統進程隔離利用SELinux來進一步限制給予每一個進程的權限。