diff options
| -rw-r--r-- | core/java/android/app/Activity.java | 3 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManager.java | 39 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 22 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 5 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ResolverActivity.java | 63 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 39 |
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 // ========================================================= |
