From 8f7f56e25b2f289cd3d025d717fdc7fa422d1f98 Mon Sep 17 00:00:00 2001 From: Paul Crowley Date: Fri, 27 Nov 2015 09:29:37 +0000 Subject: [PATCH] Add --wipe-and-use-fbe option to fastboot for FBE userdata marker. With this option, userdata is wiped and recreated with the "convert_fbe" file in the root, which triggers conversion to FBE. Bug: 25898323 Change-Id: I9347b7057b6278e7e6437504896b22c82dd01d89 --- fastboot/fastboot.cpp | 95 ++++++++++++++++++++++++++++++++++++++++--- fastboot/fs.cpp | 28 +++++++++---- fastboot/fs.h | 4 +- 3 files changed, 112 insertions(+), 15 deletions(-) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index a16d7dd23..afdfd0ebc 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -81,6 +81,8 @@ static unsigned ramdisk_offset = 0x01000000; static unsigned second_offset = 0x00f00000; static unsigned tags_offset = 0x00000100; +static const std::string convert_fbe_marker_filename("convert_fbe"); + enum fb_buffer_type { FB_BUFFER, FB_BUFFER_SPARSE, @@ -322,11 +324,17 @@ static void usage() { " provided, this will default to the value\n" " given by --slot. If slots are not\n" " supported, this does nothing.\n" +#if !defined(_WIN32) + " --wipe-and-use-fbe On devices which support it,\n" + " erase userdata and cache, and\n" + " enable file-based encryption\n" +#endif " --unbuffered Do not buffer input or output.\n" " --version Display version.\n" " -h, --help show this message.\n" ); } + static void* load_bootable_image(const char* kernel, const char* ramdisk, const char* secondstage, int64_t* sz, const char* cmdline) { @@ -446,8 +454,60 @@ static FILE* win32_tmpfile() { #define tmpfile win32_tmpfile +static std::string make_temporary_directory() { + fprintf(stderr, "make_temporary_directory not supported under Windows, sorry!"); + return ""; +} + +#else + +static std::string make_temporary_directory() { + const char *tmpdir = getenv("TMPDIR"); + if (tmpdir == nullptr) { + tmpdir = P_tmpdir; + } + std::string result = std::string(tmpdir) + "/fastboot_userdata_XXXXXX"; + if (mkdtemp(&result[0]) == NULL) { + fprintf(stderr, "Unable to create temporary directory: %s\n", + strerror(errno)); + return ""; + } + return result; +} + #endif +static std::string create_fbemarker_tmpdir() { + std::string dir = make_temporary_directory(); + if (dir.empty()) { + fprintf(stderr, "Unable to create local temp directory for FBE marker\n"); + return ""; + } + std::string marker_file = dir + "/" + convert_fbe_marker_filename; + int fd = open(marker_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0666); + if (fd == -1) { + fprintf(stderr, "Unable to create FBE marker file %s locally: %d, %s\n", + marker_file.c_str(), errno, strerror(errno)); + return ""; + } + close(fd); + return dir; +} + +static void delete_fbemarker_tmpdir(const std::string& dir) { + std::string marker_file = dir + "/" + convert_fbe_marker_filename; + if (unlink(marker_file.c_str()) == -1) { + fprintf(stderr, "Unable to delete FBE marker file %s locally: %d, %s\n", + marker_file.c_str(), errno, strerror(errno)); + return; + } + if (rmdir(dir.c_str()) == -1) { + fprintf(stderr, "Unable to delete FBE marker directory %s locally: %d, %s\n", + dir.c_str(), errno, strerror(errno)); + return; + } +} + static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { FILE* fp = tmpfile(); if (fp == nullptr) { @@ -994,7 +1054,8 @@ static int64_t parse_num(const char *arg) static void fb_perform_format(Transport* transport, const char* partition, int skip_if_not_supported, - const char* type_override, const char* size_override) { + const char* type_override, const char* size_override, + const std::string& initial_dir) { std::string partition_type, partition_size; struct fastboot_buffer buf; @@ -1058,7 +1119,7 @@ static void fb_perform_format(Transport* transport, } fd = fileno(tmpfile()); - if (fs_generator_generate(gen, fd, size)) { + if (fs_generator_generate(gen, fd, size, initial_dir)) { fprintf(stderr, "Cannot generate image: %s\n", strerror(errno)); close(fd); return; @@ -1087,6 +1148,7 @@ int main(int argc, char **argv) bool wants_reboot_bootloader = false; bool wants_set_active = false; bool erase_first = true; + bool set_fbe_marker = false; void *data; int64_t sz; int longindex; @@ -1109,6 +1171,9 @@ int main(int argc, char **argv) {"slot", required_argument, 0, 0}, {"set_active", optional_argument, 0, 'a'}, {"set-active", optional_argument, 0, 'a'}, +#if !defined(_WIN32) + {"wipe-and-use-fbe", no_argument, 0, 0}, +#endif {0, 0, 0, 0} }; @@ -1190,6 +1255,15 @@ int main(int argc, char **argv) return 0; } else if (strcmp("slot", longopts[longindex].name) == 0) { slot_override = std::string(optarg); +#if !defined(_WIN32) + } else if (strcmp("wipe-and-use-fbe", longopts[longindex].name) == 0) { + wants_wipe = true; + set_fbe_marker = true; +#endif + } else { + fprintf(stderr, "Internal error in options processing for %s\n", + longopts[longindex].name); + return 1; } break; default: @@ -1283,7 +1357,8 @@ int main(int argc, char **argv) if (erase_first && needs_erase(transport, partition.c_str())) { fb_queue_erase(partition.c_str()); } - fb_perform_format(transport, partition.c_str(), 0, type_override, size_override); + fb_perform_format(transport, partition.c_str(), 0, + type_override, size_override, ""); }; do_for_partitions(transport, argv[1], slot_override.c_str(), format, true); skip(2); @@ -1413,13 +1488,23 @@ int main(int argc, char **argv) if (wants_wipe) { fprintf(stderr, "wiping userdata...\n"); fb_queue_erase("userdata"); - fb_perform_format(transport, "userdata", 1, nullptr, nullptr); + if (set_fbe_marker) { + fprintf(stderr, "setting FBE marker...\n"); + std::string initial_userdata_dir = create_fbemarker_tmpdir(); + if (initial_userdata_dir.empty()) { + return 1; + } + fb_perform_format(transport, "userdata", 1, nullptr, nullptr, initial_userdata_dir); + delete_fbemarker_tmpdir(initial_userdata_dir); + } else { + fb_perform_format(transport, "userdata", 1, nullptr, nullptr, ""); + } std::string cache_type; if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) { fprintf(stderr, "wiping cache...\n"); fb_queue_erase("cache"); - fb_perform_format(transport, "cache", 1, nullptr, nullptr); + fb_perform_format(transport, "cache", 1, nullptr, nullptr, ""); } } if (wants_set_active) { diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp index 90d84742b..8539e2382 100644 --- a/fastboot/fs.cpp +++ b/fastboot/fs.cpp @@ -1,7 +1,8 @@ +#include "fs.h" + #include "fastboot.h" #include "make_ext4fs.h" #include "make_f2fs.h" -#include "fs.h" #include #include @@ -13,24 +14,32 @@ #include -static int generate_ext4_image(int fd, long long partSize) +static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir) { - make_ext4fs_sparse_fd(fd, partSize, NULL, NULL); - + if (initial_dir.empty()) { + make_ext4fs_sparse_fd(fd, partSize, NULL, NULL); + } else { + make_ext4fs_sparse_fd_directory(fd, partSize, NULL, NULL, initial_dir.c_str()); + } return 0; } #ifdef USE_F2FS -static int generate_f2fs_image(int fd, long long partSize) +static int generate_f2fs_image(int fd, long long partSize, const std::string& initial_dir) { + if (!initial_dir.empty()) { + fprintf(stderr, "Unable to set initial directory on F2FS filesystem\n"); + return -1; + } return make_f2fs_sparse_fd(fd, partSize, NULL, NULL); } #endif static const struct fs_generator { - const char* fs_type; //must match what fastboot reports for partition type - int (*generate)(int fd, long long partSize); //returns 0 or error value + + //returns 0 or error value + int (*generate)(int fd, long long partSize, const std::string& initial_dir); } generators[] = { { "ext4", generate_ext4_image}, @@ -48,7 +57,8 @@ const struct fs_generator* fs_get_generator(const std::string& fs_type) { return nullptr; } -int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize) +int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize, + const std::string& initial_dir) { - return gen->generate(tmpFileNo, partSize); + return gen->generate(tmpFileNo, partSize, initial_dir); } diff --git a/fastboot/fs.h b/fastboot/fs.h index 289488b2d..0a68507b0 100644 --- a/fastboot/fs.h +++ b/fastboot/fs.h @@ -1,11 +1,13 @@ #ifndef _FS_H_ #define _FS_H_ +#include #include struct fs_generator; const struct fs_generator* fs_get_generator(const std::string& fs_type); -int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize); +int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize, + const std::string& initial_dir); #endif