HQX SELinux 权限问题分析与解决

发布于:2025-09-05 ⋅ 阅读:(21) ⋅ 点赞:(0)

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

  1. BoardConfig
    File: device/rockchip/common/BoardConfig.mk
BOARD_SELINUX_ENFORCING ?= false
  1. 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")
  1. 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 := true
 TARGET_USES_NEW_ION_API :=true
 TARGET_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=7
 androidboot.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=7
 androidboot.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

  1. 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

  1. Kernel 中关闭selinux
    config
CONFIG_SECURITY_SELINUX=y

关闭以上配置。

可通过以下命令确实kernel中配置:

# zcat /proc/config.gz | grep SELINUX
CONFIG_SECURITY_SELINUX=y
  1. Others
    某些平台中,可能需要修改devicetree中chosen字段

增加SElinux权限

  1. 通过以下命令获取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
  1. Log解析
    avc: denied { 操作权限 } for pid=7201 comm=“进程名” scontext=u:r:源类型:s0 tcontext=u:r:目标类型:s0 tclass=访问类型 permissive=0

#============= 源类型 ==============
allow 源类型 目标类型:访问类型 操作权限;
完整的意思是: "源类型"进程对"目标类型"的"访问类型"缺少 “操作权限”

  1. 手动添加权限
    File path:
#============= test_init ==============
allow test_init radio_prop:property_service getattr;
  1. 工具添加权限
    使用 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的报错不会一次性的全部暴露出来,要解决完一个,才会报下一个问题。
比如:一个进程需要读、写和打开的权限,但是一般情况下,可能会先报其中一个权限缺失,等你加了这个权限后,才会报另一个权限缺失,以此类推。

  1. te文件路径
    Path:
device/qcom/sepolicy_vndr;
device/qcom/sepolicy;
/system/sepolicy

尽量只修改device目录下的te文件,修改system目录下te会影响Google CTS测试。