Android获root权限后仍无法访问/dev/smd7设备文件的问题咨询
问题描述
设备已完成root,应用也获取了root权限,但尝试读写/dev/smd7这类特殊设备文件时始终提示Permission denied。无论是用Flutter还是原生Java代码实现,都会触发权限错误,但在拥有root权限的终端中,使用cat或echo命令却能正常操作该文件。
Flutter代码及报错日志
代码:
bool rootStatus = await RootAccess.requestRootAccess; File file = File('/dev/smd7'); String text = await file.readAsString();
日志:
W/DartWorker( 3970): type=1400 audit(0.0:257920): avc: denied { getattr } for path="/dev/smd7" dev="tmpfs" ino=12484 scontext=u:r:untrusted_app:s0:c57,c257,c512,c768 tcontext=u:object_r:vendor_smd7_device:s0 tclass=chr_file permissive=0 app=app.ussd.ussd E/flutter ( 3970): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FileSystemException: Cannot open file, path = '/dev/smd7' (OS Error: Permission denied, errno = 13) E/flutter ( 3970): #0 _File.open.<anonymous closure> (dart:io/file_impl.dart:356:9) E/flutter ( 3970): #1 _rootRunUnary (dart:async/zone.dart:1434:47) E/flutter ( 3970): #2 _CustomZone.runUnary (dart:async/zone.dart:1335:19) E/flutter ( 3970): <asynchronous suspension> E/flutter ( 3970): #3 _MyAppState.build.<anonymous closure> (package:ussd/main.dart:71:35) E/flutter ( 3970): <asynchronous suspension> E/flutter ( 3970):
原生Java代码及报错日志
代码:
public void onClick(View view) { File file = new File("/dev/smd7"); try { mSerR = new FileInputStream(file); mSerW = new FileOutputStream(file); } catch (FileNotFoundException e) { Log.d("Error", "onClick: " + e.getLocalizedMessage()); } }
日志:
W/mple.myussdtest: type=1400 audit(0.0:272431): avc: denied { read } for name="smd7" dev="tmpfs" ino=12484 scontext=u:r:untrusted_app:s0:c61,c257,c512,c768 tcontext=u:object_r:vendor_smd7_device:s0 tclass=chr_file permissive=0 app=com.example.myussdtest D/Error: onClick: /dev/smd7: open failed: EACCES (Permission denied)
解决思路
从日志中的avc: denied可以明确,这是SELinux权限限制导致的问题,而非普通root权限不足。以下是几种可行的解决方法:
方案1:通过root执行Shell命令间接操作文件
既然终端中root权限能正常使用cat/echo操作文件,那么可以绕过直接读写文件的方式,通过root权限执行Shell命令完成读写:
Flutter示例代码:// 读取/dev/smd7内容 var readResult = await Process.run('su', ['-c', 'cat /dev/smd7']); String fileContent = readResult.stdout.toString().trim(); // 写入AT命令到/dev/smd7(比如发送AT+CSQ) String atCommand = 'AT+CSQ\r'; await Process.run('su', ['-c', 'echo -e "$atCommand" > /dev/smd7']);原生Java可通过
Runtime.getRuntime().exec()执行su命令,注意处理命令的输入输出流。方案2:临时关闭SELinux(仅适合测试)
执行su -c setenforce 0临时关闭SELinux强制模式,之后应用即可直接读写文件。但该操作会降低系统安全性,且设备重启后SELinux会恢复默认状态。方案3:添加SELinux权限规则(长期解决方案)
若需要长期解决,需为应用的SELinux域添加访问vendor_smd7_device类型文件的权限:- 编写SELinux规则文件(如
my_app.te):allow untrusted_app vendor_smd7_device:chr_file { getattr read write open }; - 将规则编译为policy文件,推送至设备的
/system/etc/selinux/或对应vendor目录,再加载生效。
该方法需要了解SELinux基本原理,部分设备可能需要解锁system分区才能修改。
- 编写SELinux规则文件(如
方案4:修改设备文件权限(简单但重启失效)
执行su -c chmod 666 /dev/smd7,赋予所有用户读写该文件的权限。但设备重启后,文件权限会恢复默认,需添加开机自启脚本维持权限。
内容的提问来源于stack exchange,提问作者TheSquad
相关产品推荐
相关产品推荐

