需求背景

之前介绍了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访问SystemProperty遇到的一些坑

第三方app中读写自界说property

由于SystemProperties类是系统私有类

第三方App访问SystemProperty遇到的一些坑

第三方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过错

第三方App访问SystemProperty遇到的一些坑

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抵触问题

第三方App访问SystemProperty遇到的一些坑

不止这一个,还有许多其他的neverallow抵触问题,但终究都是根据报错信息,免除neverallow约束

第三方App访问SystemProperty遇到的一些坑

第三方App访问SystemProperty遇到的一些坑

免除约束后,依然报上述过错

第三方App访问SystemProperty遇到的一些坑

查询材料得知或许跟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规矩抵触了

第三方App访问SystemProperty遇到的一些坑

正常报错如下:

第三方App访问SystemProperty遇到的一些坑

这个当地也琢磨了好几天,查阅了许多材料,并无收获。后经过逐渐排查,跟untrusted_app、untrusted_app_all、untrusted_app_25、all_untrusted_apps这几个界说的区别有关,这几个界说不能随便运用,应该根据当时module中的界说来,尤其是untrusted_app_all和all_untrusted_apps。实际应用当中能够根据当时te文件里边来,当时te文件用的啥,咱们就用啥,如果当时te文件没有用到,能够查找当时module是怎么界说的

第三方App访问SystemProperty遇到的一些坑

第三方App访问SystemProperty遇到的一些坑

也能够两个都试一下,如果运用不对编译会报错

第三方App访问SystemProperty遇到的一些坑

修正为正确的界说后依然报上述过错,崩溃中……

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能够读写第三方属性了

第三方App访问SystemProperty遇到的一些坑

总结

写完这个工具,现在对selinux有了愈加深入的了解了,今后再遇到权限相关的问题,那不是手拿把掐。