diff options
-rw-r--r-- | bootstat/bootstat.cpp | 4 | ||||
-rw-r--r-- | fastboot/fuzzy_fastboot/fixtures.cpp | 41 | ||||
-rw-r--r-- | fastboot/fuzzy_fastboot/fixtures.h | 2 | ||||
-rw-r--r-- | fastboot/fuzzy_fastboot/main.cpp | 87 | ||||
-rw-r--r-- | fs_mgr/fs_mgr_remount.cpp | 15 | ||||
-rwxr-xr-x | fs_mgr/tests/adb-remount-test.sh | 14 | ||||
-rw-r--r-- | init/Android.mk | 2 | ||||
-rw-r--r-- | libmemunreachable/HeapWalker.cpp | 9 | ||||
-rw-r--r-- | libmemunreachable/MemUnreachable.cpp | 7 |
9 files changed, 153 insertions, 28 deletions
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp index ea49798c9..1ce0ec4c2 100644 --- a/bootstat/bootstat.cpp +++ b/bootstat/bootstat.cpp @@ -295,6 +295,10 @@ const std::map<std::string, int32_t> kBootReasonMap = { {"kernel_panic,_sde_encoder_phys_cmd_handle_ppdone_timeout", 168}, {"recovery,quiescent", 169}, {"reboot,quiescent", 170}, + {"reboot,rtc", 171}, + {"reboot,dm-verity_device_corrupted", 172}, + {"reboot,dm-verity_enforcing", 173}, + {"reboot,keys_clear", 174}, }; // Converts a string value representing the reason the system booted to an diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp index 280cfb691..eb043ce36 100644 --- a/fastboot/fuzzy_fastboot/fixtures.cpp +++ b/fastboot/fuzzy_fastboot/fixtures.cpp @@ -55,6 +55,8 @@ #include "test_utils.h" #include "usb_transport_sniffer.h" +using namespace std::literals::chrono_literals; + namespace fastboot { int FastBootTest::MatchFastboot(usb_ifc_info* info, const char* local_serial) { @@ -159,6 +161,26 @@ void FastBootTest::TearDownSerial() { } } +void FastBootTest::ReconnectFastbootDevice() { + fb.reset(); + transport.reset(); + while (UsbStillAvailible()) + ; + printf("WAITING FOR DEVICE\n"); + // Need to wait for device + const auto matcher = [](usb_ifc_info* info) -> int { return MatchFastboot(info, nullptr); }; + while (!transport) { + std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT)); + if (usb) { + transport = std::unique_ptr<UsbTransportSniffer>( + new UsbTransportSniffer(std::move(usb), serial_port)); + } + std::this_thread::sleep_for(1s); + } + device_path = cb_scratch; + fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true)); +} + void FastBootTest::SetLockState(bool unlock, bool assert_change) { if (!fb) { return; @@ -197,25 +219,8 @@ void FastBootTest::SetLockState(bool unlock, bool assert_change) { std::string cmd = unlock ? "unlock" : "lock"; ASSERT_EQ(fb->RawCommand("flashing " + cmd, &resp), SUCCESS) << "Attempting to change locked state, but 'flashing" + cmd + "' command failed"; - fb.reset(); - transport.reset(); printf("PLEASE RESPOND TO PROMPT FOR '%sing' BOOTLOADER ON DEVICE\n", cmd.c_str()); - while (UsbStillAvailible()) - ; // Wait for disconnect - printf("WAITING FOR DEVICE"); - // Need to wait for device - const auto matcher = [](usb_ifc_info* info) -> int { return MatchFastboot(info, nullptr); }; - while (!transport) { - std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT)); - if (usb) { - transport = std::unique_ptr<UsbTransportSniffer>( - new UsbTransportSniffer(std::move(usb), serial_port)); - } - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - putchar('.'); - } - device_path = cb_scratch; - fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true)); + ReconnectFastbootDevice(); if (assert_change) { ASSERT_EQ(fb->GetVar("unlocked", &resp), SUCCESS) << "getvar:unlocked failed"; ASSERT_EQ(resp, unlock ? "yes" : "no") diff --git a/fastboot/fuzzy_fastboot/fixtures.h b/fastboot/fuzzy_fastboot/fixtures.h index e0f829e48..9c955eae5 100644 --- a/fastboot/fuzzy_fastboot/fixtures.h +++ b/fastboot/fuzzy_fastboot/fixtures.h @@ -48,6 +48,7 @@ class FastBootTest : public testing::Test { static int MatchFastboot(usb_ifc_info* info, const char* local_serial = nullptr); bool UsbStillAvailible(); bool UserSpaceFastboot(); + void ReconnectFastbootDevice(); protected: RetCode DownloadCommand(uint32_t size, std::string* response = nullptr, @@ -86,6 +87,7 @@ class Fuzz : public ModeTest<true> { // differently class BasicFunctionality : public ModeTest<true> {}; class Conformance : public ModeTest<true> {}; +class LogicalPartitionCompliance : public ModeTest<true> {}; class UnlockPermissions : public ModeTest<true> {}; class LockPermissions : public ModeTest<false> {}; diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp index ef3477109..7ffc7d57c 100644 --- a/fastboot/fuzzy_fastboot/main.cpp +++ b/fastboot/fuzzy_fastboot/main.cpp @@ -177,6 +177,93 @@ TEST(USBFunctionality, USBConnect) { } } +// Test commands related to super partition +TEST_F(LogicalPartitionCompliance, SuperPartition) { + ASSERT_TRUE(UserSpaceFastboot()); + std::string partition_type; + // getvar partition-type:super must fail for retrofit devices because the + // partition does not exist. + if (fb->GetVar("partition-type:super", &partition_type) == SUCCESS) { + std::string is_logical; + EXPECT_EQ(fb->GetVar("is-logical:super", &is_logical), SUCCESS) + << "getvar is-logical:super failed"; + EXPECT_EQ(is_logical, "no") << "super must not be a logical partition"; + std::string super_name; + EXPECT_EQ(fb->GetVar("super-partition-name", &super_name), SUCCESS) + << "'getvar super-partition-name' failed"; + EXPECT_EQ(super_name, "super") << "'getvar super-partition-name' must return 'super' for " + "device with a super partition"; + } +} + +// Test 'fastboot getvar is-logical' +TEST_F(LogicalPartitionCompliance, GetVarIsLogical) { + ASSERT_TRUE(UserSpaceFastboot()); + std::string has_slot; + EXPECT_EQ(fb->GetVar("has-slot:system", &has_slot), SUCCESS) << "getvar has-slot:system failed"; + std::string is_logical_cmd; + if (has_slot == "yes") { + std::string current_slot; + EXPECT_EQ(fb->GetVar("current-slot", ¤t_slot), SUCCESS) + << "getvar current-slot failed"; + is_logical_cmd = "is-logical:system_" + current_slot; + } else { + is_logical_cmd = "is-logical:system"; + } + std::string is_logical; + EXPECT_EQ(fb->GetVar(is_logical_cmd, &is_logical), SUCCESS) << "getvar is-logical failed"; + ASSERT_EQ(is_logical, "yes"); +} + +TEST_F(LogicalPartitionCompliance, FastbootRebootTest) { + ASSERT_TRUE(UserSpaceFastboot()); + GTEST_LOG_(INFO) << "Rebooting to bootloader mode"; + // Test 'fastboot reboot bootloader' from fastbootd + fb->RebootTo("bootloader"); + + // Test fastboot reboot fastboot from bootloader + ReconnectFastbootDevice(); + ASSERT_FALSE(UserSpaceFastboot()); + GTEST_LOG_(INFO) << "Rebooting back to fastbootd mode"; + fb->RebootTo("fastboot"); + + ReconnectFastbootDevice(); + ASSERT_TRUE(UserSpaceFastboot()); +} + +// Testing creation/resize/delete of logical partitions +TEST_F(LogicalPartitionCompliance, CreateResizeDeleteLP) { + ASSERT_TRUE(UserSpaceFastboot()); + GTEST_LOG_(INFO) << "Testing 'fastboot create-logical-partition' command"; + EXPECT_EQ(fb->CreatePartition("test_partition_a", "0"), SUCCESS) + << "create-logical-partition failed"; + GTEST_LOG_(INFO) << "Testing 'fastboot resize-logical-partition' command"; + EXPECT_EQ(fb->ResizePartition("test_partition_a", "4096"), SUCCESS) + << "resize-logical-partition failed"; + std::vector<char> buf(4096); + + GTEST_LOG_(INFO) << "Flashing a logical partition.."; + EXPECT_EQ(fb->FlashPartition("test_partition_a", buf), SUCCESS) + << "flash logical -partition failed"; + GTEST_LOG_(INFO) << "Rebooting to bootloader mode"; + // Reboot to bootloader mode and attempt to flash the logical partitions + fb->RebootTo("bootloader"); + + ReconnectFastbootDevice(); + ASSERT_FALSE(UserSpaceFastboot()); + GTEST_LOG_(INFO) << "Attempt to flash a logical partition.."; + EXPECT_EQ(fb->FlashPartition("test_partition", buf), DEVICE_FAIL) + << "flash logical partition must fail in bootloader"; + GTEST_LOG_(INFO) << "Rebooting back to fastbootd mode"; + fb->RebootTo("fastboot"); + + ReconnectFastbootDevice(); + ASSERT_TRUE(UserSpaceFastboot()); + GTEST_LOG_(INFO) << "Testing 'fastboot delete-logical-partition' command"; + EXPECT_EQ(fb->DeletePartition("test_partition_a"), SUCCESS) + << "delete logical-partition failed"; +} + // Conformance tests TEST_F(Conformance, GetVar) { std::string product; diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp index e2a4d1607..24044d873 100644 --- a/fs_mgr/fs_mgr_remount.cpp +++ b/fs_mgr/fs_mgr_remount.cpp @@ -176,6 +176,15 @@ int main(int argc, char* argv[]) { fstab_read = android::fs_mgr::ReadFstabFromFile(fstab_file, &fstab); } else { fstab_read = android::fs_mgr::ReadDefaultFstab(&fstab); + // Manufacture a / entry from /proc/mounts if missing. + if (!GetEntryForMountPoint(&fstab, "/system") && !GetEntryForMountPoint(&fstab, "/")) { + android::fs_mgr::Fstab mounts; + if (android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) { + if (auto entry = GetEntryForMountPoint(&mounts, "/")) { + if (entry->fs_type != "rootfs") fstab.emplace_back(*entry); + } + } + } } if (!fstab_read || fstab.empty()) { PLOG(ERROR) << "Failed to read fstab"; @@ -211,21 +220,21 @@ int main(int argc, char* argv[]) { // Do we know about the partition? auto it = std::find_if(fstab.begin(), fstab.end(), find_part); if (it == fstab.end()) { - LOG(ERROR) << "Unknown partition " << partition << ", skipping"; + LOG(ERROR) << "Unknown partition " << argv[optind] << ", skipping"; retval = UNKNOWN_PARTITION; continue; } // Is that one covered by an existing overlayfs? auto wrap = is_wrapped(overlayfs_candidates, *it); if (wrap) { - LOG(INFO) << "partition " << partition << " covered by overlayfs for " + LOG(INFO) << "partition " << argv[optind] << " covered by overlayfs for " << wrap->mount_point << ", switching"; partition = system_mount_point(*wrap); } // Is it a remountable partition? it = std::find_if(all.begin(), all.end(), find_part); if (it == all.end()) { - LOG(ERROR) << "Invalid partition " << partition << ", skipping"; + LOG(ERROR) << "Invalid partition " << argv[optind] << ", skipping"; retval = INVALID_PARTITION; continue; } diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index ec6eb5252..b95e54ea6 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -514,8 +514,8 @@ skip_administrative_mounts() { cat - fi | grep -v \ - -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\) " \ - -e "^\(bpf\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \ + -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\|bpf\) " \ + -e "^\(binfmt_misc\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \ -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \ -e "^rootfs / rootfs rw," \ -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) " @@ -608,7 +608,7 @@ fi D=`get_property ro.serialno` [ -n "${D}" ] || D=`get_property ro.boot.serialno` -[ -z "${D}" ] || ANDROID_SERIAL=${D} +[ -z "${D}" -o -n "${ANDROID_SERIAL}" ] || ANDROID_SERIAL=${D} USB_SERIAL= [ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial | grep usb | @@ -998,8 +998,14 @@ echo "${GREEN}[ OK ]${NORMAL} /system/lib/bootstrap/libc.so content remain echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears" >&2 H=`adb_sh echo '${HOSTNAME}' </dev/null 2>/dev/null` +is_bootloader_fastboot=false +# cuttlefish? +[ X"${H}" != X"${H#vsoc}" ] || is_bootloader_fastboot=true is_userspace_fastboot=false -if [ -z "${ANDROID_PRODUCT_OUT}" ]; then + +if ! ${is_bootloader_fastboot}; then + echo "${ORANGE}[ WARNING ]${NORMAL} does not support fastboot, skipping" +elif [ -z "${ANDROID_PRODUCT_OUT}" ]; then echo "${ORANGE}[ WARNING ]${NORMAL} build tree not setup, skipping" elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then echo "${ORANGE}[ WARNING ]${NORMAL} vendor image missing, skipping" diff --git a/init/Android.mk b/init/Android.mk index c63760cde..39af0e686 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir) -include system/sepolicy/policy_version.mk +-include system/sepolicy/policy_version.mk # -- diff --git a/libmemunreachable/HeapWalker.cpp b/libmemunreachable/HeapWalker.cpp index 89837f7d2..e11f0798a 100644 --- a/libmemunreachable/HeapWalker.cpp +++ b/libmemunreachable/HeapWalker.cpp @@ -59,12 +59,19 @@ bool HeapWalker::Allocation(uintptr_t begin, uintptr_t end) { } } +// Sanitizers may consider certain memory inaccessible through certain pointers. +// With MTE this will need to use unchecked instructions or disable tag checking globally. +static uintptr_t ReadWordAtAddressUnsafe(uintptr_t word_ptr) + __attribute__((no_sanitize("address", "hwaddress"))) { + return *reinterpret_cast<uintptr_t*>(word_ptr); +} + bool HeapWalker::WordContainsAllocationPtr(uintptr_t word_ptr, Range* range, AllocationInfo** info) { walking_ptr_ = word_ptr; // This access may segfault if the process under test has done something strange, // for example mprotect(PROT_NONE) on a native heap page. If so, it will be // caught and handled by mmaping a zero page over the faulting page. - uintptr_t value = *reinterpret_cast<uintptr_t*>(word_ptr); + uintptr_t value = ReadWordAtAddressUnsafe(word_ptr); walking_ptr_ = 0; if (value >= valid_allocations_range_.begin && value < valid_allocations_range_.end) { AllocationMap::iterator it = allocations_.find(Range{value, value + 1}); diff --git a/libmemunreachable/MemUnreachable.cpp b/libmemunreachable/MemUnreachable.cpp index 3d7b8a8aa..299c320ac 100644 --- a/libmemunreachable/MemUnreachable.cpp +++ b/libmemunreachable/MemUnreachable.cpp @@ -217,6 +217,10 @@ static bool has_prefix(const allocator::string& s, const char* prefix) { return ret == 0; } +static bool is_sanitizer_mapping(const allocator::string& s) { + return s == "[anon:low shadow]" || s == "[anon:high shadow]" || has_prefix(s, "[anon:hwasan"); +} + bool MemUnreachable::ClassifyMappings(const allocator::vector<Mapping>& mappings, allocator::vector<Mapping>& heap_mappings, allocator::vector<Mapping>& anon_mappings, @@ -258,7 +262,8 @@ bool MemUnreachable::ClassifyMappings(const allocator::vector<Mapping>& mappings } else if (mapping_name.size() == 0) { globals_mappings.emplace_back(*it); } else if (has_prefix(mapping_name, "[anon:") && - mapping_name != "[anon:leak_detector_malloc]") { + mapping_name != "[anon:leak_detector_malloc]" && + !is_sanitizer_mapping(mapping_name)) { // TODO(ccross): it would be nice to treat named anonymous mappings as // possible leaks, but naming something in a .bss or .data section makes // it impossible to distinguish them from mmaped and then named mappings. |