• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.fsverity;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.platform.test.annotations.RequiresFlagsEnabled;
22 import android.platform.test.annotations.RootPermissionTest;
23 import android.platform.test.flag.junit.CheckFlagsRule;
24 import android.platform.test.flag.junit.host.HostFlagsValueProvider;
25 import android.security.Flags;
26 
27 import com.android.blockdevicewriter.BlockDeviceWriter;
28 import com.android.tradefed.device.DeviceNotAvailableException;
29 import com.android.tradefed.device.ITestDevice;
30 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
31 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
32 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
33 
34 import org.junit.Rule;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 
38 /**
39  * This test verifies fs-verity works end-to-end. There is a corresponding helper app.
40  *
41  * <p>The helper app uses a FileIntegrityManager API to enable fs-verity to a file. The host test
42  * here * tampers with the file's backing storage, then tells the helper app to read and expect
43  * success/failure on read.
44  *
45  * <p>In order to make sure a block of the file is readable only if the underlying block on disk
46  * stay intact, the test needs to bypass the filesystem and tampers with the corresponding physical
47  * address against the block device.
48  */
49 @RootPermissionTest
50 @RunWith(DeviceJUnit4ClassRunner.class)
51 @RequiresFlagsEnabled(Flags.FLAG_FSVERITY_API)
52 public class FsVerityHostTest extends BaseHostJUnit4Test {
53     private static final String TARGET_PACKAGE = "com.android.fsverity";
54 
55     private static final String BASENAME = "test.file";
56 
57     @Rule
58     public final CheckFlagsRule mCheckFlagsRule =
59             HostFlagsValueProvider.createCheckFlagsRule(this::getDevice);
60 
61     @Test
testFsVeritySmallFile()62     public void testFsVeritySmallFile() throws Exception {
63         prepareTest(10000);
64 
65         ITestDevice device = getDevice();
66         BlockDeviceWriter.damageFileAgainstBlockDevice(device, getTargetFilePath(), 0);
67         BlockDeviceWriter.damageFileAgainstBlockDevice(device, getTargetFilePath(), 8192);
68         BlockDeviceWriter.dropCaches(device);
69 
70         verifyRead(getTargetFilePath(), "0,2");
71     }
72 
73     @Test
testFsVerityLargerFileWithOneMoreMerkleTreeLevel()74     public void testFsVerityLargerFileWithOneMoreMerkleTreeLevel() throws Exception {
75         prepareTest(128 * 4096 + 1);
76 
77         ITestDevice device = getDevice();
78         BlockDeviceWriter.damageFileAgainstBlockDevice(device, getTargetFilePath(), 4096);
79         BlockDeviceWriter.damageFileAgainstBlockDevice(device, getTargetFilePath(), 100 * 4096);
80         BlockDeviceWriter.damageFileAgainstBlockDevice(device, getTargetFilePath(), 128 * 4096 + 1);
81         BlockDeviceWriter.dropCaches(device);
82 
83         verifyRead(getTargetFilePath(), "1,100,128");
84     }
85 
getTargetFilePath()86     private String getTargetFilePath() throws DeviceNotAvailableException {
87         return "/data/user/" + getDevice().getCurrentUser() + "/" + TARGET_PACKAGE + "/files/"
88                 + BASENAME;
89     }
90 
prepareTest(int fileSize)91     private void prepareTest(int fileSize) throws Exception {
92         DeviceTestRunOptions options = new DeviceTestRunOptions(TARGET_PACKAGE);
93         options.setTestClassName(TARGET_PACKAGE + ".Helper");
94         options.setTestMethodName("prepareTest");
95         options.addInstrumentationArg("basename", BASENAME);
96         options.addInstrumentationArg("fileSize", String.valueOf(fileSize));
97         assertThat(runDeviceTests(options)).isTrue();
98     }
99 
verifyRead(String path, String indicesCsv)100     private void verifyRead(String path, String indicesCsv) throws Exception {
101         DeviceTestRunOptions options = new DeviceTestRunOptions(TARGET_PACKAGE);
102         options.setTestClassName(TARGET_PACKAGE + ".Helper");
103         options.setTestMethodName("verifyFileRead");
104         options.addInstrumentationArg("brokenBlockIndicesCsv", indicesCsv);
105         options.addInstrumentationArg("filePath", getTargetFilePath());
106         assertThat(runDeviceTests(options)).isTrue();
107     }
108 }
109