• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 
17 package com.android.compatibility.common.util;
18 
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.io.InputStreamReader;
22 import org.json.JSONArray;
23 import org.json.JSONException;
24 import org.json.JSONObject;
25 import org.junit.Assert;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.junit.runners.JUnit4;
30 import java.util.regex.Pattern;
31 
32 /** Unit tests for {@link CrashUtils}. */
33 @RunWith(JUnit4.class)
34 public class CrashUtilsTest {
35 
36     private JSONArray mCrashes;
37 
38     @Before
setUp()39     public void setUp() throws IOException {
40         try (BufferedReader txtReader =
41                 new BufferedReader(
42                         new InputStreamReader(
43                                 getClass().getClassLoader().getResourceAsStream("logcat.txt")))) {
44             StringBuffer input = new StringBuffer();
45             String tmp;
46             while ((tmp = txtReader.readLine()) != null) {
47                 input.append(tmp + "\n");
48             }
49             mCrashes = CrashUtils.addAllCrashes(input.toString(), new JSONArray());
50         }
51     }
52 
53     @Test
testGetAllCrashes()54     public void testGetAllCrashes() throws Exception {
55         JSONArray expectedResults = new JSONArray();
56         expectedResults.put(createCrashJson(
57                 11071, 11189, "AudioOut_D", "/system/bin/audioserver", "e9380000", "SIGSEGV", null));
58         expectedResults.put(createCrashJson(
59                 12736, 12761, "Binder:12736_2", "/system/bin/audioserver", "0", "SIGSEGV", null));
60         expectedResults.put(createCrashJson(
61                 26201, 26227, "Binder:26201_3", "/system/bin/audioserver", "0", "SIGSEGV", null));
62         expectedResults.put(createCrashJson(
63                 26246, 26282, "Binder:26246_5", "/system/bin/audioserver", "0", "SIGSEGV", null));
64         expectedResults.put(createCrashJson(
65                 245, 245, "installd", "/system/bin/installd", null, "SIGABRT",
66                 "'utils.cpp:67] Check failed: is_valid_package_name(package_name) == 0 '"));
67         expectedResults.put(createCrashJson(
68                 6371, 8072, "media.codec", "omx@1.0-service", "ed000000", "SIGSEGV", null));
69         expectedResults.put(createCrashJson(
70                 8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
71                 "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
72         expectedResults.put(createCrashJson(
73                 8080, 11665, "generic", "/system/bin/mediaserver", null, "SIGABRT",
74                 "'frameworks/av/media/libstagefright/MPEG4Extractor.cpp:6853 CHECK_EQ( (unsigned)ptr[0],1u) failed: 129 vs. 1'"));
75         expectedResults.put(createCrashJson(
76                 11071, 11189, "synthetic_thread", "synthetic_process_0", "e9380000", "SIGSEGV", null));
77         expectedResults.put(createCrashJson(
78                 12736, 12761, "synthetic_thread", "synthetic_process_1", "0", "SIGSEGV", null));
79 
80         Assert.assertEquals(expectedResults.toString() + "\n" +  mCrashes.toString() + "\n", expectedResults.toString(), mCrashes.toString());
81     }
82 
createCrashJson( int pid, int tid, String name, String process, String faultaddress, String signal, String abortMessage)83     public JSONObject createCrashJson(
84                 int pid,
85                 int tid,
86                 String name,
87                 String process,
88                 String faultaddress,
89                 String signal,
90                 String abortMessage) {
91         JSONObject json = new JSONObject();
92         try {
93             json.put(CrashUtils.PID, pid);
94             json.put(CrashUtils.TID, tid);
95             json.put(CrashUtils.NAME, name);
96             json.put(CrashUtils.PROCESS, process);
97             json.put(CrashUtils.FAULT_ADDRESS, faultaddress);
98             json.put(CrashUtils.SIGNAL, signal);
99             json.put(CrashUtils.ABORT_MESSAGE, abortMessage);
100         } catch (JSONException e) {}
101         return json;
102     }
103 
104     @Test
testValidCrash()105     public void testValidCrash() throws Exception {
106         Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
107                 .checkMinAddress(true)
108                 .setProcessPatterns(Pattern.compile("synthetic_process_0"))));
109     }
110 
111     @Test
testMissingName()112     public void testMissingName() throws Exception {
113         Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
114                 .checkMinAddress(true)
115                 .setProcessPatterns(Pattern.compile(""))));
116     }
117 
118     @Test
testSIGABRT()119     public void testSIGABRT() throws Exception {
120         Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
121                 .checkMinAddress(true)
122                 .setProcessPatterns(Pattern.compile("installd"))));
123     }
124 
125     @Test
testFaultAddressBelowMin()126     public void testFaultAddressBelowMin() throws Exception {
127         Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
128                 .checkMinAddress(true)
129                 .setProcessPatterns(Pattern.compile("synthetic_process_1"))));
130     }
131 
132     @Test
testIgnoreMinAddressCheck()133     public void testIgnoreMinAddressCheck() throws Exception {
134         Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
135                 .checkMinAddress(false)
136                 .setProcessPatterns(Pattern.compile("synthetic_process_1"))));
137     }
138 
139     @Test
testBadAbortMessage()140     public void testBadAbortMessage() throws Exception {
141         Assert.assertFalse(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
142                 .checkMinAddress(true)
143                 .setProcessPatterns(Pattern.compile("generic"))));
144     }
145 
146     @Test
testGoodAndBadCrashes()147     public void testGoodAndBadCrashes() throws Exception {
148         Assert.assertTrue(CrashUtils.securityCrashDetected(mCrashes, new CrashUtils.Config()
149                 .checkMinAddress(true)
150                 .setProcessPatterns(
151                         Pattern.compile("synthetic_process_0"),
152                         Pattern.compile("generic"))));
153     }
154 
155     @Test
testNullFaultAddress()156     public void testNullFaultAddress() throws Exception {
157         JSONArray crashes = new JSONArray();
158         crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGSEGV", ""));
159         Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
160                 .checkMinAddress(true)
161                 .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
162     }
163 
164     @Test
testAbortMessageInclude()165     public void testAbortMessageInclude() throws Exception {
166         JSONArray crashes = new JSONArray();
167         crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
168               "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
169         Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
170                 .appendSignals(CrashUtils.SIGABRT)
171                 .appendAbortMessageIncludes("Check failed:")
172                 .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
173 
174         Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
175                 .appendSignals(CrashUtils.SIGABRT)
176                 .appendAbortMessageIncludes("include not matches")
177                 .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
178     }
179 
180     @Test
testAbortMessageExclude()181     public void testAbortMessageExclude() throws Exception {
182         JSONArray crashes = new JSONArray();
183         crashes.put(createCrashJson(8373, 8414, "loo", "com.android.bluetooth", null, "SIGABRT",
184               "'[FATAL:allocation_tracker.cc(143)] Check failed: map_entry != allocations.end()."));
185         Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
186                 .appendSignals(CrashUtils.SIGABRT)
187                 .appendAbortMessageExcludes("Check failed:")
188                 .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
189 
190         Assert.assertTrue(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
191                 .appendSignals(CrashUtils.SIGABRT)
192                 .appendAbortMessageExcludes("exclude not matches")
193                 .setProcessPatterns(Pattern.compile("com\\.android\\.bluetooth"))));
194     }
195 
196     @Test
testAbortMessageExcludeCannotLink()197     public void testAbortMessageExcludeCannotLink() throws Exception {
198         JSONArray crashes = new JSONArray();
199         crashes.put(createCrashJson(
200                 18959, 18959, "CVE-2020-0073", "/data/local/tmp/CVE-2020-0073", null, "SIGABRT",
201                 "'CANNOT LINK EXECUTABLE \"/data/local/tmp/CVE-2020-0073\": library "
202                 + "\"libnfc-nci.so\" (\"(default)\", \"/data/local/tmp/CVE-2020-0073\", \"\") "
203                 + "not found'"));
204         Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
205                 .appendSignals(CrashUtils.SIGABRT)
206                 .setProcessPatterns(Pattern.compile("CVE-2020-0073"))));
207 
208         crashes.put(createCrashJson(
209                 5105, 5105, "CVE-2015-6616-2", "/data/local/tmp/CVE-2015-6616-2", null, "SIGABRT",
210                 "'CANNOT LINK EXECUTABLE \"/data/local/tmp/CVE-2015-6616-2\": "
211                 + "cannot locate symbol \""
212                 + "_ZN7android14MediaExtractor17CreateFromServiceERKNS_2spINS_10DataSourceEEEPKc"
213                 + "\" referenced by \"/data/local/tmp/CVE-2015-6616-2\"...'"));
214         Assert.assertFalse(CrashUtils.securityCrashDetected(crashes, new CrashUtils.Config()
215                 .appendSignals(CrashUtils.SIGABRT)
216                 .setProcessPatterns(Pattern.compile("CVE-2015-6616-2"))));
217 
218     }
219 }
220