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

需求背景

之前介绍了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

adb shell中读写property

第三方app中读写自定义property

因为SystemProperties类是系统私有类

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错误

app读写报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冲突问题,但最终都是根据报错信息,解除neverallow限制

解决neverallow冲突问题

解决neverallow冲突问题2

解除限制后,仍然报上述错误

app读写报avc错误

查询资料得知可能跟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规则冲突了

neverallow冲突待解决

正常报错如下:

image-20230605164826273

这个地方也琢磨了好几天,查阅了许多资料,并无收获。后经过逐步排查,跟untrusted_app、untrusted_app_all、untrusted_app_25、all_untrusted_apps这几个定义的区别有关,这几个定义不能随便使用,应该根据当前module中的定义来,尤其是untrusted_app_all和all_untrusted_apps。实际应用当中可以根据当前te文件里面来,当前te文件用的啥,我们就用啥,如果当前te文件没有用到,可以搜索当前module是如何定义的

image-20230605165621943

image-20230605165829026

也可以两个都试一下,如果使用不对编译会报错

neverallow_编译报错

修改为正确的定义后仍然报上述错误,崩溃中……

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

image-20230607150053278

总结

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYBPmLQJ' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片