*** is not owned by the current user. Shared storage cannot protect your application from code injection attacks.
起因由于上面Log中的一段Exception
发现这个问题源于动态加载APK中的函数和资源,在4.1之前的Android系统,均能正常使用,发现升级到4.1之后会有这个Exception报出;
所谓动态加载,就是手机本地有一个APK包,用户不需要执行安装过程,程序就可以解包并运行APK中的函数和调取资源。很多场景会用到,比如一些游戏组件,插件,皮肤等等;
动态加载其中一个过程就是将APK解包,即将class.dex从APK中解压出来,这样才能通过java的反射调用到其中的方法。
解包过程中一定会调用这个方法
01
02
03
04
05
06
07
08
09
10
11
12
|
static
public
DexFile loadDex(String sourcePathName, String outputPathName,
int flags) throws IOException {
/*
* TODO: we may want to cache previously-opened DexFile objects.
* The cache would be synchronized with close(). This would help
* us avoid mapping the same DEX more than once when an app
* decided to open it multiple times. In practice this may not
* be a real issue.
*/
return
new
DexFile(sourcePathName, outputPathName, flags);
}
|
问题就出现在这里,查看4.1的源码,发现Google基于安全考虑在DexFile这个函数中增加了一个验证文件归属权的步骤。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
private
DexFile(String sourceName, String outputName, int flags) throws IOException {
if
(outputName != null) {
try
{
String parent =
new
File(outputName).getParent();
if
(Libcore.os.getuid() != Libcore.os.stat(parent).st_uid) {
//就是这里
//4.1增加了一个验证目录uid与当前进程uid是否一致的步骤,致使下面的异常被抛出
throw
new
IllegalArgumentException(
"Optimized data directory "
+ parent
+
" is not owned by the current user. Shared storage cannot protect"
+
" your application from code injection attacks."
);
}
}
catch
(ErrnoException ignored) {
// assume we'll fail with a more contextual error later
}
}
mCookie = openDexFile(sourceName, outputName, flags);
mFileName = sourceName;
guard.open(
"close"
);
//System.out.println("DEX FILE cookie is " + mCookie);
}
|
解决方法,参数outputPathName一定要是运行程序本身的私有地址,通过
01
|
getDir(
"dexfile"
, 0)
|
方法来获取这个dex文件存储位置就可以解决这个问题。
http://timcho.net/2013/01/16/android_4_1_dong_tai_jia_zai_apk_zhong_de_zi_yuan/