平台
RK3566 + Android 11
概述
在之前的SDK(Android 5, 6, 7, 8, 9)中, 增加了服务和系统接口, 方便第三方应用调用. 其中有一些功能, 需要让SYSTEM去访问内部存储的文件.
常用的路径有:
File f = new File("/sdcard"); f = new File("/mnt/sdcard"); f = new File("/storage/emulated/0"); f = Environment.getExternalStorageDirectory();
实际上, 都指向一个位置, 其形态大多类似:
ls -l /sdcard lrw-r--r-- 1 root root 21 2022-02-18 07:12 sdcard -> /storage/self/primary
正题
增加的系统服务, 一般是运行在system_server进程中:
rk3566_r:/ $ ps | grep system_server system 444 255 16878032 429340 0 0 S system_server
要让它能访问SDCARD, 旧的SDK可以参考:
【framework】framework中为systemserver添加权限
在刚拿到的 Android 11 中, 在解决了组权限 及 SELINUX权限后, 发现仍然无法正常访问.
原因
看了一SDCARD 目录, 发现了一堆u0_a120
rk3566_r:/sdcard $ ll total 204 drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Alarms drwxrws--x 5 media_rw media_rw 3452 2022-02-18 07:12 Android drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Audiobooks drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 DCIM drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Documents drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Download drwx------ 3 u0_a120 u0_a120 3452 2022-02-18 07:12 Movies drwx------ 3 u0_a120 u0_a120 3452 2022-02-18 07:12 Music drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Notifications drwx------ 4 u0_a120 u0_a120 3452 2022-02-18 08:35 Pictures drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Podcasts drwx------ 2 u0_a120 u0_a120 3452 2022-02-18 07:12 Ringtones
按旧的版本, 用户和组应该是 sdcard_rw 或 media_rw
如3288 7.1上是:
rk3288:/sdcard $ ll total 35M drwxrwx--x 20 root sdcard_rw 4.0K 2022-02-18 10:52 . drwx--x--x 4 root sdcard_rw 4.0K 2021-12-27 11:40 .. drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Alarms drwxrwx--x 3 root sdcard_rw 4.0K 2021-12-27 11:40 Android drwxrwx--x 2 root sdcard_rw 4.0K 2022-01-18 15:30 CircleDetector drwxrwx--x 4 root sdcard_rw 4.0K 2021-12-30 09:35 DCIM drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Download drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Movies drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Music drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Notifications drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Pictures drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Podcasts drwxrwx--x 2 root sdcard_rw 4.0K 2021-12-27 11:40 Ringtones
关于 u0_a120:
rk3566_r:/sdcard $ ps | grep a120 u0_a120 1263 255 13913292 140492 0 0 S com.android.providers.media.module
源码:
packages/providers/MediaProvider/
在此不对MediaProvider作过多分析
另一个现象, 尝试编译一个测试APP, 进行SDCARD写入操作(b.txt), 最终发现, 访问的文件权限同样为:
-rw------- 1 u0_a120 u0_a120 4 2022-02-18 07:27 b.txt
App 权限申请见后文.
记录几个路径便于日后分析:
libcore/luni/src/main/native/libcore_io_Linux.cpp
libcore/luni/src/main/java/libcore/io/IoBridge.java
kernel/fs/namei.c
kernel/fs/open.c
kernel/fs/namei.c 最终输出 EACCES的函数
//记录下调用流程, 内核中输出LOG: //[ 59.897756] do_sys_open.c /mnt/sdcard/test.png flag=131649 mode=438 //[ 59.897805] namei.c path_openat /mnt/sdcard/test.png //[ 59.897807] namei.c link_path_walk /mnt/sdcard/test.png //[ 59.897819] namei.c do_inode_permission //[ 59.897829] namei.c acl_permission_check 1000, 0 //[ 59.897839] namei.c generic_permission ret=0 //[ 59.897848] namei.c inode_permission2 retval=0 //[ 59.897860] namei.c may_lookup err=0 /* * This does the basic permission checking */ static int acl_permission_check(struct inode *inode, int mask) { unsigned int mode = inode->i_mode; if (likely(uid_eq(current_fsuid(), inode->i_uid))) mode >>= 6; else { if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { int error = check_acl(inode, mask); if (error != -EAGAIN) return error; } if (in_group_p(inode->i_gid)) mode >>= 3; } /* * If the DACs are ok we don't need any capability check. */ if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) return 0; return -EACCES; }
所以, 就算如【framework】framework中为systemserver添加权限
文中所提解决方案打上补丁, 这个函数最终还是会返回 EACCESS.
暴力修改 return -EACCES;改为 return 0; 后, 验证文件读写成功!!
参考
Linux 系统调用之open(三)
关于安卓open failed: EACCES (Permission denied)