FrameWork 客户定制接口如何如何绕开系统权限管控

本文介绍了如何在Android Framework中绕过系统权限管控,以允许客户定制接口。通过分析蓝牙管理服务的权限检查过程,揭示了权限检查的实现路径,并提出了解决方案,即在系统层面声明自定义权限,修改权限管理系统,从而在不使用系统签名的情况下允许apk调用需要系统权限的接口。
摘要由CSDN通过智能技术生成

在公司中做Framework的定制也已经两年多了,陆陆续续的也改了不少的系统服务,替客户制定过不少api接口。之前关于一些需要系统级权限的接口也都是通过将apk进行系统签名的方式来实现的,虽然这种做法也并无不妥,但是仔细考虑了一下应该还是有其他方式可以让apk与系统的耦合度变的更低的。(大不了就是在其他机器上调用不了这个接口了)

网上找了一下也早就已经有人对权限机制和安全机制做过一些分析,但是都不太涉及到具体的调用链,而且一般都是添加新的权限限制而不是绕开原有限制。

浅析Android权限机制(一) —— Android的权限机制
Android安全机制(2) Android Permission权限控制机制

好了,接下来就是一些系统Framework的接口调用追踪了,只想看解决方案的话可以直接拉到最后。

调用流程(MT8735_M平台):
这里我们就挑一个具体的案例来分析吧,以蓝牙作为例子,apk如果需要管理蓝牙连接,就必须声明蓝牙相关的permission,那么这个permission的检查又是在哪里进行的呢。

BluetoothManagerService.java

 public boolean enable() {
   
        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
            (!checkIfCallerIsForegroundUser())) {
   
            Log.w(TAG,"enable(): not allowed for non-active and non system user");
            return false;
        }
 
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH ADMIN permission");
        if (DBG) {
   
            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +
                    " mBinding = " + mBinding);

       } 

从这个enable函数可以看到,在执行enable函数开启蓝牙时,会先检查是否是系统进程,如果不是系统进程的话就需要在前台运行。

然后就通过Context(aondroid.content.Context)类的enforceCallingOrSelfPermission函数来检查相应的权限,这里的权限是一个常量,具体的定义是

private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
现在我们转到Context.java这个类里去看看:

 /**
     * Determine whether the calling process of an IPC <em>or you</em> have been
     * granted a particular permission.  This is the same as
     * {
   @link #checkCallingPermission}, except it grants your own permissions
     * if you are not currently processing an IPC.  Use with care!
     *
     * @param permission The name of the permission being checked.
     *
     * @return {
   @link PackageManager#PERMISSION_GRANTED} if the calling
     * pid/uid is allowed that permission, or
     * {
   @link PackageManager#PERMISSION_DENIED} if it is not.
     *
     * @see PackageManager#checkPermission(String, String)
     * @see #checkPermission
     * @see #checkCallingPermission
     */
    @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)")
    @PackageManager.PermissionResult
    public abstract int checkCallingOrSelfPermission(@NonNull String permission)

这里的注释已经写的很详细了(谷歌aosp里的源码注释还是挺多的,很多比较难懂的地方都会有详细的注释),简单解释一下就是检查你的应用有没有声明这个权限,或者应用运行的uid(通过AndroidManifest.xml里的sharedUserId定义)是否有相应的权限。

这是一个抽象方法,那么一定会有一个实现这个方法的类,一般来说aosp里的命名都比较规范,这种实现一般都是xxxImpl.java或者xxxService.java之类的,不过一般我会直接用git grep去确认。这里的具体实现是在ContextImpl.java(framework/base/core/java/android/app/ContextImpl.java)中:

  @Override
    public int checkCallingOrSelfPermission(String permission) {
   
        if (permission == null) {
   
            throw new IllegalArgumentException("permission is null");
        }
 
        return checkPermission(permission, Binder.getCallingPid(),
                Binder.getCallingUid());

可以看到这里是调用了checkPermission这个函数,如果把代码稍微浏览一遍的话会发现,context中检查权限的代码,包括checkxxxPermission或者enforcexxxPermission最后都是调到了这个 checkPermission的函数。

这里也贴一下enforce的调用吧,帮大家省点找代码的时间:

 private void enforce(
            String permission, int resultOfCheck,
            boolean selfToo, int uid, String message) {
   
        if 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值