Merge the android-9.0.0_r55 release tag
Android 9.0.0 Release 55 (6197209)

* tag 'android-9.0.0_r55':
  DO NOT MERGE Check permissions for URL_SIMINFO
  resolve merge conflicts of 72b6ac9075afff486072049416d38b44c046c9f2 to pi-dev
  Examine sort field for sensitive fields

Change-Id: I9817026d051d84e9f9d417d609416325e3fd039f
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 8ff9121..8963559 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -190,6 +190,9 @@
 
     private static final String DEFAULT_PROTOCOL = "IP";
     private static final String DEFAULT_ROAMING_PROTOCOL = "IP";
+    // Used to check if certain queries contain subqueries that may attempt to access sensitive
+    // fields in the carriers db.
+    private static final String SQL_SELECT_TOKEN = "select";
 
     private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
@@ -2512,24 +2515,26 @@
             qb.appendWhere(TextUtils.join(" AND ", constraints));
         }
 
-        if (match != URL_SIMINFO) {
-            // Determine if we need to do a check for fields in the selection
-            boolean selectionContainsSensitiveFields;
-            try {
-                selectionContainsSensitiveFields = containsSensitiveFields(selection);
-            } catch (Exception e) {
-                // Malformed sql, check permission anyway.
-                selectionContainsSensitiveFields = true;
-            }
+        // Determine if we need to do a check for fields in the selection
+        boolean selectionOrSortContainsSensitiveFields;
+        try {
+            selectionOrSortContainsSensitiveFields = containsSensitiveFields(selection);
+            selectionOrSortContainsSensitiveFields |= containsSensitiveFields(sort);
+        } catch (Exception e) {
+            // Malformed sql, check permission anyway.
+            selectionOrSortContainsSensitiveFields = true;
+        }
 
-            if (selectionContainsSensitiveFields) {
-                try {
-                    checkPermission();
-                } catch (SecurityException e) {
-                    EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
-                    throw e;
-                }
+        if (selectionOrSortContainsSensitiveFields) {
+            try {
+                checkPermission();
+            } catch (SecurityException e) {
+                EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
+                throw e;
             }
+        }
+
+        if (match != URL_SIMINFO) {
             if (projectionIn != null) {
                 for (String column : projectionIn) {
                     if (TYPE.equals(column) ||
@@ -2547,6 +2552,9 @@
                 // null returns all columns, so need permission check
                 checkPermission();
             }
+        } else {
+            // For the sim_info table, we only require READ_PHONE_STATE
+            checkReadSimInfoPermission();
         }
 
         SQLiteDatabase db = getReadableDatabase();
@@ -2577,9 +2585,10 @@
     private boolean containsSensitiveFields(String sqlStatement) {
         try {
             SqlTokenFinder.findTokens(sqlStatement, s -> {
-                switch (s) {
+                switch (s.toLowerCase()) {
                     case USER:
                     case PASSWORD:
+                    case SQL_SELECT_TOKEN:
                         throw new SecurityException();
                 }
             });
@@ -3207,6 +3216,23 @@
         throw new SecurityException("No permission to write APN settings");
     }
 
+    private void checkReadSimInfoPermission() {
+        try {
+            // Even if the caller doesn't have READ_PHONE_STATE, we'll let them access sim_info as
+            // long as they have the more restrictive write_apn_settings or carrier priv.
+            checkPermission();
+            return;
+        } catch (SecurityException e) {
+            int status = getContext().checkCallingOrSelfPermission(
+                    "android.permission.READ_PHONE_STATE");
+            if (status == PackageManager.PERMISSION_GRANTED) {
+                return;
+            }
+            EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
+            throw new SecurityException("No READ_PHONE_STATE permission");
+        }
+    }
+
     private DatabaseHelper mOpenHelper;
 
     private void restoreDefaultAPN(int subId) {