背景:
近来有学员反馈说wms课程中讲解的借壳Shell帮忙执行一些shell命令有问题,具体啥问题呢?
在ShellProvider的call方法加入如下代码:
目的就是想让shell帮我们执行一下settings值的写入,这里其实可以更加简单的settings put命令既可以,但学员就想知道为这样是不是也可以执行,其实也肯定是可以的哈。
但他发现如果在system_server中调用会报错如下:
08-26 15:21:35.004 19922 19922 E AndroidRuntime: Process: com.example.injectmotion, PID: 19922
08-26 15:21:35.004 19922 19922 E AndroidRuntime: java.lang.SecurityException: Given calling package android does not match caller’s uid 10189
原因分析
先看看这个源码是怎么写的
直接在wms的relayout中调用了Shell的provider的call方法,想让Shell帮我们执行代码。
但是报错核心堆栈如下:
E AndroidRuntime: at com.android.server.am.ContentProviderHelper.getContentProvider(ContentProviderHelper.java:141)
E AndroidRuntime: at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:6782)
可以看到这里是acquireProvider就已经报错了,根本没有到达Shell的Provider的call方法,属于压根连Provider获取时候就有校验报错。
具体看看报错代码日志:
日志
Given calling package android does not match caller’s uid 10189
这个大概意思是包名 android和uid 没有匹配到一起
这里看看报错具体代码
可以看到这里的uid明显是通过 Binder.getCallingUid(),即谁发起的跨进程调用获取的就是谁的uid,所以这个uid明显就是我们app包名为com.example.injectmotion的uid,但是这里的callingPackage明显是android即我们的systemserver,因为这个获取Provider明显是在systemserver进程发起的,不是在app端发起的。
所以这里当然就会报错因为com.example.injectmotion的uid个android包名对应uid不一样,从而导致安全报错。
解决方法
方法其实这个在前面的blog都是有讲解,还有相关模拟面试也有多次提到,那就是 Binder.clearCallingIdentity()方法来清除一下binder相关的调用记录。
具体修改如下:
这样后续的Binder.getCallingUid()就是获取的system_server进程的,就不会有这个安全报错,具体原理可以看这个blog
https://blog.csdn.net/learnframework/article/details/127543333
投屏专题部分:
https://mp.weixin.qq.com/s/IGm6VHMiAOPejC_H3N_SNg
更多framework详细代码和资料参考如下链接
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
其他课程七件套专题:
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw
视频试看:
https://www.bilibili.com/video/BV1wc41117L4/
参考相关链接:
https://blog.csdn.net/zhimokf/article/details/137958615
更多framework假威风耗:androidframework007