void CrasherTest::FinishCrasher() { if (crasher_pipe == -1) { FAIL() << "crasher pipe uninitialized"; } ssize_t rc = write(crasher_pipe.get(), "\n", 1); if (rc == -1) { FAIL() << "failed to write to crasher pipe: " << strerror(errno); } else if (rc == 0) { FAIL() << "crasher pipe was closed"; } }
static void abort_handler(pid_t target, const bool tombstoned_connected, unique_fd& tombstoned_socket, unique_fd& output_fd, const char* abort_msg) { // If we abort before we get an output fd, contact tombstoned to let any // potential listeners know that we failed. if (!tombstoned_connected) { if (!tombstoned_connect(target, &tombstoned_socket, &output_fd, kDebuggerdAnyIntercept)) { // We failed to connect, not much we can do. LOG(ERROR) << "failed to connected to tombstoned to report failure"; _exit(1); } } dprintf(output_fd.get(), "crash_dump failed to dump process"); if (target != 1) { dprintf(output_fd.get(), " %d: %s\n", target, abort_msg); } else { dprintf(output_fd.get(), ": %s\n", abort_msg); } _exit(1); }
void CrasherTest::FinishIntercept(int* result) { InterceptResponse response; // Timeout for tombstoned intercept is 10 seconds. ssize_t rc = TIMEOUT(20, read(intercept_fd.get(), &response, sizeof(response))); if (rc == -1) { FAIL() << "failed to read response from tombstoned: " << strerror(errno); } else if (rc == 0) { *result = -1; } else if (rc != sizeof(response)) { FAIL() << "received packet of unexpected length from tombstoned: expected " << sizeof(response) << ", received " << rc; } else { *result = response.status == InterceptStatus::kStarted ? 1 : 0; } }
void CrasherTest::StartProcess(std::function<void()> function, std::function<pid_t()> forker) { unique_fd read_pipe; unique_fd crasher_read_pipe; if (!Pipe(&crasher_read_pipe, &crasher_pipe)) { FAIL() << "failed to create pipe: " << strerror(errno); } crasher_pid = forker(); if (crasher_pid == -1) { FAIL() << "fork failed: " << strerror(errno); } else if (crasher_pid == 0) { char dummy; crasher_pipe.reset(); TEMP_FAILURE_RETRY(read(crasher_read_pipe.get(), &dummy, 1)); function(); _exit(0); } }
static void ConsumeFd(unique_fd fd, std::string* output) { constexpr size_t read_length = PAGE_SIZE; std::string result; while (true) { size_t offset = result.size(); result.resize(result.size() + PAGE_SIZE); ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &result[offset], read_length)); if (rc == -1) { FAIL() << "read failed: " << strerror(errno); } else if (rc == 0) { result.resize(result.size() - PAGE_SIZE); break; } result.resize(result.size() - PAGE_SIZE + rc); } *output = std::move(result); }
inline void swap(unique_fd& a, unique_fd& b) noexcept { a.swap(b); }
void remount_service(unique_fd fd, const std::string& cmd) { bool user_requested_reboot = cmd == "-R"; if (getuid() != 0) { WriteFdExactly(fd.get(), "Not running as root. Try \"adb root\" first.\n"); return; } bool system_verified = !(android::base::GetProperty("partition.system.verified", "").empty()); bool vendor_verified = !(android::base::GetProperty("partition.vendor.verified", "").empty()); std::vector<std::string> partitions{"/", "/odm", "/oem", "/product_services", "/product", "/vendor"}; bool verity_enabled = (system_verified || vendor_verified); // If we can use overlayfs, lets get it in place first // before we struggle with determining deduplication operations. if (!verity_enabled && fs_mgr_overlayfs_setup()) { Fstab fstab; if (ReadDefaultFstab(&fstab) && fs_mgr_overlayfs_mount_all(&fstab)) { WriteFdExactly(fd.get(), "overlayfs mounted\n"); } } // Find partitions that are deduplicated, and can be un-deduplicated. std::set<std::string> dedup; for (const auto& part : partitions) { auto partition = part; if ((part == "/") && !find_mount("/system", false).empty()) partition = "/system"; std::string dev = find_mount(partition.c_str(), partition == "/"); if (dev.empty() || !fs_mgr_has_shared_blocks(partition, dev)) { continue; } if (can_unshare_blocks(fd.get(), dev.c_str())) { dedup.emplace(partition); } } // Reboot now if the user requested it (and an operation needs a reboot). if (user_requested_reboot) { if (!dedup.empty() || verity_enabled) { if (verity_enabled) { set_verity_enabled_state_service(unique_fd(dup(fd.get())), false); } reboot_for_remount(fd.get(), !dedup.empty()); return; } WriteFdExactly(fd.get(), "No reboot needed, skipping -R.\n"); } // If we need to disable-verity, but we also need to perform a recovery // fsck for deduplicated partitions, hold off on warning about verity. We // can handle both verity and the recovery fsck in the same reboot cycle. if (verity_enabled && dedup.empty()) { // Allow remount but warn of likely bad effects bool both = system_verified && vendor_verified; WriteFdFmt(fd.get(), "dm_verity is enabled on the %s%s%s partition%s.\n", system_verified ? "system" : "", both ? " and " : "", vendor_verified ? "vendor" : "", both ? "s" : ""); WriteFdExactly(fd.get(), "Use \"adb disable-verity\" to disable verity.\n" "If you do not, remount may succeed, however, you will still " "not be able to write to these volumes.\n"); WriteFdExactly(fd.get(), "Alternately, use \"adb remount -R\" to disable verity " "and automatically reboot.\n"); } bool success = true; for (const auto& partition : partitions) { // Don't try to remount partitions that need an fsck in recovery. if (dedup.count(partition)) { continue; } success &= remount_partition(fd.get(), partition.c_str()); } if (!dedup.empty()) { WriteFdExactly(fd.get(), "The following partitions are deduplicated and cannot " "yet be remounted:\n"); for (const std::string& name : dedup) { WriteFdFmt(fd.get(), " %s\n", name.c_str()); } WriteFdExactly(fd.get(), "To reboot and un-deduplicate the listed partitions, " "please retry with adb remount -R.\n"); if (system_verified || vendor_verified) { WriteFdExactly(fd.get(), "Note: verity will be automatically disabled after reboot.\n"); } return; } if (!success) { WriteFdExactly(fd.get(), "remount failed\n"); } else { WriteFdExactly(fd.get(), "remount succeeded\n"); } }
void framebuffer_service(unique_fd fd) { struct fbinfo fbinfo; unsigned int i, bsize; char buf[640]; int fd_screencap; int w, h, f, c; int fds[2]; pid_t pid; if (pipe2(fds, O_CLOEXEC) < 0) return; pid = fork(); if (pid < 0) goto done; if (pid == 0) { dup2(fds[1], STDOUT_FILENO); adb_close(fds[0]); adb_close(fds[1]); const char* command = "screencap"; const char *args[2] = {command, nullptr}; execvp(command, (char**)args); perror_exit("exec screencap failed"); } adb_close(fds[1]); fd_screencap = fds[0]; /* read w, h, format & color space */ if(!ReadFdExactly(fd_screencap, &w, 4)) goto done; if(!ReadFdExactly(fd_screencap, &h, 4)) goto done; if(!ReadFdExactly(fd_screencap, &f, 4)) goto done; if(!ReadFdExactly(fd_screencap, &c, 4)) goto done; fbinfo.version = DDMS_RAWIMAGE_VERSION; fbinfo.colorSpace = c; /* see hardware/hardware.h */ switch (f) { case 1: /* RGBA_8888 */ fbinfo.bpp = 32; fbinfo.size = w * h * 4; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 0; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 16; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 8; break; case 2: /* RGBX_8888 */ fbinfo.bpp = 32; fbinfo.size = w * h * 4; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 0; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 16; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 0; break; case 3: /* RGB_888 */ fbinfo.bpp = 24; fbinfo.size = w * h * 3; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 0; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 16; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 0; break; case 4: /* RGB_565 */ fbinfo.bpp = 16; fbinfo.size = w * h * 2; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 11; fbinfo.red_length = 5; fbinfo.green_offset = 5; fbinfo.green_length = 6; fbinfo.blue_offset = 0; fbinfo.blue_length = 5; fbinfo.alpha_offset = 0; fbinfo.alpha_length = 0; break; case 5: /* BGRA_8888 */ fbinfo.bpp = 32; fbinfo.size = w * h * 4; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 16; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 0; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 8; break; default: goto done; } /* write header */ if (!WriteFdExactly(fd.get(), &fbinfo, sizeof(fbinfo))) goto done; /* write data */ for(i = 0; i < fbinfo.size; i += bsize) { bsize = sizeof(buf); if (i + bsize > fbinfo.size) bsize = fbinfo.size - i; if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done; if (!WriteFdExactly(fd.get(), buf, bsize)) goto done; } done: adb_close(fds[0]); TEMP_FAILURE_RETRY(waitpid(pid, nullptr, 0)); }