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) {