天天看點

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

目錄

1概述

2 DAC機制

2.2 權限

3 seAndroid/seLinux安全機制

3.1 安全上下文(SContext)

3.2 基本規則

3.3執行個體

4 總結

1概述

         最近在android的開發過程中遇到一些權限問題。借此機會做個學習總結。

         簡單的來說Android/Linux的權限分為兩大類,一個是seLinux的安全機制,是一種MAC機制(Mandatory Access Control強制通路控制),通俗點了解就是你在門衛處需要預留指紋和規定的通路權限,在通路時指紋和通路的全限必須比對才能夠通路指定資源;還有一種基于程序式所屬的使用者以及使用者組,是一種DAC機制(Discretionary Access Control:自主通路控制),通俗的說就是你需要一個工作牌證明自己可以進入通路資源。第一種是第二種的加強版。在android/linux中目前兩種權限機制同時工作。

2 DAC機制

DAC是傳統的Linux的通路控制方式,DAC可以對檔案、檔案夾、共享資源等進行通路控制。在DAC這種模型中,檔案客體的所有者負責管理通路控制。 DAC使用了ACL(Access Control List,通路控制清單)來給普通的使用者提供不同的權限,而root使用者對檔案系統有完全自由的控制權。

2.1 使用者/組

         首先linux是一個多使用者系統,什麼是多使用者系統?

         就是一個系統同時能夠多個使用者登入,在各自的使用者空間進行操作,而互相不幹擾。不同的使用者有不同的角色,功能,當然還有不同的權限;而他們是通過UID來識别。UID在系統中有唯一性,不能共用。linux将使用者分為管理者(root)和普通使用者,普通使用者又分為系統使用者和自定義使用者。

使用者(user)

         如上面描述,user可以簡單的了解為系統的使用者,每個使用者都有自己的名稱,通過UID區分不同的user,user不同權限不同,root對其它user管理的權限,而普通user隻能夠管理自己的資源。

組(group)

         group可以認為是具有相同屬性的user的集合。比如幾個使用者在同一個系統上開發項目,将其編到統一group中就可以互相通路共享資源,而且可統一修改同一個group中的檔案或其它資源的通路權限,便于管理,每個group有對應的GID。一個group可以包括多個user,一個user可以從屬于不同的group。

對于使用者可以再在/etc/passwd中可以檢視相關配置:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

         格式為: 注冊名:密碼:使用者辨別(UID):組辨別(GID):注釋:使用者目錄:使用者登入的shell類型。

上圖中root為管理者UID是0,具有絕對的權限,其它為普通使用者。其中jimmy為自定義使用者UID為1000,而向上的其它user為系統使用者UID在1-500之間。

在linux中的每個使用者必須屬于一個組,不能獨立于組外。在linux中每個檔案有所有者、所在組、其它組的概念。同樣使用者組的資訊我們可以在/etc/group中檢視:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

 格式為:組名:組密碼:組辨別号(GID):附加組成員

2.2 權限

         為什麼需要介紹user和group,原因是linux的DAC機制就是基于它們。

便于了解我們先舉個示例,使用ls –al顯示目錄中檔案資訊:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

先解釋一下資訊含義:

第一組的第一個表示檔案類型:d 目錄;- 檔案 ;l 連結 ;c 字元裝置

        後面就是改檔案的權限:r讀 w 寫 x可執行,三組對應的是所有者/所有者組别/其它

rw-rw-r--表示所有者有讀寫權限,和所有者同組的有讀寫權限,其它隻能讀取。

  第二組是檔案個數

  第三組是user 即檔案的所有者

  第四組是group 即user所屬的組

你可以看到每個檔案都有自己的user以及group屬性。根據前文解釋每個檔案為所有者user,user所在得組,和其它設定了權限。如assert.c 對于user:jimmy開放了讀寫權限,和user同組的也有讀寫權限,其它則是隻有隻讀權限。

         DAC就是根據通路主體的user去對比通路客體資源的權限屬性,對比資訊來判别主體對資源客體是否相應的操作權限。

         linux還為我們提供了一些列的指令來配置user、group,以及修改檔案等資源所屬的user,權限等級等。

user
useradd 添加使用者
userdel 删除使用者
passwd 為使用者設定密碼
usermod 修改使用者指令,可以通過usermod 來修改登入名、使用者的家目錄等等
pwcov 同步使用者從/etc/passwd 到/etc/shadow
pwunconv 是pwcov 的立逆向操作,是從/etc/shadow和 /etc/passwd 建立/etc/passwd ,然後會删除 /etc/shadow 檔案
group
groupadd 添加使用者組
groupdel 删除使用者組
groupmod 修改使用者組資訊
groups 顯示使用者所屬的使用者組
grpck grpconv 通過/etc/group和/etc/gshadow 的檔案内容來同步或建立/etc/gshadow ,如果/etc/gshadow 不存在則建立;
grpunconv 通過/etc/group 和/etc/gshadow 檔案内容來同步或建立/etc/group ,然後删除gshadow檔案;

還有chgrp/chown/chmod幾個關鍵的操作指令:

chgrp [-R] 使用者組名 檔案名

目的是将檔案所屬的組,修改為組名指向的組。

chown [-R] 使用者[:使用者組] 檔案名

目的是将 檔案的所屬的使用者以及組修改為指定的。

chmod [-R] 權限 檔案名

目的是修改檔案權限為指定權限。其中權限有特别的指定方法,記得前面我們說過檔案的權限分為讀、寫、執行,對應r、w、x,而又分為3組對應user、group、other,為了便于修改rwx分别對應一個bit,如果隻讀就是100,隻寫就是010,可執行是001,如果可讀可寫就是110,是以修改檔案user可讀可寫,group可讀,other可讀就是:

chmod 644 file_name

6:110 rwx    4:100  rwx

當然chmod還有很多組合方式這裡不一一列出。

2.3示例

說了這麼多不如實踐一下,我們建立一個示例代碼,在代碼中是打開一個檔案:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

我們使用gcc 編譯生成test可執行檔案:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

建立一個test_file.txt檔案:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

可以看到檔案的所有者是jimmy,我們執行test:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

成功打開。

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

         修改檔案權限為000,則打開失敗。下面我們将檔案權限修改還原,增加user然後修改檔案user:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

可以看到我們已經修改了檔案的user和group,然後執行test:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

可以看出我們的程序已經沒有權限open改檔案了。為什麼呢?因為我實在jimmy這個使用者下執行test,是以test程序user是jimmy,沒有權限打開test_user的檔案。

我們切換user到test_user在執行:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

可以看到成功執行。

3 seAndroid/seLinux安全機制

seLinux 是一種MAC安全機制(Mandatory Access Control,強制通路控制)。SELinux在核心中使用MAC檢查操作是否允許;系統管理者管理負責通路控制,使用者不能直接改變強制通路控制屬性;可以定義所有的程序(稱為主體)對系統的其他部分(檔案、裝置、socket、端口和其它程序等,稱為客體)進行操作的權限或許可。

3.1 安全上下文(SContext)

和DAC模式不同,seLinux不是基于使用者、組來設定權限。而是基于主體與客體,利用安全上下文(SContext)來限制,主體對客體的通路權限。seLinux對2種類型做限制,一個是“死物”即檔案類型,還有一種就是“活物”即程序。下面我們在手機檢視一下檔案和程序的上下文:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

檔案

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

程序

         如圖,對于檔案SContext如u:object_r:vendor_configs_file:s0。

1)u: user,指使用者,注意該使用者非DAC中的使用者,而是在MAC中定義的。目前android隻定義了“u”這一個user。

2)object_r: 表示role 角色,android目前隻定義了一個role即“r”。一個user可以屬于多個role,每個role有不同的權限。

3)vendor_configs: 表示type,類,MAC的管理都是基于type來限制的。

4)s0:  MLS級别,即安全等級,目前android都是s0

對于程序u:r:kernel:s0和上述類似,u指user,r指role,kernel是type,s0為安全等級。seLinux規範中完整的SContext是:user:role:type[:level]。在這裡面需要着重關注的就是type,因為在android中目前user隻有一個u,role隻有一個r,s等級目前也都是s0。

那麼user和role是如何定義的呢?

在android系統中system/sepolicy/public/role_decl中定義了一個role:

role r;

role r types domain;   //将r與domain關聯

在system/sepolicy/public/users檔案中定義了user:

user u roles { r } level s0 range s0 – mls_systemhigh;

此處聲明了一個user u,可用的role為 r,預設安全等級為s0,安全範圍是s0 到系統定義的最進階别(mls_systemhigh)。

基于上面的聲明,如果沒有其它的user和role,那麼在android中所有的SContext必須基于u、r、domain(type)、s0 – mls_systemhigh定義才是合法的。看一下系統是如何為資源聲明SContext的:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

其中的rootfs、init_exec等都是屬于domain的type。

3.2 基本規則

         按照seLinux規範,安全權限設定文法的基本格式如下:

rule_name  source_type  target_type : class  permissive

rule_name:指令如allow、neverallow等

source_type: 主體,通常為屬性domain的type

target_type:客體,主體需要通路的type,如fs_type、audio_device、dev_type等

class :通路客體的客體類别

perm:主體對客體具備的權限

以allow為例:

         allow audioserver audio_device : chr_file { read write }

audioserver: 主體程序

audio_device:通路客體

chr_file:通路客體類别

read write :權限

描述的意思就是允許程序audioserver對客體audio_device中的chr_file類别進行read/write操作。

1) permissive

         在/system/sepolicy/private/access_vectors定義了各種class類别資源的權限,以chr_file為例:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

定義class chr_file 并繼承file的操作,在繼承的基礎上還添加了幾個操作權限,file的權限如下:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

是以chr_file包括了如上的所有操作權限,這樣allow就可以設定這些權限;這些權限是系統定義好的,與kernel /security/selinux/include/classmap.h檔案中形成映射,是以輕易不能修改。

2) class

         在/system/sepolicy/private/security_class檔案中,定義了各種class:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

這些class也與與kernel /security/selinux/include/classmap.h檔案中的定義有相關映射,是以輕易也不能修改。

3) type和attribute

定義一個type的完整指令:

 type type_id [alias alias_id,] [attribute_id]  

  type_id:type名稱

alias:指定了type的别名

alias_id: type的别名

attribute_id:屬性名稱

如:

type init , domain;

type sysfs , fs_type;

其中domain/ fs_type 是type的屬性,可以了解為具有相同功能的type的集合,這些屬性是約定好的,在/system/sepolicy/public/attribute檔案中我們可以檢視到相關的定義以及功能描述:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

可以看到dev_type是用于devices的,fs_type則是filesystems。attribute的目的是什麼?一般在系統中會定義幾十或者上百個type,如果對type一個一個的進行修改權限,會很麻煩,但是将不同的type歸類通過attribute可以以妻子不該attribute中包含的type的權限。

定義兩個type,分别是A和B,它們都管理到attr_test

type A attr_test;

type B attr_test;

使用allow語句,直接針對attr_test

allow attr_test  C:file {read write};

上面這個allow語句在編譯後的安全政策檔案中會被如下兩條語句替代:

allow A C:file {read write};

allow B C:file {read write};

attribute可以出現在source_type中,也可以出現在target_type中。

4) Labeling

         前面我們說過安全上下文,也簡單說明了SContext的設定,SELinux中将設定或配置設定SContext給程序或檔案的工作叫Security Labeling,簡單點說叫打标簽。一般在叫*_context檔案中限制。

         LSM初始化時所需要的資訊以及SContext資訊儲存在兩個特殊的檔案中:initial_sids和initial_sid_context檔案。

initial_sids:

定義了LSM初始化時相關的資訊。SID是SELinux中一個概念,全稱是Security Identifier。SID其實類似SContext的key值。因為在實際運作時,去比較字元串(還u:r:kernel:s0)會嚴重影響效率。是以SELinux會用SID來比對每個SContex設定SID(key值),如下是定義SID:

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

initial_sid_context:

該檔案為這些SContext設定SID資訊,就是将SID與SContext綁定。

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

最後就是在*_context檔案中設定SContext

(device/qcom/sepolicy/vendor/msm8953/file_contexts):

android/linux權限簡單了解1概述2 DAC機制3 seAndroid/seLinux安全機制4 總結

3.3執行個體

遇到權限問題,首先需要确認是否是權限導緻的,一般Android手機如果有root權限,可以暫時關閉SeLinux子產品,确認執行是否正常。如果關閉SeLinux後執行正常說明的确是權限問題,關閉、開啟以及擷取SeLinux狀态指令如下:

setenforce 0              ##設定SELinux 成為permissive模式

setenforce 1              ##設定SELinux 成為enforcing模式 (SELinux開啟)

getenforce               ##擷取SELinux狀态(permissive,enforcing,disabled)

确認是權限問題後,開啟selinux 系統子產品,使用 cat /proc/kmsg |grep avc 或者logcat –v time |grep avc 檢視關于權限的log,比如如下log:

type=1400 audit(32.939:25): avc: denied { open } for pid=2592 comm="chmod" path="/dev/block/mmcblk0p25" dev="tmpfs" ino=6494 scontext=u:r:init_shell:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=1

根據log,按照錄下方法,尋找關鍵字,在對應得te檔案中添權重限:

scontext  tcontext tclass permissive
u:r:init_shell:s0 u:object_r:block_device:s0 blk_file denied{ open }

你就需要在 init_shell相應的te檔案中添加如下設定           

allow  init_shell  block_device:blk_ file  { open };

這條語句表示允許init_shell對block_device 中的 blk_file類别的檔案進行open操作。

不過在添加property_set權限是發現按照上述添加方式,會出現與原有neverallow規則沖突的地方,如果去除neverallow 規則又可能導緻安全問題後期可能出現CTS測試不過問題,像華為還有自己的安全測試軟體用于測試檔案權限修該也可能導緻測試不過,這個時候可以根據原有的屬性關鍵字查找對應屬性添權重限方式添加。

以MTK平台添加MEC算法時遇到的權限問題為例:

1)在device/metiake/sepolicy/下查找系統音頻相關屬性關鍵字如

   一般在property_context檔案中:

   可以看到af.   u:object_r:audio_prop:s0   MTK 系統有類似af.mixer.pcm 以af. 開頭的屬性。

有兩種操作方式,一個就是就是将添加的屬性修改為af開頭,如af.awinic.suppot 在測試是否可以正常使用property_set。

另一個就是添加自己客制化的:

在property_context添加awinic.  u:object_r:audio_prop:s0

在property.te添加 type audio_prop  property_type,core_property_type;

在對應的mediaserver.te添加allow mediaserver audio_prop:property_service set;

編譯燒錄;

一般使用第一種方案,這樣不需要添加額外的權限,也可以防止權限添加不當等問題。

4 總結

         android/linux有2中權限機制,一種DAC基于使用者、組機制,不同的使用者、組對不同的資源有不同的權限。可以說是按照類别區分,一旦你具有和資源使用者同等級别,你就可以通路資源。這種機制有明顯的缺陷,比如root程序衍生的子程序就完全繼承了父程序的權限,可以通路所有資源,給黑客們留下了攻破系統的緻命後門。

         為了系統的安全,第二種基于MAC機制的seLinux被引入,該機制能夠對所有的資源對用不同的通路者設定不同的權限,由管理者監看權限,而不是使用者管理。該機制基于user和role,注意user非第一種user的含義。對不同的資源設定SContext,主體通路客體的資源時通過SContext确定是否有權限。

         兩種機制共同存在,組成Android/linux安全系統。

參考文獻:

https://www.jianshu.com/p/ba7c4e8cd699

https://www.jianshu.com/p/14a54a49e007?from=timeline&isappinstalled=0