其他分享
首页 > 其他分享> > Android-SEAndroid权限问题指南

Android-SEAndroid权限问题指南

作者:互联网

 

                                 Android-SEAndroid权限问题指南

前言

    SEAndroid是在Android系统中基于SELinux推出的强制访问控制模型,来完善自主访问模型中只要取得root权限就可以为所欲为的情况。

    SELinux是一种基于域-类型(domain-type)模型的强制访问控制(MAC)安全系统,其原则是任何进程想在SELinux系统中干任何事,都必须先在安全策略的配置文件中赋予权限。凡是没有在安全策略中配置的权限,进程就没有该项操作的权限。在SELinux出现之前,Linux的安全模型是DAC(DiscretionaryAccess Control),译为自主访问控制。其核心思想是进程理论上所拥有的权限与运行它的用户权限相同。比如,以root用户启动shell,那么shell就有root用户的权限,在Linux系统上能干任何事。这种管理显然比较松散。在SELinux中,如果需要访问资源,系统会先进行DAC检查,不通过则访问失败,然后再进行MAC权限检查。

 

一.SELinux知识点分析

1.1.SEAndroid app分类和其他

SELinux(或SEAndroid)将app划分为主要三种类型(根据user不同,也有其他的domain类型):

1.untrusted_app  第三方app,没有Android平台签名,没有system权限

2.platform_app    有android平台签名,没有system权限

3.system_app      有android平台签名和system权限

4.untrusted_app_25 第三方app,没有Android平台签名,没有system权限,其定义如下This file defines the rules for untrusted apps running with targetSdkVersion <= 25.

从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app按照这个进行排序

property_contexts(系统属性)主要描述系统属性相关  

1.2.seapp_contexts定义

system/sepolicy/seapp_contexts数据文件

isSystemServer=true domain=system_server
user=system seinfo=platform domain=system_app type=system_app_data_file
user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
user=nfc seinfo=platform domain=nfc type=nfc_data_file
user=radio seinfo=platform domain=radio type=radio_data_file
user=shared_relro domain=shared_relro
user=shell seinfo=platform domain=shell type=shell_data_file
user=_isolated domain=isolated_app levelFrom=user
user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
user=_app domain=untrusted_app type=app_data_file levelFrom=user

从上面可以看出,domain和type由user和seinfo两个参数决定。

比如:

user=system  seinfo=platform,domain才是system_app

user=_app,可以是untrusted_app或platform_app,如果seinfo=platform,则是platform_app。

 

1.3.user和seinfo判定方式

首先看user,user可以理解为UID,例如ps -Z结果如下:

u:r:system_app:s0              system    2414  1172  com.android.keychain
u:r:platform_app:s0            u0_a6     2439  1172  com.android.managedprovisioning
u:r:untrusted_app:s0           u0_a8     2460  1172  com.android.onetimeinitializer
u:r:system_app:s0              system    2480  1172  com.android.tv.settings
u:r:untrusted_app:s0           u0_a27    2504  1172  com.android.email
u:r:untrusted_app:s0           u0_a28    2523  1172  com.android.exchange
u:r:untrusted_app:s0           u0_a7     2567  1172  com.android.musicfx

第一列是SContext,第二列是UID,只要UID是system的基本都是system_app,反过来一样。

其他的U0_XXX要么属于platform_app或untrusted_app

seinfo由external\sepolicy\mac_permissions.xml决定,内容如下:

    <!-- Platform dev key in AOSP -->
    <signer signature="@PLATFORM" >
      <seinfo value="platform" />
    </signer>


    <!-- All other keys -->

    <default>
      <seinfo value="default" />
    </default>

即如果签名是platform,seinfo就是platform,其他的比如shared等,seinfo是default。

比如上面ps -Z的结果里面,OneTimeInitializer.apk是untrusted_app,ManagedProvisioning.apk是platform_app。

分别查看这两个app的Android.mk

packages\apps\OneTimeInitializer\Android.mk  没有定义LOCAL_CERTIFICATE,默认是shared

packages\apps\ManagedProvisioning\Android.mk    有定义LOCAL_CERTIFICATE := platform

因为ManagedProvisioning.apk有platform签名,所以seinfo是platform。

 

1.4.RBAC和constrain

由前文可知,.te文件内部包含各种allow, type等语句,这些都是TEAC(type enforcement access control),属于SELinux MAC中的核心组成部分。

在TEAC之上,SELinux还有一种基于Role的安全策略,也就是RBAC(role based access control)。

e.g.

constrain file write (u1 == u2 and r1 == r2)

这句话表示只有source和targe的user相同,并且role也相同,才允许write file

 

 

1.5.mlsconstrain语句

1.5.1.MLS约束

SELinux支持两个MLS约束语句:mlsconstrain 和mlsvalidatetrans。它们两个一起让我们可以指定可选的MLS访问强制规则,除了它们允许你基于安全上下文的安全级别表示约束外,这两个语句在无MLS的副本中是等同的。你可能只能在开启了MLS特性的策略中使用MLS约束,你可以在任何策略类型中使用无MLS的约束语句。

1.5.2.mlsconstrain语句

mlsconstrain语句是以constrain语句为基础的,我们可以使用第7章"约束"中讨论的constrain语句的所有语法,为了描述基于源(l1 和 h1)和目标(l2 和 H2)的低和高安全级别的约束,mlsconstrain语句添加了新的关键词。下面是mlsconstrain语句的完整语法:

mlsconstrain语句语法

mlsconstrain语句允许你限制特定客体类别指定的许可,通过基于源和目标安全上下文之间的关系定义约束,源和目标安全上下文包括了MLS特性(即高和低安全级别),完整的mlsconstrain语句语法如下:

mlsconstrain 类别集 许可集 表达式;

类别集     一个或多个客体类别。多个客体类别必须使用空格分隔,并用一对大括号将它们括起来,如{file lnk_file},在这个语句中,类别集不接受*,~和-特殊操作符。

许可集     一个或多个许可。所有的许可对类别集中指定的客体类别都要有效,多个许可必须使用空格分隔,并用一对大括号将它们括起来,如{read create},在这个语句中,类别集不接受*,~和-特殊操作符。

表达式     一个布尔表达式。

布尔表达式语法支持下列关键字:

t1, r1, u1, l1, h1      分别表示源类型、源角色、源用户、源低级别和源高级别。

t2, r2, u2, l2, H2      分别表示目标类型、目标角色、目标用户、目标低级别和目标高级别。

约束表达式语法也支持下列特殊操作符:

==     是…的一个成员或等于。

!=     不是…的成员或不等于。

eq     (只用于角色和安全级别)等于。

dom   (只用于角色和安全级别)优先于

domby (只用于角色和安全级别)被…优先

incomp (只用于角色和安全级别)不可比

这些操作符完整的语义含义和它们可接受的参数放在表8-1中了,表8-1是根据表7-1制作的。

mlsconstrain语句仅在非强制MLS策略中受到支持。

mlsconstrain语句仅在单个策略和基础载入模块中有效,在条件语句和非基础载入模块中无效。

为了解释mlsconstrain语句,我们来看一个将MLS应用给普通文件系统对象的例子,因为是一个简单示例,我们假设那个文件对象只有一个安全级别,即高和低安全级别是相同的,我们可以使用下面这样一条约束语句来实现这个约束:

mlsconstrain file { create relabelto }
( l2 eq h2 );

假设create和relabelto是为设置文件客体安全级别需要的file许可,这个约束足以要求所有的文件高安全级别等于低安全级别。接下来我们来看一看更核心的MLS策略约束,回顾一下第2章中关于MLS的基础前提,即阻止信息从高安全级别滑向低安全级别或无法比较的安全级别,我们通过在所有客体上执行"不能读就不能写"的规则来实现这个要求,在SELinux中,低安全级别通常表示进程或客体的当前安全级别,因此,对于文件我们使用以下MLS约束:

mlsconstrain file write ( l1 domby l2 );

在这个语句中,我们对file客体类别限制了write许可,要求客体安全级别(l2)优先源安全级别(l1),换句话说就是进程仅在它当前的安全级别上可以写文件。遗憾的是这个约束太简单而不能保证MLS策略对文件客体有效,首先,我们考虑一下文件客体类别许可,除了write外还有许多许可允许向文件写入信息,如append许可也允许往文件中写入信息(追加在文件末尾),还有rename许可,为了充分理解,我们需要扩展我们的约束,覆盖所有的"有能力写"文件许可:

mlsconstrain file { write create setattr relabelfrom append
unlink link rename mounton }
( l1 domby l2 );

在这个语句中除了write许可外,还列出了一系列的许可,它们都可以以某种形式往客体写入信息,约束表达式仍然相同。这个约束语句仍然相当简单,我们需要指出受信任的域类型在何处,并且要给它提供特殊的许可,以跳过"不能写"规则,即使你应该避免使用这种受信任的域,但实际上,几乎所有的MLS系统应用程序都会使用它们,为了适应这个原理,我们需要扩展这些约束语句让它们接受这些受信任的域。

为了实现这些受信任的降级域,可以创建一个类型属性,叫做mlsfilewritedown,它可以识别出所有受信任的域,现在,我们的约束语句如下:

mlsconstrain file { write create setattr relabelfrom append
unlink link rename mounton }
( ( l1 domby l2 ) or
( t1 == mlsfilewritedown ) );

这个约束语句允许一个例外,就是任何属性为mlsfilewritedown的源域(t1),这就是所谓就信任的域了。对于一个完整的MLS策略,我们也需要限制读权限,和写权限一样,除了read许可外,也有大量的许可是允许"读"访问权的,如execute许可肯定会允许进程读取可执行文件的内容的,下面是一个对文件客体的MLS读约束:

mlsconstrain  file  { read getattr execute }
( ( l1 dom l2 ) or
( t1 == mlsfilewritedown ) );

在这个约束语句中,它允许读取那些有特权的属性包含有mlsfilereadup的域类型的特权。在编写一个完整的MLS策略时,你需要检查所有的客体类别和它们的许可,确保读和写限制是正确约束的。如在前面的读约束语句中,我们可能想在单条语句中标出所有的文件系统客体,如:

mlsconstrain { dir file lnk_file chr_file
blk_file sock_file fifo_file }
{ read getattr execute }
( ( l1 dom l2 ) or
( t1 == mlsfilereadup ) );

对于一个给定的SELinux策略,你会发现MLS约束通常是在一个源策略文件中的,一般都叫做mls,除了这一章外,我们不打算过多地谈及SELinux的MLS特性,如果你对这方面的东西感兴趣,你可以直接打开这个文件研究研究。

表8-1. Mlsconstrain表达式接受的参数对应的语义含义(参考表7-1)

操作符

左边

右边

语义含义

==

l1

l2,H1,H2

源的低安全级别(当前安全级别)等于目标的低安全级别l2,源的高安全级别(H1)或目标的高安全级别(H2)

l2

h2

目标的低安全(当前)级别等于目标的高安全级别

h1

l2,h2

源的高安全级别等于目标的低安全级别或高安全级别

!=

l1

l2, h1, H2

源的低安全(当前)级别不等于目标的低安全级别l2,源的高安全级别(H1)或目标的高安全级别(H2)

l2

H2

目标的低安全(当前)级别不等于目标的高安全级别

h1

l2,h2

源的高安全级别不等于目标的低安全级别或高安全级别

eq

l1

l2, H1, H2

和==的语义完全一样

l2

h2

和==的语义完全一样

h1

l2,h2

和==的语义完全一样

dom

l1

l2, H1, H2

源的低安全级别(当前安全级别)优先于目标的低安全级别l2,源的高安全级别(H1)或目标的高安全级别(H2)

l2

h2

目标的低安全(当前)级别优先于目标的高安全级别

h1

l2,h2

源的高安全级别优先于目标的低安全级别或高安全级别

domby

l1

l2, H1, H2

目标的低安全级别(当前安全级别)优先于源的低安全级别l2,源的高安全级别(H1)或目标的高安全级别(H2)

l2

h2

目标的高安全级别优先于目标的低(当前)安全级别

h1

l2,h2

目标的低安全级别或高安全级别优先于源的高安全级别

incomp

l1

l2, H1, H2

源的低安全级别(当前安全级别)与目标的低安全级别l2,源的高安全级别(H1)或目标的高安全级别(H2)不可比

l2

h2

目标的低安全(当前)级别与目标的高安全级别不可比

h1

l2,h2

目标的低安全级别或高安全级别与源的高安全级别不可比

 

 

1.6.小技巧

使用allow语句的时候,可以使用下面的一些小技巧来简化命令书写;

”~”号,表示除了”~”以外;

”-”号,表示去除某项内容;

”*”号,表示所有内容

 

 

1.7.SELinux 策略构建和客制化

在Android8.0中,SELinux策略分离成平台(platform)和非平台(non-platform)两部分,而平台策略为了给非平台作者导出特定的类型和属性,又分为平台私有(platform private)和平台公有(platform public)部分。

1.7.1.平台公有策略(platform public seoplicy)

平台共有策略全部定义在/system/sepolicy/public下,public下的type和attribute可以被non-platform中的策略所使用,也就是说,设备制造商的sepolicy作者在non-platform下可以对platform public sepolicy的策略进行扩展。

1.7.2.平台私有策略(platform private seoplicy)

与公有策略相反,被声明为私有策略的type或attribute对non-platform的策略作者是不可见的,这里有些费解,我们举例来说,这里以8.0版本的aosp源代码中的/system/sepolicy/private/目录下的atrace.te文件为例;

  1. 8.0版本的aosp中的/system/sepolicy/private/file_contexts定义了“/system/bin/atrace    u:object_r:atrace_exec:s0”
  2. 然后在/system/sepolicy/private/atrace.te中定义atrace相关的规则;
  3. 我们在device/qcom/sepolicy/common目录下新增一个atrace.te文件,并添加规则 "allow atrace sdcardfs:file read;"

当我们make进行编译时会在校验的时候失败,提示我们“device/qcom/sepolicy/common/atrace.te:2:ERROR 'unknown type atrace' at token ';' on line 23355”,那么也就是说private策略中的type和attribute对我们是不可见的。

1.7.3.平台私有映射

映射主要针对旧版本的映射,应用比较少,这里不作研究;

二、实际案例分析

Android 5.x开始,引入了非常严格的SELinux权限管理机制,我们经常会遇到因为SELinux权限问题造成的各种avc denied困扰。

 

本文结合具体案例,讲解如何根据log来快速解决90%的权限问题。

遇到权限问题,在logcat或者kernel的log中一定会打印avc denied提示缺少什么权限,

Command:
cat /proc/kmsg | grep avc 或 dmesg | grep avc

解决原则是:缺什么补什么,一步一步补到没有avc denied为止。

 

下面给出几个具体案例:

 

2.1.案例分析一

分析过程:

缺少什么权限:      { write }权限,

谁缺少权限:        scontext=u:r:kernel:s0,

对哪个文件缺少权限:tcontext=u:object_r:block_device

什么类型的文件:    tclass=blk_file

解决方法:kernel.te

allow kernel block_device:blk_file write;

 

2.2.案例分析二

解决方法 :platform_app.te

allow  platform_app  app_data_file:file  execute;

 

2.3.案例分析三

                       

解决方法 :engsetmacaddr.te

allow  engsetmacaddr  vfat:dir  { search write add_name create }; 或者

allow  engsetmacaddr   vfat:dir  create_dir_perms;

 

2.4.案例分析四

解决方法 :sdcardd.te 

allow  sdcardd  system_data_file:dir  read;  或者
allow  sdcardd  system_data_file:dir  rw_dir_perms

(rw_dir_perms包含read write,可以参考external/sepolicy/global_macros的定义声明)

通过这四个案例,我们可以总结出一般规律,

以第4个为例,允许某个scontext对某个tcontext拥有某个权限

我们的log重新排列一下,

scontext=u:r:sdcardd

tcontext=u:object_r:system_data_file:s0

tclass=dir

avc: denied { read }

得到万能套用公式如下:

在scontext所指的te文件中加入类似如下内容:

 

以上以.te为后缀的文件都在external/sepolicy/或者device/softwinner/xxxx-commm/sepolicy/下,修改之后,都要重刷boot.img。(重点,在Android7和Android 8上面.te后缀的文件都在system/sepolicy或者device/softwinner/xxxx-commm/sepolicy/下面这个需要注意,且此时需要烧录system.img或者vendor.img)

 

补充说明:

1. 有时候avc denied的log不是一次性显示所有问题,要等你解决一个权限问题之后,才会提示另外一个权限问题。比如提示确实某个目录的read权限,你加入read之后,再显示缺少write权限,要你一次次一次试,一次一次加。这时你可以简单粗暴写个rw_dir_perms,这个权限包含了{open search write ...}等等很多权限。可以查看external/sepolicy/global_macros来了解更多权限声明(相对应的在Android 7和Android 8对应的就是external/sepolicy/global_macros,如果有定义的话);

2. 要加入的权限很多时,可以用中括号,比如

allow engsetmacaddr  vfat:dir { search write add_name create};

3. 遇到问题不确定是否由于selinux问题造成,可先在adb shell 下,输入setenforce 0,让selinux失效,看是否问题还出现。以此可以澄清是非selinux造成的问题。

 

2.5.后话

有一个开源的工具audit2allow,没有具体使用过,网上流程如下而对于如何解决该类权限问题,一般的做法是,缺少什么就补什么,先介绍一下简化方法:

简化方法:

1、 提取所有的avc LOG.   如 adb shell "cat /proc/kmsg | grepavc" > avc_log.txt

2、  使用 audit2allow tool 直接生成policy. audit2allow -i avc_log.txt  即可自动输出生成的policy

还是建议不要使用这个工具,最好自己手动编写相关的策略。因为上面这个工具知识机械的转化,不一定符合具体的要求

 

 

三、特殊案例分析

3.1.android系统增加native本地服务

上述就以E/SELinux (  261): avc:  denied  { add } for service=PaxApiService scontext=u:r:init:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager为例说明,这个错误主要是添加ServiceManager添加Native Service没有配置SELinux权限导致,由于现在SELinux的启用是在展讯平台,所以这里就以以展讯平台来说明,步骤如下:

1.vi编辑device/sprd/sharkle/common/plat_sepolicy/private/service_contexts在其最后添加

#add for PaxApiService
PaxApiService                     u:object_r:PaxApiService_service:s0

2.vi编辑device/sprd/sharkle/common/plat_sepolicy/public/service.te在其最后添加

#type for PaxApiService
type PaxApiService_service, service_manager_type;

3.vi编辑device/sprd/sharkle/common/sepolicy/system_server.te在其最后添加

#add for PaxApiService
allow system_server PaxApiService_service:service_manager { add find };

4.vi编辑device/sprd/sharkle/common/sepolicy/platform_app.te在其最后添加

#add for PaxService
allow platform_app PaxApiService_service:service_manager { find };

5.最后根据在使用中报什么avc的错误,然后再按照规则添加相关规则

 

3.2.android系统增加java层服务

上述就以E/SELinux (  261): avc:  denied  { add } for service=PaxSystemUtil scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager,这个错误主要是添加ServiceManager添加Native Service没有配置SELinux权限导致,由于现在SELinux的启用是在展讯平台,所以这里就以以展讯平台来说明,步骤如下:

1.vi编辑device/sprd/sharkle/common/plat_sepolicy/private/service_contexts在其最后添加

#add for PaxSystemUtil
PaxSystemUtil  u:object_r:PaxSystemUtil_service:s0

2.vi编辑device/sprd/sharkle/common/plat_sepolicy/public/service.te在其最后添加

#type for PaxSystemUtil
type PaxSystemUtil_service, service_manager_type;

3.vi编辑device/sprd/sharkle/common/sepolicy/system_server.te在其最后添加

#add for PaxSystemUtil
allow system_server PaxSystemUtil_service:service_manager { add find };

4.vi编辑device/sprd/sharkle/common/sepolicy/platform_app.te在其最后添加

#add for PaxSystemUtil
allow platform_app PaxSystemUtil_service:service_manager { find };

 

 

四、新增加权限文件

4.1.新建.te安全策略文件方法

以上基本是对已经存在的进程增加权限,但对第三方进程改如何新增一个全新的te文件并赋予权限呢?

以写mac地址的setmacaddr执行文件为例(这个执行档android原生不存在,自行添加的),这个案例可以扩展到我们的paxservice添加在init脚本自运行启动的的案例,且由于paxservice是运行在/system/bin里面情况更加的特殊

 

1. 在device/sprd/sharkle/common/sepolicy/file_contexts中,参考其他进程声明一个:

/system/bin/install-recovery.sh u:object_r:install_recovery_exec:s0
/system/bin/dex2oat     u:object_r:dex2oat_exec:s0
/system/bin/patchoat    u:object_r:dex2oat_exec:s0
/system/bin/setmacaddr  u:object_r:engsetmacaddr_exec:s0
/system/bin/paxservice  u:object_r:paxservice_exec:s0

指定setmacaddr和paxservice的路径,并指定一个名字,一定要以_exec结尾

 

2.参考其他文件在device/sprd/sharkle/common/sepolicy/ 创建engsetmacaddr.te文件,内容如下:

type engsetmacaddr, domain;
type engsetmacaddr_exec, exec_type, file_type;
init_daemon_domain(engsetmacaddr)
allow engsetmacaddr  vfat:dir { search write add_name create};
allow engsetmacaddr  vfat:file { create read write open };
allow engsetmacaddr  engsetmacaddr:capability dac_override;
allow engsetmacaddr  shell_exec:file { execute read open execute_no_trans};
allow engsetmacaddr  system_data_file:dir { write add_name remove_name };
allow engsetmacaddr  system_data_file:file { create execute_no_trans write open setattr};
allow engsetmacaddr  system_file:file { execute_no_trans};

以上赋予的权限全部是根据avc denied的log缺什么一步一步补什么来的。

 

3.

3.1针对paxservice在device/sprd/sharkle/common/plat_sepolicy/private/ 创建paxservice.te文件,内容如下:

typeattribute paxservice coredomain;
init_daemon_domain(paxservice)

3.2在device/sprd/sharkle/common/plat_sepolicy/public创建paxservice.te文件,添加如下内容:

type paxservice, domain, mlstrustedsubject;
type paxservice_exec, exec_type,file_type;

3.3在device/sprd/sharkle/common/sepolicy/创建paxservice.te文件,添加如下内容:

allow paxservice servicemanager:binder {  call };   #call "dumpsys"
allow paxservice system_server:binder {  call };   #call "dumpsys"
allow servicemanager paxservice:dir { search };
allow servicemanager paxservice:file { read };

4.2.新设备节点增加访问权限

驱动创建了一个新的设备节点,即使权限是777,android层也是没有访问权限的。

下面以一个/dev/wifi_bt节点为示范,让此节点被用户空间的system_server进程访问。

1. 由于我们的SELinux的启动是在展讯平台上面,所以编辑编辑device/sprd/sharkle/common/sepolicy/device.te,仿照这个文件里的写法,定义一个dev_type类型的wifi_bt_device设备:

type misc_block_device, dev_type;
type private_block_device, dev_type;
……
type wf_bt_device, dev_type;   

2. 编辑file_contexts.te,将/dev/wf_bt节点声明为第1步定义的wf_bt_device:

/dev/block/by-name/misc         u:object_r:misc_block_device:0
/dev/block/by-name/alog         u:object_r:log_block_device:s0
/dev/block/by-name/private      u:object_r:private_block_device:s0
# We add here  

/dev/wf_bt              u:object_r:wf_bt_device:s0  

 

3. 在system_server.te,根据dmesg | grep avc允许system_server对wf_bt_device这个节点可读可写:

# Read/Write to /proc/net/xt_qtaguid/ctrl and and /dev/xt_qtaguid.allow system_server qtaguid_proc:file rw_file_perms;  

allow system_server qtaguid_device:chr_file rw_file_perms;  

 ……

allow system_server wf_bt_device:chr_file rw_file_perms;  

其他进程如需访问/dev/wf_bt节点,依样画葫芦,增加对wf_bt_device的权限即可。

 

 

4.3.常见错误

01-02 10:01:37.596   238   300 W YLOG    : [01-02 10:01:37.596] ylog<critical> android cacheline write wrong 4317 -> 1008

01-02 10:01:37.598   217   217 E SELinux : avc:  denied  { add } for service=PaxSystemUtil pid=4311 uid=1000 scontext=u:r:system_app:s0 tcontext=u:object_r:PaxSystemUtil_service:s0 tclass=service_manager permissive=0

01-02 10:01:37.599   217   217 E ServiceManager: add_service('PaxSystemUtil',91) uid=1000 - PERMISSION DENIED

libsepol.report_failure: neverallow on line 554 of system/sepolicy/private/system_server.te (or line 31144 of policy.conf) violated by allow system_app SettingsManagerService_service:service_manager { add };

Caused by: java.lang.RuntimeException: failed to set system property

 

 

01-01 11:11:39.434 E/SELinux (  218): avc:  denied  { add } for service=PaxApiService pid=2021 uid=0 scontext=u:r:paxservice:s0 tcontext=u:object_r:PaxApiService_service:s0 tclass=service_manager permissive=0

01-01 11:11:39.435 E/ServiceManager(  218): add_service('PaxApiService',92) uid=0 - PERMISSION DENIED

 

调试技巧:

由于SELinux的问题,而且由于adb连接比较慢,必须借串口抓相关的日志,现在通过属性控制paxsservice的启动

on post-fs-data



on property:pax.ctrl.paxservice=1
     start paxservice


service paxservice /system/bin/paxservice

    class core
    user root
    group root
    disabled

 

4.4.进程无法访问直接访问data 目录的说明

[Description]
[SELinux] Android M 版本后进程无法访问直接访问data 目录的说明
 
[Keyword]
SELinux, data, 拒绝, permission denied, 安全 , security

[Version]
android >= 6.0
 
[Solution]
Google 在android M 版本后, 通过SELinux 的neverallow 语法强制性限制了普通进程访问data 目录的权限. 严禁除init system_server installd system_app 之外的其他进程直接操作/data 目录比如在data 目录下面创建文件,写文件,重命名文件等等.

有很多客户都会在data 目录下创建文件, 保存资讯, 在M 版本上这个操作会被SELinux 直接拦截下来,并且没法直接添加访问system_data_file 的权限, 需要按下面的流程操作。
(1).  在init.rc 或者 其他的init.xxx.rc 的on post-fs-data 段 添加:

mkdir /data/xxxx 0770 root system

(2). 在/device/mediatek/common/sepolicy/file.te 里面添加:

type xxxx_data_file, file_type, data_file_type;

(3). /device/mediatek/common/sepolicy/file_contexts 里面添加:

/data/xxxx(/.*)? u:object_r:xxxx_data_file:s0

(4). 给你的进程添加权限, 比如你的进程的SELinux domain 是 yyyy

allow yyyy xxxx_data_file:dir create dir_perms;
allow yyyy xxxx_data_file:file create_file_perms;

这样你才能绕过Google 的设置. 这个xxxx 目录随你定义.

下面是一个完整的添加过程:

出于历史原因,项目需要对/data/resource目录下面的目录文件进行访问,在没有开启SELinux检测之前,只需要对目录开启相应的读写访问权限即可,可是开启SELinux之后就不同了。通过SELinux 的neverallow 语法强制性限制了普通进程访问data 目录的权限. 严禁除init system_server installd system_app 之外的其他进程直接操作/data 目录比如在data 目录下面创建文件,写文件,重命名文件等等.在O版本上面有很多客户都会在data 目录下创建文件, 保存资讯, 这个操作会被SELinux 直接拦截下来,并且没法直接添加访问system_data_file 和data_file_type的权限, 需要按下面的流程操作。

 

1.在system/sepolicy/public/file.te和system/sepolicy/prebuilts/api/26.0/public/file.te添加
 

type paxdroid_share_file, file_type, data_file_type, mlstrustedobject;#其中mlstrustedobject这个很重要后面会重点强调

2.system/sepolicy/prebuilts/api/26.0/private/file_contexts和system/sepolicy/private/file_contexts添加

/data/resource(/.*)? u:object_r:paxdroid_share_file:s0

3.在system/sepolicy/prebuilts/api/26.0/private/app_neverallows.te和system/seplicy/private/app_neverallows.te下面做如下修改

#neverallow all_untrusted_apps file_type:file link;

#不允许all_untrusted_apps对file_type进行访问,除开paxdroid_share_file

neverallow {all_untrusted_apps} {file_type -paxdroid_share_file}:file link;

#同上

neverallow { all_untrusted_apps -mediaprovider } {

fs_type

-fuse # sdcard

-sdcardfs # sdcard

-vfat

file_type

-app_data_file # The apps sandbox itself

-media_rw_data_file # Internal storage. Known that apps can

# leave artfacts here after uninstall.

-user_profile_data_file # Access to profile files

userdebug_or_eng(`

-method_trace_data_file # only on ro.debuggable=1

-coredump_file # userdebug/eng only

')

-paxdroid_share_file

}:dir_file_class_set { create unlink };

4.然后在device/sprd/sharkle/common/sepolicy/paxdroid_share_file.te增加该文件,然后增加相关的权限

allow system_app paxdroid_share_file:file {create write setattr relabelfrom relabelto append unlink link rename open getattr read lock };


allow untrusted_app paxdroid_share_file:dir { search write create add_name remove_name setattr relabelfrom relabelto append unlink link rename getattr};

allow untrusted_app paxdroid_share_file:file {create write setattr relabelfrom relabelto append unlink link rename open getattr read lock };



allow untrusted_app_25 paxdroid_share_file:dir {search write create add_name remove_name setattr relabelfrom relabelto append unlink link rename getattr};

allow untrusted_app_25 paxdroid_share_file:file {create write setattr relabelfrom relabelto append unlink link rename open getattr read lock };



allow platform_app paxdroid_share_file:dir { search write create add_name remove_name setattr relabelfrom relabelto append unlink link rename getattr};

allow platform_app paxdroid_share_file:file { create write setattr relabelfrom relabelto append rename open getattr read lock };


allow paxservice paxdroid_share_file:dir { search write create add_name remove_name setattr relabelfrom relabelto append unlink link rename getattr};

allow paxservice paxdroid_share_file:file { create write setattr relabelfrom relabelto append rename open getattr read lock };

 

5..重点来了,后面发现怎么修改都untrusted_app_25都不能对该文件进行修改,后面发现了是由于mls规则导致,错误类似如下:

type=1400 avc: denied { connectto } for pid=6884 scontext=u:r:​untrusted_app:s0:c512,c768 tcontext=u:r:bluetooth:s0 tclass=unix_stream_socket permissive=0

在system/sepolicy/private/mls存在如下的规则,所以就需要对paxdroid_share_file加上mlstrustedobject才可以

mlsconstrain dir { write setattr rename add_name remove_name reparent rmdir }

(t2 == app_data_file or l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);



mlsconstrain { file lnk_file sock_file chr_file blk_file } { write setattr append unlink link rename }

(t2 == app_data_file or l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);

具体可以参考如下的博客文章:SELinux中的MLC规则约束

 

4.5.添加属性访问权限

由于历史原因,前面的开发过程中使用了很多的property属性,但是由于现在平台开启了SELinux的控制,在移植以前代码的过程中经常会出现Caused by: java.lang.RuntimeException: failed to set system property的错误,这就需要我们制定相关的策略来满足对特定属性的访问需求,具体的制定流程如下:

1.在device/sprd/sharkle/common/plat_sepolicy/private/property_contexts最后添加如下定义

# add property contexts for pax

pax.ctrl.                       u:object_r:pax_ctrl_prop:s0
pax.soc.                        u:object_r:pax_ctrl_prop:s0
com.pax.                        u:object_r:pax_ctrl_prop:s0  
pax.sp.                         u:object_r:pax_ctrl_prop:s0
persist.pax.                    u:object_r:pax_ctrl_prop:s0
ro.epay.serial                  u:object_r:pax_ctrl_prop:s0
ro.ums.manufacturer.info        u:object_r:pax_ctrl_prop:s0
pax.sys.                        u:object_r:pax_ctrl_prop:s0
pax.sdk.                        u:object_r:pax_ctrl_prop:s0
pax.persist.                    u:object_r:pax_ctrl_prop:s0
pax.param.                      u:object_r:pax_ctrl_prop:s0
ro.pax.                         u:object_r:pax_ctrl_prop:s0

2.在device/sprd/sharkle/common/plat_sepolicy/public/property.te最后添加如下的定义,具体如下

#add for pax.ctrl  property

type pax_ctrl_prop, property_type;

3.最后就是对定义的属性访问,添加相应的访问规则了,由于太多就不一一表述出来,可以参见下面的截图

  

 

 

4.6 增加NTFS格式外接U盘访问权限

由于Android原生只支持VFAT格式的U盘挂载,现在需要增加NTFS格式的U盘挂载,今天的重点不是怎么增加NTFS格式的支持,重点是怎么在SELinux增加NTFS格式U盘的挂载。原来以为非常的简单只需要参照VFAT格式的做就ok了,但是发现就是一个坑根本行不懂,尝试了很多办法,最好通过内核打印发现了如下的信息:

sdcardfs: mounted on top of /mnt/media_rw/exsdcard0 type fuseblk

sdcardfs: mounted on top of /mnt/media_rw/exsdcard0 type vfat

驱动的小哥哥根本挂载的不是把U盘挂载称为utfs格式的而是fuseblk类型的,所以发现了这个点问题就迎刃而解了,只需要参照VFAT格式的添加SELinux权限就ok了,这里需要注意地是虚拟文件系统的安全上下文和关键词genfscon。

 

 

 

标签:SEAndroid,data,app,system,安全级别,file,Android,权限,type
来源: https://blog.csdn.net/tkwxty/article/details/98213671