From 75c72cec7fd1010cd80bdfddcc2422da52dc859b Mon Sep 17 00:00:00 2001 From: mattgilbride Date: Tue, 20 Sep 2022 16:33:32 +0000 Subject: [PATCH] Add @PermissionMethod annotation For use by static analysis, @PermissionMethod documents the methods in the platform that perform permission "checks" (e.g. context.enforceCallingOrSelfPermission). Said methods either return in int of type @PermissionResult, or return void and potentially throw a SecurityException. There are currently two platform lints that care about this information. ManualPermissionCheckDetector and PackageVisibilityDetector. See: go/enforcepermission-migration-design Bug: 247537842 Test: Tested manually, ultimately will be tested in presubmit (atest AndroidFrameworkLintCheckerTest, see b/240445172) Change-Id: Ia21ba748eab37b532b591edb2599bb78ea0c8c9d --- .../android/app/ActivityManagerInternal.java | 2 ++ core/java/android/content/Context.java | 7 ++++ .../android/content/pm/PermissionMethod.java | 36 +++++++++++++++++++ .../server/am/ActivityManagerService.java | 11 ++++++ 4 files changed, 56 insertions(+) create mode 100644 core/java/android/content/pm/PermissionMethod.java diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 419b8e1ef0164..626b7d3cd5b1c 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -30,6 +30,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ActivityPresentationInfo; import android.content.pm.ApplicationInfo; +import android.content.pm.PermissionMethod; import android.content.pm.UserInfo; import android.net.Uri; import android.os.Bundle; @@ -292,6 +293,7 @@ public abstract class ActivityManagerInternal { boolean allowAll, int allowMode, String name, String callerPackage); /** Checks if the calling binder pid as the permission. */ + @PermissionMethod public abstract void enforceCallingPermission(String permission, String func); /** Returns the current user id. */ diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 97da2daf6e595..430b52c28f272 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -51,6 +51,7 @@ import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.PermissionMethod; import android.content.res.AssetManager; import android.content.res.ColorStateList; import android.content.res.Configuration; @@ -6066,6 +6067,7 @@ public abstract class Context { */ @CheckResult(suggest="#enforcePermission(String,int,int,String)") @PackageManager.PermissionResult + @PermissionMethod public abstract int checkPermission(@NonNull String permission, int pid, int uid); /** @hide */ @@ -6098,6 +6100,7 @@ public abstract class Context { */ @CheckResult(suggest="#enforceCallingPermission(String,String)") @PackageManager.PermissionResult + @PermissionMethod public abstract int checkCallingPermission(@NonNull String permission); /** @@ -6118,6 +6121,7 @@ public abstract class Context { */ @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") @PackageManager.PermissionResult + @PermissionMethod public abstract int checkCallingOrSelfPermission(@NonNull String permission); /** @@ -6146,6 +6150,7 @@ public abstract class Context { * * @see #checkPermission(String, int, int) */ + @PermissionMethod public abstract void enforcePermission( @NonNull String permission, int pid, int uid, @Nullable String message); @@ -6167,6 +6172,7 @@ public abstract class Context { * * @see #checkCallingPermission(String) */ + @PermissionMethod public abstract void enforceCallingPermission( @NonNull String permission, @Nullable String message); @@ -6183,6 +6189,7 @@ public abstract class Context { * * @see #checkCallingOrSelfPermission(String) */ + @PermissionMethod public abstract void enforceCallingOrSelfPermission( @NonNull String permission, @Nullable String message); diff --git a/core/java/android/content/pm/PermissionMethod.java b/core/java/android/content/pm/PermissionMethod.java new file mode 100644 index 0000000000000..021b2e1cd8f12 --- /dev/null +++ b/core/java/android/content/pm/PermissionMethod.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Documents that the subject method's job is to look + * up whether the provided or calling uid/pid has the requested permission. + * + * Methods should either return `void`, but potentially throw {@link SecurityException}, + * or return {@link android.content.pm.PackageManager.PermissionResult} `int`. + * + * @hide + */ +@Retention(CLASS) +@Target({METHOD}) +public @interface PermissionMethod {} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9d24e8e8638ee..8f9676c5fc3a2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -245,6 +245,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionInfo; +import android.content.pm.PermissionMethod; import android.content.pm.ProcessInfo; import android.content.pm.ProviderInfo; import android.content.pm.ProviderInfoList; @@ -5963,6 +5964,12 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * Allows if {@code pid} is {@link #MY_PID}, then denies if the {@code pid} has been denied + * provided non-{@code null} {@code permission} before. Otherwise calls into + * {@link ActivityManager#checkComponentPermission(String, int, int, boolean)}. + */ + @PermissionMethod public static int checkComponentPermission(String permission, int pid, int uid, int owningUid, boolean exported) { if (pid == MY_PID) { @@ -6009,6 +6016,7 @@ public class ActivityManagerService extends IActivityManager.Stub * This can be called with or without the global lock held. */ @Override + @PermissionMethod public int checkPermission(String permission, int pid, int uid) { if (permission == null) { return PackageManager.PERMISSION_DENIED; @@ -6020,6 +6028,7 @@ public class ActivityManagerService extends IActivityManager.Stub * Binder IPC calls go through the public entry point. * This can be called with or without the global lock held. */ + @PermissionMethod int checkCallingPermission(String permission) { return checkPermission(permission, Binder.getCallingPid(), @@ -6029,6 +6038,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * This can be called with or without the global lock held. */ + @PermissionMethod void enforceCallingPermission(String permission, String func) { if (checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { @@ -6046,6 +6056,7 @@ public class ActivityManagerService extends IActivityManager.Stub /** * This can be called with or without the global lock held. */ + @PermissionMethod void enforcePermission(String permission, int pid, int uid, String func) { if (checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED) { return;