Android P SELinux (一) 基础概念

Android P SELinux (一) 基础概念
Android P SELinux (二) 开机初始化与策略文件编译过程
Android P SELinux (三) 权限检查原理与调试
Android P SELinux (四) CTS neverallow处理总结
在这里插入图片描述
在处理了一些SELinux相关的问题之后,深深厌恶这个东西,一打开就报一大堆权限问题,添加te权限还特别麻烦,第一次搞下来没有1-2天是不行的。

抽时间查阅相关资料后,结合理论知识和源码进行分析,随着在项目中不断处理了一些CTS neverallow的失败项,慢慢地对SELinux有了更深入的理解,接下来的内容将分别介绍基础概念、SELinux开机初始化、SELinux编译相关和实际案例分享,让大家对SELinux有更加深入的认识。

学习一个模块的东西,我更喜欢从实际的问题出发去探索,因为目标很明确,不会漫无目的地跟着博客或书籍作者的思路游走,过程中不断提出新的问题,从而剥开这个模块的层层面纱并解决我的疑问,在总结的时候记忆也会更加深刻。

困扰已久的几个问题:

  1. make sepolicy局部编译后替换生成的目录/vendor/etc/selinux/和/system/etc/selinux/到板子,没有生效;每次都得整包编译升级才行,为什么有些平台就可以,这不是Android原生的吗?
  2. 项目上遇到升级后第一次开机,会报SELinux权限问题导致功能异常,第二次开机及以后功能就正常了,这是为什么?
  3. 我们遇到很多SELinux权限问题添加了权限之后,如果违反了neverallow规则,直接修改neverallow规则去掉限制,这个做法没有问题吗?既然都可以干掉规则了,那打开SELinux的意义又在哪里呢?
  4. 添加一个脚本的时候,为什么要添加这么多个te(在android/device/xxxxx/common/sepolicy和android/system/sepolicy都要添加 xxx.te ),而有些平台并不需要这样,这又是为什么?

之前一直比较认同没有办法了,才得修改neverallow
既然没法遵守规则,那就废除规则?
直到看到这篇博客的时候,我才意识到是我的认知窄了
selinux常见neverallow项解决方法与常用命令

一、必读文章

SELinux(Security Enhanced Linux)是一个Linux内核模块,也是Linux的一个安全子系统
SELinux主要作用: 最大限度地减小系统中服务进程可访问的资源(最小权限原则)
在网上浏览了很多关于SELinux的文章,分享一些文章:

本文内容开始之前,还望阅读一遍上面大佬的文章,会有很大帮助~

二、DAC 和 MAC

正如很多文章都会提到的两个概念:DAC 和 MAC
DAC:Discretionary Access Control 自主访问控制
在这里插入图片描述
进程理论上所拥有的权限与执行它的用户的权限相同,只要获得root权限,几乎无所不能
比如上面的图片,user是没有权限写入test.txt的
但是可以获取root权限,接着就能写入了

MAC:Mandatory Access Control 强制访问控制在这里插入图片描述
相比DAC,这里进程和文件都被打上了安全上下文,user在写入test.txt的时候,除了要拥有写权限,同时也要在规则库里面声明权限,才能正常写入。
任何进程想在 SELinux 系统上干任何事情,都必须在安全策略文件中赋予权限,凡是没有出现在安全策略文件中的权限都不拥有;即使你是root,也不一定拥有权限操作,这个并不能做到防御一切攻击,但是能将损失降到最小

更多详细的介绍可以看看上面大佬们文章,这里只是简单说说自己的理解

三、SELinux Policy规则

3.1 安全上下文(Security Context)

完整的 Security Context 字符串为:

user:role:type[:range]

SELinux给每一个文件、进程、属性、服务都给打上一个标签,叫安全上下文(Security Context)
用下面的命令可以分别查看对应的安全上下文

  • id -Z 查看当前进程的scontext
console:/ $ id -Z
context=u:r:shell:s0
 
console:/ # id -Z
context=u:r:su:s0
  • ls -Z 查看文件的scontext
console:/ # ls -Z /data/property/persistent_properties
u:object_r:property_data_file:s0 /data/property/persistent_properties
  • ps -AZ 查看所有进程的scontext
console:/ # ps -AZ | grep surface
u:r:surfaceflinger:s0          system        2930     1   67104  12856 SyS_epoll_wait      0 S surfaceflinger
  • getprop -Z 查看属性的scontext
console:/ # getprop -Z | grep selinux
[ro.boot.selinux]: [u:object_r:default_prop:s0]
[ro.boottime.init.selinux]: [u:object_r:boottime_prop:s0]
[selinux.restorecon_recursive]: [u:object_r:restorecon_prop:s0]
  • user:用户,Android里面就一个 u
  • role:角色,进程用 r ,文件用 object_r
  • type :类型,对进程而言也通常叫域,都是一个概念
  • range,也就是上面的s0,是Multi-Level Security(MLS)的等级,这个有个概念就行了,MLS 将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问

安全上下文其实就是一个字符串,我们最需要关注的就是type,MAC基本管理单位是TEAC(Type Enforcement Accesc Control)

3.2 TE (Type Enforcement)

3.2.1 SELinux策略规则语句格式

rules domains types:classes permissions;
  • rules 包括的规则有四个:allow、neverallow、dontaudit、auditallow
    allow : 允许主体对客体进行操作
    neverallow :拒绝主体对客体进行操作
    dontaudit : 表示不记录某条违反规则的决策信息
    auditallow :记录某项决策信息,通常 SElinux 只记录失败的信息,应用这条规则后会记录成功的决策信息
  • domains 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型
  • types 一个对象(例如:文件、属性)或一组对象的标签
  • classes 要访问的对象(例如:文件、属性)的类型
  • permissions 要执行的操作(例如:读、写)

规则库以白名单的形式存在,要求所有允许的操作都必须要用allow规则来定义,不然都会被禁止操作
domains、types、classes、permissions都可以是单独的一个,也可以是一个集合,用花括号括起来
其中的domains和types,既可以指定一个type,也可以指定一组type(也就是attribute),这些定义在te文件里面
classes的定义在/android/system/sepolicy/private/security_classes
permissions的定义在/android/system/sepolicy/private/access_vectors
上面这些规则我们用最多的就是allow和neverallow,搞清楚这两个之后其他的规则是一样的道理

3.2.2 type和attribute

1、type的定义规则

type type_name [alias alias_set] [, attribute_set] ;

比如system_app.te里面定义:

type system_app, domain;

type的名字是system_app
alias定义的是别名,在Android里面这个基本没有用到,见不到它的身影
逗号后面的是属性(attribute),也就是说domain是一个属性,type可以关联多个属性,后面用逗号分割,比如:

type traced_probes, domain, coredomain, mlstrustedsubject;

表示traced_probes这个type关联上了domain、coredomain、mlstrustedsubject这三个属性

如果在type定义的时候没有关联属性,后面也可以通过typeattribute关键字来关联

typeattribute type_name attribute_name;

2、attribute的定义规则

attribute attribute_name;

代码里面属性的定义在:
/android/system/sepolicy/public/attributes

# All types used for processes.
attribute domain;
 
# All types used for files that can exist on a labeled fs.
# Do not use for pseudo file types.
# On change, update CHECK_FC_ASSERT_ATTRS
# definition in tools/checkfc.c.
attribute file_type;
 
# All types used for domain entry points.
attribute exec_type;
 
# All types used for /data files.
attribute data_file_type;
expandattribute data_file_type false;
# All types in /data, not in /data/vendor
attribute core_data_file_type;
expandattribute core_data_file_type false;
# All types in /vendor
attribute vendor_file_type;
......

3、type和attribute的区别
关于type和attribute,一开始接触,很难理解这两个的区别
它们两个有很多类似的点,但是又不大一样:

  • type和attribute都是不能重复定义的,它们位于同一个命令空间,也就意味着定义一个type之后,就不能定义一个同名的attribute
下面的都会定义会报错提示,重复定义

type system_app, domain;
attribute system_app;
 
 
type system_app, domain;
type system_app, coredomain, mlstrustedsubject;
  • type就是一个类型;attribute可以找到所有关联了这个属性的type,可以把它当成一个集合、组、标签

attribute其实就是为了方便书写te规则,我们可以用attribute找到所有关联了属性的type集合,而不用每一个都写出来

3.2.3 例子

上面的概念比较抽象,通常我们能比较快理解的是如何在te文件里使用allow语句添加权限,但是对于neverallow语句所表达的意思就很难理解了

下面我用例子来解释(提到的权限只是示例,并不一定是代码里面的,也有可能违反neverallow规则

1、假如有几个文件,以及它们的安全上下文:

console:/ # ls -Z /data/test.txt
u:object_r:system_data_file:s0 /data/test.txt
 
console:/ # ls -Z /data/vendor/log_test.txt
u:object_r:vendor_data_file:s0 /data/vendor/log_test.txt
 
console:/ # ls -Z /data/media/media_test.txt
u:object_r:media_rw_data_file:s0 /data/media/media_test.txt

2、有如下几个脚本,内容都一样
/system/bin/testA.sh
/vendor/bin/testB.sh
/vendor/bin/testC.sh

echo "hello world" > /data/test.txt
echo "hello world" > /data/vendor/log_test.txt
echo "hello world" > /data/media/media_test.txt

3、init.rc里面的定义如下:

service testA /system/bin/testA.sh
    user root
    group root
    disabled
    oneshot
    seclabel u:r:testA:s0
 
service testB /vendor/bin/testB.sh
    user root
    group root
    disabled
    oneshot
    seclabel u:r:testB:s0
 
service testC /vendor/bin/testC.sh
    user root
    group root
    disabled
    oneshot
    seclabel u:r:testC:s0

4、假设系统里面定义的type和attribute只有下面这些:

type system_server, coredomain, domain;
type testA, domain;
type testB, domain;
type performanced, domain, coredomain;
type kernel, domain, data_between_core_and_vendor_violators;
type testC, domain;
type init, domain, data_between_core_and_vendor_violators;
 
type system_data_file, file_type, data_file_type, core_data_file_type;
type vendor_data_file, file_type, data_file_type;
type media_rw_data_file, file_type, data_file_type, core_data_file_type;
 
attribute domain;
attribute coredomain;
attribute data_between_core_and_vendor_violators;
attribute file_type;
attribute data_file_type;
attribute core_data_file_type;

正如前面提到的概念:

1、属性domain是type集合 : { system_server testA testB performanced kernel testC init }
2、属性coredomain是type集合 : { system_server performanced }
3、属性data_between_core_and_vendor_violators是type集合 : { kernel init }
4、属性file_type是type集合 :{ system_data_file vendor_data_file media_rw_data_file }
5、属性data_file_type是type集合 : { system_data_file vendor_data_file media_rw_data_file }
6、属性core_data_file_type是type集合 : { system_data_file media_rw_data_file }

脚本testA.sh运行起来之后,脚本的进程所在的安全上下文是u:r:testA:s0

如果要想写文件 /data/test.txt,就要给它足够的权限才行:

allow testA system_data_file:file { read write open create };

这句话的意思是type为testA的进程,拥有对type为system_data_file的文件(file)的read write open create权限
此时写第二个文件 /data/vendor/log_test.txt 就没有权限了,因为文件log_test.txt的type是vendor_data_file
同样的得添加权限

allow testA vendor_data_file:file { read write open create };

同理,/data/media/media_test.txt也是一样的道理

allow testA media_rw_data_file:file { read write open create };

上面的allow语句大家很容易理解
再比如:

allow coredomain data_file_type:file { read write open create };

这里coredomain和data_file_type是一个属性(一个type集合,而不仅仅是一个type了),等价于

allow { system_server performanced } { system_data_file vendor_data_file media_rw_data_file }:file { read write open create };

当然,Android系统里面关联data_file_type这个属性的不止这三个,那么data_file_type其实就是所有关联了这个属性的type的集合

domain是所有进程type的总和,因为所有的进程type都要关联属性domain,不然脚本都没有办法运行起来

5、neverallow规则

再看看neverallow规则,其实和allow规则是一样格式的

假如:
neverallow {
  domain
  -coredomain
  -data_between_core_and_vendor_violators
} {
  core_data_file_type
}:file { create open };

减号 - 代表去掉一个type或者一组type
还有几个:
*号表示所有内容
~号表示取反,剩下的所有内容

{ domain -coredomain -data_between_core_and_vendor_violators } 等于
{ system_server testA testB performanced kernel testC init } - { system_server performanced } - { kernel init }
也就是: { testA testB testC }

上面的neverallow语句等价于:

neverallow { testA testB testC } { system_data_file media_rw_data_file }:file { create open };

整理成这样之后,就会发现和前面提到的规则是一模一样的:

  • rules : neverallow
  • domains : { testA testB testC }
  • types : { system_data_file vendor_data_file media_rw_data_file }
  • classes : file
  • permissions : { create open }

neverallow语句的意思是:不允许testA testB testC这些type的进程,对type为system_data_file vendor_data_file media_rw_data_file的file,有create和open权限

如果我们添加了这样的权限,将会报错:

allow testA system_data_file:file create;

之所以说neverallow和allow的书写规则是一样的,是因为如果把neverallow换成allow之后,就是允许给testA testB testC添加对类型为core_data_file_type的file的create和open权限

neverallow就是反过来,不允许你给它们这些权限

6、题外话

我们在添加脚本的时候,通常对应的te会有类似下面的三句:

type testA, domain;
type testA_exec, exec_type, vendor_file_type, file_type;
 
init_daemon_domain(testA)

第一个是testA.sh脚本运行起来之后,进程的type,它的安全上下文是 u:r:testA:s0

第二个是testA.sh这个文件的type,它的安全上下文是 u:object_r:testA_exec:s0

第三个是域转移,我们这些脚本都是init进程启动的,如果没有域转移,那么脚本运行起来它的安全上下文就是 u:r:init:s0了,显然没有细分出来

那这里的意思就是type为init的进程,在运行type为testA_exec的脚本时,会把域切换到testA来

init_daemon_domain的定义在/system/sepolicy/public/te_macros

#####################################
# init_daemon_domain(domain)
# Set up a transition from init to the daemon domain
# upon executing its binary.
define(`init_daemon_domain', `
domain_auto_trans(init, $1_exec, $1)
tmpfs_domain($1)
')

四、SELinux 配置

4.1 开关SELinux

SELinux的状态有两个

  • enforcing 权限拒绝事件会被记录下来并强制执行
  • permissive 权限拒绝事件会被记录下来,但不会被强制执行
    (当然有些还会有disable作为第三个状态,就是彻底关闭的状态)

进入系统后,可以使用setenforce命令来开关

关闭:
setenforce 0
 
打开:
setenforce 1

但如果要开机阶段也是关闭的状态,那就要修改到bootargs的参数了

打开
androidboot.selinux=enforcing
 
关闭
androidboot.selinux=permissive

这里面还需要注意一点,一个宏: ALLOW_PERMISSIVE_SELINUX

/android/system/core/init/Android.mk

ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
init_options += \
    -DALLOW_LOCAL_PROP_OVERRIDE=1 \
    -DALLOW_PERMISSIVE_SELINUX=1 \
    -DREBOOT_BOOTLOADER_ON_PANIC=1 \
    -DWORLD_WRITABLE_KMSG=1 \
    -DDUMP_ON_UMOUNT_FAILURE=1
else
init_options += \
    -DALLOW_LOCAL_PROP_OVERRIDE=0 \
    -DALLOW_PERMISSIVE_SELINUX=0 \
    -DREBOOT_BOOTLOADER_ON_PANIC=0 \
    -DWORLD_WRITABLE_KMSG=0 \
    -DDUMP_ON_UMOUNT_FAILURE=0
endif

/android/system/core/init/selinux.cpp

EnforcingStatus StatusFromCmdline() {
    EnforcingStatus status = SELINUX_ENFORCING;
 
    import_kernel_cmdline(false,
                          [&](const std::string& key, const std::string& value, bool in_qemu) {
                              if (key == "androidboot.selinux" && value == "permissive") {
                                  status = SELINUX_PERMISSIVE;
                              }
                          });
 
    return status;
}
 
bool IsEnforcing() {
    if (ALLOW_PERMISSIVE_SELINUX) {
        return StatusFromCmdline() == SELINUX_ENFORCING;
    }
    return true;
}

对于user版本,是没有办法通过bootargs的androidboot.selinux来关闭的,一直都是enforcing状态的

上面的方法只适用于eng和userdebug版本,在user版本上,权限收缩管控得非常严格

不仅改bootargs没有作用,进入系统后,即使你是root用户,setenforce也没有权限操作

console:/ # setenforce 0
setenforce: Couldn't set enforcing status to '0': Permission denied
[ 4427.467459@3] type=1404 audit(1623583196.490:218): enforcing=1 old_enforcing=0 auid=4294967295 ses=4294967295
[ 4427.477347@3] type=1400 audit(1623583199.930:219): avc: denied { setenforce } for pid=4412 comm="setenforce" scontext=u:r:shell:s0 tcontext=u:object_r:kernel:s0 tclass=security permissive=0

所以user版本要想关闭SELinux,只能修改代码逻辑了

4.2 策略文件配置

Google原生的te在/android/system/sepolicy目录下

设备制造商客制化部分的策略文件te可以通过变量BOARD_SEPOLICY_DIRS来指定,是对/android/system/sepolicy/vendor目录的拓展

这是个很关键的变量,通过这个变量就可以找到你要添加的te在哪个路径

比如:

BOARD_SEPOLICY_DIRS += device/google/marlin/sepolicy
BOARD_SEPOLICY_DIRS += device/google/marlin/sepolicy/verizon

还有两个变量也是对策略文件拓展,这个大家会比较陌生

BOARD_PLAT_PUBLIC_SEPOLICY_DIR    #对PLAT_PUBLIC_POLICY的拓展  即对/android/system/sepolicy/public目录的拓展
BOARD_PLAT_PRIVATE_SEPOLICY_DIR   #对PLAT_PRIVATE_POLICY的拓展 即对/android/system/sepolicy/private目录的拓展

五、判断SELinux问题

判断是否为SELinux导致的权限问题很简单

  • 打开SELinux情况下必现问题
  • 关闭SELinux之后如果问题消失,那基本上就可以认定是权限问题导致的

接着重要的就是抓取avc报错信息,添加权限

kernel log:
dmesg | grep avc

[ 8839.922581@3] type=1400 audit(1623587612.374:455): avc: denied { setattr } for pid=4570 comm="chmod" name="video" dev="mmcblk0p21" ino=384 scontext=u:r:system_app:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0

logcat:
logcat | grep avc

01-01 08:00:09.652  3259  3259 I init    : type=1400 audit(0.0:17): avc: denied { entrypoint } for path="/vendor/bin/testA.sh" dev="mmcblk0p16" ino=705 scontext=u:r:testA:s0 tcontext=u:object_r:vendor_file:s0 tclass=file permissive=1

如果是SELinux权限问题,那必然是100%必现的

前面提到的会出现第一次开机有权限问题,后面开机就没有问题了
找了很久的原因,发现是其他脚本会操作SELinux的开关,没有复现的情况刚好被关掉了

六、一些思考

看完上面的一些文章介绍,我在思考:

  • SELinux存在的意义是什么?
    更安全吧,即使某个进程被黑了或者直接被获取了root权限,也没有拥有所有权限,没有在te策略文件里面声明的权限都不允许

  • 前面提到了即使被root了,也不一定有权限操作,但是我们在板子上su获取root之后,不是拥有权限setenforce吗,直接关了SELinux不就完了?
    在userdebug版本中,为了方便调试,Google原生是有给su足够的权限去操作很多事情的,基本上root就是无敌的存在,所以我们可以直接用setenforce命令去关闭SELinux

user版本中,权限收紧,即使是su获取了root权限,有很多命令都是没有权限执行的,也就是说user版本的系统打开SELinux之后才是最安全的

比如访问data目录:
console:/ # ls /data
ls: /data: Permission denied
[   54.174060@2] type=1400 audit(1623598725.309:119): avc: denied { dac_override } for pid=4212 comm="ls" capability=1 scontext=u:r:shell:s0 tcontext=u:r:shell:s0 tclass=capability permissive=0
[   54.207516@2] type=1400 audit(1623598725.309:120): avc: denied { dac_read_search } for pid=4212 comm="ls" capability=2 scontext=u:r:shell:s0 tcontext=u:r:shell:s0 tclass=capability permissive=0
 
查看ip:
console:/ # ifconfig
[  119.627496@1] type=1400 audit(1623598789.861:186): avc: denied { dac_read_search } for pid=4193 comm="sh" capability=2 scontext=u:r:shell:s0 tcontext=u:r:shell:s0 tclass=capability permissive=0
[  119.639129@1] type=1400 audit(1623598790.781:187): avc: denied { net_raw } for pid=4214 comm="ifconfig" capability=13 scontext=u:r:shell:s0 tcontext=u:r:shell:s0 tclass=capability permissive=0
ifconfig: socket 2 0: Permission denied

这些是因为在te文件里面有这些定义:

userdebug_or_eng(`
  # Domain used for su processes, as well as for adbd and adb shell
  # after performing an adb root command.  The domain definition is
  # wrapped to ensure that it does not exist at all on -user builds.
  typeattribute su mlstrustedsubject;
 
  # Add su to various domains
  net_domain(su)
 
  # grant su access to vndbinder
  vndbinder_use(su)
 
  dontaudit su self:capability_class_set *;
  dontaudit su kernel:security *;
  dontaudit su kernel:system *;
  dontaudit su self:memprotect *;
  dontaudit su domain:process *;
  dontaudit su domain:fd *;
  dontaudit su domain:dir *;
  dontaudit su domain:lnk_file *;
  dontaudit su domain:{ fifo_file file } *;
  dontaudit su domain:socket_class_set *;
  dontaudit su domain:ipc_class_set *;
  dontaudit su domain:key *;
  dontaudit su fs_type:filesystem *;
  dontaudit su {fs_type dev_type file_type}:dir_file_class_set *;
  dontaudit su node_type:node *;
  dontaudit su node_type:{ tcp_socket udp_socket rawip_socket } *;
  dontaudit su netif_type:netif *;
  dontaudit su port_type:socket_class_set *;
  dontaudit su port_type:{ tcp_socket dccp_socket } *;
  dontaudit su domain:peer *;
  dontaudit su domain:binder *;
  dontaudit su property_type:property_service *;
  dontaudit su property_type:file *;
  dontaudit su service_manager_type:service_manager *;
  dontaudit su hwservice_manager_type:hwservice_manager *;
  dontaudit su vndservice_manager_type:service_manager *;
  dontaudit su servicemanager:service_manager list;
  dontaudit su hwservicemanager:hwservice_manager list;
  dontaudit su vndservicemanager:service_manager list;
  dontaudit su keystore:keystore_key *;
  dontaudit su domain:drmservice *;
  dontaudit su unlabeled:filesystem *;
  dontaudit su postinstall_file:filesystem *;
 
  # VTS tests run in the permissive su domain on debug builds, but the HALs
  # being tested run in enforcing mode. Because hal_foo_server is enforcing
  # su needs to be declared as hal_foo_client to grant hal_foo_server
  # permission to interact with it.
  typeattribute su halclientdomain;
  typeattribute su hal_allocator_client;
  typeattribute su hal_audio_client;
  typeattribute su hal_authsecret_client;
  typeattribute su hal_bluetooth_client;
  typeattribute su hal_bootctl_client;
  typeattribute su hal_camera_client;
  typeattribute su hal_configstore_client;
  typeattribute su hal_confirmationui_client;
  typeattribute su hal_contexthub_client;
  typeattribute su hal_drm_client;
  typeattribute su hal_cas_client;
  typeattribute su hal_dumpstate_client;
  typeattribute su hal_fingerprint_client;
  typeattribute su hal_gatekeeper_client;
  typeattribute su hal_gnss_client;
  typeattribute su hal_graphics_allocator_client;
  typeattribute su hal_graphics_composer_client;
  typeattribute su hal_health_client;
  typeattribute su hal_ir_client;
  typeattribute su hal_keymaster_client;
  typeattribute su hal_light_client;
  typeattribute su hal_memtrack_client;
  typeattribute su hal_neuralnetworks_client;
  typeattribute su hal_nfc_client;
  typeattribute su hal_oemlock_client;
  typeattribute su hal_power_client;
  typeattribute su hal_secure_element_client;
  typeattribute su hal_sensors_client;
  typeattribute su hal_telephony_client;
  typeattribute su hal_tetheroffload_client;
  typeattribute su hal_thermal_client;
  typeattribute su hal_tv_cec_client;
  typeattribute su hal_tv_input_client;
  typeattribute su hal_usb_client;
  typeattribute su hal_vibrator_client;
  typeattribute su hal_vr_client;
  typeattribute su hal_weaver_client;
  typeattribute su hal_wifi_client;
  typeattribute su hal_wifi_hostapd_client;
  typeattribute su hal_wifi_offload_client;
  typeattribute su hal_wifi_supplicant_client;
')
 
还有其他很多地方也给su申请了很多权限,看看userdebug_or_eng的定义:
 
#####################################
# Userdebug or eng builds
# SELinux rules which apply only to userdebug or eng builds
#
define(`userdebug_or_eng', ifelse(target_build_variant, `eng', $1, ifelse(target_build_variant, `userdebug', $1)))
 
就是判断是否为userdebug版本或者eng版本

所以如果是userdebug版本,SELinux即使是打开的状态,其实并没有发挥最大的作用
修改neverallow规则,CTS是一定过不了的,后面还会提到~

七、文章汇总

下面的文章都可以学习学习,皆为我师,多看看多思考总有收获~

  • 8
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值