zoukankan      html  css  js  c++  java
  • Android/SELinux 添加 AVC 权限

    Android/SELinux 添加 AVC 权限

    背景

    在Android应用层中编写c/c++应用时,发现接口调用出现问题,logcat才知道是因为:权限不够。

    type=1400 audit(0.0:4): avc: denied { create } for scontext=u:r:bootanim:s0 tcontext=u:r:bootanim:s0 tclass=netlink_socket permissive=0
    

    参考:

    介绍

    安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是 Linux 的一个安全子系统。SELinux 主要作用是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。对资源的访问控制分为两类: DAC和MAC

    SELinux工作模式

    SELinux 有三种工作模式,分别为:

    • enforcing: 强制模式, 执行SELinux规则, 违反的行为会被阻止
    • permissive: 宽容模式, 执行SELinux规则, 违反的行不会被阻止
    • disabled: 关闭SELinux

    avc denied

    在Android系统开发中, 可能会遇到SELinux的权限不足而引起的各种问题;可以尝试将SELinux工作模式临时改为宽容模式看问题是否解决, 来判定是否是SELinux引起的问题

    标志性 log: avc: denied { 操作权限 } for pid=7201 comm=“进程名” scontext=u:r:源类型:s0 tcontext=u:r:目标类型:s0 tclass=访问类型 permissive=0

    • 源类型:授予访问的类型,通常是进程的域类型
    • 目标类型:客体的类型,它被授权可以访问的类型
    • 访问类型
    • 操作权限:表示主体对客体访问时允许的操作类型(也叫做访问向量)。

    举例

    打开三方apk出问题,其中错误log如下:

    03-28 10:18:07.990 11883 11883 W re-initialized>: type=1400 audit(0.0:2918): 
    avc: denied { read } for name="u:object_r:mtk_amslog_prop:s0" 
    dev="tmpfs" ino=7544 scontext=u:r:system_app:s0 
    tcontext=u:object_r:mtk_amslog_prop:s0 
    tclass=file permissive=0
    

    解释:

    • read:表示没有 read 权限
    • system_app:system_app 中缺少权限
    • mtk_amslog_prop:mtk_amslog_prop 文件系统缺少权限
    • file:file 类型的文件
    • 分析:adb shell setenforce 0。设置SELinux 成为permissive模式。若apk可正常使用,则进行规避此权限问题

    修改selinux规则

    type=1400 audit(0.0:4): avc: denied { create } for 
    scontext=u:r:bootanim:s0 
    tcontext=u:r:bootanim:s0 
    tclass=netlink_socket 
    permissive=0
    
    type=1400 audit(0.0:41): avc: denied { read } for 
    name="u:object_r:media_prop:s0" 
    dev="tmpfs" ino=11511 
    scontext=u:r:mediacodec:s0 
    tcontext=u:object_r:media_prop:s0 
    tclass=file 
    permissive=0
    
    节点 寻找点 结果
    缺少的权限 denied { 权限 } create
    谁(哪个进程)缺少权限 scontext=u:r:进程:s0 bootanim
    对哪个节点缺少权限 tcontext=u:r:节点:s0 bootanimself
    缺少要访问的对象 tclass=被访问对象 netlink_socket

    技巧:

    • 如果tcontext中的节点与scontext中的进程名相同,则可以写成self
    • 因为有时候avc denied 的log不是一次性显示所有问题,要等解决一个权限问题后,才会显示另外一个权限问题,比如显示缺失某个目录的read权限。所以建议是先参考其他可能出现访问权限的问题的有关接口关键字,进行多次添加。
    • 要加入的权限很多时,可以用中括号,比如:allow untrusted_app vfat:dir { search write }

    由于,scontext对应的是我们要修改的文件(这里是bootanim),根据type=1400 audit(0.0:4): avc: denied { create } for scontext=u:r:bootanim:s0 tcontext=u:r:bootanim:s0 tclass=netlink_socket permissive=0的提示;因此,需要在bootanim.te最后面中添加所对应的权限是:

    # file : bootanim.te
    allow bootanim self:netlink_socket {create};
    

    再看一个例子:

    # type=1400 audit(0.0:41): avc: denied { read } for 
    # name="u:object_r:media_prop:s0" 
    # dev="tmpfs" ino=11511 
    # scontext=u:r:mediacodec:s0 
    # tcontext=u:object_r:media_prop:s0 
    # tclass=file permissive=0
    
    # file: mediacodec.te
    allow mediacodec media_prop:file {read}
    

    修改系统selinux模式

    临时修改

    adb shell setenforce 0 #设置SELinux 成为permissive模式
    adb shell setenforce 1 #设置SELinux 成为enforcing模式
    adb shell getenforce #获取SELinux状态(permissive,enforcing,disabled)
    

    永久修改

    安卓7

    路径:system/core/init/init.cpp

    static selinux_enforcing_status selinux_status_from_cmdline() {
        selinux_enforcing_status status = SELINUX_ENFORCING;   // 强制模式, 执行SELinux规则, 违反的行为会被阻止
        //selinux_enforcing_status status = SELINUX_PERMISSIVE;// 宽容模式, 执行SELinux规则, 违反的行不会被阻止
        import_kernel_cmdline(false, [&](const std::string& key, const std::string& value, bool in_qemu) {
            if (key == "androidboot.selinux" && value == "permissive") {
                status = SELINUX_PERMISSIVE;
            }
        });
    
        return status;
    }
    

    安卓9/10

    路径:system/core/init/selinux.cpp

    EnforcingStatus StatusFromCmdline() {
        // EnforcingStatus status = SELINUX_ENFORCING;// 强制模式, 执行SELinux规则, 违反的行为会被阻止
        EnforcingStatus status = SELINUX_PERMISSIVE;  // 宽容模式, 执行SELinux规则, 违反的行不会被阻止
        import_kernel_cmdline(false,
                              [&](const std::string& key, const std::string& value, bool in_qemu) {
                                  if (key == "androidboot.selinux" && value == "permissive") {
                                      status = SELINUX_PERMISSIVE;
                                  }
                              });
    
        return status;
    }
    

    附录A:在permissive模式下,有些app仍然无法访问具体节点

    敏感权限的特征:log中带有c512,c768字样

    试着在untrusted_app.te 中添加了allow untrusted_app audio_device:chr_file { open write read };还是报如下权限错误:

    [ 141.935275] type=1400 audit(1546939304.786:43): avc: denied { write } for 
    pid=1836 comm="Thread-4"
    name="pcmC0D1c"
    dev="tmpfs"
    ino=11947
    scontext=u:r:untrusted_app:s0:c512,c768
    tcontext=u:object_r:audio_device:s0
    tclass=chr_file
    permissive=1
    

    先确认需要访问的节点是否为audio_device,这个节点属于敏感权限,可以的话请修改访问的目录和文件,缩小audio_device的范围

    方法为:

    1、确定访问的节点位置,通过源码或者log确定到底访问的哪一个具体的节点, 例如 /dev/pcmc00xx

    2、在相应的te文件中新声明一个节点名称, 如 file.te: type test_audio_device, dev_type;

    3、在file_context中将具体节点绑定新的节点名称, 如: file_context: /dev/pcmc00xx test_audio_device

    4、增加或修改需要的权限: allow untrusted_app test_audio_device:chr_file { open write read };

    如果不过GMS认证,敏感权限(c512,c768)可以直接把对象关联mlstrustedobject, 但不推荐这样修改,会造成严重的安全问题。 例如: typeattribute audio_device mlstrustedobject;

    附录B:DAC和MAC有什么区别?

    DAC

    DAC(Discretionary Access Control,自主访问控制)

    • DAC是传统的Linux的访问控制方式,DAC可以对文件、文件夹、共享资源等进行访问控制。
    • 在DAC这种模型中,文件客体的所有者(或者管理员)负责管理访问控制。
    • DAC使用了ACL(Access Control List,访问控制列表)来给非管理者用户提供不同的权限,而root用户对文件系统有完全自由的控制权。

    MAC

    MAC(Mandatory Access Control,强制访问控制)

    • SELinux在内核中使用MAC检查操作是否允许。
    • 在MAC这种模型中,系统管理员管理负责访问控制,用户不能直接改变强制访问控制属性。
    • MAC可以定义所有的进程(称为主体)对系统的其他部分(文件、设备、socket、端口和其它进程等,称为客体)进行操作的权限或许可。

    DAC和MAC的其它区别

    ① DAC的主体是真实有效的用户和组ID,MAC的主体是安全上下文,两者的UID是各自独立的。

    ② DAC的访问控制模式是rwxrwxrwx,MAC的访问控制模式是user:role:type。

    附录C:高通平台修改selinux权限路径

    Android 7 :device/qcom/sepolicy/common/

    Android 9:其中的某一个

    • device/qcom/sepolicy/vendor/common/
    • device/sprd/sharkl3/common/sepolicy/

    Android 10:其中的某一个

    • device/qcom/sepolicy/vendor/common/
    • device/qcom/sepolicy/legacy/vendor/common/
    • device/sprd/sharkl3/common/sepolicy/
    如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。
    若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
    博客地址:https://www.cnblogs.com/schips/
  • 相关阅读:
    commons-logging.jar 和 log4j.jar 的关系
    百钱买百鸡
    reflect
    golang结构体、接口、反射
    golang文件操作
    sqlx使用说明
    go example
    goroutine
    生成二维码
    method&interface
  • 原文地址:https://www.cnblogs.com/schips/p/android-selinux_about_avc.html
Copyright © 2011-2022 走看看