Merge "Add sarahchin to OWNERS" am: 5ae1ab9935 am: 8b8eea4e26 am: 3e9f16d0e8
am: 961f3663ab
Change-Id: I96108f5e5c906108ffcc9b20f20a449bd0bda613
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
index 44f053d..d43e6c6 100644
--- a/src/com/android/providers/telephony/CarrierIdProvider.java
+++ b/src/com/android/providers/telephony/CarrierIdProvider.java
@@ -25,23 +25,23 @@
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.MatrixCursor;
-import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.SystemProperties;
import android.provider.Telephony.CarrierId;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.nano.CarrierIdProto;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -54,8 +54,6 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import libcore.io.IoUtils;
-
/**
* This class provides the ability to query the Carrier Identification databases
* (A.K.A. cid) which is stored in a SQLite database.
@@ -536,7 +534,7 @@
} catch (IOException ex) {
Log.e(TAG, "read carrier list from assets pb failure: " + ex);
} finally {
- IoUtils.closeQuietly(is);
+ FileUtils.closeQuietly(is);
}
try {
is = new FileInputStream(new File(Environment.getDataDirectory(), OTA_UPDATED_PB_PATH));
@@ -544,7 +542,7 @@
} catch (IOException ex) {
Log.e(TAG, "read carrier list from ota pb failure: " + ex);
} finally {
- IoUtils.closeQuietly(is);
+ FileUtils.closeQuietly(is);
}
// compare version
@@ -553,7 +551,7 @@
version = assets.version;
}
// bypass version check for ota carrier id test
- if (ota != null && ((Build.IS_DEBUGGABLE && SystemProperties.getBoolean(
+ if (ota != null && ((TelephonyUtils.IS_DEBUGGABLE && SystemProperties.getBoolean(
"persist.telephony.test.carrierid.ota", false))
|| (ota.version > version))) {
carrierList = ota;
diff --git a/src/com/android/providers/telephony/CellBroadcastProvider.java b/src/com/android/providers/telephony/CellBroadcastProvider.java
index 4c8a7e2..ccb3f4a 100644
--- a/src/com/android/providers/telephony/CellBroadcastProvider.java
+++ b/src/com/android/providers/telephony/CellBroadcastProvider.java
@@ -61,7 +61,7 @@
private static final String DATABASE_NAME = "cellbroadcasts.db";
/** Database version. */
- private static final int DATABASE_VERSION = 1;
+ private static final int DATABASE_VERSION = 2;
/** URI matcher for ContentProvider queries. */
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
@@ -243,6 +243,7 @@
return "CREATE TABLE " + tableName + " ("
+ CellBroadcasts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ CellBroadcasts.SUB_ID + " INTEGER,"
+ + CellBroadcasts.SLOT_INDEX + " INTEGER DEFAULT 0,"
+ CellBroadcasts.GEOGRAPHICAL_SCOPE + " INTEGER,"
+ CellBroadcasts.PLMN + " TEXT,"
+ CellBroadcasts.LAC + " INTEGER,"
@@ -299,7 +300,16 @@
}
@Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (DBG) {
+ Log.d(TAG, "onUpgrade: oldV=" + oldVersion + " newV=" + newVersion);
+ }
+ if (newVersion == 2) {
+ db.execSQL("ALTER TABLE " + CELL_BROADCASTS_TABLE_NAME + " ADD COLUMN "
+ + CellBroadcasts.SLOT_INDEX + " INTEGER DEFAULT 0;");
+ Log.d(TAG, "add slotIndex column");
+ }
+ }
}
private class CellBroadcastPermissionChecker implements PermissionChecker {
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index 30158c3..96059d7 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -31,7 +31,6 @@
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Binder;
-import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.provider.BaseColumns;
@@ -44,6 +43,8 @@
import android.provider.Telephony.Mms.Rate;
import android.provider.Telephony.MmsSms;
import android.provider.Telephony.Threads;
+import android.system.ErrnoException;
+import android.system.Os;
import android.text.TextUtils;
import android.util.Log;
@@ -518,9 +519,13 @@
// Give everyone rw permission until we encrypt the file
// (in PduPersister.persistData). Once the file is encrypted, the
// permissions will be set to 0644.
- int result = FileUtils.setPermissions(path, 0666, -1, -1);
- if (LOCAL_LOGV) {
- Log.d(TAG, "MmsProvider.insert setPermissions result: " + result);
+ try {
+ Os.chmod(path, 0666);
+ if (LOCAL_LOGV) {
+ Log.d(TAG, "MmsProvider.insert chmod is successful");
+ }
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Exception in chmod: " + e);
}
} catch (IOException e) {
Log.e(TAG, "createNewFile", e);
@@ -816,10 +821,13 @@
String path = getContext().getDir(PARTS_DIR_NAME, 0).getPath() + '/' +
uri.getPathSegments().get(1);
// Reset the file permission back to read for everyone but me.
- int result = FileUtils.setPermissions(path, 0644, -1, -1);
- if (LOCAL_LOGV) {
- Log.d(TAG, "MmsProvider.update setPermissions result: " + result +
- " for path: " + path);
+ try {
+ Os.chmod(path, 0644);
+ if (LOCAL_LOGV) {
+ Log.d(TAG, "MmsProvider.update chmod is successful for path: " + path);
+ }
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Exception in chmod: " + e);
}
return 0;
diff --git a/src/com/android/providers/telephony/SqlTokenFinder.java b/src/com/android/providers/telephony/SqlTokenFinder.java
deleted file mode 100644
index 9be49fe..0000000
--- a/src/com/android/providers/telephony/SqlTokenFinder.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.providers.telephony;
-
-import android.annotation.Nullable;
-
-import java.util.function.Consumer;
-
-/**
- * Simple SQL parser to check statements for usage of prohibited/sensitive fields. Mostly copied
- * from
- * packages/providers/ContactsProvider/src/com/android/providers/contacts/sqlite/SqlChecker.java
- */
-public class SqlTokenFinder{
- private static boolean isAlpha(char ch) {
- return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || (ch == '_');
- }
-
- private static boolean isNum(char ch) {
- return ('0' <= ch && ch <= '9');
- }
-
- private static boolean isAlNum(char ch) {
- return isAlpha(ch) || isNum(ch);
- }
-
- private static boolean isAnyOf(char ch, String set) {
- return set.indexOf(ch) >= 0;
- }
-
- private static char peek(String s, int index) {
- return index < s.length() ? s.charAt(index) : '\0';
- }
-
- /**
- * SQL Tokenizer specialized to extract tokens from SQL (snippets).
- *
- * Based on sqlite3GetToken() in tokenzie.c in SQLite.
- *
- * Source for v3.8.6 (which android uses): http://www.sqlite.org/src/artifact/ae45399d6252b4d7
- * (Latest source as of now: http://www.sqlite.org/src/artifact/78c8085bc7af1922)
- *
- * Also draft spec: http://www.sqlite.org/draft/tokenreq.html
- */
- public static void findTokens(@Nullable String sql, Consumer<String> checker) {
- if (sql == null) {
- return;
- }
- int pos = 0;
- final int len = sql.length();
- while (pos < len) {
- final char ch = peek(sql, pos);
-
- // Regular token.
- if (isAlpha(ch)) {
- final int start = pos;
- pos++;
- while (isAlNum(peek(sql, pos))) {
- pos++;
- }
- final int end = pos;
-
- final String token = sql.substring(start, end);
- checker.accept(token);
-
- continue;
- }
-
- // Handle quoted tokens
- if (isAnyOf(ch, "'\"`")) {
- final int quoteStart = pos;
- pos++;
-
- for (;;) {
- pos = sql.indexOf(ch, pos);
- if (pos < 0) {
- throw new IllegalArgumentException("Unterminated quote in" + sql);
- }
- if (peek(sql, pos + 1) != ch) {
- break;
- }
- // Quoted quote char -- e.g. "abc""def" is a single string.
- pos += 2;
- }
- final int quoteEnd = pos;
- pos++;
-
- if (ch != '\'') {
- // Extract the token
- final String tokenUnquoted = sql.substring(quoteStart + 1, quoteEnd);
-
- final String token;
-
- // Unquote if needed. i.e. "aa""bb" -> aa"bb
- if (tokenUnquoted.indexOf(ch) >= 0) {
- token = tokenUnquoted.replaceAll(
- String.valueOf(ch) + ch, String.valueOf(ch));
- } else {
- token = tokenUnquoted;
- }
- checker.accept(token);
- }
- continue;
- }
- // Handle tokens enclosed in [...]
- if (ch == '[') {
- final int quoteStart = pos;
- pos++;
-
- pos = sql.indexOf(']', pos);
- if (pos < 0) {
- throw new IllegalArgumentException("Unterminated quote in" + sql);
- }
- final int quoteEnd = pos;
- pos++;
-
- final String token = sql.substring(quoteStart + 1, quoteEnd);
-
- checker.accept(token);
- continue;
- }
-
- // Detect comments.
- if (ch == '-' && peek(sql, pos + 1) == '-') {
- pos += 2;
- pos = sql.indexOf('\n', pos);
- if (pos < 0) {
- // We disallow strings ending in an inline comment.
- throw new IllegalArgumentException("Unterminated comment in" + sql);
- }
- pos++;
-
- continue;
- }
- if (ch == '/' && peek(sql, pos + 1) == '*') {
- pos += 2;
- pos = sql.indexOf("*/", pos);
- if (pos < 0) {
- throw new IllegalArgumentException("Unterminated comment in" + sql);
- }
- pos += 2;
-
- continue;
- }
-
- // Semicolon is never allowed.
- if (ch == ';') {
- throw new IllegalArgumentException("Semicolon is not allowed in " + sql);
- }
-
- // For this purpose, we can simply ignore other characters.
- // (Note it doesn't handle the X'' literal properly and reports this X as a token,
- // but that should be fine...)
- pos++;
- }
- }
-}
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 56e9c8b..ae1d9cb 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -106,20 +106,19 @@
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
-import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.IApnSourceService;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.dataconnection.ApnSettingUtils;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.XmlUtils;
+import android.service.carrier.IApnSourceService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -207,10 +206,6 @@
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);
private static final ContentValues s_currentNullMap;
@@ -2807,7 +2802,7 @@
List<String> constraints = new ArrayList<String>();
int match = s_urlMatcher.match(url);
- checkQueryPermission(match, projectionIn, selection, sort);
+ checkPermission();
switch (match) {
case URL_TELEPHONY_USING_SUBID: {
subIdString = url.getLastPathSegment();
@@ -3016,69 +3011,6 @@
return ret;
}
- private void checkQueryPermission(int match, String[] projectionIn, String selection,
- String sort) {
- // Determine if we need to do a check for fields in the selection
- boolean selectionOrSortContainsSensitiveFields;
- try {
- selectionOrSortContainsSensitiveFields = containsSensitiveFields(selection);
- selectionOrSortContainsSensitiveFields |= containsSensitiveFields(sort);
- } catch (IllegalArgumentException e) {
- // Malformed sql, check permission anyway and return.
- checkPermission();
- return;
- }
-
- if (selectionOrSortContainsSensitiveFields) {
- try {
- checkPermission();
- } catch (SecurityException e) {
- EventLog.writeEvent(0x534e4554, "124107808", Binder.getCallingUid());
- throw e;
- }
- }
-
- if (match != URL_SIMINFO && match != URL_SIMINFO_USING_SUBID) {
- if (projectionIn != null) {
- for (String column : projectionIn) {
- if (TYPE.equals(column) ||
- MMSC.equals(column) ||
- MMSPROXY.equals(column) ||
- MMSPORT.equals(column) ||
- MVNO_TYPE.equals(column) ||
- MVNO_MATCH_DATA.equals(column) ||
- APN.equals(column)) {
- } else {
- checkPermission();
- break;
- }
- }
- } else {
- // null returns all columns, so need permission check
- checkPermission();
- }
- } else {
- // if querying siminfo, caller should have read privilege permissions
- checkPhonePrivilegePermission();
- }
- }
-
- private boolean containsSensitiveFields(String sqlStatement) {
- try {
- SqlTokenFinder.findTokens(sqlStatement, s -> {
- switch (s.toLowerCase()) {
- case USER:
- case PASSWORD:
- case SQL_SELECT_TOKEN:
- throw new SecurityException();
- }
- });
- } catch (SecurityException e) {
- return true;
- }
- return false;
- }
-
/**
* To find the current sim APN. Query APN based on {MCC, MNC, MVNO} to support backward
* compatibility but will move to carrier id in the future.
@@ -3847,15 +3779,6 @@
throw new SecurityException("No permission to write APN settings");
}
- private void checkPhonePrivilegePermission() {
- int status = getContext().checkCallingOrSelfPermission(
- "android.permission.READ_PRIVILEGED_PHONE_STATE");
- if (status == PackageManager.PERMISSION_GRANTED) {
- return;
- }
- throw new SecurityException("No phone privilege permission");
- }
-
private DatabaseHelper mOpenHelper;
private void restoreDefaultAPN(int subId) {