志在指尖
用双手敲打未来

Android CTS中neverallow规则生成过程

CTS里面SELinux相关测试中neverallow测试项占绝大多数,Android系统开发者都应该晓得,在修正sepolicy时,需求确保不能违背这些neverallow规则,不然会过不了CTS。CTS中nerverallow测试都是在SELinuxNeverallowRulesTest.java文件中,并且从AOSP代码中发现该文件不是人工提交的,而是经过python脚本生成的,为了以后更好的修正sepolicy,就需求理解下SELinuxNeverallowRulesTest.java是如何生成的。
Makefile
首先看下SELinuxNeverallowRulesTest.java的生成的Makefile.
selinux_general_policy:=$(callintermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
selinux_neverallow_gen:=cts/tools/selinux/SELinuxNeverallowTestGen.py
selinux_neverallow_gen_data:=cts/tools/selinux/SELinuxNeverallowTestFrame.py
LOCAL_ADDITIONAL_DEPENDENCIES:=$(COMPATIBILITY_TESTCASES_OUT_cts)/sepolicy-analyze
LOCAL_GENERATED_SOURCES:=$(calllocal-generated-sources-dir)/android/cts/security/SELinuxNeverallowRulesTest.java#目的文件
$(LOCAL_GENERATED_SOURCES):PRIVATE_SELINUX_GENERAL_POLICY:=$(selinux_general_policy)
$(LOCAL_GENERATED_SOURCES):$(selinux_neverallow_gen)$(selinux_general_policy)$(selinux_neverallow_gen_data)
mkdir-p$(dir$@)
$<$(PRIVATE_SELINUX_GENERAL_POLICY)$@
#$<为:右边依赖的第一个元素,即$(selinux_neverallow_gen)=cts/tools/selinux/SELinuxNeverallowTestGen.py
#$@为:左边目的,即要生成的目的文件SELinuxNeverallowRulesTest.java
#这条命令相当于cts/tools/selinux/SELinuxNeverallowTestGen.py$(callintermediates-dirfor,ETC,general_sepolicy.conf)/general_sepolicy.confSELinuxNeverallowRulesTest.java
include$(BUILD_CTS_HOST_JAVA_LIBRARY)
从上面能够看到,执行SELinuxNeverallowTestGen.pygeneral_sepolicy.confSELinuxNeverallowRulesTest.java会生成SELinuxNeverallowRulesTest.java文件。
general_sepolicy.conf生成
该文件的生成Makfile
#SELinuxpolicyembeddedintoCTS.
#CTSchecksneverallowrulesofthispolicyagainstthepolicyofthedeviceundertest.
##################################Android
include$(CLEAR_VARS)
LOCAL_MODULE:=general_sepolicy.conf#目的文件
LOCAL_MODULE_CLASS:=ETC
LOCAL_MODULE_TAGS:=tests
include$(BUILD_SYSTEM)/base_rules.mk
$(LOCAL_BUILT_MODULE):PRIVATE_MLS_SENS:=$(MLS_SENS)
$(LOCAL_BUILT_MODULE):PRIVATE_MLS_CATS:=$(MLS_CATS)
$(LOCAL_BUILT_MODULE):PRIVATE_TARGET_BUILD_VARIANT:=user
$(LOCAL_BUILT_MODULE):PRIVATE_TGT_ARCH:=$(my_target_arch)
$(LOCAL_BUILT_MODULE):PRIVATE_WITH_ASAN:=false
$(LOCAL_BUILT_MODULE):PRIVATE_SEPOLICY_SPLIT:=cts
$(LOCAL_BUILT_MODULE):PRIVATE_COMPATIBLE_PROPERTY:=cts
$(LOCAL_BUILT_MODULE):$(callbuild_policy,$(sepolicy_build_files),\
$(PLAT_PUBLIC_POLICY)$(PLAT_PRIVATE_POLICY))#PLAT_PUBLIC_POLICY=syetem/sepolicy/publicPLAT_PRIVATE_POLICY=system/sepolicy/private
$(transform-policy-to-conf)#这里是运用m4将te规则文件都处置合成为目的文件$@,即general_sepolicy.conf
$(hide)sed’/dontaudit/d’$@>$@.dontaudit
##################################
能够看到,general_sepolicy.conf文件是将system/sepolicy/public和system/sepolicy/private规则文件整合在一同,而这些目录包含的是AOSPsepolicy大多数配置信息。
SELinuxNeverallowTestGen.py脚本逻辑
生成的逻辑都是在该脚本中,下面脚本我调整了次第,便当阐明执行的逻辑,脚本代码
#!/usr/bin/envpython
importre
importsys
importSELinuxNeverallowTestFrame
usage=”Usage:./SELinuxNeverallowTestGen.py

if__name__==”__main__”:
#checkusage
iflen(sys.argv)!=3:
printusage
exit(1)
input_file=sys.argv[1]
output_file=sys.argv[2]
#这三个变量是同目录下SELinuxNeverallowTestFrame.py文件中的内容,是生成java文件的模版
src_header=SELinuxNeverallowTestFrame.src_header
src_body=SELinuxNeverallowTestFrame.src_body
src_footer=SELinuxNeverallowTestFrame.src_footer
#grabtheneverallowrulesfromthepolicyfileandtransformintotests
neverallow_rules=extract_neverallow_rules(input_file)#提取neverallow规则从general_sepolicy.conf中
i=0
forruleinneverallow_rules:
src_body+=neverallow_rule_to_test(rule,i)
i+=1
#然后将neverallow规则写入到SELinuxNeverallowRulesTest.java文件中
withopen(output_file,’w’)asout_file:
out_file.write(src_header)
out_file.write(src_body)
out_file.write(src_footer)
#extract_neverallow_rules-takesanintermediatepolicyfileandpullsoutthe
#neverallowrulesbytakingallofthenon-commentedtextbetweenthe’neverallow’
#keywordandaterminating’;’
#returns:alistofrules
defextract_neverallow_rules(policy_file):
withopen(policy_file,’r’)asin_file:
policy_str=in_file.read()
#full-TrebleonlytestsareinsidesectionsdelimitedbyBEGIN_TREBLE_ONLY
#andEND_TREBLE_ONLYcomments.
#uncommentTREBLE_ONLYsectiondelimiterlines
remaining=re.sub(
r’^\s*#\s*(BEGIN_TREBLE_ONLY|END_TREBLE_ONLY|BEGIN_COMPATIBLE_PROPERTY_ONLY|END_COMPATIBLE_PROPERTY_ONLY)’,
r’\1′,#group援用
policy_str,
flags=re.M)#该办法是将#开头的注释行恣意空格后跟着BEGIN_TREBLE_ONLY、END_TREBLE_ONLY、BEGIN_COMPATIBLE_PROPERTY_ONLY和END_COMPATIBLE_PROPERTY_ONLY时,交换为这些关键字,即去掉注释
#removecomments
remaining=re.sub(r’#.+?$’,r”,remaining,flags=re.M)#将文件中的#开头注释行去掉
#matchneverallowrules
lines=re.findall(
r’^\s*(neverallow\s.+?;|BEGIN_TREBLE_ONLY|END_TREBLE_ONLY|BEGIN_COMPATIBLE_PROPERTY_ONLY|END_COMPATIBLE_PROPERTY_ONLY)’,
remaining,
flags=re.M|re.S)#将neverallow和以这几个关键字开头的行取出来
#extractneverallowrulesfromtheremaininglines
#这些关键字会修饰里面的neverallowrules,若treble_only_depth>1阐明是适用于treble系统,若compatible_property_only_depth>1,阐明适用于compatible_property系统
rules=list()
treble_only_depth=0
compatible_property_only_depth=0
forlineinlines:
ifline.startswith(“BEGIN_TREBLE_ONLY”):
treble_only_depth+=1
continue
elifline.startswith(“END_TREBLE_ONLY”):
iftreble_only_depth<1:
exit(“ERROR:END_TREBLE_ONLYoutsideofTREBLE_ONLYsection”)
treble_only_depth-=1
continue
elifline.startswith(“BEGIN_COMPATIBLE_PROPERTY_ONLY”):
compatible_property_only_depth+=1
continue
elifline.startswith(“END_COMPATIBLE_PROPERTY_ONLY”):
ifcompatible_property_only_depth<1:
exit(“ERROR:END_COMPATIBLE_PROPERTY_ONLYoutsideofCOMPATIBLE_PROPERTY_ONLYsection”)
compatible_property_only_depth-=1
continue
rule=NeverallowRule(line)
rule.treble_only=(treble_only_depth>0)
rule.compatible_property_only=(compatible_property_only_depth>0)
rules.append(rule)
iftreble_only_depth!=0:
exit(“ERROR:endofinputwhileinsideTREBLE_ONLYsection”)
ifcompatible_property_only_depth!=0:
exit(“ERROR:endofinputwhileinsideCOMPATIBLE_PROPERTY_ONLYsection”)
returnrules
#neverallow_rule_to_test-takesaneverallowstatementandtransformsitinto
#theoutputnecessarytoformactsunittestinajavasourcefile.
#returns:astringrepresentingagenerictestmethodbasedonthisrule.
#将neverallowrules交换到java模版中
defneverallow_rule_to_test(rule,test_num):
squashed_neverallow=rule.statement.replace(“\n”,””)
method=SELinuxNeverallowTestFrame.src_method
method=method.replace(“testNeverallowRules()”,
“testNeverallowRules”+str(test_num)+”()”)
method=method.replace(“$NEVERALLOW_RULE_HERE$”,squashed_neverallow)
method=method.replace(
“$FULL_TREBLE_ONLY_BOOL_HERE$”,
“true”ifrule.treble_onlyelse”false”)
method=method.replace(
“$COMPATIBLE_PROPERTY_ONLY_BOOL_HERE$”,
“true”ifrule.compatible_property_onlyelse”false”)
returnmethod
总结下脚本功用
将BEGIN_TREBLE_ONLY|END_TREBLE_ONLY|BEGIN_COMPATIBLE_PROPERTY_ONLY|
END_COMPATIBLE_PROPERTY_ONLY这几个关键字前面的注释去掉,以便后面解析时运用;
删除冗余的注释行;
取neverallow和上面四个关键字的局部停止解析,并依据下面状况对treble_only和compatible_property_only停止设置;
neverallow包含在BEGIN_TREBLE_ONLY和END_TREBLE_ONLY之间,treble_only被设置为true;
neverallow包含在BEGIN_COMPATIBLE_PROPERTY_ONLY和END_COMPATIBLE_PROPERTY_ONLY之间,compatible_property_only被设置为true;
neverallow不在任何BEGIN_TREBLE_ONLY/END_TREBLE_ONLY和BEGIN_COMPATIBLE_PROPERTY_ONLY/END_COMPATIBLE_PROPERTY_ONLY之间,则treble_only和compatible_property_only都被设置为false。
然后用neverallow局部、treble_only和compatible_property_only值对下面办法模板中的$NEVERALLOW_RULE_HERE$、$FULL_TREBLE_ONLY_BOOL_HERE$和$COMPATIBLE_PROPERTY_ONLY_BOOL_HERE$分别交换。
src_method=”””
@RestrictedBuildTest
publicvoidtestNeverallowRules()throwsException{
StringneverallowRule=”$NEVERALLOW_RULE_HERE$”;
booleanfullTrebleOnly=$FULL_TREBLE_ONLY_BOOL_HERE$;
booleancompatiblePropertyOnly=$COMPATIBLE_PROPERTY_ONLY_BOOL_HERE$;
if((fullTrebleOnly)&&(!isFullTrebleDevice())){
//ThistestappliesonlytoTrebledevicesbutthisdeviceisn’tone
return;
}
if((compatiblePropertyOnly)&&(!isCompatiblePropertyEnforcedDevice())){
//Thistestappliesonlytodevicesonwhichcompatiblepropertyisenforcedbutthis
//deviceisn’tone
return;
}
//Ifsepolicyissplitandvendorsepolicyversionisbehindplatform’s,
//onlytestagainstplatformpolicy.
FilepolicyFile=
(isSepolicySplit()&&mVendorSepolicyVersion<P_SEPOLICY_VERSION)?
deviceSystemPolicyFile:
devicePolicyFile;
/*runsepolicy-analyzeneverallowcheckonpolicyfileusinggivenneverallowrules*/
ProcessBuilderpb=newProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
policyFile.getAbsolutePath(),”neverallow”,”-w”,”-n”,
neverallowRule);
pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
pb.redirectErrorStream(true);
Processp=pb.start();
p.waitFor();
BufferedReaderresult=newBufferedReader(newInputStreamReader(p.getInputStream()));
Stringline;
StringBuildererrorString=newStringBuilder();
while((line=result.readLine())!=null){
errorString.append(line);
errorString.append(“\\n”);
}
assertTrue(“ThefollowingerrorswereencounteredwhenvalidatingtheSELinux”
+”neverallowrule:\\n”+neverallowRule+”\\n”+errorString,
errorString.length()==0);
}
本地生成SELinuxNeverallowRulesTest.java文件
在修正SELinux后,想肯定下能否满足neverallow规则,固然编译过程中会停止neverallow检查,但由于打包时间比拟耗时,假如在本地生成的话,那速度会更快。
本地生成SELinuxNeverallowRulesTest.java命令
默许是在源码的根目录
makegeneral_sepolicy.conf
cts/tools/selinux/SELinuxNeverallowTestGen.pyout/target/product/cepheus/obj/ETC/general_sepolicy.conf_intermediates/general_sepolicy.confSELinuxNeverallowRulesTest.java
由于某些规则是运用attribute,可能不是很明显,还需求分离其他办法来肯定。
总结
从生成代码中能够看到,neverallow规则都属于AOSPsystem/sepolicy/private和system/sepolicy/public中的neverallow,所以在添加规则时不能修正neverallow,也不能违犯。
附件
cts_neverallow.zip,中包含有:
SELinuxNeverallowTestGen.py脚本
general_sepolicy.conf
SELinuxNeverallowTestFrame.pyJava测试代码模板
first为SELinuxNeverallowTestGen.py第一步执行的结果
second为SELinuxNeverallowTestGen.py第二步执行的结果
SELinuxNeverallowRulesTest.java为生成的文件
后面三个文件是前三个文件所生成,执行命令为:
SELinuxNeverallowTestGen.pygeneral_sepolicy.confSELinuxNeverallowRulesTest.java

未经允许不得转载:IT技术网站 » Android CTS中neverallow规则生成过程
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载