From 2143ee8d61193f4e61efb5163767d9129280d08d Mon Sep 17 00:00:00 2001 From: Paul Crowley Date: Tue, 28 Jun 2016 14:24:07 -0700 Subject: [PATCH] Zero out blocks if BLKSECDISCARD fails On a device where we can't BLKSECDISCARD sectors, we "overwrite" them with zeroes. This changes the FTL to remap those sectors to new locations. With this done, the old contents are accessible only given a compromise of flash firmware or a die level attack. Bug: 26021231 Change-Id: Ia065921389886fac1ba456c19c138187237c2561 --- secdiscard.cpp | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/secdiscard.cpp b/secdiscard.cpp index 5c12cdd..fe51990 100644 --- a/secdiscard.cpp +++ b/secdiscard.cpp @@ -43,11 +43,12 @@ constexpr uint32_t max_extents = 32; bool read_command_line(int argc, const char * const argv[], Options &options); void usage(const char *progname); -int secdiscard_path(const std::string &path); +bool secdiscard_path(const std::string &path); std::unique_ptr path_fiemap(const std::string &path, uint32_t extent_count); bool check_fiemap(const struct fiemap &fiemap, const std::string &path); std::unique_ptr alloc_fiemap(uint32_t extent_count); std::string block_device_for_path(const std::string &path); +bool overwrite_with_zeros(int fd, off64_t start, off64_t length); } @@ -58,9 +59,11 @@ int main(int argc, const char * const argv[]) { usage(argv[0]); return -1; } - for (auto target: options.targets) { + for (auto const &target: options.targets) { LOG(DEBUG) << "Securely discarding '" << target << "' unlink=" << options.unlink; - secdiscard_path(target); + if (!secdiscard_path(target)) { + LOG(ERROR) << "Secure discard failed for: " << target; + } if (options.unlink) { if (unlink(target.c_str()) != 0 && errno != ENOENT) { PLOG(ERROR) << "Unable to unlink: " << target; @@ -95,19 +98,19 @@ void usage(const char *progname) { } // BLKSECDISCARD all content in "path", if it's small enough. -int secdiscard_path(const std::string &path) { +bool secdiscard_path(const std::string &path) { auto fiemap = path_fiemap(path, max_extents); if (!fiemap || !check_fiemap(*fiemap, path)) { - return -1; + return false; } auto block_device = block_device_for_path(path); if (block_device.empty()) { - return -1; + return false; } AutoCloseFD fs_fd(block_device, O_RDWR | O_LARGEFILE); if (!fs_fd) { PLOG(ERROR) << "Failed to open device " << block_device; - return -1; + return false; } for (uint32_t i = 0; i < fiemap->fm_mapped_extents; i++) { uint64_t range[2]; @@ -115,10 +118,11 @@ int secdiscard_path(const std::string &path) { range[1] = fiemap->fm_extents[i].fe_length; if (ioctl(fs_fd.get(), BLKSECDISCARD, range) == -1) { PLOG(ERROR) << "Unable to BLKSECDISCARD " << path; - return -1; + if (!overwrite_with_zeros(fs_fd.get(), range[0], range[1])) return false; + LOG(DEBUG) << "Used zero overwrite"; } } - return 0; + return true; } // Read the file's FIEMAP @@ -206,4 +210,23 @@ std::string block_device_for_path(const std::string &path) return result; } +bool overwrite_with_zeros(int fd, off64_t start, off64_t length) { + if (lseek64(fd, start, SEEK_SET) != start) { + PLOG(ERROR) << "Seek failed for zero overwrite"; + return false; + } + char buf[BUFSIZ]; + memset(buf, 0, sizeof(buf)); + while (length > 0) { + size_t wlen = static_cast(std::min(static_cast(sizeof(buf)), length)); + auto written = write(fd, buf, wlen); + if (written < 1) { + PLOG(ERROR) << "Write of zeroes failed"; + return false; + } + length -= written; + } + return true; +} + }