From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aishwarya Mallampati Date: Wed, 23 Aug 2023 18:30:46 +0000 Subject: [PATCH] DO NOT MERGE Block access to sms/mms db from work profile. Bug: 289242655 Test: Manually verified work profile cannot access personal sms by following steps mentioned in b/289242655#comment26 - atest SmsProviderTest - atest MmsProviderTest - atest SmsBackupRestoreTest - QA performed regression testing and confirmed fix is working as intended here: b/294459052#comment30 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:950a7e5a4bf1b38e846fe00642105479efded57d) Merged-In: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277 Change-Id: Ib1c9ec75f77e8412b53df50f5414caa0e5aaa277 Change-Id: I7e4cf14fabb2c00e916504ce44816462a8b5215e --- .../providers/telephony/MmsProvider.java | 36 +++++ .../telephony/MmsSmsDatabaseHelper.java | 150 ++++++++++-------- .../providers/telephony/MmsSmsProvider.java | 36 +++++ .../providers/telephony/SmsProvider.java | 35 ++++ 4 files changed, 189 insertions(+), 68 deletions(-) diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java index ba057828..7e50535c 100755 --- a/src/com/android/providers/telephony/MmsProvider.java +++ b/src/com/android/providers/telephony/MmsProvider.java @@ -35,6 +35,7 @@ import android.os.Binder; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.os.UserHandle; +import android.os.UserManager; import android.provider.BaseColumns; import android.provider.Telephony; import android.provider.Telephony.CanonicalAddressesColumns; @@ -161,6 +162,16 @@ public class MmsProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + Cursor emptyCursor = new MatrixCursor((projection == null) ? + (new String[] {}) : projection); + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to query mms, return empty cursor. + Log.e(TAG, "Managed profile is not allowed to query MMS."); + return emptyCursor; + } + // First check if a restricted view of the "pdu" table should be used based on the // caller's identity. Only system, phone or the default sms app can have full access // of mms data. For other apps, we present a restricted view which only contains sent @@ -508,6 +519,15 @@ public class MmsProvider extends ContentProvider { if (values != null && values.containsKey(Part._DATA)) { return null; } + + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to insert mms, return null. + Log.e(TAG, "Managed profile is not allowed to insert MMS."); + return null; + } + final int callerUid = Binder.getCallingUid(); final String callerPkg = getCallingPackage(); int msgBox = Mms.MESSAGE_BOX_ALL; @@ -787,6 +807,14 @@ public class MmsProvider extends ContentProvider { @Override public int delete(Uri uri, String selection, String[] selectionArgs) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to delete mms, return 0. + Log.e(TAG, "Managed profile is not allowed to delete MMS."); + return 0; + } + int match = sURLMatcher.match(uri); if (LOCAL_LOGV) { Log.v(TAG, "Delete uri=" + uri + ", match=" + match); @@ -960,6 +988,14 @@ public class MmsProvider extends ContentProvider { @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to update mms, return 0. + Log.e(TAG, "Managed profile is not allowed to update MMS."); + return 0; + } + // 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 diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java index 9e5715dd..64cc50cd 100644 --- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java +++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java @@ -636,78 +636,92 @@ public class MmsSmsDatabaseHelper extends SQLiteOpenHelper { } } + public static String CREATE_ADDR_TABLE_STR = + "CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + + Addr._ID + " INTEGER PRIMARY KEY," + + Addr.MSG_ID + " INTEGER," + + Addr.CONTACT_ID + " INTEGER," + + Addr.ADDRESS + " TEXT," + + Addr.TYPE + " INTEGER," + + Addr.CHARSET + " INTEGER);"; + + public static String CREATE_PART_TABLE_STR = + "CREATE TABLE " + MmsProvider.TABLE_PART + " (" + + Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + Part.MSG_ID + " INTEGER," + + Part.SEQ + " INTEGER DEFAULT 0," + + Part.CONTENT_TYPE + " TEXT," + + Part.NAME + " TEXT," + + Part.CHARSET + " INTEGER," + + Part.CONTENT_DISPOSITION + " TEXT," + + Part.FILENAME + " TEXT," + + Part.CONTENT_ID + " TEXT," + + Part.CONTENT_LOCATION + " TEXT," + + Part.CT_START + " INTEGER," + + Part.CT_TYPE + " TEXT," + + Part._DATA + " TEXT," + + Part.TEXT + " TEXT);"; + + public static String CREATE_PDU_TABLE_STR = + "CREATE TABLE " + MmsProvider.TABLE_PDU + " (" + + Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + Mms.THREAD_ID + " INTEGER," + + Mms.DATE + " INTEGER," + + Mms.DATE_SENT + " INTEGER DEFAULT 0," + + Mms.MESSAGE_BOX + " INTEGER," + + Mms.READ + " INTEGER DEFAULT 0," + + Mms.MESSAGE_ID + " TEXT," + + Mms.SUBJECT + " TEXT," + + Mms.SUBJECT_CHARSET + " INTEGER," + + Mms.CONTENT_TYPE + " TEXT," + + Mms.CONTENT_LOCATION + " TEXT," + + Mms.EXPIRY + " INTEGER," + + Mms.MESSAGE_CLASS + " TEXT," + + Mms.MESSAGE_TYPE + " INTEGER," + + Mms.MMS_VERSION + " INTEGER," + + Mms.MESSAGE_SIZE + " INTEGER," + + Mms.PRIORITY + " INTEGER," + + Mms.READ_REPORT + " INTEGER," + + Mms.REPORT_ALLOWED + " INTEGER," + + Mms.RESPONSE_STATUS + " INTEGER," + + Mms.STATUS + " INTEGER," + + Mms.TRANSACTION_ID + " TEXT," + + Mms.RETRIEVE_STATUS + " INTEGER," + + Mms.RETRIEVE_TEXT + " TEXT," + + Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," + + Mms.READ_STATUS + " INTEGER," + + Mms.CONTENT_CLASS + " INTEGER," + + Mms.RESPONSE_TEXT + " TEXT," + + Mms.DELIVERY_TIME + " INTEGER," + + Mms.DELIVERY_REPORT + " INTEGER," + + Mms.LOCKED + " INTEGER DEFAULT 0," + + Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT " + + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + + Mms.SEEN + " INTEGER DEFAULT 0," + + Mms.CREATOR + " TEXT," + + Mms.TEXT_ONLY + " INTEGER DEFAULT 0);"; + + public static String CREATE_RATE_TABLE_STR = + "CREATE TABLE " + MmsProvider.TABLE_RATE + " (" + + Rate.SENT_TIME + " INTEGER);"; + + public static String CREATE_DRM_TABLE_STR = + "CREATE TABLE " + MmsProvider.TABLE_DRM + " (" + + BaseColumns._ID + " INTEGER PRIMARY KEY," + + "_data TEXT);"; + private void createMmsTables(SQLiteDatabase db) { // N.B.: Whenever the columns here are changed, the columns in // {@ref MmsSmsProvider} must be changed to match. - db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PDU + " (" + - Mms._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Mms.THREAD_ID + " INTEGER," + - Mms.DATE + " INTEGER," + - Mms.DATE_SENT + " INTEGER DEFAULT 0," + - Mms.MESSAGE_BOX + " INTEGER," + - Mms.READ + " INTEGER DEFAULT 0," + - Mms.MESSAGE_ID + " TEXT," + - Mms.SUBJECT + " TEXT," + - Mms.SUBJECT_CHARSET + " INTEGER," + - Mms.CONTENT_TYPE + " TEXT," + - Mms.CONTENT_LOCATION + " TEXT," + - Mms.EXPIRY + " INTEGER," + - Mms.MESSAGE_CLASS + " TEXT," + - Mms.MESSAGE_TYPE + " INTEGER," + - Mms.MMS_VERSION + " INTEGER," + - Mms.MESSAGE_SIZE + " INTEGER," + - Mms.PRIORITY + " INTEGER," + - Mms.READ_REPORT + " INTEGER," + - Mms.REPORT_ALLOWED + " INTEGER," + - Mms.RESPONSE_STATUS + " INTEGER," + - Mms.STATUS + " INTEGER," + - Mms.TRANSACTION_ID + " TEXT," + - Mms.RETRIEVE_STATUS + " INTEGER," + - Mms.RETRIEVE_TEXT + " TEXT," + - Mms.RETRIEVE_TEXT_CHARSET + " INTEGER," + - Mms.READ_STATUS + " INTEGER," + - Mms.CONTENT_CLASS + " INTEGER," + - Mms.RESPONSE_TEXT + " TEXT," + - Mms.DELIVERY_TIME + " INTEGER," + - Mms.DELIVERY_REPORT + " INTEGER," + - Mms.LOCKED + " INTEGER DEFAULT 0," + - Mms.SUBSCRIPTION_ID + " INTEGER DEFAULT " - + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " + - Mms.SEEN + " INTEGER DEFAULT 0," + - Mms.CREATOR + " TEXT," + - Mms.TEXT_ONLY + " INTEGER DEFAULT 0" + - ");"); + db.execSQL(CREATE_PDU_TABLE_STR); + + db.execSQL(CREATE_ADDR_TABLE_STR); + + db.execSQL(CREATE_PART_TABLE_STR); + + db.execSQL(CREATE_RATE_TABLE_STR); - db.execSQL("CREATE TABLE " + MmsProvider.TABLE_ADDR + " (" + - Addr._ID + " INTEGER PRIMARY KEY," + - Addr.MSG_ID + " INTEGER," + - Addr.CONTACT_ID + " INTEGER," + - Addr.ADDRESS + " TEXT," + - Addr.TYPE + " INTEGER," + - Addr.CHARSET + " INTEGER);"); - - db.execSQL("CREATE TABLE " + MmsProvider.TABLE_PART + " (" + - Part._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - Part.MSG_ID + " INTEGER," + - Part.SEQ + " INTEGER DEFAULT 0," + - Part.CONTENT_TYPE + " TEXT," + - Part.NAME + " TEXT," + - Part.CHARSET + " INTEGER," + - Part.CONTENT_DISPOSITION + " TEXT," + - Part.FILENAME + " TEXT," + - Part.CONTENT_ID + " TEXT," + - Part.CONTENT_LOCATION + " TEXT," + - Part.CT_START + " INTEGER," + - Part.CT_TYPE + " TEXT," + - Part._DATA + " TEXT," + - Part.TEXT + " TEXT);"); - - db.execSQL("CREATE TABLE " + MmsProvider.TABLE_RATE + " (" + - Rate.SENT_TIME + " INTEGER);"); - - db.execSQL("CREATE TABLE " + MmsProvider.TABLE_DRM + " (" + - BaseColumns._ID + " INTEGER PRIMARY KEY," + - "_data TEXT);"); + db.execSQL(CREATE_DRM_TABLE_STR); // Restricted view of pdu table, only sent/received messages without wap pushes db.execSQL("CREATE VIEW " + MmsProvider.VIEW_PDU_RESTRICTED + " AS " + diff --git a/src/com/android/providers/telephony/MmsSmsProvider.java b/src/com/android/providers/telephony/MmsSmsProvider.java index 7b44583e..a9914257 100644 --- a/src/com/android/providers/telephony/MmsSmsProvider.java +++ b/src/com/android/providers/telephony/MmsSmsProvider.java @@ -23,12 +23,14 @@ import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.DatabaseUtils; +import android.database.MatrixCursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.os.Binder; import android.os.UserHandle; +import android.os.UserManager; import android.provider.BaseColumns; import android.provider.Telephony; import android.provider.Telephony.CanonicalAddressesColumns; @@ -335,6 +337,16 @@ public class MmsSmsProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + Cursor emptyCursor = new MatrixCursor((projection == null) ? + (new String[] {}) : projection); + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to query mms/sms, return empty cursor. + Log.e(LOG_TAG, "Managed profile is not allowed to query MMS/SMS."); + return emptyCursor; + } + // First check if restricted views of the "sms" and "pdu" tables should be used based on the // caller's identity. Only system, phone or the default sms app can have full access // of sms/mms data. For other apps, we present a restricted view which only contains sent @@ -1244,6 +1256,14 @@ public class MmsSmsProvider extends ContentProvider { @Override public int delete(Uri uri, String selection, String[] selectionArgs) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to delete mms/sms, return 0. + Log.e(LOG_TAG, "Managed profile is not allowed to delete MMS/SMS."); + return 0; + } + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); Context context = getContext(); int affectedRows = 0; @@ -1300,6 +1320,14 @@ public class MmsSmsProvider extends ContentProvider { @Override public Uri insert(Uri uri, ContentValues values) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to insert mms/sms, return null. + Log.e(LOG_TAG, "Managed profile is not allowed to insert MMS/SMS."); + return null; + } + if (URI_MATCHER.match(uri) == URI_PENDING_MSG) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long rowId = db.insert(TABLE_PENDING_MSG, null, values); @@ -1311,6 +1339,14 @@ public class MmsSmsProvider extends ContentProvider { @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to update mms/sms, return 0. + Log.e(LOG_TAG, "Managed profile is not allowed to update MMS/SMS."); + return 0; + } + final int callerUid = Binder.getCallingUid(); final String callerPkg = getCallingPackage(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java index 20817564..6fa85875 100644 --- a/src/com/android/providers/telephony/SmsProvider.java +++ b/src/com/android/providers/telephony/SmsProvider.java @@ -38,6 +38,7 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.os.Binder; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Contacts; import android.provider.Telephony; import android.provider.Telephony.MmsSms; @@ -146,6 +147,16 @@ public class SmsProvider extends ContentProvider { @Override public Cursor query(Uri url, String[] projectionIn, String selection, String[] selectionArgs, String sort) { + Cursor emptyCursor = new MatrixCursor((projectionIn == null) ? + (new String[] {}) : projectionIn); + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to query sms, return empty cursor. + Log.e(TAG, "Managed profile is not allowed to query SMS."); + return emptyCursor; + } + // First check if a restricted view of the "sms" table should be used based on the // caller's identity. Only system, phone or the default sms app can have full access // of sms data. For other apps, we present a restricted view which only contains sent @@ -521,6 +532,14 @@ public class SmsProvider extends ContentProvider { } private Uri insertInner(Uri url, ContentValues initialValues, int callerUid, String callerPkg) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to insert sms, return null. + Log.e(TAG, "Managed profile is not allowed to insert SMS."); + return null; + } + ContentValues values; long rowID; int type = Sms.MESSAGE_TYPE_ALL; @@ -1050,6 +1069,14 @@ public class SmsProvider extends ContentProvider { @Override public int delete(Uri url, String where, String[] whereArgs) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to delete sms, return 0. + Log.e(TAG, "Managed profile is not allowed to delete SMS."); + return 0; + } + int count; int match = sURLMatcher.match(url); SQLiteDatabase db = getDBOpenHelper(match).getWritableDatabase(); @@ -1161,6 +1188,14 @@ public class SmsProvider extends ContentProvider { @Override public int update(Uri url, ContentValues values, String where, String[] whereArgs) { + UserManager userManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); + if ((userManager != null) && (userManager.isManagedProfile( + Binder.getCallingUserHandle().getIdentifier()))) { + // If work profile is trying to update sms, return 0. + Log.e(TAG, "Managed profile is not allowed to update SMS."); + return 0; + } + final int callerUid = Binder.getCallingUid(); final String callerPkg = getCallingPackage(); int count = 0;