美文网首页
【Android笔记】Android应用层读取驱动设备节点

【Android笔记】Android应用层读取驱动设备节点

作者: 宇辰妈咪 | 来源:发表于2020-04-29 15:06 被阅读0次

        Android应用层读取驱动层设备节点在Android应用中使用广泛,设备节点文件是设备驱动的逻辑文件,可以通过设备节点来访问设备驱动。

    很多设备信息都可存储在节点中。apk可以访问节点,获取设备信息或状态。

    对于读写设别节点,需要root权限和selinux权限,在开发中,我们经常会遇到由于SELinux造成的各种权限不足,即使拥有“万能的root权限”,也不能获取全部的权限。本文旨在结合具体案例,讲解如何根据log来快速解决90%的SELinux权限问题。要在系统的SELinux相关te文件中加入权限。先来看看应用层读取节点的方法:

    private void readdata() {

    try {       

    FileInputStream fp_read = new FileInputStream("/sys/devices/soc/soc:usb_switch/function_otg_en");   

    byte[] mbyte = new byte[4]; 

      fp_read.read(mbyte);   

    otg_enabled = new String(mbyte);

           } catch (Exception e) {   

          e.printStackTrace();}  }


    添加对应节点的权限,需要在目录android\device\qcom\sepolicy\vendor\common下修改几个相关的文件。

    system_app.te

    file.te

    file_contexts

    init.te

    platform_app.te

    system_server.te

    ,比如针对上面的设备节点"/sys/devices/soc/soc:usb_switch/function_otg_en"

    1.在file_contexts文件中添加(普通的节点和虚拟节点都需要添加)

    /sys/class/Usb_switch/usbswitch/function_otg_en u:object_r:sysfs_function_otg:s0

    /sys/devices/soc/soc:usb_switch/function_otg_en  u:object_r:sysfs_function_otg:s0

    2. init.target.rc(device/qcom/sdm660_64)文件中添加以下777权限:

    chmod 777/sys/class/Usb_switch/usbswitch/function_otg_en

    chmod 777/sys/devices/soc/soc:usb_switch/function_otg_en

    3.file.te中添加以下代码:

    type sysfs_function_otg, fs_type, sysfs_type;

    4.system_app.te中添加以下代码:

    allow system_app sysfs_function_otg:file rw_file_perms;

    5.system_server.te中添加以下代码:

    allow system_serversysfs_function_otg:file rw_file_perms;

    然后全编,编译,运行,如果还是提示permision denied,要根据log中的type 1400定位问题分析缺少的权限

    05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:13): avc: denied { read } for comm="medoctorstation" name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:13): avc: denied { read } for name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:14): avc: denied { write } for comm="medoctorstation" name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:14): avc: denied { write } for name="ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:15): avc: denied { open } for comm="medoctorstation" path="/dev/ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:15): avc: denied { open } for path="/dev/ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I auditd : type=1400 audit(0.0:16): avc: denied { ioctl } for comm="medoctorstation" path="/dev/ttyS0" dev="tmpfs" ino=8685 ioctlcmd=5401 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.040 1546 1546 I medoctorstation: type=1400 audit(0.0:16): avc: denied { ioctl } for path="/dev/ttyS0" dev="tmpfs" ino=8685 ioctlcmd=5401 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 05-20 09:25:11.060 1546 1546 I auditd : type=1400 audit(0.0:17): avc: denied { getattr } for comm="medoctorstation" path="/dev/ttyS0" dev="tmpfs" ino=8685 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:serial_device:s0 tclass=chr_file permissive=1 


    6.调试确认SELinux问题

    为了澄清是否因为SELinux导致的问题,可先执行:

    setenforce 0 (临时禁用掉SELinux)

    getenforce  (得到结果为Permissive)

    进入到设备节点目录执行 chmod 777 function_otg_en。

    如果问题消失了,基本可以确认是SELinux造成的权限问题,需要通过正规的方式来解决权限问题。

    遇到权限问题,在logcat或者kernel的log中一定会打印avc denied提示缺少什么权限,可以通过命令过滤出所有的avc denied,再根据这些log各个击破:

    cat /proc/kmsg | grep avc 

    dmesg | grep avc

    例如:

    audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0

    可以看到有avc denied,且最后有permissive=0,表示不允许。

    同时需要注意增加权限的时候虚拟设备节点也要增加相应的权限,获取虚拟节点的方法可以采用adb命令进行查找:

    adb shell find / -name "*userdata*",

    比如"/sys/devices/platform/soc/soc:usb_switch/gpio_pogo_det" 这个就换成adb shell find / -name "*gpio_pogo_det*".

    7.案例分析

    解决原则是:缺什么权限补什么,一步一步补到没有avc denied为止。

    解决权限问题需要修改的权限文件如下位置,以.te结尾

    A:Android/devicesoftwinner/astar-common/sepolicy/*.te

    B:Android/external/sepolicy/*.te

    其中,A是对B的overlay(覆盖),能在A修改的尽量在A修改,尽量避免修改B,修改B可能会导致CTS fail问题,修改A不会影响CTS测试。

    (如果不需要深入了解,请直接跳到万能公式这一章阅读更简洁)

    下面给出四个案例:

    案例1

    audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=/1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0

    分析过程:

    缺少什么权限:      { write }权限,

    谁缺少权限:        scontext=u:r:kernel:s0

    对哪个文件缺少权限:tcontext=u:object_r:block_device

    什么类型的文件:    tclass=blk_file

    完整的意思: kernel进程对block_device类型的blk_file缺少write权限。

    解决方法:在上文A位置,找到kernel.te这个文件,加入以下内容:

    allow  kernel  block_device:blk_file  write;

    相关文章

      网友评论

          本文标题:【Android笔记】Android应用层读取驱动设备节点

          本文链接:https://www.haomeiwen.com/subject/ftwgwhtx.html