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

Commit 4a7c4ead authored by Pavel Grafov's avatar Pavel Grafov
Browse files

Add internal listener for unredacted events

Bug: 385730709
Test: atest CtsDevicePolicyManagerTestCases:MixedDeviceOwnerTest#testSecurityLoggingWithSingleUser
Test: atest CtsDevicePolicyTestCases:SecurityLoggingTest
Flag: android.app.admin.flags.internal_log_event_listener
Change-Id: I5734a7bcc07a743c8e28417634816b6c9a764d6f
parent d4815549
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.UserManager.EnforcingUser;

import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

/**
 * Device policy manager local system service interface.
@@ -338,4 +339,10 @@ public abstract class DevicePolicyManagerInternal {
     * Enforces resolved audit logging policy, should only be invoked from device policy engine.
     */
    public abstract void enforceAuditLoggingPolicy(boolean enabled);

    /**
     * Installs internal callback for security log events.
     */
    public abstract void setInternalEventsCallback(
            @Nullable Consumer<List<SecurityLog.SecurityEvent>> callback);
}
+10 −0
Original line number Diff line number Diff line
@@ -151,6 +151,16 @@ flag {
  bug: "295324350"
}

flag {
  name: "internal_log_event_listener"
  namespace: "enterprise"
  description: "Allow internal listeners to see unfiltered event stream"
  bug: "385730709"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
    name: "allow_querying_profile_type"
    is_exported: true
+6 −0
Original line number Diff line number Diff line
@@ -16138,6 +16138,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            enforceLoggingPolicy(Boolean.TRUE.equals(securityLoggingEnabled), enabled);
        }
        @Override
        public void setInternalEventsCallback(
                @Nullable Consumer<List<SecurityEvent>> callback) {
            mSecurityLogMonitor.setInternalEventsCallback(callback);
        }
        private List<EnforcingUser> getEnforcingUsers(Set<EnforcingAdmin> admins) {
            List<EnforcingUser> enforcingUsers = new ArrayList();
            ComponentName deviceOwner = mOwners.getDeviceOwnerComponent();
+36 −4
Original line number Diff line number Diff line
@@ -19,10 +19,12 @@ package com.android.server.devicepolicy;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;

import android.annotation.Nullable;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.IAuditLogEventsCallback;
import android.app.admin.SecurityLog;
import android.app.admin.SecurityLog.SecurityEvent;
import android.app.admin.flags.Flags;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
@@ -45,6 +47,7 @@ import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

/**
 * A class managing access to the security logs. It maintains an internal buffer of pending
@@ -183,6 +186,10 @@ class SecurityLogMonitor implements Runnable {
    @GuardedBy("mLock")
    private final ArrayDeque<SecurityEvent> mAuditLogEventBuffer = new ArrayDeque<>();

    @GuardedBy("mLock")
    @Nullable
    private Consumer<List<SecurityEvent>> mInternalEventsCallback;

    void stop() {
        Slog.i(TAG, "Stopping security logging.");
        mLock.lock();
@@ -221,7 +228,6 @@ class SecurityLogMonitor implements Runnable {
        } finally {
            mLock.unlock();
        }

    }

    @GuardedBy("mLock")
@@ -365,7 +371,9 @@ class SecurityLogMonitor implements Runnable {
                break;
            }
        }
        if (!Flags.internalLogEventListener()) {
            SecurityLog.redactEvents(newLogs, mEnabledUser);
        }
        if (DEBUG) Slog.d(TAG, "Got " + newLogs.size() + " new events.");
    }

@@ -400,7 +408,7 @@ class SecurityLogMonitor implements Runnable {
     */
    @GuardedBy("mLock")
    private void mergeBatchLocked(final ArrayList<SecurityEvent> newLogs) {
        List<SecurityEvent> dedupedLogs = new ArrayList<>();
        ArrayList<SecurityEvent> dedupedLogs = new ArrayList<>();
        // Run through the first events of the batch to check if there is an overlap with previous
        // batch and if so, skip overlapping events. Events are sorted by timestamp, so we can
        // compare it in linear time by advancing two pointers, one for each batch.
@@ -438,8 +446,19 @@ class SecurityLogMonitor implements Runnable {
                curPos++;
            }
        }
        // Assign an id to the new logs, after the overlap with mLastEvents.

        dedupedLogs.addAll(newLogs.subList(curPos, newLogs.size()));

        if (Flags.internalLogEventListener() && !dedupedLogs.isEmpty()) {
            if (mInternalEventsCallback != null) {
                final ArrayList<SecurityEvent> events = new ArrayList<>(dedupedLogs);
                final Consumer<List<SecurityEvent>> callback = mInternalEventsCallback;
                mHandler.post(() -> callback.accept(events));
            }
            SecurityLog.redactEvents(dedupedLogs, mEnabledUser);
        }

        // Assign an id to the new logs, after the overlap with mLastEvents.
        for (SecurityEvent event : dedupedLogs) {
            assignLogId(event);
        }
@@ -719,4 +738,17 @@ class SecurityLogMonitor implements Runnable {
            mLock.unlock();
        }
    }

    public void setInternalEventsCallback(@Nullable Consumer<List<SecurityEvent>> callback) {
        if (!Flags.internalLogEventListener()) {
            Slog.wtf(TAG, "Internal callbacks not enabled");
            return;
        }
        mLock.lock();
        try {
            this.mInternalEventsCallback = callback;
        } finally {
            mLock.unlock();
        }
    }
}