Merge "Protect usage data with OP_GET_USAGE_STATS." into pi-dev

am: ddb15c471c

Change-Id: Ieccbac3a53b14f196a3ceb7924f7bb6880660c97
This commit is contained in:
Jeff Sharkey
2018-04-19 19:55:24 -07:00
committed by android-build-merger
5 changed files with 69 additions and 50 deletions

View File

@@ -2831,7 +2831,7 @@ public class ApplicationPackageManager extends PackageManager {
synchronized (mLock) {
if (mArtManager == null) {
try {
mArtManager = new ArtManager(mPM.getArtManager());
mArtManager = new ArtManager(mContext, mPM.getArtManager());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -16,12 +16,16 @@
package android.content.pm.dex;
import static android.Manifest.permission.PACKAGE_USAGE_STATS;
import static android.Manifest.permission.READ_RUNTIME_PROFILES;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -62,13 +66,14 @@ public class ArtManager {
@Retention(RetentionPolicy.SOURCE)
public @interface ProfileType {}
private IArtManager mArtManager;
private final Context mContext;
private final IArtManager mArtManager;
/**
* @hide
*/
public ArtManager(@NonNull IArtManager manager) {
public ArtManager(@NonNull Context context, @NonNull IArtManager manager) {
mContext = context;
mArtManager = manager;
}
@@ -99,7 +104,7 @@ public class ArtManager {
* @param callback the callback which should be used for the result
* @param executor the executor which should be used to post the result
*/
@RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
@RequiresPermission(allOf = { READ_RUNTIME_PROFILES, PACKAGE_USAGE_STATS })
public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName,
@Nullable String codePath, @NonNull @CallbackExecutor Executor executor,
@NonNull SnapshotRuntimeProfileCallback callback) {
@@ -108,9 +113,10 @@ public class ArtManager {
SnapshotRuntimeProfileCallbackDelegate delegate =
new SnapshotRuntimeProfileCallbackDelegate(callback, executor);
try {
mArtManager.snapshotRuntimeProfile(profileType, packageName, codePath, delegate);
mArtManager.snapshotRuntimeProfile(profileType, packageName, codePath, delegate,
mContext.getOpPackageName());
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
throw e.rethrowAsRuntimeException();
}
}
@@ -122,14 +128,13 @@ public class ArtManager {
* @param profileType can be either {@link ArtManager#PROFILE_APPS}
* or {@link ArtManager#PROFILE_BOOT_IMAGE}
*/
@RequiresPermission(android.Manifest.permission.READ_RUNTIME_PROFILES)
@RequiresPermission(allOf = { READ_RUNTIME_PROFILES, PACKAGE_USAGE_STATS })
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType) {
try {
return mArtManager.isRuntimeProfilingEnabled(profileType);
return mArtManager.isRuntimeProfilingEnabled(profileType, mContext.getOpPackageName());
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
throw e.rethrowAsRuntimeException();
}
return false;
}
/**

View File

@@ -44,8 +44,8 @@ interface IArtManager {
* {@link ArtManager#isRuntimeProfilingEnabled(int)} does not return true for the given
* {@code profileType}.
*/
oneway void snapshotRuntimeProfile(int profileType, in String packageName,
in String codePath, in ISnapshotRuntimeProfileCallback callback);
void snapshotRuntimeProfile(int profileType, in String packageName,
in String codePath, in ISnapshotRuntimeProfileCallback callback, String callingPackage);
/**
* Returns true if runtime profiles are enabled for the given type, false otherwise.
@@ -54,5 +54,5 @@ interface IArtManager {
*
* @param profileType
*/
boolean isRuntimeProfilingEnabled(int profileType);
boolean isRuntimeProfilingEnabled(int profileType, String callingPackage);
}

View File

@@ -2462,7 +2462,7 @@ public class PackageManagerService extends IPackageManager.Stub
installer, mInstallLock);
mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock,
dexManagerListener);
mArtManagerService = new ArtManagerService(this, installer, mInstallLock);
mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mOnPermissionChangeListeners = new OnPermissionChangeListeners(

View File

@@ -16,8 +16,9 @@
package com.android.server.pm.dex;
import android.Manifest;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
@@ -38,7 +39,9 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.system.Os;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
@@ -47,14 +50,17 @@ import com.android.server.LocalServices;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageManagerServiceCompilerMapping;
import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
import java.io.File;
import java.io.FileNotFoundException;
import libcore.io.IoUtils;
import libcore.util.NonNull;
import libcore.util.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
/**
* A system service that provides access to runtime and compiler artifacts.
*
@@ -69,9 +75,7 @@ import libcore.util.Nullable;
*/
public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
private static final String TAG = "ArtManagerService";
private static boolean DEBUG = false;
private static boolean DEBUG_IGNORE_PERMISSIONS = false;
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
// Package name used to create the profile directory layout when
// taking a snapshot of the boot image profile.
@@ -79,6 +83,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
// Profile name used for the boot image profile.
private static final String BOOT_IMAGE_PROFILE_NAME = "android.prof";
private final Context mContext;
private final IPackageManager mPackageManager;
private final Object mInstallLock;
@GuardedBy("mInstallLock")
@@ -90,7 +95,9 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
verifyTronLoggingConstants();
}
public ArtManagerService(IPackageManager pm, Installer installer, Object installLock) {
public ArtManagerService(Context context, IPackageManager pm, Installer installer,
Object installLock) {
mContext = context;
mPackageManager = pm;
mInstaller = installer;
mInstallLock = installLock;
@@ -99,9 +106,37 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
LocalServices.addService(ArtManagerInternal.class, new ArtManagerInternalImpl());
}
private boolean checkPermission(int callingUid, String callingPackage) {
// Callers always need this permission
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_RUNTIME_PROFILES, TAG);
// Callers also need the ability to read usage statistics
switch (mContext.getSystemService(AppOpsManager.class)
.noteOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage)) {
case AppOpsManager.MODE_ALLOWED:
return true;
case AppOpsManager.MODE_DEFAULT:
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_USAGE_STATS, TAG);
return true;
default:
return false;
}
}
@Override
public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName,
@Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback) {
@Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback,
String callingPackage) {
if (!checkPermission(Binder.getCallingUid(), callingPackage)) {
try {
callback.onError(ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
} catch (RemoteException ignored) {
}
return;
}
// Sanity checks on the arguments.
Preconditions.checkNotNull(callback);
@@ -111,9 +146,8 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
Preconditions.checkStringNotEmpty(packageName);
}
// Verify that the caller has the right permissions and that the runtime profiling is
// enabled. The call to isRuntimePermissions will checkReadRuntimeProfilePermission.
if (!isRuntimeProfilingEnabled(profileType)) {
// Verify that runtime profiling is enabled.
if (!isRuntimeProfilingEnabled(profileType, callingPackage)) {
throw new IllegalStateException("Runtime profiling is not enabled for " + profileType);
}
@@ -231,9 +265,10 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
}
@Override
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType) {
// Verify that the caller has the right permissions.
checkReadRuntimeProfilePermission();
public boolean isRuntimeProfilingEnabled(@ProfileType int profileType, String callingPackage) {
if (!checkPermission(Binder.getCallingUid(), callingPackage)) {
return false;
}
switch (profileType) {
case ArtManager.PROFILE_APPS :
@@ -305,27 +340,6 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {
});
}
/**
* Verify that the binder calling uid has {@code android.permission.READ_RUNTIME_PROFILE}.
* If not, it throws a {@link SecurityException}.
*/
private void checkReadRuntimeProfilePermission() {
if (DEBUG_IGNORE_PERMISSIONS) {
return;
}
try {
int result = mPackageManager.checkUidPermission(
Manifest.permission.READ_RUNTIME_PROFILES, Binder.getCallingUid());
if (result != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("You need "
+ Manifest.permission.READ_RUNTIME_PROFILES
+ " permission to snapshot profiles.");
}
} catch (RemoteException e) {
// Should not happen.
}
}
/**
* Prepare the application profiles.
* For all code paths: