背景:
近来有学员反馈说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.youkuaiyun.com/learnframework/article/details/127543333
更多framework技术干货,请关注下面“千里马学框架”

923

被折叠的 条评论
为什么被折叠?



