XposedBridge
XposedBridge copied to clipboard
Preferences of a module cannot be read from different process on some devices running MM
I have couple of reports from the users of my module that the preferences set in the settings part of a module don't stick. Unfortunately, I don't have any technical details about devices where that happens nor logs, but couple of users were the owners of Nexus 6P. I guess it has something to do with SeLinux or some other security restrictions. Could it be related to e.g. systemless rooting method? I run my module on couple of marshmallow nexus devices without any issues. My devices have modified kernel to allow classic SuperSU. I'm not using systemless root.
I can confirm that on a Nexus 5. I was no longer able to read or write module settings from e.g. SystemUI context when I switched to M. I ended up using a content provider instead. Am 06.12.2015 11:27 schrieb "C3C0" [email protected]:
I have couple of reports from the users of my module that the preferences set in the settings part of a module don't stick. Unfortunately, I don't have any technical details about devices where that happens nor logs, but couple of users were the owners of Nexus 6P. I guess it has something to do with SeLinux or some other security restrictions. Could it be related to e.g. systemless rooting method? I run my module on couple of marshmallow nexus devices without any issues. Those devices have modified kernel to allow classic SuperSU.
— Reply to this email directly or view it on GitHub https://github.com/rovo89/XposedBridge/issues/74.
Then it would be interesting to know the difference between setup of my and your N5 since I don't have any problems reading preferences within SystemUI process on mine.
I'm not near my PC right now, but this sounds like the known issue I mentioned in the Marshmallow release announcement. It's an SELinux restriction that I didn't find any solution for yet.
I have some new information. Found out that devices which suffer from this are those with permissions of shared_prefs folder being drwx------
My N5X has permissions of this folder set as drwxrwx--x without me doing any manual changes.
What could be causing this difference?
One solution would be for my module to set proper permissions in boot completed receiver although it's too late. But at least it would prepare correct permissions for the next reboot cycle.
Why not setting the proper permission while closing the App (onpause or ondestroy)?
I have the same issue with my TW module on some LL FWs and i use this workaround.
@wanam like setReadble(true, false) on the SharedPrefs XML file in onPause and onDestroy or by using some sort of shell command?
Additonal Info I found: I have two devices, one kitkat which my module works fine on, while the marshmallow one always fails to read. Seems for the shared prefs XML file the Kitkat device has 'rw-rw-r--' (0664) while the marshmallow device has 'rw-rw----'(0660). And when changing it to 664 in root explorer it works, but will change back on restart.
EDIT: I put new File("/data/data/PACKAGE_NAME/shared_prefs/PACKAGE_NAME_preferences.xml").setReadable(true, false);
in all activities's onPause
and onDestroy
. When you attempt to read the preferences in initZygote(...)
it says its doesn't exist, and is not world- or file- readable but can still get data from the XML file, which can be shown by prefs.getAll.size()
. When handleLoadPackage(..)
is executed, it will be completely readable. Note, I also refresh/reload the preferences in each hook (to update settings on runtime). A dodgy workaround but still works.
@pbombnz Actually setReadble(true, false) is not enough on MM (at least on my case TW MM), as it just sets 660 permission, we need to set it to 664 to get a readable prefs on the module process.
The only way that seems to work properly for me is to set it through the PreferenceFragment:
getPreferenceManager().setSharedPreferencesMode(Context.MODE_WORLD_READABLE);
getPreferenceManager().setSharedPreferencesName(YourActivity.class.getSimpleName());
sharedPref = getActivity().getPreferences(Context.MODE_WORLD_READABLE);
I change the prefs file name to the activity's simple name because it's used on "getActivity().getPreferences" that seems the only method that still sets the required permission "664" for the flag "MODE_WORLD_READABLE".
Having the same problem with my Xposed module on a Nexus 5 running MM. It seems like SELinux is kicking in as I found these AVCs: system:ui: type=1400 audit(0.0:49): avc: denied { search } for name="com.fifsource.android.resolveractivitytweaks" dev="mmcblk0p23" ino=603480 scontext=u:r:system_app:s0 tcontext=u:object_r:app_data_file:s0:c512,c768 tclass=dir permissive=0
Yep, the system UI cannot read data in packages. Are there any solutions?
@F-i-f Normally, if the hooked method is in system process, it's in system process; and the hooked method in app process, it's in app process. So, don't read app's files in system process. The hooked app can get rid of the xposed if it's in app's process. (I do this in my xposed module Prevent Running.)
For Prevent Running (not just a xposed module), I never read the file from system process (This works in below 4.4, but doesn't work in 5.0+). I use other android component to read/write files, like content provider and receiver.
@F-i-f Yep, that's exactly the issue we're talking about here. There's no solution to this yet.
@rovo89 but, why app can read /data/de.robv.android.xposed.installer/log/error.log
?
Which app? The issue is that system apps can't access data files from user apps. Xposed Installer can obviously read its own data files.
The error.log is logged by xposed module, and by system process too.
And, of course, prevent running (http://repo.xposed.info/module/me.piebridge.forcestopgb) read /data/de.robv.android.xposed.installer/log/error.log
directly when it's not activated in xposed installer.
https://github.com/liudongmiao/ForceStopGB/blob/master/src/me/piebridge/prevent/ui/util/ReportUtils.java#L48 I always received the error.log.
The error.log is logged by xposed module, and by system process too.
Not anymore. Since Lollipop, I changed XposedBridge.log()
to write only to Logcat. An additional daemon starts logcat and write the output to a file. This daemon process runs with the same SELinux context as a user app.
I always received the error.log.
Yes, the SELinux rules permit accessing data files of the same user account (if you have a multi-user ROM) as long as the Unix permissions are WORLD_READABLE. System apps like the System UI are a separate category and cannot access any user app's files.
Got it. I didn't know why xposed can write file to xposed installer's app. I will look into the codes.
For my xposed module (As I said, not just a xposed module), I use content-provider to send log from system process to user app process.
@rovo89
The issue is that system apps can't access data files from user apps.
Well I found out you can from the initZygoteHook, but once the framework is fully launched, selinux kicks in and it's over. It means that the user has to reboot to enact some changes which need to propagate to system ui, which is annoying, but not a deal-breaker.
How can I communicate from the system ui to my app for exchanging settings? I've read that the content provider route seems the easiest, but I don't have a context in system ui, therefore I don't seem to be able to query the provider.
Ran in to this issue when working with com.android.Settings and ended up using a content provider to resolve. Found a great implementation on github that was pretty much everything I needed.
On Wed, 2016-05-18 at 06:59 -0700, afxefx wrote:
Ran in to this issue when working with com.android.Settings and ended up using a content provider to resolve. Found a great implementation on github that was pretty much everything I needed.
Would you mind sharing that github repo? Thanks.
I did lol at least it's showing for me but here you go:
https://github.com/hamsterksu/MultiprocessPreferences
and just in case the link doesn't show here's the link in text format:
https://github.com/hamsterksu/MultiprocessPreferences
Shameless self promotion: I recently wrote a similar library, which is compatible with the SharedPreferences
API: https://github.com/apsun/RemotePreferences
This one offers granular access control to preferences (so you can deny third party apps from reading/writing your preferences, which could be a security issue). Also, registerOnSharedPreferenceChangeListener
works (yes, even across processes, so you can use it in your Xposed module).
@rovo89 is there any chance the XposedBridge itself could use a content provider based solution for XSharedPreferences so modules that aren't rewritten for MM could start working? As a bonus that looks like it would potentially allow writing to prefs from the module side too.
is there any chance the XposedBridge itself could use a content provider based solution for XSharedPreferences so modules that aren't rewritten for MM could start working?
Generally, that would be a possiblity, but several things like the requirement of a Context
and security aspects have to be considered carefully.
As a bonus that looks like it would potentially allow writing to prefs from the module side too.
Yeah, but the UI also has to use SharedPreferences in the same way. The good thing about the standard preferences saved in XML files is that you can easily and out-of-the-box create complex preferences UIs - not sure if it's possible to make them write to the content provider instead.
Yeah, but the UI also has to use SharedPreferences in the same way. The good thing about the standard preferences saved in XML files is that you can easily and out-of-the-box create complex preferences UIs - not sure if it's possible to make them write to the content provider instead.
Not necessarily, you can just back your ContentProvider
with SharedPreferences
instead of a real database. Since the provider is running in the same context as the config app process, it can access the preferences directly. That way you can keep on using PreferenceFragment
, etc.
Remote preference accesses (e.g. from an Xposed module running in a different process) go like this:
App code
-> ContentResolver
-> ContentProvider
-> SharedPreferences
Local preference accesses (e.g. configuration activity for the module) keep using the direct method:
App code
-> SharedPreferences
Not too sure on the Context
requirement. For normal apps, it should be possible to just hook android.app.Application
and get a Context
object from that (I think).
On Mon, 2016-05-30 at 02:21 -0700, Andrew Sun wrote:
Yeah, but the UI also has to use SharedPreferences in the same way. The good thing about the standard preferences saved in XML files is that you can easily and out-of-the-box create complex preferences UIs - not sure if it's possible to make them write to the content provider instead.
8< snip >8
Not too sure on the Context requirement. For normal apps, it should be possible to just hook android.app.Application and get a Context object from that (I think).
That's the hard part. Most of the Xposed modules shared preferences breaking on MM is due to system-level apps being denied access to user-level app data by SELinux. User-installed-app-to-user-installed-app shared prefs is not a problem as the usual "chmod 666" trick is still effective (for how long we don't know). But any module that need to retrieve shared prefs from say the System UI gets an AVC denial. And it's hard to get a Context from the System UI (at least for me).
I was wondering if patching the SELinux policy to allow system-level apps to read user-level app data would be an acceptable middle ground. I think that if system-level apps are compromised, you're already hosed anyways. That choice could be left to the user, for example in the Xposed installer.
Phil.
And it's hard to get a Context from the System UI (at least for me).
Really? I thought you could just use SystemUIApplication
for hooks running in SystemUI (haven't tried myself though, I've always been able to get it out of the constructor somehow).