1 package android.security.cts; 2 3 import com.android.tradefed.device.DeviceNotAvailableException; 4 import com.android.tradefed.device.ITestDevice; 5 import com.android.tradefed.testtype.DeviceTestCase; 6 7 import java.util.Arrays; 8 import java.util.HashSet; 9 import java.util.Set; 10 11 public class FileSystemPermissionTest extends DeviceTestCase { 12 13 /** 14 * A reference to the device under test. 15 */ 16 private ITestDevice mDevice; 17 18 /** 19 * Used to build the find command for finding insecure file system components 20 */ 21 private static final String INSECURE_DEVICE_ADB_COMMAND = "find %s -type %s -perm /o=rwx 2>/dev/null"; 22 23 @Override setUp()24 protected void setUp() throws Exception { 25 super.setUp(); 26 mDevice = getDevice(); 27 } 28 testAllBlockDevicesAreSecure()29 public void testAllBlockDevicesAreSecure() throws Exception { 30 Set<String> insecure = getAllInsecureDevicesInDirAndSubdir("/dev", "b"); 31 assertTrue("Found insecure block devices: " + insecure.toString(), 32 insecure.isEmpty()); 33 } 34 35 /** 36 * Searches for all world accessable files, note this may need sepolicy to search the desired 37 * location and stat files. 38 * @path The path to search, must be a directory. 39 * @type The type of file to search for, must be a valid find command argument to the type 40 * option. 41 * @returns The set of insecure fs objects found. 42 */ getAllInsecureDevicesInDirAndSubdir(String path, String type)43 private Set<String> getAllInsecureDevicesInDirAndSubdir(String path, String type) throws DeviceNotAvailableException { 44 45 String cmd = getInsecureDeviceAdbCommand(path, type); 46 String output = mDevice.executeShellCommand(cmd); 47 // Splitting an empty string results in an array of an empty string. 48 String [] found = output.length() > 0 ? output.split("\\s") : new String[0]; 49 return new HashSet<String>(Arrays.asList(found)); 50 } 51 getInsecureDeviceAdbCommand(String path, String type)52 private static String getInsecureDeviceAdbCommand(String path, String type) { 53 return String.format(INSECURE_DEVICE_ADB_COMMAND, path, type); 54 } 55 56 private static String HW_RNG_DEVICE = "/dev/hw_random"; 57 testDevHwRandomPermissions()58 public void testDevHwRandomPermissions() throws Exception { 59 if (!mDevice.doesFileExist(HW_RNG_DEVICE)) { 60 // Hardware RNG device is missing. This is OK because it is not required to be exposed 61 // on all devices. 62 return; 63 } 64 65 // This test asserts that, if present, /dev/hw_random must: 66 // 67 // 1. Have ownership prng_seeder:prng_seeder 68 // 2. Have permissions 0400 - The only user space process requiring 69 // access is the PRNG seeder daemon which only needs read access. 70 // 3. Be a character device with major:minor 10:183 (the kernel 71 // default). 72 73 // That translates to `ls -l` output like this: 74 // cr-------- 1 prng_seeder prng_seeder 10, 183 2021-02-11 17:55 /dev/hw_random 75 76 String command = "ls -l " + HW_RNG_DEVICE; 77 String output = mDevice.executeShellCommand(command).trim(); 78 if (!output.endsWith(" " + HW_RNG_DEVICE)) { 79 fail("Unexpected output from " + command + ": \"" + output + "\""); 80 } 81 String[] outputWords = output.split("\\s"); 82 assertEquals("Wrong mode on " + HW_RNG_DEVICE, "cr--------", outputWords[0]); 83 assertEquals("Wrong owner of " + HW_RNG_DEVICE, "prng_seeder", outputWords[2]); 84 assertEquals("Wrong group of " + HW_RNG_DEVICE, "prng_seeder", outputWords[3]); 85 assertEquals("Wrong device major on " + HW_RNG_DEVICE, "10,", outputWords[4]); 86 assertEquals("Wrong device minor on " + HW_RNG_DEVICE, "183", outputWords[5]); 87 } 88 } 89