android 解决java.lang.SecurityException: Package com.xxx.xxx does not belong to 1000

Recently, I encountered a strange thing. The call method of accessing ContentProvider keeps reporting this error. After continuous research, I finally know where the problem is, and make a record here;

For example, if process B is called in process A, and process B then accesses the methods such as call and query of ContentProvider, and the methods such as call and query call ContentProvider.getCallingPackage(), then this error will be reported;

First look at the source code of ContentProvider.getCallingPackage(),

public final @Nullable String getCallingPackage() {
        final AttributionSource callingAttributionSource = getCallingAttributionSource();
        return (callingAttributionSource != null)
                ? callingAttributionSource.getPackageName() : null;
    }
public final @Nullable AttributionSource getCallingAttributionSource() {
        final AttributionSource attributionSource = mCallingAttributionSource.get();
        if (attributionSource != null) {
            mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(),
                    attributionSource.getPackageName());
        }
        return attributionSource;
    }

Here you can see that the source code will check the package name and uid of the caller to see if they are paired. If not, an exception will be thrown

    /**
     * @deprecated Use {@link PackageManager#getPackageUid} instead
     */
    @Deprecated
    public void checkPackage(int uid, @NonNull String packageName) {
        try {
            if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
                throw new SecurityException(
                        "Package " + packageName + " does not belong to " + uid);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

The problem is that process A calls process B, and process B accesses ContentProvider.getCallingPackage(), and then Binder.getCallingUid gets the uid of process A's identity, not the identity uid of process B

Posted below how to solve it?

val token = Binder.clearCallingIdentity()
        val client =
            UMSEnv.applicationContext.contentResolver.acquireUnstableContentProviderClient(
                providerAuthorityUri
            )
        kotlin.runCatching {
            val extras = Bundle()
            extras.putInt(KEY_HOST_PID, pid)
            val bundle = client?.call(METHOD_QUERY_HOST_PACKAGE_NAME, null, extras)
            client?.close()
            hostPackageName = bundle?.getString(KEY_HOST_PACKAGE_NAME)
        }.onFailure {
            client?.close()
            LogUtils.e(TAG, "queryHostPackageName, exception: $it")
            it.printStackTrace()
        }
        Binder.restoreCallingIdentity(token)

See the above code? The key to solving the problem is to add code before and after call()

Binder.clearCallingIdentity()

Binder.restoreCallingIdentity(token)

The purpose is to clear the identity of process A stored in Binder. These two codes need to be used in pairs!

Here are links to related issues:

Android ContentProvider call error "Bad call: specified package xxx under uid 10032 but it is really 10001" and Binder permission problem analysis

https://www.jianshu.com/p/a609b965364b  

Well, you can have fun again.

Guess you like

Origin blog.csdn.net/msn465780/article/details/131035276