需求背景
之前介绍了App拜访驱动节点所需求处理的权限问题,但仅仅针对某个项目,如果换一个项目,App和framework里边的节点途径都需求修正。现在需求优化一下,界说一个SystemProperty
,将节点的值存放到该Property里边,第三方app直接读写这个Property,这样换项目之后,只需求修正framework的节点途径即可,app的源码不需求修正。
界说SystemProperty
在device/qcom/msmnile_gvmq/system.prop
中新增一个属性
#usb mode
persist.vendor.usb.mode=none
persist.vendor.usb
已经在device/qcom/sepolicy_vndr/generic/vendor/common/property_contexts
中界说了域空间名为vendor_usb_prop
persist.vendor.usb. u:object_r:vendor_usb_prop:s0
ro.vendor.usb. u:object_r:vendor_usb_prop:s0
vendor_usb_prop
文件类型的界说device/qcom/sepolicy_vndr/legacy/vendor/common/property.te
type vendor_usb_prop, property_type;
adb shell中读写自界说property
第三方app中读写自界说property
由于SystemProperties类是系统私有类
第三方app无法直接拜访此类中的方法,可是咱们能够通过反射间接拜访
public class SysProp {
private static Method sysPropGet;
private static Method sysPropSet;
private SysProp() {
}
static {
try {
Class<?> S = Class.forName("android.os.SystemProperties");
Method M[] = S.getMethods();
for (Method m : M) {
String n = m.getName();
if (n.equals("get")) {
sysPropGet = m;
} else if (n.equals("set")) {
sysPropSet = m;
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static String get(String name, String default_value) {
try {
return (String) sysPropGet.invoke(null, name, default_value);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return default_value;
}
public static void set(String name, String value) {
try {
sysPropSet.invoke(null, name, value);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
但此时会报avc过错
在device/qcom/sepolicy_vndr/qva/vendor/common/untrusted_app.te
中增加权限
allow untrusted_app property_socket:sock_file write;
allow untrusted_app vendor_usb_prop:file read;
编译报错
编译报neverallow抵触问题
不止这一个,还有许多其他的neverallow抵触问题,但终究都是根据报错信息,免除neverallow约束
免除约束后,依然报上述过错
查询材料得知或许跟MLS权限判断有关
mlsconstrain dir { read getattr search }
(t2 == app_data_file or t2 == privapp_data_file or l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);
mlsconstrain { file lnk_file sock_file chr_file blk_file } { read getattr execute }
(t2 == app_data_file or t2 == privapp_data_file or t2 == appdomain_tmpfs or l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);
所以给vendor_usb_prop
的界说加上mlstrustedobject
类型
type vendor_usb_prop, property_type, mlstrustedobject;
但依然报上述过错。后讨教搭档得知,device/qcom/sepolicy_vndr/qva/vendor/common/untrusted_app.te
底子没有编译到,我在此文件中随便修正后编译不报错,不仅如此,device/qcom/sepolicy_vndr/qva/vendor/common/
和device/qcom/sepolicy_vndr/legacy/vendor/common/
途径下的te文件均没有被编译,就这个当地被坑了一个星期。
从头在device/qcom/sepolicy_vndr/generic/vendor/common/untrusted_app_25.te
中增加权限,编译收效,但依然存在nerverallow抵触的问题,但没有具体说明跟哪条neverallow规矩抵触了
正常报错如下:
这个当地也琢磨了好几天,查阅了许多材料,并无收获。后经过逐渐排查,跟untrusted_app、untrusted_app_all、untrusted_app_25、all_untrusted_apps这几个界说的区别有关,这几个界说不能随便运用,应该根据当时module中的界说来,尤其是untrusted_app_all和all_untrusted_apps。实际应用当中能够根据当时te文件里边来,当时te文件用的啥,咱们就用啥,如果当时te文件没有用到,能够查找当时module是怎么界说的
也能够两个都试一下,如果运用不对编译会报错
修正为正确的界说后依然报上述过错,崩溃中……
selinux宏函数
静下心来,仔细思考问题原因,既然唯一声明vendor_usb_prop
类型的te文件没有被编译到,那vendor_usb_prop
到底在哪里声明类型的呢,再次全局查找vendor_usb_prop
,在device/qcom/sepolicy_vndr/generic/vendor/common/property.te
中搜到了如下装备
vendor_internal_prop(vendor_usb_prop);
去研究了一下这种写法的意义,这是selinux的宏函数,表示一组selinux语法的组合,运用m4言语来写的,所以编译AOSP需求安装m4环境
sudo apt-get install m4
回到上面,vendor_internal_prop()
函数的界说为
define(`vendor_internal_prop', `
define_prop($1, vendor, internal)
treble_sysprop_neverallow(`
# init and dumpstate are in coredomain, but should be able to read all props.
neverallow { coredomain -init -dumpstate } $1:file no_rw_file_perms;
')
')
里边又引用了define_prop()
函数,其界说为
define(`define_prop', `
type $1, property_type, $2_property_type, $2_$3_property_type;
')
能够看到,vendor_usb_prop
其实是在vendor_internal_prop(vendor_usb_prop)
里边声明类型的,并且里边还声明了neverallow,之所以没有报具体抵触的代码行号,是由于neverallow界说在了宏函数里边,那么现在在宏函数里边除掉untrusted_app的约束,即加上-untrusted_app_all
define(`vendor_internal_prop', `
define_prop($1, vendor, internal)
treble_sysprop_neverallow(`
# init and dumpstate are in coredomain, but should be able to read all props.
# 除掉untrusted_app约束
neverallow { coredomain -init -dumpstate -untrusted_app_all } $1:file no_rw_file_perms;
')
')
然后在device/qcom/sepolicy_vndr/generic/vendor/common/untrusted_app_25.te
中增加该有权限装备
allow untrusted_app property_socket:sock_file write;
allow untrusted_app init:unix_stream_socket connectto;
allow untrusted_app vendor_usb_prop:file { map read write open getattr };
allow untrusted_app vendor_usb_prop:property_service set;
一个一个试,缺啥补啥,终究第三方app能够读写第三方属性了
总结
写完这个工具,现在对selinux有了愈加深入的了解了,今后再遇到权限相关的问题,那不是手拿把掐。