summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/PacProxySelector.java9
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java14
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java33
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java2
-rw-r--r--services/core/java/com/android/server/SystemConfig.java25
5 files changed, 75 insertions, 8 deletions
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java
index 9bdf4f6..85bf79a 100644
--- a/core/java/android/net/PacProxySelector.java
+++ b/core/java/android/net/PacProxySelector.java
@@ -30,6 +30,7 @@ import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
+import java.net.URISyntaxException;
import java.util.List;
/**
@@ -67,7 +68,15 @@ public class PacProxySelector extends ProxySelector {
String response = null;
String urlString;
try {
+ // Strip path and username/password from URI so it's not visible to PAC script. The
+ // path often contains credentials the app does not want exposed to a potentially
+ // malicious PAC script.
+ if (!"http".equalsIgnoreCase(uri.getScheme())) {
+ uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null);
+ }
urlString = uri.toURL().toString();
+ } catch (URISyntaxException e) {
+ urlString = uri.getHost();
} catch (MalformedURLException e) {
urlString = uri.getHost();
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 7699673..e137f94 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -656,7 +656,19 @@ public class ChooserActivity extends ResolverActivity {
}
intent.setComponent(mChooserTarget.getComponentName());
intent.putExtras(mChooserTarget.getIntentExtras());
- activity.startActivityAsCaller(intent, options, true, userId);
+
+ // Important: we will ignore the target security checks in ActivityManager
+ // if and only if the ChooserTarget's target package is the same package
+ // where we got the ChooserTargetService that provided it. This lets a
+ // ChooserTargetService provide a non-exported or permission-guarded target
+ // to the chooser for the user to pick.
+ //
+ // If mSourceInfo is null, we got this ChooserTarget from the caller or elsewhere
+ // so we'll obey the caller's normal security checks.
+ final boolean ignoreTargetSecurity = mSourceInfo != null
+ && mSourceInfo.getResolvedComponentName().getPackageName()
+ .equals(mChooserTarget.getComponentName().getPackageName());
+ activity.startActivityAsCaller(intent, options, ignoreTargetSecurity, userId);
return true;
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1629a37..3e57d31 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -80,7 +80,9 @@ import android.os.storage.StorageManager;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
+import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -93,6 +95,7 @@ import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
+import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
@@ -300,6 +303,7 @@ public class BackupManagerService {
volatile boolean mClearingData;
// Transport bookkeeping
+ final ArraySet<ComponentName> mTransportWhitelist;
final Intent mTransportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST);
final ArrayMap<String,String> mTransportNames
= new ArrayMap<String,String>(); // component name -> registration name
@@ -1084,11 +1088,15 @@ public class BackupManagerService {
// Set up our transport options and initialize the default transport
// TODO: Don't create transports that we don't need to?
- mCurrentTransport = Settings.Secure.getString(context.getContentResolver(),
+ SystemConfig systemConfig = SystemConfig.getInstance();
+ mTransportWhitelist = systemConfig.getBackupTransportWhitelist();
+
+ String transport = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.BACKUP_TRANSPORT);
- if ("".equals(mCurrentTransport)) {
- mCurrentTransport = null;
+ if (TextUtils.isEmpty(transport)) {
+ transport = null;
}
+ mCurrentTransport = transport;
if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport);
// Find all transport hosts and bind to their services
@@ -1099,11 +1107,11 @@ public class BackupManagerService {
}
if (hosts != null) {
for (int i = 0; i < hosts.size(); i++) {
- final ServiceInfo transport = hosts.get(i).serviceInfo;
+ final ServiceInfo transportService = hosts.get(i).serviceInfo;
if (MORE_DEBUG) {
- Slog.v(TAG, " " + transport.packageName + "/" + transport.name);
+ Slog.v(TAG, " " + transportService.packageName + "/" + transportService.name);
}
- tryBindTransport(transport);
+ tryBindTransport(transportService);
}
}
@@ -1983,7 +1991,12 @@ public class BackupManagerService {
// Actually bind; presumes that we have already validated the transport service
boolean bindTransport(ServiceInfo transport) {
ComponentName svcName = new ComponentName(transport.packageName, transport.name);
- if (MORE_DEBUG) {
+ if (!mTransportWhitelist.contains(svcName)) {
+ Slog.w(TAG, "Proposed transport " + svcName + " not whitelisted; ignoring");
+ return false;
+ }
+
+ if (DEBUG) {
Slog.i(TAG, "Binding to transport host " + svcName);
}
Intent intent = new Intent(mTransportServiceIntent);
@@ -9654,6 +9667,12 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
+ " (now = " + System.currentTimeMillis() + ')');
pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled());
+ pw.println("Transport whitelist:");
+ for (ComponentName transport : mTransportWhitelist) {
+ pw.print(" ");
+ pw.println(transport.flattenToShortString());
+ }
+
pw.println("Available transports:");
final String[] transports = listAllTransports();
if (transports != null) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 4fbccb6..317e5a0 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -470,6 +470,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void setLockPattern(String pattern, String savedCredential, int userId)
throws RemoteException {
+ checkWritePermission(userId);
byte[] currentHandle = getCurrentHandle(userId);
if (pattern == null) {
@@ -498,6 +499,7 @@ public class LockSettingsService extends ILockSettings.Stub {
@Override
public void setLockPassword(String password, String savedCredential, int userId)
throws RemoteException {
+ checkWritePermission(userId);
byte[] currentHandle = getCurrentHandle(userId);
if (password == null) {
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 7f5ddaa..fe69d98 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.pm.FeatureInfo;
import android.content.pm.Signature;
import android.os.*;
@@ -109,6 +110,9 @@ public class SystemConfig {
final ArrayMap<Signature, ArraySet<String>> mSignatureAllowances
= new ArrayMap<Signature, ArraySet<String>>();
+ // These are the permitted backup transport service components
+ final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
+
public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
@@ -158,6 +162,10 @@ public class SystemConfig {
return mSignatureAllowances;
}
+ public ArraySet<ComponentName> getBackupTransportWhitelist() {
+ return mBackupTransportWhitelist;
+ }
+
SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
@@ -432,6 +440,23 @@ public class SystemConfig {
mLinkedApps.add(makeLink(pkgname, state));
}
XmlUtils.skipCurrentTag(parser);
+ } else if ("backup-transport-whitelisted-service".equals(name)) {
+ String serviceName = parser.getAttributeValue(null, "service");
+ if (serviceName == null) {
+ Slog.w(TAG, "<backup-transport-whitelisted-service> without service in "
+ + permFile + " at " + parser.getPositionDescription());
+ } else {
+ ComponentName cn = ComponentName.unflattenFromString(serviceName);
+ if (cn == null) {
+ Slog.w(TAG,
+ "<backup-transport-whitelisted-service> with invalid service name "
+ + serviceName + " in "+ permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mBackupTransportWhitelist.add(cn);
+ }
+ }
+ XmlUtils.skipCurrentTag(parser);
} else {
XmlUtils.skipCurrentTag(parser);