Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 104cf9c8 authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by android-build-merger
Browse files

Merge "Add optional reasons why permissions were denied" into qt-dev

am: dd82c451

Change-Id: Iba294f338743c86d126eb4c4d92eb4c3d1c31cf0
parents 00454781 dd82c451
Loading
Loading
Loading
Loading
+12 −8
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource;
import android.permission.PermissionManager;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.util.Singleton;
import android.util.Singleton;
@@ -3738,6 +3739,7 @@ public class ActivityManager {
        }
        }
        // Isolated processes don't get any permissions.
        // Isolated processes don't get any permissions.
        if (UserHandle.isIsolated(uid)) {
        if (UserHandle.isIsolated(uid)) {
            PermissionManager.addPermissionDenialHint("uid " + uid + " is isolated");
            return PackageManager.PERMISSION_DENIED;
            return PackageManager.PERMISSION_DENIED;
        }
        }
        // If there is a uid that owns whatever is being accessed, it has
        // If there is a uid that owns whatever is being accessed, it has
@@ -3753,24 +3755,26 @@ public class ActivityManager {
            Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
            Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
                    here);
                    here);
            */
            */
            PermissionManager.addPermissionDenialHint(
                    "Target is not exported. owningUid=" + owningUid);
            return PackageManager.PERMISSION_DENIED;
            return PackageManager.PERMISSION_DENIED;
        }
        }
        if (permission == null) {
        if (permission == null) {
            return PackageManager.PERMISSION_GRANTED;
            return PackageManager.PERMISSION_GRANTED;
        }
        }
        try {
        return checkUidPermission(permission, uid);
            return AppGlobals.getPackageManager()
                    .checkUidPermission(permission, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    }


    /** @hide */
    /** @hide */
    public static int checkUidPermission(String permission, int uid) {
    public static int checkUidPermission(String permission, int uid) {
        try {
        try {
            List<String> hints = PermissionManager.getPermissionDenialHints();
            if (hints == null) {
                return AppGlobals.getPackageManager().checkUidPermission(permission, uid);
            } else {
                return AppGlobals.getPackageManager()
                return AppGlobals.getPackageManager()
                    .checkUidPermission(permission, uid);
                        .checkUidPermissionWithDenialHintForwarding(permission, uid, hints);
            }
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
+45 −19
Original line number Original line Diff line number Diff line
@@ -68,6 +68,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageManager;
import android.permission.PermissionManager;
import android.system.ErrnoException;
import android.system.ErrnoException;
import android.system.Os;
import android.system.Os;
import android.system.OsConstants;
import android.system.OsConstants;
@@ -98,6 +99,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteOrder;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;


@@ -1828,11 +1830,17 @@ class ContextImpl extends Context {
            }
            }
            Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
            Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
                    + permission);
                    + permission);
            PermissionManager.addPermissionDenialHint("Missing ActivityManager");
            return PackageManager.PERMISSION_DENIED;
            return PackageManager.PERMISSION_DENIED;
        }
        }


        try {
        try {
            List<String> hints = PermissionManager.getPermissionDenialHints();
            if (hints == null) {
                return am.checkPermission(permission, pid, uid);
                return am.checkPermission(permission, pid, uid);
            } else {
                return am.checkPermissionWithDenialHintForwarding(permission, pid, uid, hints);
            }
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
@@ -1889,43 +1897,61 @@ class ContextImpl extends Context {
            String permission, int resultOfCheck,
            String permission, int resultOfCheck,
            boolean selfToo, int uid, String message) {
            boolean selfToo, int uid, String message) {
        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
            List<String> hints = PermissionManager.getPermissionDenialHints();
            throw new SecurityException(
            throw new SecurityException(
                    (message != null ? (message + ": ") : "") +
                    (message != null ? (message + ": ") : "") +
                    (selfToo
                    (selfToo
                     ? "Neither user " + uid + " nor current process has "
                     ? "Neither user " + uid + " nor current process has "
                     : "uid " + uid + " does not have ") +
                     : "uid " + uid + " does not have ")
                    permission +
                            + permission + "."
                    ".");
                            + (hints == null ? "" : " Hints: " + hints));
        }
        }
    }
    }


    @Override
    @Override
    public void enforcePermission(
    public void enforcePermission(
            String permission, int pid, int uid, String message) {
            String permission, int pid, int uid, String message) {
        List<String> prev = PermissionManager.collectPermissionDenialHints(this, uid);
        try {
            enforce(permission,
            enforce(permission,
                    checkPermission(permission, pid, uid),
                    checkPermission(permission, pid, uid),
                    false,
                    false,
                    uid,
                    uid,
                    message);
                    message);
        } finally {
            PermissionManager.resetPermissionDenialHints(prev);
        }
    }
    }


    @Override
    @Override
    public void enforceCallingPermission(String permission, String message) {
    public void enforceCallingPermission(String permission, String message) {
        List<String> prev = PermissionManager.collectPermissionDenialHints(this,
                Binder.getCallingUid());
        try {
            enforce(permission,
            enforce(permission,
                    checkCallingPermission(permission),
                    checkCallingPermission(permission),
                    false,
                    false,
                    Binder.getCallingUid(),
                    Binder.getCallingUid(),
                    message);
                    message);
        } finally {
            PermissionManager.resetPermissionDenialHints(prev);
        }
    }
    }


    @Override
    @Override
    public void enforceCallingOrSelfPermission(
    public void enforceCallingOrSelfPermission(
            String permission, String message) {
            String permission, String message) {
        List<String> prev = PermissionManager.collectPermissionDenialHints(this,
                Binder.getCallingUid());
        try {
            enforce(permission,
            enforce(permission,
                    checkCallingOrSelfPermission(permission),
                    checkCallingOrSelfPermission(permission),
                    true,
                    true,
                    Binder.getCallingUid(),
                    Binder.getCallingUid(),
                    message);
                    message);
        } finally {
            PermissionManager.resetPermissionDenialHints(prev);
        }
    }
    }


    @Override
    @Override
+1 −0
Original line number Original line Diff line number Diff line
@@ -194,6 +194,7 @@ interface IActivityManager {
    int getProcessLimit();
    int getProcessLimit();
    @UnsupportedAppUsage
    @UnsupportedAppUsage
    int checkPermission(in String permission, int pid, int uid);
    int checkPermission(in String permission, int pid, int uid);
    int checkPermissionWithDenialHintForwarding(in String permission, int pid, int uid, inout List<String> permissionDenialHints);
    int checkUriPermission(in Uri uri, int pid, int uid, int mode, int userId,
    int checkUriPermission(in Uri uri, int pid, int uid, int mode, int userId,
            in IBinder callerToken);
            in IBinder callerToken);
    void grantUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
    void grantUriPermission(in IApplicationThread caller, in String targetPkg, in Uri uri,
+1 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,7 @@ interface IPackageManager {
    @UnsupportedAppUsage
    @UnsupportedAppUsage
    int checkPermission(String permName, String pkgName, int userId);
    int checkPermission(String permName, String pkgName, int userId);


    int checkUidPermissionWithDenialHintForwarding(String permName, int uid, inout List<String> permissionDenialHints);
    int checkUidPermission(String permName, int uid);
    int checkUidPermission(String permName, int uid);


    @UnsupportedAppUsage
    @UnsupportedAppUsage
+122 −0
Original line number Original line Diff line number Diff line
@@ -19,15 +19,22 @@ package android.permission;
import android.Manifest;
import android.Manifest;
import android.annotation.IntRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.TestApi;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.RemoteException;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;


import com.android.internal.annotations.Immutable;
import com.android.internal.annotations.Immutable;
import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import com.android.server.SystemConfig;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -42,6 +49,8 @@ import java.util.Objects;
@SystemApi
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
public final class PermissionManager {
    private static final String LOG_TAG = PermissionManager.class.getSimpleName();

    /**
    /**
     * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
     * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
     *
     *
@@ -54,6 +63,119 @@ public final class PermissionManager {


    private final IPackageManager mPackageManager;
    private final IPackageManager mPackageManager;


    /** Permission denials added via {@link addPermissionDenial} */
    private static final ThreadLocal<List<String>> sPermissionDenialHints = new ThreadLocal<>();

    /**
     * Report a hint that might explain why a permission check returned
     * {@link PackageManager#PERMISSION_DENIED}.
     *
     * <p>Hints are only collected if enabled via {@link collectPermissionDenialHints} or
     * when a non-null value was passed to {@link resetPermissionDenialHints}
     *
     * @param hint A description of the reason
     *
     * @hide
     */
    public static void addPermissionDenialHint(@NonNull String hint) {
        List<String> hints = sPermissionDenialHints.get();
        if (hints == null) {
            return;
        }

        hints.add(hint);
    }

    /**
     * @return hints added via {@link #addPermissionDenialHint(String)} on this thread before.
     *
     * @hide
     */
    public static @Nullable List<String> getPermissionDenialHints() {
        if (Build.IS_USER) {
            return null;
        }

        return sPermissionDenialHints.get();
    }

    /**
     * Reset the permission denial hints for this thread.
     *
     * @param initial The initial values. If not null, enabled collection on this thread.
     *
     * @return the previously collected hints
     *
     * @hide
     */
    public static @Nullable List<String> resetPermissionDenialHints(
            @Nullable List<String> initial) {
        List<String> prev = getPermissionDenialHints();
        if (initial == null) {
            sPermissionDenialHints.remove();
        } else {
            sPermissionDenialHints.set(initial);
        }
        return prev;
    }

    /**
     * Enable permission denial hint collection if package is in
     * {@link Settings.Secure.DEBUG_PACKAGE_PERMISSION_CHECK}
     *
     * @param context A context to use
     * @param uid The uid the permission check is for.
     *
     * @return the previously collected hints
     *
     * @hide
     */
    public static @Nullable List<String> collectPermissionDenialHints(@NonNull Context context,
            int uid) {
        List<String> prev = getPermissionDenialHints();

        if (Build.IS_USER) {
            return prev;
        }

        ContentResolver cr = context.getContentResolver();
        if (cr == null) {
            return prev;
        }

        String debugSetting;
        try {
            debugSetting = Settings.Secure.getString(cr,
                    Settings.Secure.DEBUG_PACKAGE_PERMISSION_CHECK);
        } catch (IllegalStateException e) {
            Log.e(LOG_TAG, "Cannot access settings", e);
            return prev;
        }
        if (debugSetting == null) {
            return prev;
        }
        String[] debugPkgs = debugSetting.split(",");

        PackageManager pm = context.getPackageManager();
        if (pm == null) {
            return prev;
        }

        String[] packages = pm.getPackagesForUid(uid);
        if (packages == null) {
            return prev;
        }

        for (String pkg : packages) {
            if (ArrayUtils.contains(debugPkgs, pkg)) {
                sPermissionDenialHints.set(new ArrayList<>(0));
                break;
            }
        }

        return prev;
    }

    /**
    /**
     * Creates a new instance.
     * Creates a new instance.
     *
     *
Loading