Commit 98faa36c authored by Andre Furtado's avatar Andre Furtado Committed by gitbuildkicker
Browse files

30481342: Security Vulnerability - TOCTOU in MmsProvider allows access to...

30481342: Security Vulnerability - TOCTOU in MmsProvider allows access to files as phone (radio) uid

Problem: MmsProvider.openFile validated the current _data column
in the DB and then called ContentProvider.openFileHelper which was again
reading from the DB. A race condition could cause the second DB read to
read an updated, malicious value.

Fix: instead of doing the first DB check and calling
ContentProvider.openFileHelper, we're now just calling
MmsProvider.safeOpenFileHelper which does a single check.

Test: used the POC provided for this incident.

b/30481342

Change-Id: I653129359130b9fae59d4c355320b266c158a698
(cherry picked from commit 5bc7f968)
parent f596d654
......@@ -16,6 +16,7 @@
package com.android.providers.telephony;
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.ContentProvider;
import android.content.ContentValues;
......@@ -300,7 +301,11 @@ public class MmsProvider extends ContentProvider {
@Override
public Uri insert(Uri uri, ContentValues values) {
// Don't let anyone insert anything with the _data column
// The _data column is filled internally in MmsProvider, so this check is just to avoid
// it from being inadvertently set. This is not supposed to be a protection against
// malicious attack, since sql injection could still be attempted to bypass the check. On
// the other hand, the MmsProvider does verify that the _data column has an allowed value
// before opening any uri/files.
if (values != null && values.containsKey(Part._DATA)) {
return null;
}
......@@ -725,9 +730,12 @@ public class MmsProvider extends ContentProvider {
}
@Override
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
// Don't let anyone update the _data column
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// The _data column is filled internally in MmsProvider, so this check is just to avoid
// it from being inadvertently set. This is not supposed to be a protection against
// malicious attack, since sql injection could still be attempted to bypass the check. On
// the other hand, the MmsProvider does verify that the _data column has an allowed value
// before opening any uri/files.
if (values != null && values.containsKey(Part._DATA)) {
return 0;
}
......@@ -833,7 +841,12 @@ public class MmsProvider extends ContentProvider {
return null;
}
// Verify that the _data path points to mms data
return safeOpenFileHelper(uri, mode);
}
@NonNull
private ParcelFileDescriptor safeOpenFileHelper(
@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
Cursor c = query(uri, new String[]{"_data"}, null, null, null);
int count = (c != null) ? c.getCount() : 0;
if (count != 1) {
......@@ -854,10 +867,16 @@ public class MmsProvider extends ContentProvider {
c.close();
if (path == null) {
return null;
throw new FileNotFoundException("Column _data not found.");
}
File filePath = new File(path);
try {
File filePath = new File(path);
// The MmsProvider shouldn't open a file that isn't MMS data, so we verify that the
// _data path actually points to MMS data. That safeguards ourselves from callers who
// inserted or updated a URI (more specifically the _data column) with disallowed paths.
// TODO(afurtado): provide a more robust mechanism to avoid disallowed _data paths to
// be inserted/updated in the first place, including via SQL injection.
if (!filePath.getCanonicalPath()
.startsWith(getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath())) {
Log.e(TAG, "openFile: path "
......@@ -865,7 +884,6 @@ public class MmsProvider extends ContentProvider {
+ " does not start with "
+ getContext().getDir(PARTS_DIR_NAME, 0).getCanonicalPath());
// Don't care return value
filePath.delete();
return null;
}
} catch (IOException e) {
......@@ -873,7 +891,8 @@ public class MmsProvider extends ContentProvider {
return null;
}
return openFileHelper(uri, mode);
int modeBits = ParcelFileDescriptor.parseMode(mode);
return ParcelFileDescriptor.open(filePath, modeBits);
}
private void filterUnsupportedKeys(ContentValues values) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment