Android Safety 系列专题【SELinux语法解析】

本文深入解析SEAndroid的权限管理机制,涵盖工作模式、进程资源安全属性、策略文件配置及问题解决思路,帮助开发者掌握SEAndroid核心概念,有效解决权限问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SELinux原本是美国国安局联合一些公司设计的一个针对Linux的安全加强系统。

SELinux出现之前,Linux系统上的安全模型叫做DAC(自主访问控制),其原理是进程所拥有的权限与执行它的用户的权限相同(例如:以root用户启动Browser,那么Browser就有root用户的权限,在Linux系统上能干任何事情)。SELinux的出现结束了这种宽松的访问。

SELinux在DAC的基础之上,设计了新的安全模型叫做MAC(强制访问控制),其原理是任何进程想在SELinux系统中干任何事情,都必须先在安全策略配置文件中赋予权限,凡是没有在安全策略配置文件配置的权限,进程就没有该权限。Android4.4版本上正式推出的一套以SELinux为基础于核心的系统安全机制,且命名为SEAndroid,自此SELinux便被"移植"到了Android上了。

一、基本概念

Selinux中涉及了很多基本概念,这些概念设计到selinux设计的底层逻辑,所以理解这些概念是必要的。

1、工作模式

SELinux通常有如下三种模式:disable、permissive、enforcing。通常发布版都将使用强制模式Enforcing。

可以通过getenforce来获取当前工作模式,还可以通过setenforce 0来设置当前模式为Permissive;也可以通过setenforce 1来设置当前模式为Enforcing。

fastboot模式设置selinux工作模式:

#设置参数bootargs
$setenv bootargs  androidboot.selinux = permissive/enforcing
#保存参数
$saveenv
#重启系统
$reset

Android模式设置selinux工作模式:

adb shell setenforce 0  #切换为宽容模式,注意重启后不生效
adb shell setenforce 1   #切换为强制模式,注意user版本不生效?
adb shell getenforce   #如果输出Permissive表示处于宽容模式下,如果输出Enforcing表示处于强制模式下

A. Disable禁用模式

如果SELinux 被关闭(开启Disable模式),就使用传统的Linux系统默认的自主访问控制(DAC)方式,不需要增强安全性的环境来说,该模式是很好用的(换句话禁止SELinux功能)

编辑配置文件/etc/selinux/config,把SELINUX=disabled,然后重启系统,SELinux 就被禁用了。

还可以通过修改源代码的方式来关闭SELINUX,再Android S修改如下代码

pengcheng.ding@cdtinno-bianyi-105:~/works/n211/system/system/core/init$ git diff selinux.cpp
diff --git a/init/selinux.cpp b/init/selinux.cpp
index b7e8def89..066f9c2d4 100755
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -123,10 +123,16 @@ EnforcingStatus StatusFromProperty() {
 }
 bool IsEnforcing() {
-    if (ALLOW_PERMISSIVE_SELINUX) {
+    LOG(INFO) << "-----SHEN: selinux isenforcing system";
+    StatusFromProperty();
+    return false;
+    /*if (ALLOW_PERMISSIVE_SELINUX) {
         return StatusFromProperty() == SELINUX_ENFORCING;
     }
-    return true;
+    return true;*/
 }

B. Permissive宽容模式

在 Permissive 模式中,安全策略规则并没有被强制执行。当安全策略规则应该拒绝访问时,访问仍然被允许。然而,此时会向日志文件发送一条消息,表示该访问应该被拒绝换句话使能SELinux功能,但是SELinux不会拒绝方法但会打印日志)

SELinux Permissive 模式主要用于以下几种情况:审核当前的 SELinux 策略规则;测试新应用程序,看看将 SELinux 策略规则应用到这些程序时会有什么效果;解决某一特定服务或应用程序在 SELinux 下不再正常工作的故障。

总结:仅记录但不强制执行 SELinux 安全政策。

C. Enforcing强制模式

Enforcing 模式, SELinux 被启动,并强制执行所有的安全策略规则(换句话使能SELinux,并强制按照SElinux的规则来进行权限访问)

总结:强制执行并记录安全政策。如果失败,则显示为 EPERM 错误。当前user版本必须要开启强制模式。

2、进程和资源

有人比喻Linux中有两种东西:死的(Inactive)、活的(Active)。活的东西就是进程,而死的东西就是资源(普通文件、特殊文件、套接字、对象等)。

他们之间就是一种使用(操作)与被使用(被操纵)的关系:进程能发起动作(例如它能打开文件并操作它);而文件只能被进程操作

SElinux Policy语言将死的和活的东西都给打上"标签",通过"标签"将系统内的资源(包括进程)分成不同的角色(比如:用户、客体),进而对整个系统资(包括进程)进行合理安全的管控。

A. 安全上下文SContext

在SELinux世界里,每种东西都会被赋予一个安全属性(官方说法叫Security Context,后文简称SContext),也可以理解为第一小节提到的标签。

Linux中的所有东西,包括活的进程、死的资源都有自己对应的SContext安全属性,因此可以把SContext分为进程SContext和资源SContext,无论哪种安全属性,他们的本质都是一个字符串,其格式如下:

user:role:type[:range]
//user表示用户:SEAndroid中仅定义了一个SELinux用户,用u表示
//role表示角色:可以暂时理解为在SELinux用户可以有多个不同的role,不同role所具有的权限也不一样
//type表示类型:不同的type所具有的权限也不一样,但跟role有本质的不同
//range表示安全级别:通常为s0,不用怎么关注

B. Active的SContext

Active翻译过来就是活的,指动态的、能主动发起操作的系统资源,通常是进程或服务。通常包含如下:

  • 进程:例如surfaceflinger进程、system_server进程、bootanim进程
  • 应用:例如com.android.systemui应用,
  • 服务:例如audioserver服务cameraserver服务,注意像PMS/WMS这些服务没有单独为进程出现,依赖于system_server进程

我们可以使用adb shell ps -A -Z来打印当前进程的SContext,如下:

OrderPAD_3:/ $ ps -Z -A
LABEL                          USER           PID  PPID        VSZ    RSS WCHAN            ADDR S NAME
//init进程的安全上下文,在A14上面存在两个init进程,一个是vendor kernel启动的,一个是通过命令启动system init
u:r:init:s0                    root             1     0   12547168  10724 0                   0 S init
u:r:vendor_init:s0             root           242     1   12439120   6628 0                   0 S init
u:r:ueventd:s0                 root           243     1   12442188   7620 0                   0 S ueventd
u:r:logd:s0                    logd           521     1   12577584   6824 0                   0 S logd
u:r:lmkd:s0                    lmkd           538     1   12606216   8808 0                   0 S lmkd
u:r:servicemanager:s0          system         544     1   12359884   5180 0                   0 S servicemanager
u:r:hwservicemanager:s0        system         551     1   12513004   6212 0                   0 S hwservicemanager
u:r:vndservicemanager:s0       system         554     1   12413232   4192 0                   0 S vndservicemanager
u:r:shell:s0                   shell          637     1   12362664   2716 n_tty_read          0 S sh
u:r:shell:s0                   shell         5523  3375   12418020   2996 __do_sys_+          0 S sh
u:r:dumpstate:s0               root          4516  1988   12429512   3364 0                   0 S logcat
u:r:keystore:s0                keystore       853     1   12609436  14044 0                   0 S keystore2
u:r:zygote:s0                  root          1081     1   16707764 184608 0                   0 S zygote64
u:r:zygote:s0                  root          1082     1    1742780 157160 0                   0 S zygote
u:r:surfaceflinger:s0          system        1342     1   13118436  47884 0                   0 S surfaceflinger
#system_server进程的安全上下文
u:r:system_server:s0           system        1806  1081   23305908 486132 0                   0 S system_server
//服务的安全上下文,注意大多数被system_server启动的服务没有独立为进程,所以没有他们的打印
u:r:audioserver:s0             audioserver   1303     1   13365972  38376 0                   0 S audioserver
u:r:vendor_rfs_access:s0       vendor_rfs    1357     1   12464008   3136 0                   0 S tftp_server
u:r:drmserver:s0               drm           1501     1      25492   5556 0                   0 S drmserver
u:r:cameraserver:s0            cameraserver  1575     1   12933632  32720 0                   0 S cameraserver
u:r:mediaserver:s0             media         1599     1      78476  25544 0                   0 S mediaserver
//HAL进程的安全上下文
u:r:hal_health_default:s0      system        1173     1   12457988   5852 0                   0 S android.hardware.health-service.qti
u:r:vendor_hal_identity_qti:s0 system        1175     1   12414892   6396 0                   0 S android.hardware.identity-service-qti
u:r:hal_nfc_default:s0         nfc           1181     1   12508268   6828 0                   0 S android.hardware.nfc_pn72xx@1.2-service
u:r:hal_power_default:s0       system        1183     1   12484040   6424 0                   0 S android.hardware.power-service
u:r:hal_sensors_default:s0     system        1189     1   12803584  10212 0                   0 S android.hardware.sensors@2.1-service.multihal
u:r:hal_thermal_default:s0     root          1191     1   12433980   4632 0                   0 S android.hardware.thermal@2.0-service.qti-v2
u:r:vendor_hal_usb_qti:s0      root          1194     1   12461460   4440 0                   0 S android.hardware.usb.gadget@1.1-service-qti
u:r:vendor_hal_usb_qti:s0      root          1197     1   12402524   4492 0                   0 S android.hardware.usb@1.2-service-qti
//应用的安全上下文
u:r:platform_app:s0:c512,c768  u0_a154       2598  1081   20358644 258496 0                   0 S com.android.systemui
u:r:priv_app:s0:c512,c768      u0_a155       2957  1081   18782288 216704 0                   0 S com.android.launcher3
u:r:system_app:s0              system        2935  1081   18635732 155008 0                   0 S com.android.settings
u:r:radio:s0                   radio         2887  1081   19065740 143584 0                   0 S com.android.phone
u:r:bluetooth:s0               bluetooth     3359  1081   18821812 128340 0                   0 S com.android.bluetooth
u:r:mediaprovider_app:s0:c183+ u0_a183       3689  1081   18802176 117328 0                   0 S com.google.android.providers.media.module
u:r:priv_app:s0:c512,c768      u0_a102       3713  1081   19732200 200084 0                   0 S com.google.android.googlequicksearchbox:interactor
u:r:untrusted_app:s0:c115,c25+ u0_a115       5225  1081   19641788 156404 0                   0 S com.google.android.apps.photos
u:r:untrusted_app:s0:c133,c25+ u0_a133       5260  1082    1482556 106644 0                   0 S com.android.chrome
u:r:untrusted_app:s0:c139,c25+ u0_a139       6379  1081   20815808 167432 0                   0 S com.google.android.youtube
u:r:system_app:s0              system        6406  1081   18285768  96800 0                   0 S com.journey.logger
u:r:radio:s0                   radio         6470  1081   18320752  97540 0                   0 S com.qualcomm.qti.modemtestmode
u:r:vendor_cs_app:s0:c81,c256+ u0_a81        6490  1081   18558964  92444 0                   0 S com.qualcomm.qti.qms.service.connectionsecurity
//kernel进程的安全上下文
u:r:kernel:s0                  root           507     2          0      0 0                   0 I [kworker/6:2H-kverityd]
u:r:kernel:s0                  root           508     2          0      0 0                   0 I [kworker/7:2H-kblockd]
u:r:kernel:s0                  root           514     2          0      0 0                   0 I [cwfg_gauge]
u:r:kernel:s0                  root           517     2          0      0 0                   0 S [tcpc_timer_type_c_port0]
u:r:kernel:s0                  root           221     2          0      0 0                   0 S [f2fs_gc-8:15]
u:r:kernel:s0                  root           222     2          0      0 0                   0 I [kdmflush]

C. Inactive的SContext

inactive翻译过来就是死的。指静态的、无法主动发起操作的系统资源,仅作为被访问或操作的对象。通常包含如下:

  • 文件‌:普通文件、配置文件、脚本、应用资源文件等
  • 目录‌:例如/system/data等目录
  • 设备节点‌:例如/dev/block/mmcblk0,其本质还是特殊的文件
  • 套接字‌:例如UNIX Domain Socket,其本质还是特殊的文件
  • 属性文件‌:例如sysprop这类系统属性存储在/sys/class 目录的虚拟文件,其本质还是特殊的文件
  • 可执行文件:例如system/bin/里面的文件,其本质还是可执行的文件
  • 服务对象:这个有点不好理解,通常用于binder通信里面的服务对象,servicemanager维护了一个服务列表,在注册服务的时候需要把服务对象实例添加到这个列表里面,其他进程使用这个服务的时候才能从servicemanager里面查找这个服务对象,所以这个列表本质只是一系列对象实例的集合,所以他们的本质并不是进程,可以理解为一种抽象的客体资源

3、类型type和属性Attribute

在 Android SELinux 中,‌Type‌和Attribute‌是策略规则的核心组成部分,两者既有明确差异又有紧密关联。这里我们把type用汉语"类型"来进行统称,把attribute用汉语"属性"来进行统称。那么它们到底有什么区别和关联呢?

  • Type‌ 是 SELinux 中最小的安全标签单元,用于标识主体(如进程)和客体(如文件、设备)的安全属性。例如system_server和surfaceflinger都属于进程的type;system_data_file和vendor_configs_file都属于资源的type。
  • Attribute‌ 是一组 Type 的抽象集合,用于简化策略规则的编写和管理。即表示一类type的共有特点,把这些特点抽象出来统一进行管理。例如domain表示所有进程Type的集合;file_type表示所有文件Type的集合。

如上的理解,是否可以抽象的理解:type和attribute之间的关系,就是类名与属性之间的关系。

A. Type的定义

如何定义一个type?需要在xxx.te文件里面如下两种方式:

  • 定义一个type,不继承任何属性
type  类型名
//当为进程定义type的时候,通常以进程名来进行命名。例如surfaceflinger.te文件第一行为type surfaceflinger
//当为资源定义type的时候,根据实际情况进行命名。例如file.te文件中定义了很多文件的type
  • 定义一个type,继承多个属性
type  类型名, 属性名1, 属性名2, 属性名3, 属性名N
//注意type后面的第一个名字才是类型名,后面的都是属性名,各个属性名之间没有什么继承关系,即type带有后面所有属性具有的权限规则,可以理解为多继承的关系
//例如surfaceflinger.te文件第一行为type surfaceflinger, domain表示surfaceflinger是一个domain进程的属性
//例如type uwb_service, app_api_service, system_server_service, service_manager_type表示uwb_service继承多个属性

B.Attribute‌的定义

AOSP已经定义了很多属性,可以参考aosp/sepolicy目录下的attributes:

  • 定义属性
attribute 属性名
  • type直接关联
type <type_name>,  <attribute_name_1> , <attribute_name_2>, <attribute_name_n>;
//定义type_name的同时,关联/继承后面的属性。通常用于新创建一个type同时进行关联
  • typeattribute关联已存在的type
typeattribute <type_name> <attribute_name>;
//type_name已存在,关联后面的属性。即针对一个已存在的type进行关联

4、TE安全策略

SEAndroid世界将所有事物都打上了标签(每个事物都有自己的SContext),那么SEAndroid就能根据这些SContext来进行统一管理。SEAndroid就是通过一系列的te文件来管理所有进程和资源的权限,每个te文件里面都有无数条te语句,每条te语句对应一条安全策略。

  • 主体:主体和客体只是一个逻辑上的概念,就跟主谓宾语句:小红在吃米饭,其中主语是小红(活的),宾语是米饭(死的)。同理在Linux世界中,活的东西只有进程,死的东西是资源。即资源是被使用的东西,进程是使用者,这里的主体就是指使用者。SEAndroid中的主体就是指的进程,当然可能是单一的进程,也可以是一组具有相同权限的进程,但是它们都对应一个type。
  • 客体:同上客体就是这个被使用者。SEAndroid中的客体就是指的资源(包括普通文件/特殊文件/套接字),当然可能是单一的资源,也可以是一组相同类型的资源,但是他们都对应一个type。
  • 客体类别:客体与客体类别的概念就类似于Java语言中的object和class,其中class表示一个类,object表示一个实例对象。同样客体和客体类别也是这样的关系,例如小红在吃米饭,小红在吃鱼肉,米饭和鱼肉都是具体的事物(客体),但是他们却是不一样的类别(客体类别)。SEAndroid中已经为资源定义了一些客体类别,我们也可以自定义。例如/etc/password是一个普通文件,/atv/socket_0是一个套接字。
  • 访问许可:这个比较好理解,代表对客体的访问权限,例如读写权限,查询发送等权限。这个也是可以自定义的。
  • AV规则:既然已经有了主体和客体,那么就有对应访问规则,又叫AV规则。属于SElinux策略语言的控制部分,即te文件中每一条AV规则语句都需要能够描述清楚:主体 对 客体 是否具有 访问许可。其实就是te文件里面的allow、neverallow、dontaudit、auditallow等语句。

A. AVC日志

selinux的日志通常以avc开头,当然存在ap的avc日志和kernel的avc日志,因此我们针对这种两种抓取方式还不一样:

  • AP的avc日志:直接adb shell logcat | grep avc即可,如下内容
04-30 11:05:32.618   454   454 E SELinux : avc:  denied  { find } for interface=vendor.tinno.hardware.demo::IDemo sid=u:r:system_server:s0 pid=1376 scontext=u:r:system_server:s0 tcontext=u:object_r:hal_demo_hwservice:s0 tclass=hwservice_manager permissive=0
04-30 03:04:36.200  1341  1341 W binder:1341_10: type=1400 audit(0.0:90): avc:  denied  { call } for  scontext=u:r:system_server:s0 tcontext=u:r:hal_demo_default:s0 tclass=binder permissive=0
  • kernel的avc日志:需要使用adb shell dmesg | grep avc即可,如下内容
[  281.740040] .(4)[457:servicemanager]SELinux: avc:  denied  { add } for pid=10936 uid=1000 name=tinno_can scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0

B. allow规则

selinux这类日志都是以关键字avc开头,需要注意其中几个很重要的字段:

  • denied { 权限 }:找到denied字段,后面通常跟随大括号,里面的内部就表示被拒绝的操作,即什么操作权限被拒绝,例如读写查等权限
  • scontext=主体上下文:找到scontext字段,后面跟随的为主体安全上下文SContext,即代表主体进程
  • tcontext=客体上下文:找到tcontext字段,后面跟随的为客体安全上下文SContext,即代表被访问单个资源或一系列资源的上下文
  • tclass=客体类别:找到tclass字段,后面为客体类别

因此我们可以使用allow语句来进行配置,其格式如下:

allow  主体type  客体type  客体类别:  {权限}
//avc:denied { map } for path="/data/local/data/mute.png" dev="mmcblk0p37" ino=5338 scontext=u:r:bootvideo:s0 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=0
//allow bootvideo system_data_file:file { map }

我们除了手动转换avc日志之外,还可以使用audit2allow -i  avc_log.txt工具来转换,如下:

C. neverallow规则

有时候我们配置的allow语句可能会触发一些neverallow规则,android编译系统在编译的时候会对neverallow进行校验,因此会导致neverallow引起的编译报错,如下案例:

FAILED: out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor/policy

out/host/linux-x86/bin/checkpolicy -M -c 30 -o out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor/policy out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor.checkpolicy.conf/android_common/sepolicy_neverallows_vendor.checkpolicy.conf # hash of input list: 15871fa7f1904c26cfc726ea362c19ede7f225bff09f1871b1f7d5657882753a

libsepol.report_failure: neverallow on line 993 of system/sepolicy/public/domain.te (or line 13508 of out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor.checkpolicy.conf/android_common/sepolicy_neverallows_vendor.checkpolicy.conf) violated by allow bootlogo toolbox_exec:file { read getattr map execute open execute_no_trans };

libsepol.report_failure: neverallow on line 993 of system/sepolicy/public/domain.te (or line 13508 of out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor.checkpolicy.conf/android_common/sepolicy_neverallows_vendor.checkpolicy.conf) violated by allow bootlogo shell_exec:file { read getattr map execute open execute_no_trans };

libsepol.report_failure: neverallow on line 925 of system/sepolicy/public/domain.te (or line 13354 of out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor.checkpolicy.conf/android_common/sepolicy_neverallows_vendor.checkpolicy.conf) violated by allow bootlogo toolbox_exec:file { execute execute_no_trans };

libsepol.report_failure: neverallow on line 925 of system/sepolicy/public/domain.te (or line 13354 of out/soong/.intermediates/system/sepolicy/sepolicy_neverallows_vendor.checkpolicy.conf/android_common/sepolicy_neverallows_vendor.checkpolicy.conf) violated by allow bootlogo shell_exec:file { execute execute_no_trans };

libsepol.check_assertions: 4 neverallow failures occurred

Error while expanding policy

如上的neverallow报错,触发原因就是违反了类似如下neverallow这样的语句配置,通常可以根据日志来找到这样的语句配置, 如上neverallow on line 925 of system/sepolicy/public/domain.te 的代码如下:

//vendor/system/sepolicy/public/domain.te
full_treble_only(`
    # Do not allow vendor components to execute files from system
    # except for the ones allowed here.
    neverallow {
        domain
        -coredomain         // 排除核心域(如 system_server)
        -appdomain          // 排除应用域
        -vendor_executes_system_violators
        -vendor_init       // 排除vendor_init
    } {
        system_file_type
        -system_lib_file
        -system_linker_exec
        -crash_dump_exec
        -iorap_prefetcherd_exec
        -iorap_inode2filename_exec
        -netutils_wrapper_exec
        userdebug_or_eng(`-tcpdump_exec')
    }:file { entrypoint execute execute_no_trans };
') //禁止所有非核心域(vendor 域)执行 system 分区的可执行文件‌(除明确豁免的类型外)

5、编译调试

  • Selinux权限配置目录:aosp/system/sepolicy/
  • Selinux权限单编步骤:source build/envsetup.sh  &&  lunch xxx  && make selinux_policy 
  • Selinux权限自动转换:cd aosp/external/selinux/python/audit2allow/  &&  audit2allow -i  avc_log.txt
  • Selinux编译输出路径:aosp/out|out_sys/target/product/xxx/system|system_ext|vendor/etc/selinux

注意:这里的aosp是指vendor或者system:

  • 如果是system侧的进程,那么需要进入system/system/sepolicy目录下进行编译
  • 如果是vendor侧的进程,那么需要进入vendor/system/sepolicy目录下进行编译

如上准备了selinux权限调试的常用路径,我们配置了allow语句之后,可能还没生效,这个时候就可能需要调试了,查看一下我们的allow语句是否被编译到镜像里面的cil文件中。

技巧一:如何初步定位selinux权限问题?

当遇到可能与selinux有关系的权限问题的时候,我们可以选择在debug版本上面设置selinux权限为宽容模式来看看是否还出现异常,如果设置selinux为宽容模式不出现异常,那么可以断定是selinux权限问题导致。

  • 当遇到问题时,想判断是不是 selinux 权限导致时,在 userdebug 或 eng 版本,通过adb shell setenforce 0 命令,让 selinux 处于宽容模式,再看问题是否还存在。如果问题不存在,可以确认是 selinux 权限不足导致。(注意,特殊情况下可能还需要验证重启过程,上面命令重启失效,这个时候可以考虑修改init的代码来设置关闭模式)
  • 抓取 log,过滤“avc“,可以看到缺少的权限信息,类似如下错误:avc:denied{permission}for pid=257 scontext=u:r:scontext:s0 tcontext=u:object_r:tcontext:s0 tclass=tclass=0 
  •  根据报错,可以得知 scontext 缺少对 tcontext 的 tclass 的 permission 权限,可以在对应的scontext.te 文件中补上对应allown语句:allow scontext tcontext:tclass {permission};
  • 然后用 make selinux_policy 编译,然后 push 相关分区下的 etc/selinux。直到没有 avc 报错为止

先介绍audit2allow工具的使用:

技巧二:audit2allow工具生成allow语句

 audit2allow工具是android源码中自带的一个工具,可以直接使用,其源码路径:

AOSP/external/selinux/python/audit2allow/

我们可以直接跳转到上面目录执行如下命令根据日志生成allow语句:

audit2allow -i xxx_avc_log.txt

然后再介绍一下单编调试流程:

步骤一:单编selinux配置
//方式一:make selinux_policy 
source build/envsetup.sh
lunch xxx
make selinux_policy
//方式二:mm
source build/envsetup.sh
lunch xxx
cd aosp/system/sepolicy/
mm
步骤二:selinux输出目录
//这里以A14项目system为例,注意A11的路径可能不一样
aosp\out\target\product\qssi\system\etc\selinux
aosp\out\target\product\qssi\system_ext\etc\selinux
//allow语句的新增可以参考该目录下的cil结尾的文件,例如system_ext_sepolicy.cil
//context语句的新增可以参考该目录下的contexts结尾的文件,例如system_ext_property_contexts、system_ext_file_contexts、system_ext_hwservice_contexts

步骤三:推送xxx/etc/selinux目录到手机xxx/etc/selinux目录

二、基本语法

Selinux机制是属于linux的,Android基于这一套机制,配置了针对android系统的权限策略,这些策略和改模块的路径通常位于aosp/system/sepolicy/,如下目录:

如上路径为aosp原生制定的一些列策略和模块,我们前文使用的单编命令make selinux_policy其实主要就是编译这个模块,这里我们只关注android的一些列策略目录,其中最重要的private和public和vendor,以及api不同版本的兼容性配置和odm厂商的定制

  • private目录:存放AOSP 核心组件(如 system_serversurfaceflinger)的访问控制规则。厂商代码禁止直接引用 private 中的策略(如 system_server 的私有域)。Google 可在新版本中调整 private 策略(如收紧权限),无需考虑对厂商的影响
  • public目录:存放公开策略接口,供厂商(Vendor)/供应商扩展使用。即厂商策略需通过 public 接口实现扩展,避免直接依赖 private。
  • prebuilts/api/:存放了aosp不同版本的兼容性的配置,例如aosp/system/sepolicy/prebuilts/api/29/private和aosp/system/sepolicy/prebuilts/api/29/public,这些都基本上是针对android sdk为29的版本进行兼容的一些配置,通常我们不需要check
  • odm定制目录:厂商通常不应该直接修改aosp/system/sepolicy/private目录,但是readme里面已经提供了odm定制的配置应该如何集成

1、attributes:属性的定义

attributes文件中定义了aosp默认的一系列属性,并且在private和public都有配置,这里重点介绍一些常用的属性:

A. domain进程相关

  • attribute domain:All types used for processes。根据注释来看,domain翻译过来为域,根据sepolicy的用法,可以暂时把它理解为普通进程,普通进程所具有的属性
  • attribute coredomain:All core domains (as opposed to vendor/device-specific domains)。翻译为核心域,根据AI解释他为domain的子集,即用来标识核心进程,例如system_serversurfaceflinger这类进程都继承了coredomain属性。
  • attribute appdomain:All domains used for apps。同样为domain的子集,用来标识APP进程

  • attribute halserverdomain:All HAL servers。同样为domain的子集,用来标识hal服务端进程,例如vendor.hardware.demo@1.0-service,通过该属性我们不需要为每一个hal服务端进程单独赋予一些binder相关的访问规则。

  • attribute halclientdomain:All HAL clients。同样为domain的子集,用来标识hal客户端进程,例如Android Framework的服务或者system_server,通过type system_server, domain, halclientdomain来设置framework的服务可以作为hal客户端进程访问hal

  • expandattribute halclientdomain true:启用属性扩展机制,自动为所有关联到 halclientdomain 的类型继承其权限规则,true表示开启此功能,即确保子属性或子类型自动继承权限。

B. hal_attribute宏

在attributes文件中使用了大量的hal_attribute宏控,如下代码:

# hal_attribute(hal_name)
# Add an attribute for hal implementations along with necessary
# restrictions.
define(`hal_attribute', `
attribute hal_$1;
expandattribute hal_$1 true;
attribute hal_$1_client;
expandattribute hal_$1_client true;
attribute hal_$1_server;
expandattribute hal_$1_server false;
neverallow { hal_$1_server -halserverdomain } domain:process fork;
# hal_*_client and halclientdomain attributes are always expanded for
# performance reasons. Neverallow rules targeting expanded attributes can not be
# verified by CTS since these attributes are already expanded by that time.
build_test_only(`
neverallow { hal_$1_server -hal_$1 } domain:process fork;
neverallow { hal_$1_client -halclientdomain } domain:process fork;
')
')

这里以hal_attribute(thermal)展开之后的配置如下:由此可见自定义hal建议在attribute中添加hal_attribute(xxx),以统一被管理。

attribute hal_thermal;                  //定义属性hal_thermal
expandattribute hal_thermal true;       //开启hal_thermal属性的扩展功能
attribute hal_thermal_client;           //定义属性hal_thermal_client,表示hal客户端进程
expandattribute hal_thermal_client true;//开启hal_thermal_client属性的扩展功能
attribute hal_thermal_server;           //定义属性hal_thermal_server,表示hal服务端进程
expandattribute hal_thermal_server false;//关闭hal_thermal_server属性的扩展功能
neverallow { hal_thermal_server -halserverdomain } domain:process fork;//强制所有 HAL 服务端必须属于 halserverdomain 属性,保证其权限统一受控

C. file文件相关

  • attribute file_type:All types used for files that can exist on a labeled fs。根据注释来看,所有存在的文件的类型都应该叫做file_type,即用来标识文件,通常为客体资源。
  • attribute data_file_type:All types used for /data files。是file_type的子集,用来标识所有存在在于/data目录的文件。
  • attribute core_data_file_type:All types in /data, not in /data/vendor。是file_type的子集,用来标识存在/data目录但是不包含/data/vendor的所有文件。
  • attribute app_data_file_type:All types used for app private data files in seapp_contexts。用来标识/data/private里面的私有应用文件。
  • attribute system_file_type:All types in /system。是file_type的子集,用来标识所有存在/system目录的文件。
  • attribute system_dlkm_file_type:All types in /system_dlkm。用来标识所有存在/system_dlkm目录的文件。
  • attribute vendor_file_type:All types in /vendor。用来标识所有存在/vendor目录的文件。
  • attribute proc_type:All types used for procfs files。用来标识存在/proc目录下的虚拟文件。
  • attribute exec_type: All types used for domain entry points。用来标识能够被执行的文件,例如/system/bin/init/system/bin/app_process等,当进程通过 execve() 执行某个文件时,这个文件作为客体上下文必须得带有exec_type的属性

D. property属性相关

  • attribute property_type:All types used for property service. 所有与 Android 属性服务(property_service)关联的类型的基础标识符,用于统一归类属性操作相关的访问规则。
  • attribute core_property_type:All properties defined in core SELinux policy. Should not be used by device specific properties. 核心策略层定义的全局属性‌(如 SELinux 自身运行时参数),禁止设备厂商策略直接使用
  • attribute log_property_type:All properties used to configure log filtering.控制日志过滤规则的属性(如日志级别、分类过滤关键字)。用途‌:动态调整日志输出粒度(如 persist.log.tag 系列属性)。
  • attribute system_property_type:All properties defined by /system. 由 /system 分区定义的属性(Android 系统原生属性),例如系统版本、全局调试开关等
  • attribute system_internal_property_type:All /system-defined properties used only in /system. 仅在 /system 内部使用的私有属性,其他分区(如 /vendor)不可访问。场景‌:系统服务间通信的敏感参数(如 ActivityManager 内部状态)
  • attribute system_restricted_property_type:All /system-defined properties which can't be written outside /system. 仅允许 /system 自身写入的属性,外部组件(包括特权进程)只能读取。
  • attribute vendor_property_type:All properties defined by /vendor. 由 /vendor 分区定义的属性(设备厂商自定义属性),如硬件驱动参数、OEM 功能开关
  • attribute vendor_internal_property_type:All /vendor-defined properties used only in /vendor.仅在 /vendor 内部使用的私有属性,其他分区(如 /system)不可访问。场景‌:硬件适配层(HAL)与厂商驱动间的专有通信参数。
  • attribute vendor_restricted_property_type:All /vendor-defined properties which can't be written outside /vendor. 仅允许 /vendor 自身写入的属性,外部组件(包括系统服务)只能读取。
  • attribute vendor_public_property_type:All /vendor-defined properties with no restrictions.厂商定义的公开属性,允许跨分区访问(如 /system 读取或设置)。

E. 其他常用属性

# All service_manager types created by system_server
attribute system_server_service;
# services which should be available to all but isolated apps
attribute app_api_service;
# services which should be available to all ephemeral apps
attribute ephemeral_app_api_service;
# services which export only system_api
attribute system_api_service;
# services which are explicitly disallowed for untrusted apps to access
attribute protected_service;
# All types used for services managed by servicemanager.
# On change, update CHECK_SC_ASSERT_ATTRS
# definition in tools/checkfc.c.
attribute service_manager_type;
# All types used for services managed by hwservicemanager
attribute hwservice_manager_type;
# All HwBinder services guaranteed to be passthrough. These services always run
# in the process of their clients, and thus operate with the same access as
# their clients.
attribute same_process_hwservice;
# All HwBinder services guaranteed to be offered only by core domain components
attribute coredomain_hwservice;
# All HwBinder services that untrusted apps can't directly access
attribute protected_hwservice;
# All types used for services managed by vndservicemanager
attribute vndservice_manager_type;
# All services declared as part of an HAL
attribute hal_service_type;

2、客体资源的SContext配置

1)file_contexts:文件的SContext

上一小节介绍了一些aosp默认定义的属性,前文也介绍了scontext的概念,以及主体和客体的安全类型格式,安全类型的定义和与属性的关系也都介绍了。

文件file_contexts是sepolicy用来统一针对文件的安全上下文的配置。因为针对的是文件,所以这里也是对客户资源的SContext描述。

A. 根目录和特殊文件的安全类型

B. 设备节点的安全类型

dev目录下面的设备节点的安全类型

C. system/bin可执行文件的安全类型

system目录下我们最关注的主要是system/etc目录下面的一些配置文件,和system/bin下面的可执行文件,这些可执行文件的安全上下文都带有_exec这样的命名,因为她们继承了exec_type,表示属于可执行的文件。

D. vendor和product目录的安全类型

E. data目录的安全类型

F. hal可执行文件的安全类型

在vendor/file_context里面还专门为hal服务进程可执行文件进行了SContext的指定,大体格式以hal_xxx_default_exec命名,他们的本质和system/bin一致,带有exec_type,表示属于可执行的文件。

G. 其他重要文件的配置

这里主要针对system/vendor/odm/product下面的bin/lib/app等这样的文件进行展示:

//AOSP/system/sepolicy/private/file_contexts
/system(/.*)?		u:object_r:system_file:s0                #system根目录
/system/lib(64)?(/.*)?		u:object_r:system_lib_file:s0    #system/lib动态库目录
/system/lib(64)?/bootstrap(/.*)? u:object_r:system_bootstrap_lib_file:s0
#下面分别指的是vendor/vendor或者system/vemdor目录下
/(vendor|system/vendor)(/.*)?                  u:object_r:vendor_file:s0
/(vendor|system/vendor)/bin/sh                 u:object_r:vendor_shell_exec:s0
/(vendor|system/vendor)/bin/toybox_vendor      u:object_r:vendor_toolbox_exec:s0
/(vendor|system/vendor)/bin/toolbox            u:object_r:vendor_toolbox_exec:s0
/(vendor|system/vendor)/etc(/.*)?              u:object_r:vendor_configs_file:s0
/(vendor|system/vendor)/etc/cgroups\.json      u:object_r:vendor_cgroup_desc_file:s0
/(vendor|system/vendor)/etc/task_profiles\.json    u:object_r:vendor_task_profiles_file:s0
/(vendor|system/vendor)/lib(64)?/egl(/.*)?     u:object_r:same_process_hal_file:s0
/(vendor|system/vendor)/lib(64)?/vndk-sp(/.*)? u:object_r:vndk_sp_file:s0
/(vendor|system/vendor)/manifest\.xml           u:object_r:vendor_configs_file:s0
/(vendor|system/vendor)/compatibility_matrix\.xml u:object_r:vendor_configs_file:s0
/(vendor|system/vendor)/etc/vintf(/.*)?        u:object_r:vendor_configs_file:s0
/(vendor|system/vendor)/app(/.*)?              u:object_r:vendor_app_file:s0
/(vendor|system/vendor)/priv-app(/.*)?         u:object_r:vendor_app_file:s0
/(vendor|system/vendor)/overlay(/.*)?          u:object_r:vendor_overlay_file:s0
/(vendor|system/vendor)/framework(/.*)?        u:object_r:vendor_framework_file:s0
#下面分别指的odm/odm或者vendor/odm目录下
/(odm|vendor/odm)(/.*)?                       u:object_r:vendor_file:s0
/(odm|vendor/odm)/lib(64)?/egl(/.*)?          u:object_r:same_process_hal_file:s0
/(odm|vendor/odm)/lib(64)?/hw                 u:object_r:vendor_hal_file:s0
/(odm|vendor/odm)/lib(64)?/vndk-sp(/.*)?      u:object_r:vndk_sp_file:s0
/(odm|vendor/odm)/bin/sh                      u:object_r:vendor_shell_exec:s0
/(odm|vendor/odm)/etc(/.*)?                   u:object_r:vendor_configs_file:s0
/(odm|vendor/odm)/app(/.*)?                   u:object_r:vendor_app_file:s0
/(odm|vendor/odm)/priv-app(/.*)?              u:object_r:vendor_app_file:s0
/(odm|vendor/odm)/overlay(/.*)?               u:object_r:vendor_overlay_file:s0
/(odm|vendor/odm)/framework(/.*)?             u:object_r:vendor_framework_file:s0
#下面分别指的product/product或者system/product目录下
/(product|system/product)(/.*)?                                 u:object_r:system_file:s0
/(product|system/product)/etc/group                             u:object_r:system_group_file:s0
/(product|system/product)/etc/passwd                            u:object_r:system_passwd_file:s0
/(product|system/product)/overlay(/.*)?                         u:object_r:system_file:s0

2)hwservice_contexts:HIDL接口的SContext

文件hwservice_contexts专门针对硬件抽象层里面的HAL接口对象进行安全上下文的配置。

注意是针对HAL接口对象的定义,即xxx.hal文件里面的接口,它是一个对象,不是进程,因此它还是一个客体资源。HIDL接口,包括实例对象,作为一种抽象的客体资源,安全上下文配置如下:通常以hal_xxx_hwservice的格式进行命名

3)service_contexts:AIDL接口的SContext

文件service_contexts专门针对aidl接口进行描述,因此它也是一种抽象的客体资源。同上文的hwservice_contexts一致,service_contexts里面也定义差不多类似的结构的服务。

A. 通过AIDL实现HAL层服务

值得区分的是,它们不是HIDL接口,它们是针对HAL服务的最新AIDL方式实现。针对这块可以参考:https://source.android.com/docs/core/architecture/aidl/aidl-hals?hl=zh-cn

B. 通过AIDL实现FW或SystemServer层服务

这些服务是systemserver里面定义的一些服务,如上usagestats在Context.java里面进行定义,作为系统级服务被systemserver启动。相关详情参考:Android Framework 之 SystemServer进程_bpkeyattestationapplicationidprovider-CSDN博客

4)property_contexts:属性的SContext

文件property_contexts针对属性相关的scontext配置,同意属性也是属于客体资源,这里针对一些常见的属性安全配置进行说明:

//aosp/system/sepolicy/private/property_contexts
init.svc.odm.           u:object_r:vendor_default_prop:s0
init.svc.vendor.        u:object_r:vendor_default_prop:s0
ro.hardware.            u:object_r:vendor_default_prop:s0
ro.odm.                 u:object_r:vendor_default_prop:s0
ro.vendor.              u:object_r:vendor_default_prop:s0
ro.vendor_dlkm.         u:object_r:vendor_default_prop:s0
ro.odm_dlkm.            u:object_r:vendor_default_prop:s0
odm.                    u:object_r:vendor_default_prop:s0
persist.odm.            u:object_r:vendor_default_prop:s0
persist.vendor.         u:object_r:vendor_default_prop:s0
vendor.                 u:object_r:vendor_default_prop:s0
net.                    u:object_r:system_prop:s0    #以net.开头的属性
dev.                    u:object_r:system_prop:s0    #以dev.开头的属性
ro.runtime.             u:object_r:system_prop:s0
hw.                     u:object_r:system_prop:s0    #以hw.开头的属性
ro.hw.                  u:object_r:system_prop:s0
sys.                    u:object_r:system_prop:s0    #以sys.开头的属性
sys.powerctl            u:object_r:powerctl_prop:s0  #以sys.powerctl开头的属性
service.                u:object_r:system_prop:s0    #以service.开头的属性,通常为服务
debug.                  u:object_r:debug_prop:s0
debug.db.               u:object_r:debuggerd_prop:s0
dumpstate.              u:object_r:dumpstate_prop:s0
log.                    u:object_r:log_prop:s0
log.tag                 u:object_r:log_tag_prop:s0
log.tag.WifiHAL         u:object_r:wifi_log_prop:s0
service.adb.root        u:object_r:shell_prop:s0
persist.adb.wifi.       u:object_r:adbd_prop:s0
persist.audio.          u:object_r:audio_prop:s0
persist.bluetooth.      u:object_r:bluetooth_prop:s0
persist.nfc.            u:object_r:nfc_prop:s0
persist.sys.            u:object_r:system_prop:s0
persist.sys.safemode    u:object_r:safemode_prop:s0
persist.sys.theme       u:object_r:theme_prop:s0
persist.service.        u:object_r:system_prop:s0
persist.security.       u:object_r:system_prop:s0
ro.boot.bootreason      u:object_r:bootloader_boot_reason_prop:s0
persist.sys.boot.reason u:object_r:last_boot_reason_prop:s0
sys.boot.reason         u:object_r:system_boot_reason_prop:s0
sys.boot.reason.last    u:object_r:last_boot_reason_prop:s0
pm.                     u:object_r:pm_prop:s0
sys.lmk.                u:object_r:system_lmk_prop:s0
sys.trace.              u:object_r:system_trace_prop:s0
vold.                   u:object_r:vold_prop:s0
# ctl properties
ctl.bootanim            u:object_r:ctl_bootanim_prop:s0
ctl.dumpstate           u:object_r:ctl_dumpstate_prop:s0
ctl.fuse_               u:object_r:ctl_fuse_prop:s0
ctl.mdnsd               u:object_r:ctl_mdnsd_prop:s0
ctl.ril-daemon          u:object_r:ctl_rildaemon_prop:s0
ctl.bugreport           u:object_r:ctl_bugreport_prop:s0
ctl.console             u:object_r:ctl_console_prop:s0
ctl.                    u:object_r:ctl_default_prop:s0
hwservicemanager.       u:object_r:hwservicemanager_prop:s0

3、主体进程SContexts的配置

前文介绍了客体资源的安全上下文,这里介绍一下主体进程的安全上下文,可以通过adb shell ps -A -Z命令获取,参考前文

1)、native进程SContexts的配置

2)、APP应用SContexts的配置

app应用进程的安全上下文配置和其他进程不一样,因为系统有一套机制,根据这套机制自动去给应用进程赋予安全上下文的标签,常见应用的安全上下文如下:

u:r:platform_app:s0:c512,c768  u0_a170       2748   989   18481688 177400 do_epoll_wait       0 S com.android.systemui        #系统默认
u:r:system_app:s0              system        9428   989   16935584 131484 do_epoll_wait       0 S com.android.settings
u:r:priv_app:s0:c512,c768      u0_a49        3597   989   16507812  30424 do_epoll_wait       0 S com.google.android.euicc    #普通google应用
u:r:untrusted_app:s0:c129,c256,c512,c768 u0_a129 21462 989 17029492 26020 do_epoll_wait       0 S com.google.android.apps.photos
u:r:gmscore_app:s0:c512,c768   u0_a116      22907   989   17090272 168424 do_epoll_wait       0 S com.google.android.gms	  #google.gms应用
u:r:gmscore_app:s0:c512,c768   u0_a116       3211   989   17369680 214892 do_epoll_wait       0 S com.google.android.gms.persistent  
u:r:ascom_privileged_app:s0:c181,c256,c512,c768 u0_a181 3203 989 16691196 85704 do_epoll_wait 0 S com.ascom.myco.launcher2    #三方自定义应用,自己指定
u:r:ascom_privileged_app:s0:c158,c256,c512,c768 u0_a158 6075 989 16431456 51588 do_epoll_wait 0 S com.ascom.myco.oemconfig    
u:r:platform_app:s0:c512,c768  u0_a164       6120   989   16400420  38728 do_epoll_wait       0 S com.ascom.myco.phonesip      #其他三方应用
A. seapp_contexts:基本语法

app应用的安全策略基本上都是seapp_contexts来进行指定,要读懂这个文件我们先来看看这个文件的语法和详细解释:

首先:说明了seapp_contexts中的每一行都是来定义app进程的安全上下文

接下来针对每一行的配置做了一个系统的解释,先介绍了输入项,然后介绍了输出项

然后:对输出项的参数作了系统性的解释,即输出项的参数用来指定对应的安全上下文

这些输入参数会在seapp_context_lookup方法中进行匹配,匹配成功的应用进程即会输出对应的安全上下文。

最后:对输出项的参数作了系统性的解释,即输出项的参数用来指定对应的安全上下文

这里我们重点针对domain和type来进行介绍,没错,他们就是进程主体的scontext和type

如何调试?

上面的注释已经介绍了seapp_contexts的输入和输出规则,最终由android_platform.c里面的代码中实现,阅读这个文件的代码可以发现关于seapp_contexts的解析和配置主要在android设备的/system|system_ext|product|vendor|odm/etc/selinu/xxx_seapp_contexts文件中:

下面依次对不同的输入参数作一些系统性的介绍:

B. seinfo:签名
//system/sepolicy/private/mac_permissions.xml
<?xml version="1.0" encoding="utf-8"?>
<policy>
<!--
    * A signature is a hex encoded X.509 certificate or a tag defined in
      keys.conf and is required for each signer tag. The signature can
      either appear as a set of attached cert child tags or as an attribute.
    * A signer tag must contain a seinfo tag XOR multiple package stanzas.
    * Each signer/package tag is allowed to contain one seinfo tag. This tag
      represents additional info that each app can use in setting a SELinux security
      context on the eventual process as well as the apps data directory.
    * seinfo assignments are made according to the following rules:
      - Stanzas with package name refinements will be checked first.
      - Stanzas w/o package name refinements will be checked second.
      - The "default" seinfo label is automatically applied.
    * valid stanzas can take one of the following forms:
     // multiple certs protecting explicitly named app (all certs must match)
     <signer>
       <cert signature="@PLATFORM1"/>
       <cert signature="@PLATFORM2"/>
       <package name="com.android.foo">
         <seinfo value="bar" />
       </package>
     </signer>
-->
    <!-- Platform dev key in AOSP -->
    <signer signature="@PLATFORM" >
      <seinfo value="platform" />
    </signer>
    <!-- Sdk Sandbox key -->
    <signer signature="@SDK_SANDBOX" >
      <seinfo value="sdk_sandbox" />
    </signer>
    <!-- Media key in AOSP -->
    <signer signature="@MEDIA" >
      <seinfo value="media" />
    </signer>
    <signer signature="@NETWORK_STACK" >
      <seinfo value="network_stack" />
    </signer>
</policy>
//system/sepolicy/private/seapp_contexts
# seinfo= matches aginst the seinfo tag for the app, determined from mac_permissions.xml files.
# The ':' character is reserved and may not be used in seinfo.
user=_app seinfo=app_zygote domain=app_zygote levelFrom=user
user=_app seinfo=media domain=mediaprovider type=app_data_file levelFrom=user
user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
user=system seinfo=platform domain=system_app type=system_app_data_file
user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file

关于seinfo的介绍如上,用于匹配签名标签,签名标签的定义是在mac_permissions.xml文件中,改文件中明确的就定义了如何针对单独的应用进行签名,然后默认提供了Platform、Sdk Sandbox 、Media 、Net等几种应用签名方式集成的时候的seinfo的定义。例如上面的三条策略翻译过来如下:

  • user=_app的普通应用,seinfo=app_zygote使用app_zygote应用签名,能够匹配的应用指定SContext为app_zygote
  • user=_app的普通应用,seinfo=media使用media应用签名,能够匹配的应用指定SContext为mediaprovider 
  • user=_app的普通应用,seinfo=platform使用platform应用签名,能够匹配的应用指定SContext为platform_app

例如如下SContext为platform_app的三方应用和高通应用、systemui,是因为他们的集成签名配置LOCAL_CERTIFICATE := platform

C. user:sharedUserId
//system/sepolicy/private/seapp_contexts
# user=_app will match any regular app process.
# user=_isolated will match any isolated service process.
# user=_sdksandbox will match sdk sandbox process for an app.
# Other values of user are matched against the name associated with the process UID.
user=system seinfo=platform domain=system_app type=system_app_data_file
user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
user=network_stack seinfo=network_stack domain=network_stack type=radio_data_file
user=nfc seinfo=platform domain=nfc type=nfc_data_file
user=secure_element seinfo=platform domain=secure_element levelFrom=all
user=radio seinfo=platform domain=radio type=radio_data_file
user=shared_relro domain=shared_relro levelFrom=all
user=shell seinfo=platform domain=shell name=com.android.shell type=shell_data_file
user=_sdksandbox domain=sdk_sandbox_34 type=sdk_sandbox_data_file levelFrom=all
user=_sdksandbox isSdkSandboxNext=true domain=sdk_sandbox_next type=sdk_sandbox_data_file levelFrom=all

关于user的介绍如上,user=_app能够匹配所有的应用进程,user=system能够匹配应用xml中配置为android:sharedUserId="android.uid.system"的应用,同样user=bluetooth能够匹配应用xml中配置为android:sharedUserId="android.uid.bluetooth"的应用

如上为什么systemui和settings应用在集成系统的时候都使用了平台签名,为什么他们的SContext分别为platform_app和system_app呢?原来是因为他们的sharedUserId配置不一致,分别是android.uid.systemui和android.uid.system,因此user=system seinfo=platform domain=system_app type=system_app_data_file对settings应用匹配成功,蒋settings的SContext设置为system_app

//AOSP/frameworks/base/packages/SystemUI/Android.bp
android_app {
    name: "SystemUI",
    platform_apis: true,
    system_ext_specific: true,
    certificate: "platform",
    privileged: true,
}
//AOSP/frameworks/base/packages/SystemUI/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
        package="com.android.systemui"
        android:sharedUserId="android.uid.systemui"
        xmlns:tools="http://schemas.android.com/tools"
        coreApp="true">
//AOSP/packages/apps/Settings/Android.bp
android_app {
    name: "Settings",
    platform_apis: true,
    certificate: "platform",
    system_ext_specific: true,
    privileged: true,
}
//AOSP/packages/apps/Settings/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          package="com.android.settings"
          coreApp="true"
          android:sharedUserId="android.uid.system">
D. isSystemServer
//system/sepolicy/private/seapp_contexts
# isSystemServer=true only matches the system server.
# An unspecified isSystemServer defaults to false.
# only the system server can be in system_server domain
# only the system server can be assigned the system_server domains
neverallow isSystemServer=false domain=system_server
neverallow isSystemServer=false domain=system_server_startup
neverallow isSystemServer="" domain=system_server
neverallow isSystemServer="" domain=system_server_startup
isSystemServer=true domain=system_server_startup

关于isSystemServer的解释如上,它是一个bool型,根据策略得到如下两个信息:

  • 只有system server进程才能使用这个域,isSystemServer为true的应用进程的SContext被配置为system_server_startup
  • 其他应用进程isSystemServer这个参数都应该是false,且不允许isSystemServer=false和isSystemServer=""的应用进程的SContext为system_server
  • 只有system_server进程的SContext是system_server,但是我并没有找到isSystemServer=true相关源码

E. name & isPrivApp & minTargetSdkVersion
# name= matches against the package name of the app.
# isPrivApp=true will only match for applications preinstalled in /system/priv-app.
# minTargetSdkVersion will match applications with a targetSdkVersion greater than or equal to the specified value. If unspecified, it has a default value of 0.
# any non priv-app with a non-known uid with a specified name should have a specified seinfo
neverallow user=_app isPrivApp=false name=.* seinfo=""
neverallow user=_app isPrivApp=false name=.* seinfo=default
user=_app isPrivApp=true name=com.google.android.gms domain=gmscore_app type=privapp_data_file levelFrom=user
user=_app isPrivApp=true name=com.google.android.gms.* domain=gmscore_app type=privapp_data_file levelFrom=user
user=_app isPrivApp=true name=com.google.android.gms:* domain=gmscore_app type=privapp_data_file levelFrom=user
user=_app minTargetSdkVersion=34 domain=untrusted_app type=app_data_file levelFrom=all
user=_app minTargetSdkVersion=32 domain=untrusted_app_32 type=app_data_file levelFrom=all   #兼容SDK为32的应用

如上注释,name用来匹配包名,可以用*作为通配符;isPrivApp=true用来匹配安装在/system/priv-app的应用,这个字段应该默认为false;minTargetSdkVersion用来匹配大于等于对应sdk的应用

4、access_vectors:访问权限

文件acces_vectors中定义了一系列操作,例如read和write等操作,通过这一些列操作,构建了整个selinux的行为,例如是否允许读取read某个文件等

A. file & socket权限 

# Define a common prefix for file access vectors.
common file{
    ioctl               #控制设备的 I/O 操作(如调整终端参数),典型场景:终端管理工具(如 stty)
    read/write          #读取或修改文件内容,典型场景:文本编辑器读写文件
    create/unlink       #创建或删除文件,典型场景:日志轮转工具(如 logrotate)
    getattr/setattr     #查看或修改文件元数据(如权限、时间戳),典型场景:文件管理工具(如 chmod、touch)
    lock
    relabelfrom/relabelto   #修改文件安全上下文(SELinux 标签)的源和目标约束,典型场景:动态调整文件访问策略(如安全策略更新工具)
    append
    map
    link
    rename
    execute             #执行文件(二进制或脚本),典型场景:用户运行可执行程序
    quotaon
    mounton             #在文件系统对象上挂载新文件系统,典型场景:用户挂载 USB 存储设备
    audit_access
    open
    execmod             #允许修改已加载到内存的可执行文件(如运行时动态库注入),典型场景:调试工具修改进程内存
    watch/watch_mount/watch_sb/watch_with_perm/watch_reads  #监控文件系统事件(如文件修改、挂载点变动),典型场景:文件同步服务(如 inotify 监听)
}
# Define a common prefix for socket access vectors.
common socket{
    ioctl
    read
    write
    create
    getattr
    setattr
    lock
    relabelfrom
    relabelto
    append
    map
    bind/connect        #绑定本地端口或连接远程地址
    listen/accept       #监听端口请求或接受客户端连接
    getopt/setopt       #获取或设置套接字选项
    shutdown            #关闭套接字连接(如主动终止 TCP 会话)
    recvfrom/sendto     #发送或接收网络数据
    name_bind           #绑定特定端口(通常用于限制低端口号访问
}

B. Linux IPC进程间通信权限

# Define a common prefix for ipc access vectors.
common ipc{
    create          #创建新的 IPC 对象(如共享内存段、消息队列),进程初始化时分配 IPC 资源
    destroy         #删除 IPC 对象,释放系统资源,清理不再使用的共享内存或队列
    getattr         #查询 IPC 对象的元数据(如权限、所有者、大小),监控工具检查共享内存状态
    setattr         #修改 IPC 对象的属性(如调整消息队列容量或共享内存权限),动态优化 IPC 资源配置
    read/write      #从 IPC 对象读取或写入数据(如共享内存读写、消息收发),进程间传递实时数据(如音视频流)    
    associate       #将进程与现有 IPC 对象绑定(如附加到已创建的共享内存段),多进程协作访问同一块共享内存
    unix_read/unix_write #针对 Unix 域套接字(本地进程间高速通信)的读写权限控制,本地服务间传输敏感数据(如数据库连接凭证)
}

C. Linux Capability核心权限

如下注释,这些cap权限都是linux相关的核心权限,被定义在include/linux/capability.h 

common cap {
    # The capabilities are defined in include/linux/capability.h
    # Capabilities >= 32 are defined in the cap2 common. Care should be taken to ensure that these are consistent with. those definitions. (Order matters)
    chown               #基础权限控制类:CAP_CHOWN,允许修改文件的拥有者(UID)和所属组(GID)
    dac_override       #文件系统权限绕过类:CAP_DAC_OVERRIDE,完全绕过文件读写执行权限检查(即使文件权限为 600 也可强制访问)
    dac_read_search     #文件系统权限绕过类:CAP_DAC_READ_SEARCH,绕过目录读/搜索权限限制(如遍历 0700 权限目录)
    fowner              #基础权限控制类:CAP_FOWNER,绕过文件属主匹配检查(如 chmod、utime),允许非属主进程操作文件
    fsetid
    kill                #进程控制类:CAP_KILL,向任意进程发送信号(如 SIGKILL 强制终止进程)
    setgid           #基础权限控制类:CAP_SETGID,允许修改进程的组身份(GID)
    setuid           #基础权限控制类:CAP_SETUID,允许修改进程的用户身份(UID)
    setpcap          #基础权限控制类:CAP_SETPCAP,控制其他进程的能力集(如通过 prctl 修改子进程能力)
    linux_immutable     #文件系统权限绕过类:CAP_LINUX_IMMUTABLE,允许修改不可变文件(chattr +i 设置的文件)的属性
    net_bind_service
    net_broadcast
    net_admin           #网络控制类:CAP_NET_ADMIN,网络接口配置(IP 地址修改、路由表操作)、防火墙规则管理
    net_raw             #网络控制类:CAP_NET_RAW,创建原始套接字(用于实现 ping、tcpdump 等工具)
    ipc_lock
    ipc_owner
    sys_module          #系统管理与内核操作类:CAP_SYS_MODULE,加载或卸载内核模块(需谨慎授予,存在安全风险)
    sys_rawio           #系统管理与内核操作类:CAP_SYS_RAWIO,直接访问硬件端口(如 /dev/mem、/dev/port 操作)
    sys_chroot
    sys_ptrace          #进程控制类:CAP_SYS_PTRACE,调试其他进程(如 ptrace 系统调用)
    sys_pacct
    sys_admin           #系统管理与内核操作类:CAP_SYS_ADMIN,广义系统管理权限(挂载文件系统、修改主机名、控制交换空间等)
    sys_boot            #系统管理与内核操作类:CAP_SYS_BOOT,执行系统重启(reboot)或内核热加载(kexec_load)
    sys_nice            #进程控制类:CAP_SYS_NICE,调整进程优先级(nice 值)或调度策略
    sys_resource      #资源控制类:CAP_SYS_RESOURCE,突破资源限制(如 ulimit 设置的进程内存/文件句柄上限
    sys_time           #资源控制类:CAP_SYS_TIME,修改系统时间和硬件时钟
    sys_tty_config
    mknod              #文件系统权限绕过类:CAP_MKNOD,创建特殊设备文件(如 /dev 下的块/字符设备)
    lease
    audit_write         #安全控制类:CAP_AUDIT_WRITE,向内核审计日志写入记录(用于安全监控)
    audit_control       #安全控制类:CAP_AUDIT_CONTROL,配置审计规则(如启用/禁用审计子系统)
    setfcap             #安全控制类:CAP_SETFCAP,为文件设置能力属性(通过 setcap 命令)
}
common cap2{
    mac_override       #安全控制类:CAP_MAC_OVERRIDE,覆盖强制访问控制(MAC)策略(如 SELinux 标签限制),允许进程绕过安全标签检查访问资源
    mac_admin           #安全控制类:CAP_MAC_ADMIN,配置或修改 MAC 策略(如 SELinux 规则动态加载),需高度特权
    syslog              #内核硬件控制类:CAP_SYSLOG,读取内核日志(dmesg)或修改内核打印级别(需配合 /proc/sys/kernel/printk 接口)
    wake_alarm          #内核硬件控制类:CAP_WAKE_ALARM,设置定时器唤醒系统(如 RTC 时钟唤醒休眠状态的主机)
    block_suspend      #内核硬件控制类:CAP_BLOCK_SUSPEND,阻止系统休眠或挂起(如媒体播放器需保持屏幕常亮)
    audit_read          #安全控制类:CAP_AUDIT_READ,读取审计日志(auditd 记录的安全事件),用于安全监控工具
    perfmon             #安全控制类:CAP_PERFMON,访问性能监控接口(如 /sys/kernel/debug/tracing),支持 perf 等工具进行内核性能分析
}

D. Process进程控制权限

# Define the access vector interpretation for process-related objects
class process{
    fork
    transition
    sigchld # commonly granted from child to parent
    sigkill # cannot be caught or ignored
    sigstop # cannot be caught or ignored
    signull # for kill(pid, 0)
    signal  # all other signals
    ptrace
    getsched
    setsched
    getsession
    getpgid
    setpgid
    getcap
    setcap
    share
    getattr
    setexec
    setfscreate
    noatsecure
    siginh
    setrlimit
    rlimitinh
    dyntransition
    setcurrent
    execmem
    execstack
    execheap
    setkeycreate
    setsockcreate
    getrlimit
}
class process2{
    nnp_transition
    nosuid_transition
}

E. node & property & service_manager & binder

class node{
    recvfrom
    sendto
}
class property_service{
    set
}
class service_manager{
    add
    find
    list
}
class hwservice_manager{
    add
    find
    list
}
class binder{
    impersonate
    call
    set_context_mgr
    transfer
}

5、allow语句与neverallow

我们可以使用allow语句来对上文提到过的主体SContext进程赋予一系列权限操作,被赋予的就是客体SContext,这些权限操作其实就是access_vectors中定义的这些。

我们可以通过audit2allow工具根据日志来自动生成这些allow语句,通常一条allow语句对应一条权限策略。

这些allow语句通常被定义在xxx.te文件中,通常一个进程对应一个xxx.te,一个xxx.te文件中可以配置若干条allow权限,当然也可以配置一些neverallow语句。

aosp对大部分的进程都定义了te策略,除此之外,还对常见的一些进程SContext主体,定义了一些默认策略,同时还是要nerverallow限制相关type或者属性的进程不具有一些策略。

二、策略文件

这里不深入讲解SEAndroid相关的所有文件,也不讲解一些基本type和属性的一些定义,只需要明白android默认的策略配置都基本上写好了,这些策略配置基本上不需要我们去更改。但是厂商定制策略文件的sepolicy目录下。这里介绍该目录下几个比较重要的文件。

1、sepolicy/vendor/service.te

service.te文件主要定义了一些service(init.rc服务对应的进程)的type。即定义了init.rc中的service对应进程的SContext的type字段。这些type通常会继承于service_manager_type。如下:

type    hitv_service,    service_manager_type;
type    bootvideo_service,    service_manager_type;
type    quickplay_service,    service_manager_type;
type    shen_service,    service_manager_type;

2、sepolicy/system/private/service_contexts

前文定义了一些type,但是这些type并没有得到使用,service_contexts文件就是用来配置Service(四大组件之一)系统服务的安全属性SContext,其中使用service.te里面定义的type(进程的type也叫域名Domain)。如下:

TVService    u:object_r:tvservice_service:s0
hitvservice  u:object_r:tvservice_service:s0
hirmservice  u:object_r:tvservice_service:s0
bootvideo    u:object_r:bootvideo_service:s0
quickplay    u:object_r:quickplay_service:s0
shen         u:object_r:shen_service:s0

3、sepolicy/vendor/shen.te

前文已经为init.rc将启动的进程做了安全属性的配置,那么可以在为每个进程做具体的安全策略,通常每个自定义进程就会对应一个te文件,编译系统打包过程中会自动将sepolicy目录下的配置拼接到原生SEAndroid中。这里拿自定义进程shen来举例,那么就需要创建一个shen.te文件来配置具体安全策略。如下:

type shen,coredomain,domain; 
#定义shen,继承于coredomain和domain,将代表某一组进程的域名
type shen_exec,exec_type,file_type;
#定义shen_exec,继承于exec_type和file_type,将代表某一资源,继承了执行权限
init_domain_domain(shen)

#具体安全策略
allow 语句
neverallow 语句

4、sepolicy/vendor/file_contexts

前文配置了进程SContext,那么这里还需要配置资源SContext,如下:

#Devices
/dev/sockect/vold0        u:object_r:vold_sockect:s0
/dev/sockect/vold1        u:object_r:vold_sockect:s0

#System files
/system/bin/bootvideo     u:object_r:bootvideo_exec:s0
/system/bin/quickplay     u:object_r:quickplay_exec:s0
/system/bin/shen          u:object_r:shen_exec:s0

如上配置文件/system/bin/shen的type为shen_exec,前文继承于exec_type,表示该资源为一个可执行文件。

三、配置新进程的SEAndroid

service shen /system/bin/shen
    user root
    class core

现如今就可以在init.rc中配置如上代码,让init进程fock创建一个进程shen,并执行了/system/bin/shen里面的代码。其中新进程名叫shen,执行的资源文件是/system/bin/shen,但是仅仅这样,系统开机启动后并没有启动进程shen,原来是因为init进程在启动rc文件中的service之前初始化了selinux相关的东西,因此selinux校验不过,进程shen无法被启动,因此需要作如下步骤配置:

1、配置进程shen的安全策略

创建sepolicy/vendor/shen.te文件:

type shen,coredomain,domain; 
#定义shen,继承于coredomain和domain,将代表某一组进程的域名
type shen_exec,exec_type,file_type;
#定义shen_exec,继承于exec_type和file_type,将代表某一资源,继承了执行权限
init_domain_domain(shen)
binder_use(shen)
binder_service(shen)
binder_call(shen,system_server)
hwbinder_use(shen)
set_prop(shen,exported_system_prop)
set_prop(shen,exported2_system_prop)

allow shen mediaserver_service:service_manager { find };
allow shen mediaserver:binder { call};
allow shen surfaceflinger_service:service_manager { find };
allow shen surfaceflinger:binder { call };
allow shen surfaceflinger:fd { call };
allow shen system_file:dir { read open };
allow shen system_prop:property_service { set };
allow shen storage_file:link_file {read open };
allow shen system_data_file:file {read open map };

上面的策略文件,先定义了两个type,还记得type是什么吗?没错,是Linux任何东西(包括进程和资源)都具有的SContext安全属性中的type。上面的shen.te文件前两句就定义了两个type:shen和shen_exec,其中shen继承于domain,shen_exec继承于file_type。

1)、domain

深入原生sepolicy代码中的定义就会知道,domain专门用来修饰进程SContext的type,表示一个域(一组进程),我们的进程叫shen,因此用字符串shen来表示这组进程,在后面的allow语句中都是allow shen xxxx来实现安全策略。

2)、exec_type

file_type是用来修饰资源SContext的type,这里定义了一个shen_exec,并继承于exec_type/file_type,其中exec_type表示可执行文件,因此只要有某资源安全属性的type字段就表示它能够被执行。在后文中我们会把shen_exec赋予/system/bin/shen文件。

3)、init_domain_domain

init_domain_domain(shen)是一个宏,声明当一个domain为init的进程创建一个子进程执行一个type为study_exec的文件时,将该子进程的domain设置为shen,而不是继承父进程(它的父进程就是init进程)的domain。

2、赋予二进制文件SContext

rc文件中指定进程shen执行/system/bin/shen这个二进制文件,但到目前为止,这个文件就是一个普普通通的文件,shen进程读取该文件的代码时候将会被selinux权限校验的时候拒绝,因此我们还需要对该文件赋予可被执行的type。

sepolicy/vendor/file_contexts专门用来配置所有资源的SContext,因此我们只需要在该文件中进行如下配置即可:

#sepolicy/vendor/file_contexts
/system/bin/shen          u:object_r:shen_exec:s0

3、赋予binder通信功能

经过上面两个步骤init可以成功启动进程shen,但是此时的shen并不能在系统生态中使用binder进程间通信功能。

sepolicy/vendor/service.te中定义继承于service_manager_type的type,如下:

type    shen_service,    service_manager_type;

将拥有service_manager_type的type赋予给进程shen,如下:

shen         u:object_r:shen_service:s0

四、案例分析

1、案例之self:capability dac_override权限滥用

有自定义native进程去创建文件,但是总是创建不成功,最后查看avc报的日志是不具有dac相关权限:

07-26 07:02:14.578  3610  3610 W diag_callback_s: type=1400 audit(0.0:88): avc:  denied  { dac_read_search } for  capability=2  scontext=u:r:diag_callback_sample:s0 tcontext=u:r:diag_callback_sample:s0 tclass=capability permissive=0
07-26 07:02:14.578  3610  3610 W diag_callback_s: type=1400 audit(0.0:89): avc:  denied  { dac_override } for  capability=1  scontext=u:r:diag_callback_sample:s0 tcontext=u:r:diag_callback_sample:s0 tclass=capability permissive=0

通过audit2allow工具根据日志生成如下allow语句:

allow diag_callback_sample self:capability { dac_override dac_read_search };

但直接会触发neverallow的策略,这条语句的意思是允许自身进程使用dac_override权限,dac_override的意思是可以直接绕过linux的DAC策略,linux的DAC策略其实就是selinux之前的针对文件系统的用户组和读写权限的机制。类似如下:

为什么会报dac相关的访问权限呢?后经过研究,原来是当前进程在尝试访问的文件dac权限配置和自己进程所在的用户组匹配不上。就拿这个案例来进行说明:

当前进程用户组是system用户组,但是这个被访问的文件处于root用户组,且是0660权限,所以当前进程是根本无法成功访问到这个文件的,除非当前进程具有dac_override 的能力,绕过linux dac机制,所以按照如上配置可以使当前进程能够正常访问到这个文件。

然而编译的时候会直接触发neverallow规则:

neverallow check failed at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:23470 from system/sepolicy/private/domain.te:405
  (neverallow base_typeattr_631 self (capability (dac_read_search)))
    <root>
    allow at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:35458
      (allow diag_callback_sample self (capability (dac_override dac_read_search)))

为什么会触发neverallow?因为这个配置授予进程 dac_overridedac_read_search 能力,使其可绕过文件权限检查‌。因此这种题的正确处理思路是,去check linux dac机制,即需要使用chmod和chown命令去处理dac问题:

on boot
    mkdir /mnt/vendor/persist/diag 0777 system system
    chmod 0777 /mnt/vendor/persist/diag/xxx_text.xml
    chown system system /mnt/vendor/persist/diag/xxx_text.xml

2、违反neverallow规则解决思路(摘抄)

遇到neverallow规则问题,千万别急着去注释/剔除里面原有的规则(原生的尽量别动它!)。增加allow规则是常见的解决办法,但是随着 android 版本的升级,系统对 selinux 的管控越来越严,增加了大量的 neverallow。一般情况下,向默认标签授予权限的做法是错误的。其中许多权限都是 neverallow 规则所不允许的。按照上面方法去添加 selinux 可能会违反了 neverallow规则,编译时候会报 neverallow 相关的错误。

1)访问 default property 超过权限

这是比较常见的 neverallow 错误,比如在 systemserver 进程中去对新加的属性设置属性,运行时就会报 default propert 的错误。
遇到这种类型的错误,首先需要给新增的属性添加标签。在 property.te 中定义 property
type demo_prop, property_type;
在 Android 12 中,由于新的 neverallow,如果对 file 进行操作将会编译不过
neverallow domain {
 property_type
 -system_property_type
 -product_property_type
 -vendor_property_type
}:file no_rw_file_perms;
新的 property type 需要指出具体是什么 property type,比如用于 vendor 就改成如下
type demo_prop, property_type, vendor_property_type;
但是如果这个属性还需要在 coredomain 中使用,比如 shell,那么上面写法还是会报一样的 neverallow,需要额外添加 vendor_restricted_property_type 或者是 vendor_restricted_prop(demo_prop)
在 proerty_contexts 中匹配所需要访问的 property
prop u:object_r:demo_prop:s0
然后再根据提示添加政策,比如例子是在systemserver中操作,所以在system_server.te中添加如下政策:
allow system_server demo_prop:property_service set;

2)为新服务添加标签并解决拒绝事件

比如新添加了一个 java 服务,那么需要在 service.te 中新增对应 type: type new_service, service_manager_type; 然后在 service_contexts 中匹配servicename u:object_r: new_service:s0
最后添加根据报错添加相关政策
native 的服务一般是通过 rc 文件定义的可执行程序拉起并注册进 ServiceManager 的,所以要对可执行程序做如下权限配置:
创建一个新域 newdomain.te
type newdomain, domain;
type newdomain _exec, exec_type, file_type;
init_daemon_domain(newdomain)
在 file_contexts 添加对应标签
Service 地址 u:object_r:newdomain _exec:s0
最后添加相关的政策

payjoy移植过程中遇到过这个问题,同时注意一定要在项目文件中进行配置(不要去配Google那边的了)。部分配置如下:

./service_context.te
# Start of PayJoy changes
payjoy_access_service                     u:object_r:payjoy_access_service:s0
# End of PayJoy changes
./service.te
# Start of PayJoy changes
type payjoy_access_service,     system_server_service, service_manager_type;
# End of PayJoy changes

不要少了任何一步,否则都有可能不成功。

3)新设备节点增加访问权限

bsp 创建了一个新的设备节点,即使权限是 777,android 层也是没有访问权限的。
同样首先在 device.te 中添加定义
type new_device, dev_type;
然后在 file_context 中添加对应标签
device 路径 u:object_r:md_block_device:s0
最后添加相关的政策

总结:对于neverallow 需要缩小权限,明确具体需要对什么添加权限。然后根据需要的类型添加对应的 type 和 context 标签, 最后添加对应的政策。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸神黄昏EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值