1 /*
2  * Copyright (C) 2022 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 android.security.cts.CVE_2022_20475_test;
18 
19 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
20 
21 import static org.junit.Assume.assumeNoException;
22 
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 
28 import androidx.test.runner.AndroidJUnit4;
29 
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 
33 import java.util.concurrent.CompletableFuture;
34 import java.util.concurrent.TimeUnit;
35 import java.util.concurrent.TimeoutException;
36 
37 @RunWith(AndroidJUnit4.class)
38 public class DeviceTest {
39     private static final int WAIT_MS = 5000;
40 
41     @Test
testCVE_2022_20475()42     public void testCVE_2022_20475() {
43         try {
44             // Registering a receiver here to wait for a broadcast from either HijackActivity or
45             // TargetActivity
46             Context context = getApplicationContext();
47             CompletableFuture<Boolean> hijackReturn = new CompletableFuture<>();
48             CompletableFuture<Boolean> targetReturn = new CompletableFuture<>();
49             final String bcastActionHijack = context.getString(R.string.bcastActionHijack);
50             final String bcastActionTarget = context.getString(R.string.bcastActionTarget);
51             BroadcastReceiver broadcastReceiver =
52                     new BroadcastReceiver() {
53                         @Override
54                         public void onReceive(Context context, Intent intent) {
55                             if (intent.getAction().equals(bcastActionHijack)) {
56                                 hijackReturn.complete(true);
57                             } else if (intent.getAction().equals(bcastActionTarget)) {
58                                 targetReturn.complete(true);
59                             }
60                         }
61                     };
62             IntentFilter filter = new IntentFilter();
63             filter.addAction(bcastActionHijack);
64             filter.addAction(bcastActionTarget);
65             context.registerReceiver(broadcastReceiver, filter);
66 
67             // Start PocActivity which in turn starts both TargetActivity and HijackActivity
68             Intent intent = new Intent(context, PocActivity.class);
69             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
70             context.startActivity(intent);
71 
72             // Waiting on callback from HijackActivity which is started last by PocActivity
73             hijackReturn.get(WAIT_MS, TimeUnit.MILLISECONDS);
74 
75             // Start TargetActivity
76             Intent targetIntent = new Intent(Intent.ACTION_MAIN);
77             final String pkgTarget = context.getString(R.string.pkgTarget);
78             targetIntent.setClassName(pkgTarget, context.getString(R.string.activityTarget));
79             targetIntent.setFlags(
80                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
81             context.startActivity(targetIntent);
82 
83             // Wait on callback from TargetActivity. On vulnerable device, TargetActivity would
84             // not start and HijackActivity would remain on screen so the test should fail due
85             // to timeout on callback.
86             try {
87                 targetReturn.get(WAIT_MS, TimeUnit.MILLISECONDS);
88             } catch (TimeoutException e) {
89                 throw new AssertionError(context.getString(R.string.msgFail));
90             }
91         } catch (Exception e) {
92             assumeNoException(e);
93         }
94     }
95 }
96