blob: 55c75beb73767bd456dcdf0122581d81a845ca33 [file] [log] [blame]
/*
* Copyright (C) 2023 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 android.security.cts.CVE_2023_21286;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertNull;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeTrue;
import android.app.Instrumentation;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.UiAutomation;
import android.content.Context;
import android.content.pm.UserInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.UserManager;
import android.provider.MediaStore;
import android.widget.RemoteViews;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
private AutoCloseable withAdoptShellPermissionIdentity(
UiAutomation uiAutomation, String permission) {
uiAutomation.adoptShellPermissionIdentity(permission);
// Remove permissions
return () -> uiAutomation.dropShellPermissionIdentity();
}
@Test
public void testPocCVE_2023_21286() {
UiDevice uiDevice = null;
try {
final String cveId = "cve_2023_21286_";
final String title = cveId + "title";
Instrumentation instrumentation = getInstrumentation();
Context context = instrumentation.getContext();
UiAutomation uiAutomation = instrumentation.getUiAutomation();
uiDevice = UiDevice.getInstance(instrumentation);
int userId = -1;
// Retrieve created user Id
try (AutoCloseable withAdoptShellPermissionIdentity =
withAdoptShellPermissionIdentity(
uiAutomation, android.Manifest.permission.CREATE_USERS)) {
final List<UserInfo> list = context.getSystemService(UserManager.class).getUsers();
for (UserInfo info : list) {
if (info.name.contains(cveId)) {
userId = info.id;
break;
}
}
}
assumeTrue(userId != -1);
// Post a notification with a content view containing image from other user
RemoteViews rvPortrait =
new RemoteViews(context.getPackageName(), R.layout.cve_2023_21286_layout);
rvPortrait.setImageViewUri(
R.id.cve_2023_21286_img,
Uri.parse("content://" + userId + "@media/external/images/media/"));
NotificationChannel notificationChannel =
new NotificationChannel(cveId, cveId, NotificationManager.IMPORTANCE_DEFAULT);
RemoteViews rvOuter =
new RemoteViews(context.getPackageName(), R.layout.cve_2023_21286_layout_outer);
rvOuter.addView(R.id.cve_2023_21286_outer, rvPortrait);
NotificationManager notificationManager =
context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
Notification notification =
new Notification.Builder(context, cveId)
.setContentTitle(title)
.setSmallIcon(
Icon.createWithData(
new byte[0] /* data */, 0 /* offset */, 0 /* length */))
.setCustomContentView(rvOuter)
.setCustomBigContentView(rvOuter)
.build();
try {
notificationManager.notify(0 /* id */, notification);
} catch (SecurityException securityException) {
if (securityException
.getLocalizedMessage()
.toLowerCase()
.contains(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString())) {
// Ignore exception thrown with fix and exit the test
return;
} else {
throw securityException;
}
}
// Open notification shade
assumeTrue("Opening notification shade unsuccessful", uiDevice.openNotification());
// Wait for notification to appear and detect if the remote view is present
uiDevice.wait(Until.hasObject(By.text(title)), 3000 /* timeout */);
UiObject2 exposedImg =
uiDevice.findObject(By.res(context.getPackageName(), cveId + "img"));
assertNull(
"Device is vulnerable to b/277740082, Other user's images can be exposed in"
+ " notifications using remote views",
exposedImg);
} catch (Exception e) {
assumeNoException(e);
} finally {
try {
uiDevice.pressHome();
} catch (Exception e) {
// Ignore exceptions as the test has finished
}
}
}
}