Respect app-ops permission in FileIntegrityService
Previous permission doesn't consider REQUEST_INSTALL_PACKAGES permission
as an app-ops permission.
Bug: 152009905
Test: atest GtsPlayFsiTestCases
Test: remove appops setup from AndroidTest.xml, the same test failed
Change-Id: Icdbf6bb35fe146c5be8a97e29c4c554b3ce91b5d
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1aabd24..054e5e0 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1310,7 +1310,7 @@
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(
Context.FILE_INTEGRITY_SERVICE);
- return new FileIntegrityManager(
+ return new FileIntegrityManager(ctx.getOuterContext(),
IFileIntegrityService.Stub.asInterface(b));
}});
//CHECKSTYLE:ON IndentationCheck
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
index cdd6584..266046e 100644
--- a/core/java/android/security/FileIntegrityManager.java
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -31,9 +31,11 @@
@SystemService(Context.FILE_INTEGRITY_SERVICE)
public final class FileIntegrityManager {
@NonNull private final IFileIntegrityService mService;
+ @NonNull private final Context mContext;
/** @hide */
- public FileIntegrityManager(@NonNull IFileIntegrityService service) {
+ public FileIntegrityManager(@NonNull Context context, @NonNull IFileIntegrityService service) {
+ mContext = context;
mService = service;
}
@@ -69,7 +71,8 @@
public boolean isAppSourceCertificateTrusted(@NonNull X509Certificate certificate)
throws CertificateEncodingException {
try {
- return mService.isAppSourceCertificateTrusted(certificate.getEncoded());
+ return mService.isAppSourceCertificateTrusted(
+ certificate.getEncoded(), mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/security/IFileIntegrityService.aidl b/core/java/android/security/IFileIntegrityService.aidl
index ebb8bcb..dff347e 100644
--- a/core/java/android/security/IFileIntegrityService.aidl
+++ b/core/java/android/security/IFileIntegrityService.aidl
@@ -22,5 +22,5 @@
*/
interface IFileIntegrityService {
boolean isApkVeritySupported();
- boolean isAppSourceCertificateTrusted(in byte[] certificateBytes);
+ boolean isAppSourceCertificateTrusted(in byte[] certificateBytes, in String packageName);
}
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 482090a..841aca5 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -18,14 +18,19 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.security.IFileIntegrityService;
import android.util.Slog;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.io.ByteArrayInputStream;
@@ -58,10 +63,10 @@
}
@Override
- public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes) {
- enforceAnyCallingPermissions(
- android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
- android.Manifest.permission.INSTALL_PACKAGES);
+ public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes,
+ @NonNull String packageName) {
+ checkCallerPermission(packageName);
+
try {
if (!isApkVeritySupported()) {
return false;
@@ -77,14 +82,30 @@
}
}
- private void enforceAnyCallingPermissions(String ...permissions) {
- for (String permission : permissions) {
- if (getContext().checkCallingPermission(permission)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
+ private void checkCallerPermission(String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final PackageManagerInternal packageManager =
+ LocalServices.getService(PackageManagerInternal.class);
+ final int packageUid = packageManager.getPackageUid(
+ packageName, 0 /*flag*/, callingUserId);
+ if (callingUid != packageUid) {
+ throw new SecurityException(
+ "Calling uid " + callingUid + " does not own package " + packageName);
}
- throw new SecurityException("Insufficient permission");
+
+ if (getContext().checkCallingPermission(android.Manifest.permission.INSTALL_PACKAGES)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ final int mode = appOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, callingUid, packageName);
+ if (mode != AppOpsManager.MODE_ALLOWED) {
+ throw new SecurityException(
+ "Caller should have INSTALL_PACKAGES or REQUEST_INSTALL_PACKAGES");
+ }
}
};