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

Commit 697650b3 authored by Nate Myren's avatar Nate Myren
Browse files

Disable user-facing historical app ops methods

Disable the ability to see historical app ops using dumpsys, and by
calling "getHistoricalOps", unless the calling package has an
instrumentation, or is the statsd package.

Fixes: 148227477
Test: attempt to call into getHistoricalOps while not an instrumented
application or statsd. The method should return an empty bundle. Run
"adb shell dumpsys appops --history" should return "no such arg", and
"adb shell dumpsys appops -h" should not show "--history" in the args.

Change-Id: Ie5ad9a90ffc0473aba958199450bcff9315f71a6
parent 39d47275
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -367,4 +367,14 @@ public abstract class ActivityManagerInternal {
     * Unregisters the specified {@code processObserver}.
     */
    public abstract void unregisterProcessObserver(IProcessObserver processObserver);

    /**
     * Checks if there is an unfinished instrumentation that targets the given uid.
     *
     * @param uid The uid to be checked for
     *
     * @return True, if there is an instrumentation whose target application uid matches the given
     * uid, false otherwise
     */
    public abstract boolean isUidCurrentlyInstrumented(int uid);
}
+6 −0
Original line number Diff line number Diff line
@@ -172,6 +172,12 @@ public class Process {
     */
    public static final int OTA_UPDATE_UID = 1061;

    /**
     * Defines the UID used for statsd
     * @hide
     */
    public static final int STATSD_UID = 1066;

    /**
     * Defines the UID used for incidentd.
     * @hide
+14 −0
Original line number Diff line number Diff line
@@ -19040,6 +19040,20 @@ public class ActivityManagerService extends IActivityManager.Stub
        public void unregisterProcessObserver(IProcessObserver processObserver) {
            ActivityManagerService.this.unregisterProcessObserver(processObserver);
        }
        @Override
        public boolean isUidCurrentlyInstrumented(int uid) {
            synchronized (ActivityManagerService.this) {
                for (int i = mActiveInstrumentation.size() - 1; i >= 0; i--) {
                    ActiveInstrumentation activeInst = mActiveInstrumentation.get(i);
                    if (!activeInst.mFinished && activeInst.mTargetInfo != null
                            && activeInst.mTargetInfo.uid == uid) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+12 −4
Original line number Diff line number Diff line
@@ -50,12 +50,14 @@ import static android.app.AppOpsManager.resolveFirstUnrestrictedUidState;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static android.content.Intent.EXTRA_REPLACING;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.os.Process.STATSD_UID;

import android.Manifest;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -1760,6 +1762,15 @@ public class AppOpsService extends IAppOpsService.Stub {
                beginTimeMillis, endTimeMillis, flags);
        Objects.requireNonNull(callback, "callback cannot be null");

        ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
        boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid());
        boolean isCallerStatsCollector = Binder.getCallingUid() == STATSD_UID;

        if (!isCallerStatsCollector && !isCallerInstrumented) {
            mHandler.post(() -> callback.sendResult(new Bundle()));
            return;
        }

        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");

@@ -4475,8 +4486,6 @@ public class AppOpsService extends IAppOpsService.Stub {
        pw.println("    Limit output to data associated with the given feature id.");
        pw.println("  --watchers");
        pw.println("    Only output the watcher sections.");
        pw.println("  --history");
        pw.println("    Output the historical data.");
    }

    private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterFeatureId,
@@ -4609,6 +4618,7 @@ public class AppOpsService extends IAppOpsService.Stub {
        int dumpUid = Process.INVALID_UID;
        int dumpMode = -1;
        boolean dumpWatchers = false;
        // TODO ntmyren: Remove the dumpHistory and dumpFilter
        boolean dumpHistory = false;
        @HistoricalOpsRequestFilter int dumpFilter = 0;

@@ -4671,8 +4681,6 @@ public class AppOpsService extends IAppOpsService.Stub {
                    }
                } else if ("--watchers".equals(arg)) {
                    dumpWatchers = true;
                } else if ("--history".equals(arg)) {
                    dumpHistory = true;
                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
                    pw.println("Unknown option: " + arg);
                    return;
+3 −0
Original line number Diff line number Diff line
@@ -283,6 +283,8 @@ public class AppOpsServiceTest {
    }


    /*
    TODO ntmyren: re enable when we have time to rewrite test.
    @Test
    public void testPackageRemovedHistoricalOps() throws InterruptedException {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
@@ -321,6 +323,7 @@ public class AppOpsServiceTest {
        assertThat(latchRef.get().getCount()).isEqualTo(0);
        assertThat(resultOpsRef.get().isEmpty()).isTrue();
    }
     */

    @Test
    public void testUidRemoved() {