Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] Implementation #1

Open
yujincheng08 opened this issue Apr 4, 2021 · 19 comments
Open

[Proposal] Implementation #1

yujincheng08 opened this issue Apr 4, 2021 · 19 comments

Comments

@yujincheng08
Copy link
Contributor

yujincheng08 commented Apr 4, 2021

We are working on this API with @canyie and @tiann.

Description

We are proposing an API that allows Xposed modules to communicate with the Xposed framework. For modules to this API, they have to implementation-ly depend on us.

We will provide an aidl interface for modules to RPC framework's methods. Modules can get an implementation of such an aidl interface by calling a static method. Let say its name is IXpoedService getService(), where we will grab the binder from the framework.

Framework Implementation

Root Framework

Two options to get the binder for root frameworks:

  • Most modules will hook themselves to get the hook status. So for the root framework, putting the binder to a static field of modules' classloader is a stable way. And getService can directly return the binder.
  • Or, we can hook getService to return the binder.

Non-root framework

To get the binder from another app, the only way is to use ContentProvider. Thus, for non-root frameworks to provide such an API, they have to register a content provider with a certain authority: say io.github.xposed-service. Then we can get the content provider can use call to binder from the framework.
HOWEVER, using a content provider requires context, which is not available before binding the application. For non-root frameworks, I supposed they are loading framework after Application is created.

To sum up, the getService should look like:

IXPosedService getService() {
    if (sService != null) return sService; // For the first option of root framework, it should always be the case.
    sService = getFromContentProvider(); // For non-root framework, get it from content provider.
    return sService;
}

API Implementation

A brief aidl API is proposed as:

parcelable Application {
    String packageName;
    int userId;
}

interface IXposedService {
    const String FEATURE_X = "xposed.feature.x"; // some constants

    int getXposedApi(); // 89 for example
    String getFrameworkName(); // LSPosed for example
    String getFrameworkVersionName(); // v1 for example
    int getFrameworkVersionCode(); // 233 for example
    
    List<String> getSupportedFeatures(); // ["x"] for example. Should match predefined constants
    bool isFeatureSupported(String); // pass predefined constants to it
 
    XRemoteSharedPreference getRemoteSharedPreference(String name); // An alternative to XSharedPreference

    List<Application> getScope(); // Scopes of the modules. ["android", "com.android.systemui"] for example.
                                            // How about returning PackageInfo instead?
    bool setScope(List<Application>); // Set scopes to provided package names. Futher user confirm is required.
                                                  // return false only if framework fails to pop confirm windows.
                                                  // Should a callback provided?
    // For modules targeting API 30+, it's hard for them to query all packages from all users.
    // Maybe we can provide an interface to help them?


    // Other interface suggestions are welcome.
}
@ghost
Copy link

ghost commented Apr 8, 2021

XRemoteSharedPreference is interesting. For get context of application I have found a solution here, after I failed to found a solution to this issue I come back to RemotePreference. When a module is not only module but also an app, RemotePreference is a good solution.

For setScope I read "Futher user confirm is required." I hope the user can override the request with "always yes", so for well known modules I can trust without it ask me every time. With other "posed" the default is all applications and always yes.

@yujincheng08
Copy link
Contributor Author

@etmatrix our xremotesharedpref does not require context

@jaqxues
Copy link

jaqxues commented Sep 12, 2021

Since this is about the api design of the service, I just want to make sure to mention the two things that are most crucial to me (as co-developer of Instaprefs).

We need a way to correctly share files. With Android 11 enforcing Scoped Storage, there is no way to simply store files on a globally accessible path. We now need a mecanism to share the modules /data/data/com.example.lsposed.module/ files (or similar) with the target app.
As an example: Instaprefs loads both, a Preferences.json file and a Pack.jar file from storage into memory, both are stored in /storage/emulated/0/Instaprefs. Without the ability to easily share files, Instaprefs cannot function correctly.

Similarly, Android 11 enforced a kind of sandboxing with "Package Visibility". We can no longer instantiate our module context by using Context#createPackageContext(String, int), so we can no longer use any custom resources. This will make it much more difficult to build UIs inside target apps as LSPosed Modules (since even loading images becomes difficult). So a way to bypass package visibility and get the lsposed module's package context would be a great addition.

@vvb2060
Copy link

vvb2060 commented Sep 12, 2021

@jaqxues We don't bypass Android's security restrictions. The current solution is good enough for remote reading of configuration and getting resources for module apk.

@yujincheng08
Copy link
Contributor Author

yujincheng08 commented Sep 12, 2021

@jaqxues

  1. We will share a file by sending its FileDescriptor to the module. But in the target app process, this should be read-only.
  2. Why createPackageContext? Original Xposed already has an XModuleResources.

@jaqxues
Copy link

jaqxues commented Sep 13, 2021

I do not think that files being read-only would be a problem to us. Without looking into it however, there might be places where we update preferences from inside the target app (which would involve updating the file).

I can make XModuleResources work. It just felt more easy to me to just use standard createPackageContext.

We don't bypass Android's security restrictions. The current solution is good enough for remote reading of configuration and getting resources for module apk.

What is meant by reading of configuration? Since we might want to update data inside the target app, it might be useful to use some form of a content provider that would support read- & writing preferences or accessing a database. However, because of package visibility, the target app would not be able to communicate in any form with the module. Would the current solution provide a way to do so?

@vvb2060
Copy link

vvb2060 commented Sep 13, 2021

No, read and write will never be supported, which would introduce security issues.

@yujincheng08
Copy link
Contributor Author

XRemotePreference is the solution for kv preference.
The RO file is for blob file.

@yujincheng08
Copy link
Contributor Author

Note that we only provide a place for module itself to write files and for module in the target app to read (and only read) them.

Target app won't be able to modified them, otherwise all modules hooking this app can modify them as well, which is unexpected.

@jaqxues
Copy link

jaqxues commented Sep 20, 2021

The idea was just to make a Content Provider available for the target app. Currently "Package Visbility" makes that impossible (The target app would need to declare the xposed module in the android manifest to allow communications across target and module apps).

Custom Content Providers would solve a majority of the problems, even though those content providers will probably be very slow. So it would be very much appreciated.

@vvb2060
Copy link

vvb2060 commented Sep 20, 2021

Never, stop talking about it. Re-read the API changes for Android 11: https://developer.android.com/reference/android/R.attr#forceQueryable

@jaqxues
Copy link

jaqxues commented Sep 20, 2021

Then just take this comment as clarification for the previous comment

@akhilkedia
Copy link

akhilkedia commented Dec 24, 2021

A Content Provider that is available for the target app is a requirement for my module :(

My module is AllTrans, which translates apps' UI elements into the user's language.
For this, I use Google's MLKit to provide translations for text.

On running MLKit within the target app, I get errors regarding virtual methods, which I assume has to do with it being a Native Library. My solution for this is to run MLKit within my own App, and handle translations via ContentProvider to supply the translated text content. Android 11's package visibility makes it simply impossible for my module to function.

The only alternative I can think of is hooking Android's permission system to let apps access my provider, or use pm install --force-queryable to give my contentProvider permissions.

It'll be great it this is a feature supported by Xposed itself.

@XposedBot
Copy link

@akhilkedia No. We will never bypass security restriction of Android

@vvb2060
Copy link

vvb2060 commented Dec 24, 2021

@akhilkedia
Copy link

akhilkedia commented Dec 24, 2021

@vvb2060 Thank you, I had missed that attribute can be added directly to the manifest to make the content providers queryable. As android natively already has support for this, there is no reason for Xposed to do so.

@akhilkedia
Copy link

This attribute is only applied to adb installs, and not to any general installs.

Can you give me an example of a single security scenario that exposing content providers results in, provided we can run code in the target app, that cannot be enabled via simple internet requests? Almost all apps have internet permissions, and anything that can be done from a ContentProvider can be done via an internet call.

For example target App a requests "X" to xposed module provider, which replies with "Y". If this is indeed a security issue, how is this any different from -

  1. the target app making a call to "https://someserver/X"
  2. the server pushing a data notification to the Xposed app
  3. which then replies "https://someserver/X/Y" to the server
  4. which then replies the "Y" to the target app?

Saying that exposing the ContentProvider exposes security issues provided that we can already run code in the target app, is the same as accessing internet.

@ucxl
Copy link

ucxl commented Jan 14, 2022

  • themselves

I really don't understand how to use it

Is there a code example?

I just need to add and delete scopes

So for the root framework, putting the binder to a static field of modules' classloader is a stable way. And getService can directly return the binder. ----I don't understand what this sentence means

@Redeorhcs
Copy link

Will you please add an API to manage scopes? This is needed to keep the development of things like xprivacy Lua going. There is a lot of potential left with lsposed with this addition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants