前言:
OpenHarmony 上某個進程向samgr注冊SA服務,其他進程在與該進程進行IPC通信之前,需要獲取該SA服務,SA提供方需要為該SA配置SELinux標簽,否則該SA會被SELinux配置為u:object_r:default_service:s0標簽,配置訪問default_service的策略會被neverallow禁止,本文將介紹如何為新增的SA配置SELinux策略。
一、SELinux簡介
SELinux (安全增強式 Linux , Security-Enhanced Linux )是 Linux 的安全組件,包含一組內核修改和用戶空間工具,并提供了基于安全策略的強制訪問控制機制( Mandatory Access Control ,MAC )。SELinux 已經被添加到各種 Linux 發行版中,其軟件架構力圖將軟件執行與安全策略設計分離。本部件負責對文件、屬性、服務等系統資源提供強制訪問控制保護。提供neverallow規則限制系統中的高危操作,減少系統安全風險。
訪問控制基本流程如下圖所示:
1.1 整體架構
1.2 策略目錄結構
OpenHarmony SELinux策略文件存放在//base/security/selinux_adapter/sepolicy/ohos_policy
路徑下,在該目錄下按以下規范存放:
├── 子系統
│ └── 部件
│ ├── public
│ │ └── type1.te
│ ├── vendor
│ │ └── type2.te
│ └── system
│ └── type3.te
其中,系統相關策略存放在system目錄下,芯片相關策略存放在vendor目錄下,系統和芯片共用的策略存放在public目錄下。
1.3 通用策略文件
通用策略文件,是指設備開發者進行SELinux策略配置時,涉及修改的文件。
1.4 基礎策略文件
基礎策略文件,是指SELinux基礎框架的SELinux策略文件,一般不涉及修改。
1.5 SELinux模式開關
將鏡像燒錄到開發板上,開機,通過串口拿到 Shell ,在其中執行:
ls -lZ / # 查看文件標簽 ls -lLZ / # 查看link源文件標簽 ps -eZ # 查看進程標簽 setenforce 1 # 使能selinux強制模式(enforcing) setenforce 0 # 是能selinux寬容模式,當前默認寬容模式(permissive) getenforce # 獲取selinux工作模式 |
selinux模式開關配置文件 :開發板 /etc/selinux/config
二、SELinux策略
2.1 avc日志信息
當系統行為被SELinux攔截時,會在內核日志和hilog中打印相關的avc denied
日志,格式如下:
//使用dmesg查看日志 audit: type=1400 audit(1502458430.566:4): avc: denied { open } for pid=1658 comm="setenforce" path="/sys/fs/selinux/enforce" dev="selinuxfs" ino=4 scontext=u:r:hdcd:s0 tcontext=u:object_r:selinuxfs:s0 tclass=file permissive=1//關鍵字:avc: denied//日志解讀 open #操作為open pid=1658 #訪問主體進程號為1658 comm="setenforce" #訪問主體進程名為setenforce path="/sys/fs/selinux/enforce" #被訪問客體為/sys/fs/selinux/enforce dev="selinuxfs" #被訪問文件屬于selinuxfs這一文件系統 ino=4 #文件節點編號為4 scontext=u:r:hdcd:s0 #訪問主體selinux標簽為u:r:hdcd:s0 tcontext=u:object_r:selinuxfs:s0 #被訪問客體selinux標簽為u:object_r:selinuxfs:s0 tclass=file #當前告警屬于file類型的操作 permissive=1 #當前selinux處于寬容模式,只告警不做訪問攔截。強制模式時,做攔截, permissive=0//分析: 缺少啥權限:denied { open } 誰缺少權限:scontext=u:r:hdcd:s0 對哪個文件缺少:tcontext=u:object_r:selinuxfs:s0 什么類型:tclass=file 通用公式為:allow {scontext} {tcontext}:{tclass} {denied權限} |
開發者可以使用關鍵字avc denied
來過濾日志,對于影響業務的avc告警,可以利用告警提供的信息來編寫相應的SELinux策略,例如:
上述avc日志對應的TE規則為
allow hdcd selinuxfs:file open; |
2.2 策略格式
SELinux策略,又稱SELinux規則,通常以allow或neverallow開頭,表示允許或禁止某種行為。在設備上使能SELinux時,SELinux會攔截所有未經allow規則授權的行為,配置allow規則可以放行,neverallow規則主要是攔截危險規則的配置。通常allow規則如下:
allow subject object:class permissions; |
表示允許subject
對object
進行class
中的permissions
操作,其中:
subject
表示主體,通常為進程的SELinux類型,如init
。object
表示客體,通常為系統資源的SELinux類型,如data_file
。class
表示要執行的操作的類型,如文件操作file、目錄操作dir、套接字操作socket。permissions
表示要執行的具體操作,如對文件file的open、read、write。
同理,
neverallow subject object:class permissions; |
表示不允許subject
對object
進行class
中的permissions
操作。
2.3 策略宏隔離
在考慮設備開發者便利的同時,需要兼顧商用設備安全性,因此OpenHarmony SELinux提供了策略宏隔離,決定在不同版本上策略是否生效。OpenHarmony SELinux中支持對僅在root版本生效的策略做宏隔離,宏名稱為debug_only
。在用于設備開發者調試的root版本中,也就是在版本編譯命令中指定--build-variant root
時,宏開啟。在用于商用發布的user版本中,也就是在版本編譯命令中指定--build-variant user
時,宏關閉。該宏的使用方法參考如下:
debug_only(`allow ueventd init:fd use; ') |
另外,OpenHarmony SELinux中也支持對開發者模式的策略做宏隔離,宏名稱為developer_only
,該宏默認開啟。開發者模式策略是指,為便于使用user版本進行調試開發的開發者,需要開放的一些用于調試的SELinux策略。開發者模式宏的使用方法參考如下:
developer_only(`allow sh init:fd use; ') |
三、配置SELinux策略
此處以開發activation_sa激活服務為例,詳細介紹如何為sa服務配置selinux策略。
3.1 配置service_contexts
在sepolicy/base/public/service_contexts文件內,新增SAID與SA標簽的映射關系:(SAID在activation_sa服務中定義,如foundation/activation/activation/sa_profile/BUILD.gn)
10 u:object_r:sa_render_service:s0 ... ... 7002 u:object_r:sa_ui_appearance:s0 8001 u:object_r:sa_ca_daemon_service:s0 10000 u:object_r:sa_activation_sa:s0 |
在service.te中定義對應的sa_activation_sa,使對應的標簽合法:
type sa_activation_sa, sa_service_attr |
3.2 配置type.te
由init通過cfg文件孵化的SA服務進程,需要在sa服務的本進程cfg文件中新增secon字段(本例子為?foundation/activation/activation/etc/activation_sa.cfg),建立進程與標簽的映射關系。如果未配置secon字段,進程在SELinux使能狀態會被攔截啟動。
{"services" : [{"name" : "activation_sa","path" : ["/system/bin/sa_main", "/system/profile/activation_sa.json"],"uid" : "system","gid" : ["system", "shell"],"start-mode" : "boot","secon" : "u:r:activation_sa:s0"}] } |
因此,需要在type.te中定義SELinux標簽u:r:activation_sa:s0中的SELinux類型activation_sa,使u:r:activation_sa:s0是合法的:
type activation_sa, sadomain, domain; |
此外,需要調用binder_call,在activation_sa.te中添加
binder_call(activation_sa, samgr); allow activation_sa sa_activation_sa:samgr_class { get add }; |
3.3 查看avc日志信息
dmesg |grep activation_sa [ 11.766938] [pid=1][Init][INFO][init_service_manager.c:1088]Start service activation_sa [ 11.768130] [pid=1][Init][INFO][init_common_service.c:567]Service activation_sa(pid 606) started [ 34.494845] audit: type=1400 audit(1502631529.323:301): avc: denied { getattr } for pid=1395 comm="ps" path="/proc/606" dev="proc" ino=27789 scontext=u:r:sh:s0 tcontext=u:r:activation_sa:s0 tclass=dir permissive=1 [ 45.994459] audit: type=1400 audit(1502631540.823:317): avc: denied { read } for pid=1426 comm="ps" name="stat" dev="proc" ino=30816 scontext=u:r:sh:s0 tcontext=u:r:activation_sa:s0 tclass=file permissive=1 [ 45.994494] audit: type=1400 audit(1502631540.823:318): avc: denied { open } for pid=1426 comm="ps" path="/proc/606/stat" dev="proc" ino=30816 scontext=u:r:sh:s0 tcontext=u:r:activation_sa:s0 tclass=file permissive=1 [ 51.714670] audit: type=1400 audit(1502631546.543:334): avc: denied { getattr } for pid=1443 comm="ps" path="/proc/606" dev="proc" ino=27789 scontext=u:r:sh:s0 tcontext=u:r:activation_sa:s0 tclass=dir permissive=1 [ 51.714712] audit: type=1400 audit(1502631546.543:335): avc: denied { search } for pid=1443 comm="ps" name="606" dev="proc" ino=27789 scontext=u:r:sh:s0 tcontext=u:r:activation_sa:s0 tclass=dir permissive=1 |
根據日志配置te策略,新增sepolicy/ohos_policy/activation/test/system/sh.te
allow sh activation_sa:dir { getattr search }; allow sh activation_sa:file { read open getattr }; |
注意:隨著策略不斷配置,還會出現很多新的avc日志,要全部配置完全。
3.4 其他
如果配置完上述策略后,應用程序還是無法調用activation_sa中的方法,那么還需在對應等級的應用te文件(如settings應用權限等級為system_basic,那么對應新增system_basic_hap.te)中添加:
allow system_basic_hap_attr activation_sa:binder { call transfer }; allow system_basic_hap_attr sa_activation_sa:samgr_class { get }; |
通過上述一系列配置,新增的activation_sa服務能夠在selinux開啟強制模式下正常啟動,且應用程序能夠調用到activation_sa服務中定義的接口。