简体   繁体   中英

Android Marshmallow: new File (…) gives permission denied

EDITED to reflect progress.

If this question has been answered already, my apologies.

Currently writing an app where content (in a small zip file) is downloaded from an external location and stored inside /data/data/package_name_removed/files/, to be read later.

I currently have a zip file in that directory "Test.zip".

A try-catch loop containing:

//where filename is Test.zip


Log.d("Target file is", sourceContext.getFilesDir() +"/"+ fileName);
File file = new File(sourceContext.getFilesDir() +"/"+ fileName);
ZipFile loadedFile = new ZipFile(file);  

//where sourceContext is passed into this object from the base Activity class

Doesn't seem to work in Marshmallow:

D/Target file is: /data/user/0/package_name_removed/files/Test.zip
W/package_name_removed: type=1400 audit(0.0:11699): avc: denied { open } for name="Test.zip" dev="mmcblk0p29" ino=57426 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0

This is a Log.d of the IOException getMessage; I think this one's generated from the new File() statement:

D/Log_title_omitted: /data/user/0/package_name_removed/files/Test.zip: open failed: EACCES (Permission denied)

I had this working in Lollipop; was debugging it for pre-lollipop too until I recently upgraded to Marshmallow. I don't think I can safely continue until I sort this out, because it means my app won't support 6.0.

I have managed to write a text file to this directory with no problems whatsoever with the same app, so I do not understand why attempting to open a zip file from that directory doesn't work.

Edit: I have also attempted to unzip the offending zip file to its own directory but to no avail:

//where file is now a json file "Test.json"
//located in .getFilesDir()/Test/
String loadedName = fileName.substring(0, fileName.length() - 5); //I need to reuse the string later.".json" is 5 char.
Log.d("Target is", sourceContext.getFilesDir() +"/"+ loadedName +"/" + fileName);
File file = new File(sourceContext.getFilesDir() + "/"+ loadedStoryName +"/" + fileName);

And got:

D/DOH: /data/user/0/package_name_removed/files/Test/Test.json: open failed: EACCES (Permission denied)
W/package_name_removed: type=1400 audit(0.0:22152): avc: denied { search } for name="Test" dev="mmcblk0p29" ino=57184 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:app_data_file:s0 tclass=dir permissive=0

I understand Marshmallow is really enforcing SELinux now, and I have to code for this eventuality - but I haven't been able to figure out how to get the proper permissions in code. Rightfully I should not need a READ_EXTERNAL anywhere as according to the documentation, there is no need to ask for permissions to the app's own files directory in internal storage.

Any help?

Note: package name omitted, not important.

From user CommonsWare:

"Rooting does not disable SELinux" -- no, but it does not mean that files that >you create through a root shell somehow get the same permission bits/ACLs/etc. as >do files you create through your application code. adb shell run-as might behave >better in this fashion.

Yep, it was indeed because I copied the file myself rather than have the app do it; having r permissions across the board is not enough to satisfy SELinux, the app must "own" the file by being the one that "creates" it.

I have yet to test this on the external write directory, but it is true for the internal app's own directory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM