Loading services/core/java/com/android/server/selinux/QuotaExceededException.java 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 com.android.server.selinux; /** An exception raised when the quota has been reached. * * This exception is raised in EventLogCollection.add(). See QuotaLimiter * for the implementation details. */ class QuotaExceededException extends Exception {} services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java +89 −58 Original line number Diff line number Diff line Loading @@ -28,10 +28,8 @@ import com.android.server.utils.Slogf; import java.io.IOException; import java.time.Instant; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.AbstractCollection; import java.util.Iterator; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; import java.util.regex.Matcher; Loading @@ -57,6 +55,7 @@ class SelinuxAuditLogsCollector { private final Supplier<String> mAuditDomainSupplier; private final RateLimiter mRateLimiter; private final QuotaLimiter mQuotaLimiter; private EventLogCollection mEventCollection; @VisibleForTesting Instant mLastWrite = Instant.MIN; Loading @@ -69,6 +68,7 @@ class SelinuxAuditLogsCollector { mAuditDomainSupplier = auditDomainSupplier; mRateLimiter = rateLimiter; mQuotaLimiter = quotaLimiter; mEventCollection = new EventLogCollection(); } SelinuxAuditLogsCollector(RateLimiter rateLimiter, QuotaLimiter quotaLimiter) { Loading @@ -86,75 +86,72 @@ class SelinuxAuditLogsCollector { mStopRequested.set(stopRequested); } /** * Collect and push SELinux audit logs for the provided {@code tagCode}. /** A Collection to work around EventLog.readEvents() constraints. * * This collection only supports add(). Any other method inherited from * Collection will throw an UnsupportedOperationException exception. * * @return true if the job was completed. If the job was interrupted, return false. * This collection ensures that we are processing one event at a time and * avoid collecting all the event objects before processing (e.g., * ArrayList), which could lead to an OOM situation. */ boolean collect(int tagCode) { Queue<Event> logLines = new ArrayDeque<>(); Instant latestTimestamp = collectLogLines(tagCode, logLines); class EventLogCollection extends AbstractCollection<Event> { boolean quotaExceeded = writeAuditLogs(logLines); if (quotaExceeded) { Slog.w(TAG, "Too many SELinux logs in the queue, I am giving up."); mLastWrite = latestTimestamp; // next run we will ignore all these logs. logLines.clear(); SelinuxAuditLogBuilder mAuditLogBuilder; int mAuditsWritten = 0; Instant mLatestTimestamp; void reset() { mAuditsWritten = 0; mLatestTimestamp = mLastWrite; mAuditLogBuilder = new SelinuxAuditLogBuilder(mAuditDomainSupplier.get()); } return logLines.isEmpty(); int getAuditsWritten() { return mAuditsWritten; } private Instant collectLogLines(int tagCode, Queue<Event> logLines) { List<Event> events = new ArrayList<>(); try { EventLog.readEvents(new int[] {tagCode}, events); } catch (IOException e) { Slog.e(TAG, "Error reading event logs", e); Instant getLatestTimestamp() { return mLatestTimestamp; } @Override public Iterator<Event> iterator() { throw new UnsupportedOperationException(); } @Override public int size() { throw new UnsupportedOperationException(); } Instant latestTimestamp = mLastWrite; for (Event event : events) { Instant eventTime = Instant.ofEpochSecond(0, event.getTimeNanos()); if (eventTime.isAfter(latestTimestamp)) { latestTimestamp = eventTime; @Override public boolean add(Event event) { if (mStopRequested.get()) { throw new IllegalStateException(new InterruptedException()); } Instant eventTime = Instant.ofEpochSecond(/* epochSecond= */ 0, event.getTimeNanos()); if (eventTime.compareTo(mLastWrite) <= 0) { continue; return true; } Object eventData = event.getData(); if (!(eventData instanceof String)) { continue; } logLines.add(event); } return latestTimestamp; return true; } private boolean writeAuditLogs(Queue<Event> logLines) { final SelinuxAuditLogBuilder auditLogBuilder = new SelinuxAuditLogBuilder(mAuditDomainSupplier.get()); int auditsWritten = 0; while (!mStopRequested.get() && !logLines.isEmpty()) { Event event = logLines.poll(); String logLine = (String) event.getData(); Instant logTime = Instant.ofEpochSecond(0, event.getTimeNanos()); String logLine = (String) eventData; if (!SELINUX_MATCHER.reset(logLine).matches()) { continue; return true; } auditLogBuilder.reset(SELINUX_MATCHER.group("denial")); final SelinuxAuditLog auditLog = auditLogBuilder.build(); mAuditLogBuilder.reset(SELINUX_MATCHER.group("denial")); final SelinuxAuditLog auditLog = mAuditLogBuilder.build(); if (auditLog == null) { continue; return true; } if (!mQuotaLimiter.acquire()) { if (DEBUG) { Slogf.d(TAG, "Running out of quota after %d logs.", auditsWritten); } return true; throw new IllegalStateException(new QuotaExceededException()); } mRateLimiter.acquire(); Loading @@ -169,16 +166,50 @@ class SelinuxAuditLogsCollector { auditLog.mTClass, auditLog.mPath, auditLog.mPermissive); auditsWritten++; if (logTime.isAfter(mLastWrite)) { mLastWrite = logTime; mAuditsWritten++; if (eventTime.isAfter(mLatestTimestamp)) { mLatestTimestamp = eventTime; } return true; } } /** * Collect and push SELinux audit logs for the provided {@code tagCode}. * * @return true if the job was completed. If the job was interrupted or * failed because of IOException, return false. * @throws QuotaExceededException if it ran out of quota. */ boolean collect(int tagCode) throws QuotaExceededException { mEventCollection.reset(); try { EventLog.readEvents(new int[] {tagCode}, mEventCollection); } catch (IllegalStateException e) { if (e.getCause() instanceof QuotaExceededException) { if (DEBUG) { Slogf.d(TAG, "Written %d logs", auditsWritten); Slogf.d(TAG, "Running out of quota after %d logs.", mEventCollection.getAuditsWritten()); } // next run we will ignore all these logs. mLastWrite = mEventCollection.getLatestTimestamp(); throw (QuotaExceededException) e.getCause(); } else if (e.getCause() instanceof InterruptedException) { mLastWrite = mEventCollection.getLatestTimestamp(); return false; } throw e; } catch (IOException e) { Slog.e(TAG, "Error reading event logs", e); return false; } mLastWrite = mEventCollection.getLatestTimestamp(); if (DEBUG) { Slogf.d(TAG, "Written %d logs", mEventCollection.getAuditsWritten()); } return true; } } services/core/java/com/android/server/selinux/SelinuxAuditLogsJob.java +6 −2 Original line number Diff line number Diff line Loading @@ -51,10 +51,14 @@ final class SelinuxAuditLogsJob { return; } mIsRunning.set(true); try { boolean done = mAuditLogsCollector.collect(SelinuxAuditLogsService.AUDITD_TAG_CODE); if (done) { jobService.jobFinished(params, /* wantsReschedule= */ false); } } catch (QuotaExceededException e) { jobService.jobFinished(params, /* wantsReschedule= */ false); } mIsRunning.set(false); } } services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsCollectorTest.java +18 −20 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; Loading Loading @@ -81,7 +82,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs() { public void testWriteAuditLogs() throws Exception { writeTestLog("granted", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm1", TEST_DOMAIN, "ttype1", "tclass1"); Loading Loading @@ -117,7 +118,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_multiplePerms() { public void testWriteAuditLogs_multiplePerms() throws Exception { writeTestLog("denied", "perm1 perm2", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm3 perm4", TEST_DOMAIN, "ttype", "tclass"); Loading Loading @@ -153,7 +154,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_withPaths() { public void testWriteAuditLogs_withPaths() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/good/path"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/very/long/path"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/short_path"); Loading Loading @@ -217,7 +218,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_withCategories() { public void testWriteAuditLogs_withCategories() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, new int[] {123}, "ttype", null, "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, new int[] {123, 456}, "ttype", null, "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, null, "ttype", new int[] {666}, "tclass"); Loading Loading @@ -288,7 +289,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_withPathAndCategories() { public void testWriteAuditLogs_withPathAndCategories() throws Exception { writeTestLog( "denied", "perm", Loading Loading @@ -318,7 +319,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_permissive() { public void testWriteAuditLogs_permissive() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", true); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", false); Loading Loading @@ -356,7 +357,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testNotWriteAuditLogs_notTestDomain() { public void testNotWriteAuditLogs_notTestDomain() throws Exception { writeTestLog("denied", "perm", "stype", "ttype", "tclass"); boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); Loading @@ -379,7 +380,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_upToQuota() { public void testWriteAuditLogs_upToQuota() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); Loading @@ -389,9 +390,9 @@ public class SelinuxAuditLogsCollectorTest { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); assertThrows(QuotaExceededException.class, () -> mSelinuxAutidLogsCollector.collect(ANSWER_TAG)); assertThat(done).isTrue(); verify( () -> FrameworkStatsLog.write( Loading @@ -409,7 +410,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_resetQuota() { public void testWriteAuditLogs_resetQuota() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); Loading @@ -418,8 +419,8 @@ public class SelinuxAuditLogsCollectorTest { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); assertThat(done).isTrue(); assertThrows(QuotaExceededException.class, () -> mSelinuxAutidLogsCollector.collect(ANSWER_TAG)); verify( () -> FrameworkStatsLog.write( Loading @@ -442,8 +443,8 @@ public class SelinuxAuditLogsCollectorTest { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); // move the clock forward to reset the quota limiter. mClock.currentTimeMillis += Duration.ofHours(1).toMillis(); done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); assertThat(done).isTrue(); assertThrows(QuotaExceededException.class, () -> mSelinuxAutidLogsCollector.collect(ANSWER_TAG)); verify( () -> FrameworkStatsLog.write( Loading @@ -461,14 +462,11 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testNotWriteAuditLogs_stopRequested() { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); public void testNotWriteAuditLogs_stopRequested() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); // These are not pushed. writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); mSelinuxAutidLogsCollector.setStopRequested(true); Loading Loading @@ -509,7 +507,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testAuditLogs_resumeJobDoesNotExceedLimit() { public void testAuditLogs_resumeJobDoesNotExceedLimit() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); mSelinuxAutidLogsCollector.setStopRequested(true); Loading services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsJobTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testFinishSuccessfully() { public void testFinishSuccessfully() throws Exception { when(mAuditLogsCollector.collect(anyInt())).thenReturn(true); mAuditLogsJob.start(mJobService, mParams); Loading @@ -63,7 +63,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testInterrupt() { public void testInterrupt() throws Exception { when(mAuditLogsCollector.collect(anyInt())).thenReturn(false); mAuditLogsJob.start(mJobService, mParams); Loading @@ -73,7 +73,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testInterruptAndResume() { public void testInterruptAndResume() throws Exception { when(mAuditLogsCollector.collect(anyInt())).thenReturn(false); mAuditLogsJob.start(mJobService, mParams); verify(mJobService, never()).jobFinished(any(), anyBoolean()); Loading @@ -85,7 +85,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testRequestStop() throws InterruptedException { public void testRequestStop() throws Exception { Semaphore isRunning = new Semaphore(0); Semaphore stopRequested = new Semaphore(0); AtomicReference<Throwable> uncaughtException = new AtomicReference<>(); Loading Loading
services/core/java/com/android/server/selinux/QuotaExceededException.java 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 com.android.server.selinux; /** An exception raised when the quota has been reached. * * This exception is raised in EventLogCollection.add(). See QuotaLimiter * for the implementation details. */ class QuotaExceededException extends Exception {}
services/core/java/com/android/server/selinux/SelinuxAuditLogsCollector.java +89 −58 Original line number Diff line number Diff line Loading @@ -28,10 +28,8 @@ import com.android.server.utils.Slogf; import java.io.IOException; import java.time.Instant; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.AbstractCollection; import java.util.Iterator; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; import java.util.regex.Matcher; Loading @@ -57,6 +55,7 @@ class SelinuxAuditLogsCollector { private final Supplier<String> mAuditDomainSupplier; private final RateLimiter mRateLimiter; private final QuotaLimiter mQuotaLimiter; private EventLogCollection mEventCollection; @VisibleForTesting Instant mLastWrite = Instant.MIN; Loading @@ -69,6 +68,7 @@ class SelinuxAuditLogsCollector { mAuditDomainSupplier = auditDomainSupplier; mRateLimiter = rateLimiter; mQuotaLimiter = quotaLimiter; mEventCollection = new EventLogCollection(); } SelinuxAuditLogsCollector(RateLimiter rateLimiter, QuotaLimiter quotaLimiter) { Loading @@ -86,75 +86,72 @@ class SelinuxAuditLogsCollector { mStopRequested.set(stopRequested); } /** * Collect and push SELinux audit logs for the provided {@code tagCode}. /** A Collection to work around EventLog.readEvents() constraints. * * This collection only supports add(). Any other method inherited from * Collection will throw an UnsupportedOperationException exception. * * @return true if the job was completed. If the job was interrupted, return false. * This collection ensures that we are processing one event at a time and * avoid collecting all the event objects before processing (e.g., * ArrayList), which could lead to an OOM situation. */ boolean collect(int tagCode) { Queue<Event> logLines = new ArrayDeque<>(); Instant latestTimestamp = collectLogLines(tagCode, logLines); class EventLogCollection extends AbstractCollection<Event> { boolean quotaExceeded = writeAuditLogs(logLines); if (quotaExceeded) { Slog.w(TAG, "Too many SELinux logs in the queue, I am giving up."); mLastWrite = latestTimestamp; // next run we will ignore all these logs. logLines.clear(); SelinuxAuditLogBuilder mAuditLogBuilder; int mAuditsWritten = 0; Instant mLatestTimestamp; void reset() { mAuditsWritten = 0; mLatestTimestamp = mLastWrite; mAuditLogBuilder = new SelinuxAuditLogBuilder(mAuditDomainSupplier.get()); } return logLines.isEmpty(); int getAuditsWritten() { return mAuditsWritten; } private Instant collectLogLines(int tagCode, Queue<Event> logLines) { List<Event> events = new ArrayList<>(); try { EventLog.readEvents(new int[] {tagCode}, events); } catch (IOException e) { Slog.e(TAG, "Error reading event logs", e); Instant getLatestTimestamp() { return mLatestTimestamp; } @Override public Iterator<Event> iterator() { throw new UnsupportedOperationException(); } @Override public int size() { throw new UnsupportedOperationException(); } Instant latestTimestamp = mLastWrite; for (Event event : events) { Instant eventTime = Instant.ofEpochSecond(0, event.getTimeNanos()); if (eventTime.isAfter(latestTimestamp)) { latestTimestamp = eventTime; @Override public boolean add(Event event) { if (mStopRequested.get()) { throw new IllegalStateException(new InterruptedException()); } Instant eventTime = Instant.ofEpochSecond(/* epochSecond= */ 0, event.getTimeNanos()); if (eventTime.compareTo(mLastWrite) <= 0) { continue; return true; } Object eventData = event.getData(); if (!(eventData instanceof String)) { continue; } logLines.add(event); } return latestTimestamp; return true; } private boolean writeAuditLogs(Queue<Event> logLines) { final SelinuxAuditLogBuilder auditLogBuilder = new SelinuxAuditLogBuilder(mAuditDomainSupplier.get()); int auditsWritten = 0; while (!mStopRequested.get() && !logLines.isEmpty()) { Event event = logLines.poll(); String logLine = (String) event.getData(); Instant logTime = Instant.ofEpochSecond(0, event.getTimeNanos()); String logLine = (String) eventData; if (!SELINUX_MATCHER.reset(logLine).matches()) { continue; return true; } auditLogBuilder.reset(SELINUX_MATCHER.group("denial")); final SelinuxAuditLog auditLog = auditLogBuilder.build(); mAuditLogBuilder.reset(SELINUX_MATCHER.group("denial")); final SelinuxAuditLog auditLog = mAuditLogBuilder.build(); if (auditLog == null) { continue; return true; } if (!mQuotaLimiter.acquire()) { if (DEBUG) { Slogf.d(TAG, "Running out of quota after %d logs.", auditsWritten); } return true; throw new IllegalStateException(new QuotaExceededException()); } mRateLimiter.acquire(); Loading @@ -169,16 +166,50 @@ class SelinuxAuditLogsCollector { auditLog.mTClass, auditLog.mPath, auditLog.mPermissive); auditsWritten++; if (logTime.isAfter(mLastWrite)) { mLastWrite = logTime; mAuditsWritten++; if (eventTime.isAfter(mLatestTimestamp)) { mLatestTimestamp = eventTime; } return true; } } /** * Collect and push SELinux audit logs for the provided {@code tagCode}. * * @return true if the job was completed. If the job was interrupted or * failed because of IOException, return false. * @throws QuotaExceededException if it ran out of quota. */ boolean collect(int tagCode) throws QuotaExceededException { mEventCollection.reset(); try { EventLog.readEvents(new int[] {tagCode}, mEventCollection); } catch (IllegalStateException e) { if (e.getCause() instanceof QuotaExceededException) { if (DEBUG) { Slogf.d(TAG, "Written %d logs", auditsWritten); Slogf.d(TAG, "Running out of quota after %d logs.", mEventCollection.getAuditsWritten()); } // next run we will ignore all these logs. mLastWrite = mEventCollection.getLatestTimestamp(); throw (QuotaExceededException) e.getCause(); } else if (e.getCause() instanceof InterruptedException) { mLastWrite = mEventCollection.getLatestTimestamp(); return false; } throw e; } catch (IOException e) { Slog.e(TAG, "Error reading event logs", e); return false; } mLastWrite = mEventCollection.getLatestTimestamp(); if (DEBUG) { Slogf.d(TAG, "Written %d logs", mEventCollection.getAuditsWritten()); } return true; } }
services/core/java/com/android/server/selinux/SelinuxAuditLogsJob.java +6 −2 Original line number Diff line number Diff line Loading @@ -51,10 +51,14 @@ final class SelinuxAuditLogsJob { return; } mIsRunning.set(true); try { boolean done = mAuditLogsCollector.collect(SelinuxAuditLogsService.AUDITD_TAG_CODE); if (done) { jobService.jobFinished(params, /* wantsReschedule= */ false); } } catch (QuotaExceededException e) { jobService.jobFinished(params, /* wantsReschedule= */ false); } mIsRunning.set(false); } }
services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsCollectorTest.java +18 −20 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; Loading Loading @@ -81,7 +82,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs() { public void testWriteAuditLogs() throws Exception { writeTestLog("granted", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm1", TEST_DOMAIN, "ttype1", "tclass1"); Loading Loading @@ -117,7 +118,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_multiplePerms() { public void testWriteAuditLogs_multiplePerms() throws Exception { writeTestLog("denied", "perm1 perm2", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm3 perm4", TEST_DOMAIN, "ttype", "tclass"); Loading Loading @@ -153,7 +154,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_withPaths() { public void testWriteAuditLogs_withPaths() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/good/path"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/very/long/path"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", "/short_path"); Loading Loading @@ -217,7 +218,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_withCategories() { public void testWriteAuditLogs_withCategories() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, new int[] {123}, "ttype", null, "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, new int[] {123, 456}, "ttype", null, "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, null, "ttype", new int[] {666}, "tclass"); Loading Loading @@ -288,7 +289,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_withPathAndCategories() { public void testWriteAuditLogs_withPathAndCategories() throws Exception { writeTestLog( "denied", "perm", Loading Loading @@ -318,7 +319,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_permissive() { public void testWriteAuditLogs_permissive() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", true); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass", false); Loading Loading @@ -356,7 +357,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testNotWriteAuditLogs_notTestDomain() { public void testNotWriteAuditLogs_notTestDomain() throws Exception { writeTestLog("denied", "perm", "stype", "ttype", "tclass"); boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); Loading @@ -379,7 +380,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_upToQuota() { public void testWriteAuditLogs_upToQuota() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); Loading @@ -389,9 +390,9 @@ public class SelinuxAuditLogsCollectorTest { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); assertThrows(QuotaExceededException.class, () -> mSelinuxAutidLogsCollector.collect(ANSWER_TAG)); assertThat(done).isTrue(); verify( () -> FrameworkStatsLog.write( Loading @@ -409,7 +410,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testWriteAuditLogs_resetQuota() { public void testWriteAuditLogs_resetQuota() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); Loading @@ -418,8 +419,8 @@ public class SelinuxAuditLogsCollectorTest { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); boolean done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); assertThat(done).isTrue(); assertThrows(QuotaExceededException.class, () -> mSelinuxAutidLogsCollector.collect(ANSWER_TAG)); verify( () -> FrameworkStatsLog.write( Loading @@ -442,8 +443,8 @@ public class SelinuxAuditLogsCollectorTest { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); // move the clock forward to reset the quota limiter. mClock.currentTimeMillis += Duration.ofHours(1).toMillis(); done = mSelinuxAutidLogsCollector.collect(ANSWER_TAG); assertThat(done).isTrue(); assertThrows(QuotaExceededException.class, () -> mSelinuxAutidLogsCollector.collect(ANSWER_TAG)); verify( () -> FrameworkStatsLog.write( Loading @@ -461,14 +462,11 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testNotWriteAuditLogs_stopRequested() { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); public void testNotWriteAuditLogs_stopRequested() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); // These are not pushed. writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); mSelinuxAutidLogsCollector.setStopRequested(true); Loading Loading @@ -509,7 +507,7 @@ public class SelinuxAuditLogsCollectorTest { } @Test public void testAuditLogs_resumeJobDoesNotExceedLimit() { public void testAuditLogs_resumeJobDoesNotExceedLimit() throws Exception { writeTestLog("denied", "perm", TEST_DOMAIN, "ttype", "tclass"); mSelinuxAutidLogsCollector.setStopRequested(true); Loading
services/tests/selinux/src/com/android/server/selinux/SelinuxAuditLogsJobTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testFinishSuccessfully() { public void testFinishSuccessfully() throws Exception { when(mAuditLogsCollector.collect(anyInt())).thenReturn(true); mAuditLogsJob.start(mJobService, mParams); Loading @@ -63,7 +63,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testInterrupt() { public void testInterrupt() throws Exception { when(mAuditLogsCollector.collect(anyInt())).thenReturn(false); mAuditLogsJob.start(mJobService, mParams); Loading @@ -73,7 +73,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testInterruptAndResume() { public void testInterruptAndResume() throws Exception { when(mAuditLogsCollector.collect(anyInt())).thenReturn(false); mAuditLogsJob.start(mJobService, mParams); verify(mJobService, never()).jobFinished(any(), anyBoolean()); Loading @@ -85,7 +85,7 @@ public class SelinuxAuditLogsJobTest { } @Test public void testRequestStop() throws InterruptedException { public void testRequestStop() throws Exception { Semaphore isRunning = new Semaphore(0); Semaphore stopRequested = new Semaphore(0); AtomicReference<Throwable> uncaughtException = new AtomicReference<>(); Loading