1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.devicepolicy; 17 18 import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD; 19 import static android.app.admin.SecurityLog.TAG_APP_PROCESS_START; 20 import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_INSTALLED; 21 import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_REMOVED; 22 import static android.app.admin.SecurityLog.TAG_KEY_DESTRUCTION; 23 import static android.app.admin.SecurityLog.TAG_KEY_GENERATED; 24 import static android.app.admin.SecurityLog.TAG_KEY_IMPORT; 25 import static android.app.admin.SecurityLog.TAG_KEY_INTEGRITY_VIOLATION; 26 import static android.app.admin.SecurityLog.TAG_MEDIA_MOUNT; 27 import static android.app.admin.SecurityLog.TAG_MEDIA_UNMOUNT; 28 29 import static com.google.common.truth.Truth.assertThat; 30 31 import android.app.admin.SecurityLog.SecurityEvent; 32 import android.os.Parcel; 33 import android.os.UserHandle; 34 import android.text.TextUtils; 35 import android.util.EventLog; 36 import android.util.EventLog.Event; 37 38 import androidx.test.runner.AndroidJUnit4; 39 40 import junit.framework.AssertionFailedError; 41 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 45 import java.util.ArrayList; 46 import java.util.List; 47 48 /** 49 * Tests for the DeviceOwner object that saves & loads device and policy owner information. 50 * 51 * <p>Run this test with: 52 * 53 * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.SecurityEventTest} 54 * 55 */ 56 @RunWith(AndroidJUnit4.class) 57 public class SecurityEventTest extends DpmTestBase { 58 59 @Test testSecurityEventId()60 public void testSecurityEventId() throws Exception { 61 SecurityEvent event = createEvent(() -> { 62 EventLog.writeEvent(TAG_ADB_SHELL_CMD, 0); 63 }, TAG_ADB_SHELL_CMD); 64 event.setId(20); 65 assertThat(event.getId()).isEqualTo(20); 66 } 67 68 @Test testSecurityEventParceling()69 public void testSecurityEventParceling() throws Exception { 70 // GIVEN an event. 71 SecurityEvent event = createEvent(() -> { 72 EventLog.writeEvent(TAG_ADB_SHELL_CMD, "test"); 73 }, TAG_ADB_SHELL_CMD); 74 // WHEN parceling the event. 75 Parcel p = Parcel.obtain(); 76 p.writeParcelable(event, 0); 77 p.setDataPosition(0); 78 SecurityEvent unparceledEvent = p.readParcelable(SecurityEventTest.class.getClassLoader()); 79 p.recycle(); 80 // THEN the event state is preserved. 81 assertThat(unparceledEvent.getTag()).isEqualTo(event.getTag()); 82 assertThat(unparceledEvent.getData()).isEqualTo(event.getData()); 83 assertThat(unparceledEvent.getTimeNanos()).isEqualTo(event.getTimeNanos()); 84 assertThat(unparceledEvent.getId()).isEqualTo(event.getId()); 85 } 86 87 @Test testSecurityEventRedaction()88 public void testSecurityEventRedaction() throws Exception { 89 SecurityEvent event; 90 91 // TAG_ADB_SHELL_CMD will has the command redacted 92 event = createEvent(() -> { 93 EventLog.writeEvent(TAG_ADB_SHELL_CMD, "command"); 94 }, TAG_ADB_SHELL_CMD); 95 assertThat(TextUtils.isEmpty((String) event.getData())).isFalse(); 96 97 // TAG_MEDIA_MOUNT will have the volume label redacted (second data) 98 event = createEvent(() -> { 99 EventLog.writeEvent(TAG_MEDIA_MOUNT, new Object[] {"path", "label"}); 100 }, TAG_MEDIA_MOUNT); 101 assertThat(TextUtils.isEmpty(event.getStringData(1))).isFalse(); 102 assertThat(TextUtils.isEmpty(event.redact(0).getStringData(1))).isTrue(); 103 104 // TAG_MEDIA_UNMOUNT will have the volume label redacted (second data) 105 event = createEvent(() -> { 106 EventLog.writeEvent(TAG_MEDIA_UNMOUNT, new Object[] {"path", "label"}); 107 }, TAG_MEDIA_UNMOUNT); 108 assertThat(TextUtils.isEmpty(event.getStringData(1))).isFalse(); 109 assertThat(TextUtils.isEmpty(event.redact(0).getStringData(1))).isTrue(); 110 111 // TAG_APP_PROCESS_START will be fully redacted if user does not match 112 event = createEvent(() -> { 113 EventLog.writeEvent(TAG_APP_PROCESS_START, new Object[] {"process", 12345L, 114 UserHandle.getUid(10, 123), 456, "seinfo", "hash"}); 115 }, TAG_APP_PROCESS_START); 116 assertThat(event.redact(10)).isNotNull(); 117 assertThat(event.redact(11)).isNull(); 118 119 // TAG_CERT_AUTHORITY_INSTALLED will be fully redacted if user does not match 120 event = createEvent(() -> { 121 EventLog.writeEvent(TAG_CERT_AUTHORITY_INSTALLED, new Object[] {1, "subject", 10}); 122 }, TAG_CERT_AUTHORITY_INSTALLED); 123 assertThat(event.redact(10)).isNotNull(); 124 assertThat(event.redact(11)).isNull(); 125 126 // TAG_CERT_AUTHORITY_REMOVED will be fully redacted if user does not match 127 event = createEvent(() -> { 128 EventLog.writeEvent(TAG_CERT_AUTHORITY_REMOVED, new Object[] {1, "subject", 20}); 129 }, TAG_CERT_AUTHORITY_REMOVED); 130 assertThat(event.redact(20)).isNotNull(); 131 assertThat(event.redact(0)).isNull(); 132 133 // TAG_KEY_GENERATED will be fully redacted if user does not match 134 event = createEvent(() -> { 135 EventLog.writeEvent(TAG_KEY_GENERATED, 136 new Object[] {1, "alias", UserHandle.getUid(0, 123)}); 137 }, TAG_KEY_GENERATED); 138 assertThat(event.redact(0)).isNotNull(); 139 assertThat(event.redact(10)).isNull(); 140 141 // TAG_KEY_IMPORT will be fully redacted if user does not match 142 event = createEvent(() -> { 143 EventLog.writeEvent(TAG_KEY_IMPORT, 144 new Object[] {1, "alias", UserHandle.getUid(1, 123)}); 145 }, TAG_KEY_IMPORT); 146 assertThat(event.redact(1)).isNotNull(); 147 assertThat(event.redact(10)).isNull(); 148 149 // TAG_KEY_DESTRUCTION will be fully redacted if user does not match 150 event = createEvent(() -> { 151 EventLog.writeEvent(TAG_KEY_DESTRUCTION, 152 new Object[] {1, "alias", UserHandle.getUid(2, 123)}); 153 }, TAG_KEY_DESTRUCTION); 154 assertThat(event.redact(2)).isNotNull(); 155 assertThat(event.redact(10)).isNull(); 156 157 // TAG_KEY_INTEGRITY_VIOLATION will be fully redacted if user does not match 158 event = createEvent(() -> { 159 EventLog.writeEvent(TAG_KEY_INTEGRITY_VIOLATION, 160 new Object[] {"alias", UserHandle.getUid(2, 123)}); 161 }, TAG_KEY_INTEGRITY_VIOLATION); 162 assertThat(event.redact(2)).isNotNull(); 163 assertThat(event.redact(10)).isNull(); 164 165 } 166 167 /** 168 * Creates an Event object. Only the native code has the serialization and deserialization logic 169 * so need to actually emit a real log in order to generate the object. 170 */ createEvent(Runnable generator, int expectedTag)171 private SecurityEvent createEvent(Runnable generator, int expectedTag) throws Exception { 172 Long markerData = System.currentTimeMillis(); 173 EventLog.writeEvent(expectedTag, markerData); 174 generator.run(); 175 176 List<Event> events = new ArrayList<>(); 177 // Give the message some time to show up in the log 178 Thread.sleep(20); 179 EventLog.readEvents(new int[] {expectedTag}, events); 180 181 for (int i = 0; i < events.size() - 1; i++) { 182 if (markerData.equals(events.get(i).getData())) { 183 return new SecurityEvent(0, events.get(i + 1).getBytes()); 184 } 185 } 186 throw new AssertionFailedError("Unable to locate marker event"); 187 } 188 } 189