Controlling application separation

From: http://mylifewithandroid.blogspot.com/2009/06/controlling-application-separation.html

 

I thought I knew how application separation in Android works. Then I had a little project and I realized that there is more than meets the eye. Here are my experiences.

The basic - and very efficient - separation method in Android is the multiprocess capability of the Dalvik VM. Dalvik is able to fork many instances of itself and can run applications in different Linux processes. By default, each application (the application tag in AndroidManifest.xml) has its own process. There is however another, often overlooked separation mechanism inside each VM process that provides further separation. The good old ClassLoader separation - originally designed to separate applets, used heavily in multi-module frameworks like OSGi - is also at work. Inside each VM process, each task - acitivity or service - uses in its own ClassLoader. This means that object instances created in different tasks are not visible to each other. The standard setup for Android applications is such that the classes.dex in the application's APK package is on the path of the application's own classloader. The application's own classloader delegates the loading of system classes to the boot classloader instance which is common for all the tasks in one particular VM process.

Class loading implementation in Dalvik is tied heavily to DEX files. This has visible side effects. Classes loaded by different class loaders that don't delegate to each other should be completely separated. The implementation differentiates the "initiating" and "defining" classloader (the latter is the one that managed to call defineClass() for a particular class from a particular DEX file in a particular VM process). This differentiation does not work very well and results in a glitch: once a class from a particular DEX file is defined, its static fields are visible and shared from all the class loaders that access the DEX file, even if they don't delegate to each other. This means that tasks of the same application (usually packed into the same DEX file) see each other's static fields.

As if this was not enough, Android provides control of task-VM process mapping. As said previously, usually each application goes into its own VM process. It is possible to declare, however, that applications share a process. This works like the following:

  • First we declare that applications wishing to share the same VM process belong to the same user ID. This is done by adding the sharedUserId attribute to the manifest tag in AndroidManifest.xml file like the following: android:sharedUserId="aexp.share.sharedapp" . The value of the attribute must be a unique string shared among the applications wishing to use the same VM process. This is a powerful mechanism, hence Android enforces strong check of the APKs containing the declaration. Only the first APK for a particular sharedUserId can be installed without limitation. The issuer of the digital signature of that APK is saved and further APKs with the same sharedUserId must have digital signature from the same issuer, else their installation is rejected.
  • We have to declare the alias of the process a certain task or the entire application goes into with the process attribute. This attribute can be added to application , activity or service tags in the AndroidManifest.xml file. For example: android:process="aexp.share.sharedappprocess" . VM processes are proper Linux processes identified by PIDs but Android does an additional transformation: whenever a process is started which is tagged by the process alias, the Android framework saves the Linux PID and the process alias. If some other application refers to that process alias and the VM process is still running, that process will be used.

How can we exploit this mechanism? We can create ordinary, well-behaving Android applications and place them into the same process. Android IPC is such that the usual binder-based communication is much faster in this case. The other approach is that we exploit our knowledge about class loaders. If we place two applications into the same process, they not only have different class loaders but also come from different DEX files. This means that the Android class loading glitch about the static fields cannot be exploited (I don't recommend it anyway as it is a clear bug and I believe, it will be corrected soon). We know, however, that each class loader in the same VM process delegates the resolution of the system classes to the boot class loader. If we find a system class that allows us to store and retrieve data, we win.

 

Click here to download the example program .

 

Our two example programs demonstrate the techniques described below. SharedApp1 allows the user to enter a string and it shares that string in different ways. With its own popup, it shares the string by means of a static field of SharedApp1 activity class. SharedApp2 is another application, having its own APK file but is placed into the same process as SharedApp1. SharedApp1 and SharedApp2 communicate through the good old System.getProperty/setProperty mechanism. Observe, that this works only if the sharedUserId/process mechanism is properly used, if you remove e.g. the process attribute from the manifest file of any of the apps, the property set by SharedApp1 is not visible anymore to SharedApp2 because they run in different VM processes. Also note that I compiled these applications with the debug option which means that they are both signed with the debug key. That key is common for both applications therefore they can have the same sharedUserIds. If you use a proper signing key, take care of using the same key when you sign applications that depend on the sharedUserId mechanism.

sharedApp2

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值