Android APP 读写设备节点

sancaiodm Android应用 2022-05-26 1968 0

   自己在PC DOS窗口中通过adb shell操作:

    echo 255 >/sys/class/leds/backlight/brightness 或是 

    echo 0 > /sys/class/leds/backlight/brightness 都可以正常写值到指定节点内,

  但想以java 代码执行writeFile修改andoid系统内部 sys/ 与proc/ 两个目录内任意一节点值时,就报如下错误:

05-24 13:22:37.606  3137  3137 W ens.factorytest: type=1400 audit(0.0:287): avc: denied { search } for name="leds" dev="sysfs" ino=16422 scontext=u:r:system_app:s0 tcontext=u:object_r:sysfs_leds:s0 tclass=dir permissive=0
05-24 13:22:37.616  3137  3137 W System.err: java.io.FileNotFoundException: /sys/class/leds/backlight/brightness: open failed: EACCES (Permission denied)
05-24 13:22:37.616  3137  3137 W System.err: 	at libcore.io.IoBridge.open(IoBridge.java:575)
05-24 13:22:37.617  3137  3137 W System.err: 	at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
05-24 13:22:37.617  3137  3137 W System.err: 	at java.io.FileOutputStream.<init>(FileOutputStream.java:125)
05-24 13:22:37.617  3137  3137 W System.err: 	at com.baidu.factorytest.utils.FileUtil.writeFile(FileUtil.java:225)
05-24 13:22:37.617  3137  3137 W System.err: 	at com.baidu.factorytest.mmi.testcases.KeypadBacklightTest.onClick(KeypadBacklightTest.java:73)
05-24 13:22:37.617  3137  3137 W System.err: 	at android.view.View.performClick(View.java:7447)
05-24 13:22:37.617  3137  3137 W System.err: 	at android.view.View.performClickInternal(View.java:7420)
05-24 13:22:37.617  3137  3137 W System.err: 	at android.view.View.access$3700(View.java:837)
05-24 13:22:37.617  3137  3137 W System.err: 	at android.view.View$PerformClick.run(View.java:28867)
05-24 13:22:37.617  3137  3137 W System.err: 	at android.os.Handler.handleCallback(Handler.java:938)
05-24 13:22:37.617  3137  3137 W System.err: 	at android.os.Handler.dispatchMessage(Handler.java:99)
05-24 13:22:37.618  3137  3137 W System.err: 	at android.os.Looper.loopOnce(Looper.java:201)
05-24 13:22:37.618  3137  3137 W System.err: 	at android.os.Looper.loop(Looper.java:288)
05-24 13:22:37.618  3137  3137 W System.err: 	at android.app.ActivityThread.main(ActivityThread.java:7881)
05-24 13:22:37.618  3137  3137 W System.err: 	at java.lang.reflect.Method.invoke(Native Method)
05-24 13:22:37.618  3137  3137 W System.err: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:568)
05-24 13:22:37.618  3137  3137 W System.err: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1045)
05-24 13:22:37.618  3137  3137 W System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
05-24 13:22:37.618  3137  3137 W System.err: 	at libcore.io.Linux.open(Native Method)
05-24 13:22:37.618  3137  3137 W System.err: 	at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
05-24 13:22:37.619  3137  3137 W System.err: 	at libcore.io.BlockGuardOs.open(BlockGuardOs.java:273)
05-24 13:22:37.619  3137  3137 W System.err: 	at libcore.io.ForwardingOs.open(ForwardingOs.java:567)
05-24 13:22:37.619  3137  3137 W System.err: 	at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7765)
05-24 13:22:37.619  3137  3137 W System.err: 	at libcore.io.IoBridge.open(IoBridge.java:561)
05-24 13:22:37.619  3137  3137 W System.err: 	... 16 more

或是以java代码封装adb shell 命令来修改sys/ 与proc/ 两个目录内节点值 也会报如下错误:

05-24 13:17:55.330  3005  3005 W sh      : type=1400 audit(0.0:222): avc: denied { search } for name="leds" dev="sysfs" ino=16422 scontext=u:r:system_app:s0 tcontext=u:object_r:sysfs_leds:s0 tclass=dir permissive=0

这错误都是因为程序无权限修改sys/ 与proc/目录下节点的值,如本想通过修改/sys/class/leds/backlight/brightness 节点值来控制led灯的开关,但都无任何反应无法写入,且程序也不会报弹窗错误,如不仔细查看logcat完全摸不着头脑,为何无反应。

  使用ls -alZ命令查看目标文件的权限域,可以看到brightness文件的权限域为sysfs, 

androidosnet:/sys/class/leds/backlight $ ls -alZ

total 0

drwxr-xr-x 3 root   root   u:object_r:sysfs_leds:s0     0 2022-06-10 19:08 .

drwxr-xr-x 4 root   root   u:object_r:sysfs_leds:s0     0 2022-06-10 19:08 ..

-rw-r--r-- 1 system system u:object_r:sysfs_leds:s0  4096 2022-06-11 00:37 brightness

lrwxrwxrwx 1 root   root   u:object_r:sysfs:s0          0 2022-06-11 00:36 device -> ../../../leds-mt65xx

-r--r--r-- 1 root   root   u:object_r:sysfs_leds:s0  4096 2022-06-11 00:36 max_brightness

drwxr-xr-x 2 root   root   u:object_r:sysfs_leds:s0     0 2022-06-10 19:08 power

lrwxrwxrwx 1 root   root   u:object_r:sysfs:s0          0 2022-06-11 00:36 subsystem -> ../../../../../class/leds

-rw-r--r-- 1 system system u:object_r:sysfs_leds:s0  4096 2022-06-10 19:08 trigger

-rw-r--r-- 1 root   root   u:object_r:sysfs_leds:s0  4096 2022-06-10 19:08 uevent

  根本原因是 Android L版本开发,google对android启动了SELinux安全访问机制,应用层及FamerWork层在默认情况下都是无权去修改设备节点的,除了添加SELinux权限途径外,也可通过JNI或是hidl来修改设备节点。

   解决方案:

   1 关闭SELinux安全机制:adb root, adb shell setenforce 0, (临时方案)

   2 给你的APP添加 system APP权限,

     【2.1】android:sharedUserId="android.uid.system"

     【2.2】在项目的Android.mk文件中增加: LOCAL_CERTIFICATE := platform  如果是android studio项目则需要在导出APK文件时使用平台 platform.keystore 签名

    并在系统源码的sepolicy目录下的te文件中添加avc权限,

     【2.3】各个平台的需要修改的te文件所在目录均不同,mtk平台下添加权限的te文件在system/sepolicy/目录下,一般需要修改三个文件

-----------------------------博主验证在Android 12平台中并不是修改如下三个文件 --------------------------------------------

     【2.3.1】system_app.te (APP是平台签名的APP且有system权限)或是platform_app.te文件 

     【2.3.2】file.te

     【2.3.3】file_contexts

以下网文按如上修改;

Android LED 工厂模式开发

Android 10 应用层如何操作设备节点/sys/devices

Android SElinux 权限[分析LOG对应添加权限]

--------------------------------------------------------------------------------

untrusted_app 第三方app,没有Android平台签名,没有system权限

platform_app 有android平台签名,没有system权限

system_app 有android平台签名和system权限

从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app < priv_app

C:\Users\androidos> adb shell ps -Z -e |findstr google

u:r:system_app:s0              system         3779       767    15388332 23852 0                   0 S com.google.testa

u:r:qtidiagservices_app:s0     system         3925       767    15426248 24144 0                   0 S com.google.testb

u:r:system_app:s0              system         4146       767    15892200 128384 0                  0 S com.google.testc

u:r:system_app:s0              system         4336       767    15406264 27028 0                   0 S com.google.testd

第一列是SContext,第二列是UID,只要UID是system的基本都是system_app

----------------------------------------------------

以下是博主自己在MTK android 12平台的的修改记录:

【1】根据运行报错 avc: denied { search },添加相应权限,如下我添加了5个权限

mtk/alps/device/mediatek/sepolicy/basic/non_plat/system_app.te

#add by hnlens for led button-backlight

allow system_app sysfs_leds:dir search;

allow system_app sysfs_leds:file write;

allow system_app sysfs_leds:file open;

allow system_app sysfs_leds:file read;

allow system_app sysfs_leds:file getattr;

也可将同类文件属性放在一起如

allow system_app sysfs_leds:file { write  open read getattr };

【2】如果只添加上面的修改,编译时可能导致违反谷歌规定的Neverallow规则而编译报错,所以还需添加下面的修改来忽略规则

    mtk/alps/system/sepolicy/prebuilts/api/31.0/private/coredomain.te

    mtk/alps/system/sepolicy/private/coredomain.te

在该两文件中添加如下代码:

full_treble_only(`

neverallow {

    coredomain


    # for chowning

    -init


    # generic access to sysfs_type

    -ueventd

    -vold

    -appdomain    #忽略APP

} sysfs_leds:file *;

')


Java IO读写Android 设备节点值

评论