Google自Android 5.0起強制實施的SELinux安全子系統,通過最小權限原則顯著提升了系統安全性,但這也導致開發過程中頻繁出現權限拒絕問題。值得注意的是,即便設備已獲取root權限,SELinux的強制訪問控制機制仍會限制部分敏感操作。
本文將聚焦實戰場景,通過典型錯誤日志解析,系統化講解如何診斷并解決SELinux權限異常問題。
獲取selinux配置
# getenforce
Enforcing
cmdline:
msmnile_gvmq:/ # cat /proc/cmdline
cgroup_disable=pressure androidboot.verifiedbootstate=orange androidboot.vbmeta.device=/dev/vbmeta androidboot.vbmeta.avb_version=1.1 androidboot.vbmeta.device_state=unlocked androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=3840 androidboot.vbmeta.digest=aaa6d414b8059e251f9aaf9cd950350c10d51acd494449855bcbbe925c58f052 androidboot.vbmeta.invalidate_on_error=yes androidboot.veritymode=enforcing console=hvc0,115200 debug user_debug=31 loglevel=9 print-fatal-signals=1 androidboot.console=ttyAMA0 androidboot.hardware=qcom androidboot.selinux=enforcing androidboot.memcg=1 init=/init swiotlb=4096 androidboot.usbcontroller=a600000.dwc3 androidboot.recover_usb=1 firmware_class.path=/vendor/firmware_mnt/image kpti=0 msm_cfg.cfg_sel=1 pcie_ports=compat androidboot.dtbo_idx=1 buildvariant=userdebug androidboot.serialno=2e036b5d androidboot.force_normal_boot=1 androidboot.fstab_suffix=ufs.qcom
Notes:
enforcing mode: 限制訪問
permissive mode: 只審查權限,不限制
臨時關閉selinux
# setenforce --help
usage: setenforce [enforcing|permissive|1|0]Sets whether SELinux is enforcing (1) or permissive (0).
setenforce 0 (臨時關閉 SELinux 的限制訪問模式)
永久關閉selinux
- BoardConfig
File: device/rockchip/common/BoardConfig.mk
BOARD_SELINUX_ENFORCING ?= false
- selinux.cpp
File: system/core/init/selinux.cpp
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 5a0255acd..db22d7b61 100755
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -104,6 +104,7 @@ EnforcingStatus StatusFromCmdline() {}bool IsEnforcing() {
+ return false;if (ALLOW_PERMISSIVE_SELINUX) {return StatusFromCmdline() == SELINUX_ENFORCING;}
or:
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 5a0255acd..42608a18b 100755
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -476,6 +476,7 @@ void SelinuxInitialize() {bool kernel_enforcing = (security_getenforce() == 1);bool is_enforcing = IsEnforcing();
+ is_enforcing = 0;if (kernel_enforcing != is_enforcing) {if (security_setenforce(is_enforcing)) {PLOG(FATAL) << "security_setenforce(" << (is_enforcing ? "true" : "false")
- Boardconfig.mk
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -194,7 +194,7 @@ BOARD_VENDOR_KERNEL_MODULES += $(shell ls $(KERNEL_MODULES_OUT)/*.ko)TARGET_USES_ION := trueTARGET_USES_NEW_ION_API :=trueTARGET_USES_QCOM_BSP := false
-BOARD_KERNEL_CMDLINE := console=ttyMSM0,115200n8 androidboot.hardware=qcom androidboot.console=ttyMSM0 androidboot.memcg=1 lpm_levels.sleep_disabled=1 video
=vfb:640x400,bpp=32,memsize=3072000 msm_rtb.filter=0x237 service_locator.enable=1 swiotlb=4096 firmware_class.path=/vendor/firmware_mnt/image loop.max_part=7androidboot.usbcontroller=a600000.dwc3 androidboot.recover_usb=1 androidboot.selinux=enforcing hibernate=nocompress noswap_randomize pcie_ports=compat kpti=
0
+BOARD_KERNEL_CMDLINE := console=ttyMSM0,115200n8 androidboot.hardware=qcom androidboot.console=ttyMSM0 androidboot.memcg=1 lpm_levels.sleep_disabled=1 video
=vfb:640x400,bpp=32,memsize=3072000 msm_rtb.filter=0x237 service_locator.enable=1 swiotlb=4096 firmware_class.path=/vendor/firmware_mnt/image loop.max_part=7androidboot.usbcontroller=a600000.dwc3 androidboot.recover_usb=1 androidboot.selinux=permissive hibernate=nocompress noswap_randomize pcie_ports=compat kpti
=0
androidboot.selinux=enforcing --> androidboot.selinux=permissive
- system.build.tmpl
File: apps/qnx_ap/target/hypervisor/host/build_files/system.build.tmpl
-cmdline "console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9 print-fatal-signals=1 no_console_suspend androidboot.console=ttyAMA0 androidboot.hardware=qcom androidboot.selinux=enforcing androidboot.memcg=1 androidboot.bootdevice=/dev/disk/system_b swiotlb=2048 gvmip=192.168.1.3 androidboot.serialno="$env{SERIAL_NO\}" veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f rootwait skip_initramfs=1 ro init=/init root=/dev/dm-0 dm=\\\"system none ro,0 1 android-verity /dev/vda\\\""+cmdline "console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9 print-fatal-signals=1 no_console_suspend androidboot.console=ttyAMA0 androidboot.hardware=qcom androidboot.selinux=permissive androidboot.memcg=1 androidboot.bootdevice=/dev/disk/system_b swiotlb=2048 gvmip=192.168.1.3 androidboot.serialno="$env{SERIAL_NO\}" veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f rootwait skip_initramfs=1 ro init=/init root=/dev/dm-0 dm=\\\"system none ro,0 1 android-verity /dev/vda\\\""
androidboot.selinux=enforcing --> androidboot.selinux=permissive
- Kernel 中關閉selinux
config
CONFIG_SECURITY_SELINUX=y
關閉以上配置。
可通過以下命令確實kernel中配置:
# zcat /proc/config.gz | grep SELINUX
CONFIG_SECURITY_SELINUX=y
- Others
某些平臺中,可能需要修改devicetree中chosen字段
增加SElinux權限
- 通過以下命令獲取selinux
logcat | grep audit > selinux.txt
or:
dmesg | grep audit > selinux.txt
cat /proc/kmsg | grep audit
Example:
type=1400 audit(0.0:29830): avc: denied { getattr } for property=ro.ril.ecclist pid=1 uid=0 gid=0 scontext=u:r:test_init:s0 tcontext=u:object_r:radio_prop:s0 tclass=property_service permissive=0
- Log解析
avc: denied { 操作權限 } for pid=7201 comm=“進程名” scontext=u:r:源類型:s0 tcontext=u:r:目標類型:s0 tclass=訪問類型 permissive=0
#============= 源類型 ==============
allow 源類型 目標類型:訪問類型 操作權限;
完整的意思是: "源類型"進程對"目標類型"的"訪問類型"缺少 “操作權限”
- 手動添加權限
File path:
#============= test_init ==============
allow test_init radio_prop:property_service getattr;
- 工具添加權限
使用 audit2allow 工具解析avc.txt。
在aosp源碼中執行如下命令:
source ./build/envsetup.sh
lunch msmnile_au-userdebug
audit2allow -i avc.txt
解析出來如下圖所示:
#============= test_init ==============
allow test_init automotive_display_service:dir getattr;
allow test_init hal_broadcastradio_default:dir getattr;
allow test_init network_stack:dir getattr;
allow test_init platform_app:dir getattr;
allow test_init secure_element:dir getattr;
上述步驟解析完了報出的權限問題,接下來需要把,這些權限添加到對應的 te 文件中,直接將上述的四條 allow xxx 拷貝到 te即可。
絕大多數的情況下 avc denied的報錯不會一次性的全部暴露出來,要解決完一個,才會報下一個問題。
比如:一個進程需要讀、寫和打開的權限,但是一般情況下,可能會先報其中一個權限缺失,等你加了這個權限后,才會報另一個權限缺失,以此類推。
- te文件路徑
Path:
device/qcom/sepolicy_vndr;
device/qcom/sepolicy;
/system/sepolicy
盡量只修改device目錄下的te文件,修改system目錄下te會影響Google CTS測試。