Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SecurityException with grantUriPermission when sharing a file with FileProvider

I have two applications. I'm trying to share a file from application A to application B using a FileProvider. Application A calls the insert method on a ContentProvider in Application B to insert a record. The data inserted includes the Uri to the file I want to share from App A. The ContentProvider in App B would then try to read the shared file from App A. Since I'm not using an Intent to share the file, I'm calling Context.grantUriPermission in App A to allow the read (and at times write):

mContext.grantUriPermission(MyPackageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

However, executing this line gives me (Names changed to protect the innocent):

java.lang.SecurityException: Uid 10066 does not have permission to uri content://au.com.example.AppA.fileprovider/MyFolder/MyFileName
at android.os.Parcel.readException(Parcel.java:1322)
at android.os.Parcel.readException(Parcel.java:1276)
at android.app.ActivityManagerProxy.grantUriPermission(ActivityManagerNative.java:2374)
at android.app.ContextImpl.grantUriPermission(ContextImpl.java:1371)
at android.content.ContextWrapper.grantUriPermission(ContextWrapper.java:400)
at etc...

App A has the following in the Manifest file:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="au.com.example.AppA.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true"
    android:readPermission="au.com.example.READ_CONTENT"
    android:writePermission="au.com.example.WRITE_CONTENT" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

filepaths.xml has:

<paths>
    <files-path
        name="MyFolder"
        path="MyFolder/" />
</paths>

Both App A and App B have the following:

<uses-permission android:name="au.com.example.READ_CONTENT" />
<uses-permission android:name="au.com.example.WRITE_CONTENT" />

I've tried defining the permissions in both apps. They are both signed with the same debug signature:

<permission
    android:name="au.com.example.READ_CONTENT"
    android:permissionGroup="MyGroup"
    android:protectionLevel="signature" >
</permission>
<permission
    android:name="au.com.example.WRITE_CONTENT"
    android:permissionGroup="MyGroup"
    android:protectionLevel="signature" >
</permission>

The actual path the file ends up in is:

/data/data/au.com.example.AppA/files/MyFolder

At this point I'm stumped. I don't know why I can't grant permission for a file I just created within the same application. So my questions are: Why am I getting this exception and how can I successfully grant permission to App B?

like image 895
DavidsAlias Avatar asked Jan 22 '14 06:01

DavidsAlias


People also ask

How do you use Granturipermission?

Try including this in your AndroidManifest. xml. On Android 6.0+ the permission must be granted by the user to the application otherwise this will throw the SecurityException. To do this go into Settings/Apps/[AppName]/Permissions and allow the Storage Permission.

How do I use FileProvider?

To make FileProvider work follow these three steps: Define the FileProvider in your AndroidManifest file. Create an XML file that contains all paths that the FileProvider will share with other applications. Bundle a valid URI in the Intent and activate it.


1 Answers

Well, after a week and a lot of trial and error, it seems the answer is to not specify permissions. So the App A Manifest should instead contain:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="au.com.example.AppA.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>

ie, I removed the read and write permissions. My initial understanding, and failing to find documentation that said otherwise, was these were necessary to restrict access. However, I've found they actually interfere and cause Context.grantUriPermission to fail. Access is limited already.

To complete the picture, and answer the second part of my question, I found the following:

Android Permission denial in Widget RemoteViewsFactory for Content

I had to add:

final long token = Binder.clearCallingIdentity();
try {
    [retrieve file here]
} finally {
    Binder.restoreCallingIdentity(token);
}

to the Content Provider in App B. Otherwise it would get security errors as well.

like image 155
DavidsAlias Avatar answered Sep 21 '22 07:09

DavidsAlias