在 Android 4.3版本之前趾娃,Android通過DAC(Discretionary Access Control)自主訪問控制來進行權(quán)限管理。
DAC 的核心思想很簡單琼腔,通俗的來講就是“誰創(chuàng)造了我薪韩,我就擁有誰的權(quán)利”炕桨。比如, root 用戶啟動 Camera利虫,那么 Camera 就有 root 用戶的權(quán)限挨厚,在 Linux 系統(tǒng)上能干任何事情堡僻。
很顯然,DAC 管理太過寬松疫剃,只要想辦法在 Android 系統(tǒng)上獲取到 root 權(quán)限就可以了钉疫。所以在Android5.0版本之前,android系統(tǒng)很容易被破壞巢价,設(shè)備廠商也經(jīng)常在保修單中明確說明“Root不保修”的政策牲阁。
那么該如何解決這個問題呢? Google在android4.3版本上便引入了SElinux壤躲,只不過是默認關(guān)閉的狀態(tài)城菊,在Android5.0上默認強制打開。
SElinux是一種新的安全模型碉克,這中模型叫 MAC(Mandatory Access Control)凌唬,翻譯為強制訪問控制。在Linux系統(tǒng)中漏麦,相信大家都聽過一句話叫作“一切皆文件”客税,但是文件可分為兩種“活的”和“死的”,“活的”是進程撕贞,映射到軟件層面的意思是:活的進程能發(fā)起動作霎挟,例如它能打開文件并操作它,而死的文件只能被進程操作麻掸。
SELinux的政策規(guī)定進程如果想干事情,都必須在《安全策略文件》中賦予權(quán)限赐纱,凡是沒有出現(xiàn)在安全策略文件中的權(quán)限都會被拒絕脊奋。
在 SELinux 中,每種東西都會被賦予一個安全屬性疙描,官方說法叫做 Security Context诚隙,Security Context 是一個字符串,同時也分為進程和文件兩種
進程的Security Context:
例如通過 ps -Z | grep sharplogcat 命令查看sharplogcat進程:
lcd_xxgae7a:/ # ps -AZ | grep sharplogcat
u:r:sharplogcat:s0 system 2640 1 9188 3092 __skb_wait_for_more_packets 0 S sharplogcat
其中
- u 為user的意思起胰,SEAndroid 中定義了一個 SELinux 用戶久又,值為 u
- r 為 role 的意思,role 是角色之意效五,它是 SELinux 中一個比較高層次地消,更方便的權(quán)限管理思路。簡單點說畏妖,一個 u 可以屬于多個 role脉执,不同的 role 具有不同的權(quán)限。
- sharplogcat代表該進程所屬的 Domain(域) 為 init 戒劫。MAC強制訪問控制 的基礎(chǔ)管理思路其實是 Type Enforcement Access Control(簡稱TEAC半夷,一般用TE表示)婆廊,對進程來說,Type 就是 Domain巫橄,比如 sharplogcat需要什么權(quán)限淘邻,都需要通過 allow 語句在 te 文件中進行說明。
- s0 是 SELinux 為了滿足軍用和教育行業(yè)而設(shè)計的 Multi-Level Security(MLS)機制有關(guān)湘换。簡單點說宾舅,MLS 將系統(tǒng)的進程和文件進行了分級,不同級別的資源需要對應(yīng)級別的進程才能訪問
文件的Security Context:
例如通過 ls -AZ vendor/bin/sharplogcat 命令查看sharplogcat文件:
lcd_xxgae7a:/ # ls -AZ vendor/bin/sharplogcat
u:object_r:sharplogcat_exec:s0 vendor/bin/sharplogcat
其中
u:同樣是 user 之意枚尼,它代表創(chuàng)建這個文件的 SELinux user
object_r:文件是死的東西贴浙,它沒法扮演角色,所以在 SELinux 中署恍,死的東西都用 object_r 來表示它的 role
sharplogcat_exec崎溃,和進程的 Domain 是一個意思,它表示 sharplogcat 文件所屬的 Type 是 sharplogcat_exec
s0:MLS 的等級
SELinux 規(guī)范
allow domains types:classes permissions;
- Domain - 一個進程或一組進程的標簽盯质。也稱為域類型袁串,因為它只是指進程的類型。
- Type - 一個對象(例如呼巷,文件囱修、套接字)或一組對象的標簽。
- Class - 要訪問的對象(例如王悍,文件破镰、套接字)的類型。
- Permission - 要執(zhí)行的操作(例如压储,讀取鲜漩、寫入)。
= allow : 允許主體對客體進行操作
= neverallow :拒絕主體對客體進行操作
= dontaudit : 表示不記錄某條違反規(guī)則的決策信息
= auditallow :記錄某項決策信息集惋,通常 SElinux 只記錄失敗的信息孕似,應(yīng)用這條規(guī)則后會記錄成功的決策信息。
實例介紹
以上面介紹的sharplogcat為例:在系統(tǒng)rc文件創(chuàng)建sharplogcat進程(該進程類似于原生的logcat刮刑,用于記錄android log)喉祭,默認不自啟動,通過程序控制啟動
service sharplogcat /vendor/bin/sharplogcat -n 1 -r ${persist.sys.logbuffer} -v time -f ${sys.android.log}
user system
group system
disabled
oneshot
system/sepolicy/目錄下是Android系統(tǒng)默認的策略文件雷绢,這些文件在編譯后會包含 SELinux 內(nèi)核安全政策泛烙,并涵蓋上游 Android 操作系統(tǒng)。但我們在配置添加SELinux策略文件時并不是在該目錄下习寸,而是在/device/manufacturer/device-name/sepolicy 目錄中胶惰,如HISI平臺的為device/hisilicon/bigfish/external/sepolicy目錄下。
1. 配置新的sharplogcat.te政策文件霞溪,在編譯到單個 SELinux 內(nèi)核政策文件時孵滞,新的政策文件會與現(xiàn)有的政策文件組合在一起中捆,te文件中按照sharplogcat所需要的權(quán)限進行配置(切記不可為了方便,把所有的權(quán)限加進去坊饶,應(yīng)該是需要哪些加哪些):
# Policy for sharplogcat
type sharplogcat, domain;
type sharplogcat_exec, exec_type, file_type, vendor_file_type;
init_daemon_domain(sharplogcat)
allow sharplogcat sharplogcat:capability { dac_override sys_nice };
allow sharplogcat sharp_log_file:dir rw_dir_perms;
allow sharplogcat sharp_log_file:file { create read open write append rename getattr setattr rw_file_perms };
allow sharplogcat logdr_socket:sock_file { write };
allow sharplogcat logd:unix_stream_socket { connectto read };
2. file_contexts泄伪,該文件用于為文件分配標簽,并且可供多種用戶空間組件使用匿级。在創(chuàng)建新政策時蟋滴,請創(chuàng)建或更新該文件,以便為文件分配新標簽:
/(vendor|system/vendor)/bin/sharplogcat u:object_r:sharplogcat_exec:s0
SELinux 相關(guān)設(shè)置
SElinux共有兩種等級可以設(shè)置痘绎,可通過getenforce查看
- 寬容模式(permissive) - 僅記錄但不強制執(zhí)行 SELinux 安全政策津函。
- 強制模式(enforcing) - 強制執(zhí)行并記錄安全政策。如果失敗孤页,則顯示為 EPERM 錯誤尔苦。
1.臨時關(guān)閉
setenforce 命令修改的是 /sys/fs/selinux/enforce 節(jié)點的值,是 kernel 意義上的修改 selinux 的策略行施,缺點是斷電之后允坚,節(jié)點值會復(fù)位。
setenforce 0
2.永久關(guān)閉
第一種方法:修改system/core/init/Android.mk
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
#HISILICON add begin
#reboot. Disable dumping when rebooting in non-user mode.
init_options +=
-DALLOW_LOCAL_PROP_OVERRIDE=1
-DALLOW_PERMISSIVE_SELINUX=1? //1:permissive
-DREBOOT_BOOTLOADER_ON_PANIC=1
-DDUMP_ON_UMOUNT_FAILURE=0
#HISILICON add end
else
init_options +=
-DALLOW_LOCAL_PROP_OVERRIDE=0
-DALLOW_PERMISSIVE_SELINUX=1? //1:permissive
-DREBOOT_BOOTLOADER_ON_PANIC=0
-DDUMP_ON_UMOUNT_FAILURE=0
endif
第二種方法:修改system/core/init/init.cpp蛾号,需要重新編譯boot分區(qū)并燒錄該分區(qū)稠项。
static bool selinux_is_enforcing(void) //直接注釋掉內(nèi)容,reture false即可鲜结。
{
if (ALLOW_PERMISSIVE_SELINUX) {
return selinux_status_from_cmdline() == SELINUX_ENFORCING;
}
return true;
}
第三種方法:開機時修改bootargs展运。開機時不斷Ctrl+c進入fastboot模式,printenv獲取當前參數(shù)配置精刷,修改其中androidboot.selinux=permissive乐疆,再setenv->saveenv->reset即可。
bootargs=selinux=1 androidboot.selinux=permissive firmware_class.path=/vendor/firmware/ console=ttyAMA0,115200 loglevel=7 no_console_suspend blkdevparts=mmcblk0:1M(fastboot),1M(bootargs),40M(recovery),8M(panelparam),2M(deviceinfo),38M(logo),2M(btfw),40M(kernel),1M(dtb),2M(atf),25M(trustedcore),10M(securestore),1M(versioninfo),1M(misc),3072M(system),300M(vendor),50M(atv),50M(db),2048M(cache),-(userdata) mtdparts=hi_sfc:-(hi_sfc) pci=nomsi mem=3072M dma_zone=2G mmz=ddr,0,1996M,48M mdlid=0 cmode=0 finit=0 panelsize=0 androidboot.sharp.serialno= androidboot.productname=--
ver=Fastboot 3.3.0-00015-g327655d-dirty (build@serd-build-008) (Mar 18 2019 - 09:17:15)
在實際的開發(fā)中贬养,配置selinux是非常繁瑣和枯燥的,但是作為官方推廣的安全策略琴庵,還是希望大家能夠了解一些误算,以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助迷殿。