網路參考資料:
SEAndroid學習筆記 - 簡書 (jianshu.com)
Android系統SELinux簡單整理_android selinux 編譯除錯-CSDN部落格
【Android】Selinux許可權問題記錄_se許可權為啥type 不能加init-CSDN部落格
SELinux許可權問題分析與修改_violated by allow-CSDN部落格
Android O selinux違反Neverallow解決辦法-CSDN部落格
Android 使用者組許可權,SELinux心得總結_android android_ids[] 高版本-CSDN部落格
SELinux(Security-Enhanced Linux)是由美國國家安全域性(NSA)開發的一種強制訪問控制機制。它主要整合在 Linux 核心當中,是針對特定的程序與指定的檔案資源進行許可權控制的系統。主要是增強傳統 Linux 作業系統的安全性,並解決傳統 Linux 系統中自主訪問控制(DAC)系統中的各種許可權問題(如 root 許可權過高等)。
一、DAC(自主訪問控制)
DAC全稱為:Discretionary Access Control
DAC 是傳統 UNIX 和 Linux 系統的訪問控制模型,它基於使用者對資源的擁有權和許可權。在 DAC 模型下,使用者擁有對自己建立的檔案和目錄的完全控制權,可以自由設定檔案的訪問許可權(讀、寫、執行)以及共享許可權(使用者組、其他使用者)。
ls -l顯示檔案的屬性前面的10個字元就代表了Linux對改檔案的訪問控制
二、MAC(強制訪問控制)
MAC全稱為Mandatory Access Control
MAC 是在 DAC 模型之上的一個額外的安全層,它強制施加系統管理員定義的訪問策略,以確保系統資源的安全性。在 Android 中,SELinux 是實現 MAC 的主要機制之一。與 DAC 不同,MAC 不允許使用者或程序直接設定或修改物件的訪問策略,而是由系統管理員透過 SELinux 策略檔案來配置訪問規則。
Android系統SELinux的兩種工作模式:
1. Permissive工作模式(寬容模式)
2. Enforcing工作模式(強制模式)
三、基本概念
1、主體(subject) 基本等同於程序
2. 客體(object) 被主體訪問的資源:檔案(含可執行檔案),目錄,節點等
3. 安全上下文(secure context)
ls -Z // 顯示檔案(如果是目錄則顯示其路徑下的檔案)的安全上下文 ps -eZ // 顯示程序的安全上下文 Id -Z // 可以顯示shell的安全上下文
安全上下文格式:
舉例:u:object_r:system_file:s0
user:role:type[:range]
user:使用者;
role:角色,一個user可以有多個role,不通的role擁有不同的許可權
type:主體or客體的型別;
range:說是跟MLS有關,簡單點說,MLS將系統的 程序和檔案進行了分級,不同級別的資源需要對應級別的程序才能訪問。
四、策略規則語句格式
allow domains types:classes permissions; - Domain - 一個程序或一組程序的標籤。也稱為域型別,因為它只是指程序的型別。 - Type - 一個物件(例如,檔案、套接字)或一組物件的標籤 - Class - 要訪問的物件(例如,檔案、套接字)的型別。 - Permission - 要執行的操作(例如,讀取、寫入)。跟~可以將兩個操作聯合起來 (如:allow unconfineddomain {fs_type dev_type file_type}:{ chr_file file }~{entrypoint relabelto};) = allow : 允許主體對客體進行操作 = neverallow :拒絕主體對客體進行操作 = dontaudit : 表示不記錄某條違反規則的決策資訊 = auditallow :記錄某項決策資訊,通常 SElinux 只記錄失敗的資訊,應用這條規則後會記錄成功的決策資訊。 = class可見system/sepolicy/private/security_classes中的定義 # file-related classesclass filesystem class file #代表普通檔案 class dir #代表目錄 class fd #代表檔案描述符 class lnk_file #代表連結檔案 class chr_file #代表字元裝置檔案 # network-related classes class socket #socket class tcp_socket class udp_socket ...... class binder #Android 平臺特有的 binder class zygote #Android 平臺特有的 zygote = permissions可見system/sepolicy/private/access_vectors 其中inherits表示繼承了某個common定義的許可權
五、型別type
#type命令的完整格式為:type type_id [alias alias_id,] [attribute_id]
#其中,方括號中的內容為可選。alias指定了type的別名,可以指定多個別名。
#下面這個例子定義了一個名為shell的type,它和一個名為domain的屬性(attribute)關聯
type shell, domain; #本例來自shell.te,注意,可以關聯多個attribute
sepolicy 現在分為多個部分:
public - 非平臺策略開發人員可以在其上編寫的匯出策略附加政策。型別和屬性被版本化幷包含在下發非平臺政策,與平臺政策相結合。
private - 平臺功能所需的僅平臺策略,但不會匯出給供應商策略開發人員,因此可能不會假設存在。
vendor - 供應商功能所需的僅限供應商策略。這個政策可以參考公共政策,但不能參考私人政策。這策略適用於從核心/非供應商樹生成的元件,並且放入供應商分割槽。
SELinux解決辦法:
adb shell getenforce 可檢視裝置selinux模式 adb shell setenforce 可設定裝置selinux模式(0:permissive;1:enforcing)
te檔案一般存在於system/sepolicy/,device/qcom/sepolicy/,external/selinux以及某些三方廠商自己預置的te檔案(不好定位具體路徑),一般在device/qcom/sepolicy/(generic|legacy)/路徑下去新增selinux規則
1、可以關閉SELinux
修改system/core/init/selinux.cpp檔案:
b shell getenforce 可檢視裝置selinux模式 adb shell setenforce 可設定裝置selinux模式(0:permissive;1:enforcing) te檔案一般存在於system/sepolicy/,device/qcom/sepolicy/,external/selinux以及某些三方廠商自己預置的te檔案(不好定位具體路徑),一般我們在device/qcom/sepolicy/(generic|legacy)/路徑下去新增selinux規則 1、可以關閉SELinux 修改system/core/init/selinux.cpp檔案: EnforcingStatus StatusFromCmdline() { EnforcingStatus status = SELINUX_PERMISSIVE; // ****** import_kernel_cmdline(false, [&](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.selinux" && value == "permissive") { status = SELINUX_PERMISSIVE; } }); return status; } bool IsEnforcing() { return false; // ****** if (IsUserBuild()) { if (RootValueFromCmdline()) return false; else return true; } if (ALLOW_PERMISSIVE_SELINUX) { return StatusFromCmdline() == SELINUX_ENFORCING; } return true; }
2、手動新增許可權
一般許可權問題都會在log檔案中列印,可透過過濾avc關鍵字檢視,如下:
auditd : type=1400 audit(0.0:1275): avc: denied { open } for comm="monitor-thread" path="/sys/devices/platform/soc/1c08000.qcom,pcie/pci0001:00/0001:00:00.0/0001:01:00.0/net/eth0/operstate" dev="sysfs" ino=63866 scontext=u:r:system_app:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
分析過程:
哪個程序缺少許可權:monitor-thread
缺少什麼許可權: { open}許可權,
誰缺少許可權: u:r:system_app:s0
對哪個檔案缺少許可權:u:object_r:sysfs:s0
什麼型別的檔案: file
完整的意思: monitor-thread(system_app)程序對sysfs型別的file缺少open許可權。
接下來只需要在system_app.te檔案中加入:
allow system_app sysfs:file open即可(全編譯會報錯,因為這句程式碼是給所有system_app程序開放了所有檔案的open許可權)
3、使用audit2allow工具新增規則
在ubuntu下執行:adb shell dmesg |grep avc > avc;audit2allow -i avc,例:
直接把規則複製貼上到對應的te檔案中(如上圖應該將規則貼上於system_app.te檔案中)
有時候avc denied的log不是一次性暴露所有許可權問題,要等解決一個許可權問題之後,才會暴露另外一個許可權問題。比如提示缺少某個目錄的read許可權,加入read之後,才顯示缺少write許可權,要一次次一次試,一次一次加,時間成本極大。
針對dir缺少的任何許可權,建議賦予create_dir_perms,基本涵蓋對dir的所有許可權,比如:{ open search write read rename create rmdir getattr }等等。
針對file缺少的任何許可權,建議賦予rwx_file_perms,基本涵蓋對file的所有許可權,比如:包含{ open read write open execute getattr create ioctl }等等。
4、自定義規則**
給節點加許可權,這類情況使用audit2allow工具一般就會給你一句:allow xxx sysfs:file {read getattr open},然後貼到對應的te檔案中,全編報錯:neverallow xxxvim
因為sysf:file 相當於我們開放了所有檔案的許可權,這是不被允許的,所以我們只能對節點單獨新增規則(如我給/sys/class/net/eth0/operate新增許可權):
在裝置內部執行ls -l /sys/class/net/eth0/ 發現他是個軟連結(給軟連結新增規則是無效的), 具體路徑是/sys/devices/platform/soc/1c08000.qcom,pcie/pci0001:00/0001:00:00.0/0001:01:00.0/net/eth0/operstate 然後在file_contexts中加上新的scontext,如下(sysfs_eth是自定義的型別): /sys/devices/platform/soc/1c08000.qcom,pcie/pci0001:00/0001:00:00.0/0001:01:00.0/net/eth0/operstate u:object_r:sysfs_eth:s0 之後在file.te中加上: # eth0 statustype sysfs_eth, fs_type, sysfs_type; 最後去system_app.te檔案中新增規則: allow system_app sysfs_eth:file { read getattr open }; allow system_app sysfs_eth:dir search;
常見編譯問題:
1、ERROR 'duplicate declaration of type/attribute' at token ';' on line 14430
解決方法:type的重定義,把你自定義的type給改了;
2、neverallow
原生selinux不允許賦予該許可權,如果專案無需過CTS,可以在system/sepolicy中去掉該項規則,如需過CTS,需找尋其他方式;