summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Activity.java3
-rw-r--r--core/java/android/app/ActivityManager.java39
-rw-r--r--core/java/android/app/ActivityManagerNative.java22
-rw-r--r--core/java/android/app/IActivityManager.java5
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java63
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java39
6 files changed, 135 insertions, 36 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 69ee434..faf946c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4999,7 +4999,8 @@ public class Activity extends ContextThemeWrapper
mCurrentConfig = config;
}
- final IBinder getActivityToken() {
+ /** @hide */
+ public final IBinder getActivityToken() {
return mParent != null ? mParent.getActivityToken() : mToken;
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4e61c3c..17b1962 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -26,7 +26,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.IPackageDataObserver;
-import android.content.res.Configuration;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
@@ -36,16 +36,17 @@ import android.os.Debug;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UserId;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -1798,6 +1799,40 @@ public class ActivityManager {
}
}
+ /** @hide */
+ public static int checkComponentPermission(String permission, int uid,
+ int owningUid, boolean exported) {
+ // Root, system server get to do everything.
+ if (uid == 0 || uid == Process.SYSTEM_UID) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ // Isolated processes don't get any permissions.
+ if (UserId.isIsolated(uid)) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ // If there is a uid that owns whatever is being accessed, it has
+ // blanket access to it regardless of the permissions it requires.
+ if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ // If the target is not exported, then nobody else can get to it.
+ if (!exported) {
+ Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
+ return PackageManager.PERMISSION_DENIED;
+ }
+ if (permission == null) {
+ return PackageManager.PERMISSION_GRANTED;
+ }
+ try {
+ return AppGlobals.getPackageManager()
+ .checkUidPermission(permission, uid);
+ } catch (RemoteException e) {
+ // Should never happen, but if it does... deny!
+ Slog.e(TAG, "PackageManager is dead?!?", e);
+ }
+ return PackageManager.PERMISSION_DENIED;
+ }
+
/**
* Returns the usage statistics of each installed package.
*
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 2f2918d..4506546 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1656,6 +1656,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_LAUNCHED_FROM_UID_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ int res = getLaunchedFromUid(token);
+ reply.writeNoException();
+ reply.writeInt(res);
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -3785,5 +3794,18 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
+ public int getLaunchedFromUid(IBinder activityToken) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(activityToken);
+ mRemote.transact(GET_LAUNCHED_FROM_UID_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int result = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return result;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index a2c7fa4..cf304df 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -350,6 +350,10 @@ public interface IActivityManager extends IInterface {
public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
throws RemoteException;
+ // This is not public because you need to be very careful in how you
+ // manage your activity to make sure it is always the uid you expect.
+ public int getLaunchedFromUid(IBinder activityToken) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -592,4 +596,5 @@ public interface IActivityManager extends IInterface {
int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147;
int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148;
+ int GET_LAUNCHED_FROM_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+149;
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 614f73f..7334ac3 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -20,6 +20,7 @@ import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +35,9 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.PatternMatcher;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserId;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -61,6 +65,7 @@ import java.util.Set;
public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {
private static final String TAG = "ResolverActivity";
+ private int mLaunchedFromUid;
private ResolveListAdapter mAdapter;
private PackageManager mPm;
private boolean mAlwaysUseOption;
@@ -102,6 +107,12 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
boolean alwaysUseOption) {
setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);
super.onCreate(savedInstanceState);
+ try {
+ mLaunchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid(
+ getActivityToken());
+ } catch (RemoteException e) {
+ mLaunchedFromUid = -1;
+ }
mPm = getPackageManager();
mAlwaysUseOption = alwaysUseOption;
mMaxColumns = getResources().getInteger(R.integer.config_maxResolverActivityColumns);
@@ -118,9 +129,14 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
mIconDpi = am.getLauncherLargeIconDensity();
mIconSize = am.getLauncherLargeIconSize();
- mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList);
+ mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList,
+ mLaunchedFromUid);
int count = mAdapter.getCount();
- if (count > 1) {
+ if (mLaunchedFromUid < 0 || UserId.isIsolated(mLaunchedFromUid)) {
+ // Gulp!
+ finish();
+ return;
+ } else if (count > 1) {
ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
mGrid = (GridView) ap.mView.findViewById(R.id.resolver_grid);
mGrid.setAdapter(mAdapter);
@@ -146,9 +162,13 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
if (alwaysUseOption) {
final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar);
- buttonLayout.setVisibility(View.VISIBLE);
- mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
- mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
+ if (buttonLayout != null) {
+ buttonLayout.setVisibility(View.VISIBLE);
+ mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
+ mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
+ } else {
+ mAlwaysUseOption = false;
+ }
}
}
@@ -207,6 +227,18 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
mPackageMonitor.unregister();
mRegistered = false;
}
+ if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ // This resolver is in the unusual situation where it has been
+ // launched at the top of a new task. We don't let it be added
+ // to the recent tasks shown to the user, and we need to make sure
+ // that each time we are launched we get the correct launching
+ // uid (not re-using the same resolver from an old launching uid),
+ // so we will now finish ourself since being no longer visible,
+ // the user probably can't get back to us.
+ if (!isChangingConfigurations()) {
+ finish();
+ }
+ }
}
@Override
@@ -363,17 +395,19 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
private final Intent[] mInitialIntents;
private final List<ResolveInfo> mBaseResolveList;
private final Intent mIntent;
+ private final int mLaunchedFromUid;
private final LayoutInflater mInflater;
private List<ResolveInfo> mCurrentResolveList;
private List<DisplayResolveInfo> mList;
public ResolveListAdapter(Context context, Intent intent,
- Intent[] initialIntents, List<ResolveInfo> rList) {
+ Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid) {
mIntent = new Intent(intent);
mIntent.setComponent(null);
mInitialIntents = initialIntents;
mBaseResolveList = rList;
+ mLaunchedFromUid = launchedFromUid;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rebuildList();
}
@@ -400,6 +434,23 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
mCurrentResolveList = mPm.queryIntentActivities(
mIntent, PackageManager.MATCH_DEFAULT_ONLY
| (mAlwaysUseOption ? PackageManager.GET_RESOLVED_FILTER : 0));
+ // Filter out any activities that the launched uid does not
+ // have permission for. We don't do this when we have an explicit
+ // list of resolved activities, because that only happens when
+ // we are being subclassed, so we can safely launch whatever
+ // they gave us.
+ if (mCurrentResolveList != null) {
+ for (int i=mCurrentResolveList.size()-1; i >= 0; i--) {
+ ActivityInfo ai = mCurrentResolveList.get(i).activityInfo;
+ int granted = ActivityManager.checkComponentPermission(
+ ai.permission, mLaunchedFromUid,
+ ai.applicationInfo.uid, ai.exported);
+ if (granted != PackageManager.PERMISSION_GRANTED) {
+ // Access not allowed!
+ mCurrentResolveList.remove(i);
+ }
+ }
+ }
}
int N;
if ((mCurrentResolveList != null) && ((N = mCurrentResolveList.size()) > 0)) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 76016f4..6464d7f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4639,35 +4639,12 @@ public final class ActivityManagerService extends ActivityManagerNative
pid = tlsIdentity.pid;
}
- // Root, system server and our own process get to do everything.
- if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
- return PackageManager.PERMISSION_GRANTED;
- }
- // Isolated processes don't get any permissions.
- if (UserId.isIsolated(uid)) {
- return PackageManager.PERMISSION_DENIED;
- }
- // If there is a uid that owns whatever is being accessed, it has
- // blanket access to it regardless of the permissions it requires.
- if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
- return PackageManager.PERMISSION_GRANTED;
- }
- // If the target is not exported, then nobody else can get to it.
- if (!exported) {
- Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
- return PackageManager.PERMISSION_DENIED;
- }
- if (permission == null) {
+ if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
- try {
- return AppGlobals.getPackageManager()
- .checkUidPermission(permission, uid);
- } catch (RemoteException e) {
- // Should never happen, but if it does... deny!
- Slog.e(TAG, "PackageManager is dead?!?", e);
- }
- return PackageManager.PERMISSION_DENIED;
+
+ return ActivityManager.checkComponentPermission(permission, uid,
+ owningUid, exported);
}
/**
@@ -13544,6 +13521,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ public int getLaunchedFromUid(IBinder activityToken) {
+ ActivityRecord srec = ActivityRecord.forToken(activityToken);
+ if (srec == null) {
+ return -1;
+ }
+ return srec.launchedFromUid;
+ }
+
// =========================================================
// LIFETIME MANAGEMENT
// =========================================================