apsun / RemotePreferences

A drop-in solution for inter-app access to SharedPreferences.
MIT License
138 stars 32 forks source link

[INFO] java.lang.SecurityException: Given calling package android does not match caller's uid #20

Closed ghost closed 3 years ago

ghost commented 3 years ago

I don't know it's a real issue of RemotePreferences, I report for info to other users. With Xposed and similar projects, it is not possible to have the Context of hooked application, thank to @MPeti1 and the info in issue #3 there was a good alternative for old versions of Android.

Context systemContext = (Context) XposedHelpers.callMethod( XposedHelpers.callStaticMethod( XposedHelpers.findClass("android.app.ActivityThread", loadPackageParam.classLoader), "currentActivityThread"), "getSystemContext" );

With this row we can get the context of package "android" and is good for create the object RemotePreferences. With Android 8 and 8.1, the context "android" can query the Provider without exception. I'm testing an old module which use RemotePreferences on Android 10 (LineageOS 17.1) and LSPosed, but everytime my module from handleLoadPackage try to query the provider I got this exception:


java.lang.SecurityException: Given calling package android does not match caller's uid 10161
    at android.os.Parcel.createException(Parcel.java:2071)
    at android.os.Parcel.readException(Parcel.java:2039)
    at android.os.Parcel.readException(Parcel.java:1987)
    at android.app.IActivityManager$Stub$Proxy.getContentProvider(IActivityManager.java:5056)
    at android.app.ActivityThread.acquireProvider(ActivityThread.java:6561)
    at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2725)
    at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:2117)
    at android.content.ContentResolver.query(ContentResolver.java:928)
    at android.content.ContentResolver.query(ContentResolver.java:880)
    at android.content.ContentResolver.query(ContentResolver.java:836)
    at com.crossbowffs.remotepreferences.RemotePreferences.query(RemotePreferences.java:214)
    at com.crossbowffs.remotepreferences.RemotePreferences.querySingle(RemotePreferences.java:263)
    at com.crossbowffs.remotepreferences.RemotePreferences.getBoolean(RemotePreferences.java:135)

I tried to set strictmode to true without success, I tried the solution in issue #12 setExecutable(true, false) and setReadable(true, false) without success. Android check the name of package in context ("android") and the uid of caller (my hooked application) and with mismatch throw an exception.

So I think this project is useless with *Posed and new Android if this check can't be disabled.

From Readme: "This library was developed to simplify Xposed module preference access. " In the past sure, now not more.

aviraxp commented 3 years ago

Is the app you are hooking (and the class) having context as a parameter somewhere? If so, you can hook it to get context.

See https://github.com/apsun/NekoSMS/blob/82205ebed9cd57fd59a59457d2a65b10a5e17751/app/src/main/java/com/crossbowffs/nekosms/xposed/SmsHandlerHook.java#L182

MPeti1 commented 3 years ago

It should have an Application Context in Application.onCreate(), if I remember it correctly, but in cases it's not practical to wait until that. I'm not entirely sure why, but I remember thinking about this and not taking this path. Edit: yeah, I'm starting #3 with why it's not a good idea. Basically it's because I need the preferences while handleLoadPackage() is running, so I can read my settings so I can decide early if I want to hook something.

But now that I'm thinking about this, is it really needed? I could just hook everything where a that early hook is crucial, and when I receive some kind of context (from a hook made to do just that) in my settings class, I could unload hooks that are not actually needed. Or an other solution would probably be making my own IPC capable services with Binder, but that's not done as easily as said, and even more I know of apps where it's been found that my phone (and apparently there are more) fails in the middle of transferring arrays, except when not but that's rare and still don't know what does it depend on.

MPeti1 commented 3 years ago

So I think this project is useless with *Posed and new Android if this check can't be disabled.

A quick question, did you look around if you could disable this check (possibly only for once every time you request it, so other apps couldn't abuse it)?

apsun commented 3 years ago

From @MPeti1:

I could just hook everything where a that early hook is crucial, and when I receive some kind of context (from a hook made to do just that) in my settings class, I could unload hooks that are not actually needed.

This is the approach I would recommend. Hook everything, and decide what to do within the callback based on the preferences. I am not a fan of grabbing random context objects out of internal APIs exactly for this reason: they can and will break with system updates.

RemotePreferences isn't magic, it's just SharedPreferences implemented on top of ContentResolver. If Android says you can't use the "system context" with ContentResolver, there isn't really much choice other than to either: a) change where you obtain the Context, or b) use a different preference sharing solution that doesn't rely on Context.

apsun commented 3 years ago

I do think we should have an official guide on "where do I get a Context instance from", since this is probably the most frequently asked question on this project. Obviously a "one-size-fits-all" approach would be ideal, like hooking Application.onCreate and deferring all the initialization logic to there, although it's been so long since I've touched Xposed that I'm not even sure if that works.

ghost commented 3 years ago

Thank to all which reply me. I found a solution. newApplication is invoked before a new Activity is created and should invoked also when there is no activity but only a service.

Class<?> clsInstrumentation = findClass("android.app.Instrumentation", classLoader);
XposedBridge.hookAllMethods(instrumentation, "newApplication", new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param)
    {
        SharedPreferences spXMain = new RemotePreferences((Context)param.getResult(), Utils.PREFS, Utils.XMAIN);
        // processHook((Context)param.getResult(), sPackageName, classLoader);
    }
});

I do think we should have an official guide on "where do I get a Context instance from"

@apsun would be great

A quick question, did you look around if you could disable this check?

@MPeti1 I tried to analyze, but it wasn't easy for me