Android APP 读写设备节点
自己在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 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 *;
')
评论