diff --git a/EncryptInplace.cpp b/EncryptInplace.cpp index 45734a8..6462dbf 100644 --- a/EncryptInplace.cpp +++ b/EncryptInplace.cpp @@ -73,6 +73,7 @@ struct encryptGroupsData int completed; time_t time_started; int remaining_time; + bool set_progress_properties; }; static void update_progress(struct encryptGroupsData* data, int is_used) @@ -88,6 +89,8 @@ static void update_progress(struct encryptGroupsData* data, int is_used) data->new_pct = data->blocks_already_done / data->one_pct; } + if (!data->set_progress_properties) return; + if (data->new_pct > data->cur_pct) { char buf[8]; data->cur_pct = data->new_pct; @@ -253,7 +256,8 @@ errout: static int cryptfs_enable_inplace_ext4(char* crypto_blkdev, char* real_blkdev, off64_t size, off64_t* size_already_done, off64_t tot_size, - off64_t previously_encrypted_upto) { + off64_t previously_encrypted_upto, + bool set_progress_properties) { u32 i; struct encryptGroupsData data; int rc; // Can't initialize without causing warning -Wclobbered @@ -268,13 +272,16 @@ static int cryptfs_enable_inplace_ext4(char* crypto_blkdev, char* real_blkdev, o memset(&data, 0, sizeof(data)); data.real_blkdev = real_blkdev; data.crypto_blkdev = crypto_blkdev; + data.set_progress_properties = set_progress_properties; + LOG(DEBUG) << "Opening" << real_blkdev; if ( (data.realfd = open(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) { PLOG(ERROR) << "Error opening real_blkdev " << real_blkdev << " for inplace encrypt"; rc = -1; goto errout; } + LOG(DEBUG) << "Opening" << crypto_blkdev; // Wait until the block device appears. Re-use the mount retry values since it is reasonable. while ((data.cryptofd = open(crypto_blkdev, O_WRONLY|O_CLOEXEC)) < 0) { if (--retries) { @@ -390,7 +397,8 @@ static int encrypt_one_block_f2fs(u64 pos, void *data) static int cryptfs_enable_inplace_f2fs(char* crypto_blkdev, char* real_blkdev, off64_t size, off64_t* size_already_done, off64_t tot_size, - off64_t previously_encrypted_upto) { + off64_t previously_encrypted_upto, + bool set_progress_properties) { struct encryptGroupsData data; struct f2fs_info *f2fs_info = NULL; int rc = ENABLE_INPLACE_ERR_OTHER; @@ -401,6 +409,7 @@ static int cryptfs_enable_inplace_f2fs(char* crypto_blkdev, char* real_blkdev, o memset(&data, 0, sizeof(data)); data.real_blkdev = real_blkdev; data.crypto_blkdev = crypto_blkdev; + data.set_progress_properties = set_progress_properties; data.realfd = -1; data.cryptofd = -1; if ( (data.realfd = open64(real_blkdev, O_RDWR|O_CLOEXEC)) < 0) { @@ -463,7 +472,8 @@ errout: static int cryptfs_enable_inplace_full(char* crypto_blkdev, char* real_blkdev, off64_t size, off64_t* size_already_done, off64_t tot_size, - off64_t previously_encrypted_upto) { + off64_t previously_encrypted_upto, + bool set_progress_properties) { int realfd, cryptofd; char *buf[CRYPT_INPLACE_BUFSIZE]; int rc = ENABLE_INPLACE_ERR_OTHER; @@ -526,7 +536,7 @@ static int cryptfs_enable_inplace_full(char* crypto_blkdev, char* real_blkdev, o /* process the majority of the filesystem in blocks */ for (i/=CRYPT_SECTORS_PER_BUFSIZE; i cur_pct) { + if (set_progress_properties && new_pct > cur_pct) { char buf[8]; cur_pct = new_pct; @@ -575,13 +585,17 @@ errout: /* returns on of the ENABLE_INPLACE_* return codes */ int cryptfs_enable_inplace(char* crypto_blkdev, char* real_blkdev, off64_t size, off64_t* size_already_done, off64_t tot_size, - off64_t previously_encrypted_upto) { + off64_t previously_encrypted_upto, bool set_progress_properties) { int rc_ext4, rc_f2fs, rc_full; + LOG(DEBUG) << "cryptfs_enable_inplace(" << crypto_blkdev << ", " << real_blkdev << ", " << size + << ", " << size_already_done << ", " << tot_size << ", " << previously_encrypted_upto + << ", " << set_progress_properties << ")"; if (previously_encrypted_upto) { LOG(DEBUG) << "Continuing encryption from " << previously_encrypted_upto; } if (*size_already_done + size < previously_encrypted_upto) { + LOG(DEBUG) << "cryptfs_enable_inplace already done"; *size_already_done += size; return 0; } @@ -590,30 +604,33 @@ int cryptfs_enable_inplace(char* crypto_blkdev, char* real_blkdev, off64_t size, * As is, cryptfs_enable_inplace_ext4 will fail on an f2fs partition, and * then we will drop down to cryptfs_enable_inplace_f2fs. * */ - if ((rc_ext4 = cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev, - size, size_already_done, - tot_size, previously_encrypted_upto)) == 0) { - return 0; + if ((rc_ext4 = cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev, size, size_already_done, + tot_size, previously_encrypted_upto, + set_progress_properties)) == 0) { + LOG(DEBUG) << "cryptfs_enable_inplace_ext4 success"; + return 0; } LOG(DEBUG) << "cryptfs_enable_inplace_ext4()=" << rc_ext4; - if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev, - size, size_already_done, - tot_size, previously_encrypted_upto)) == 0) { - return 0; + if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev, size, size_already_done, + tot_size, previously_encrypted_upto, + set_progress_properties)) == 0) { + LOG(DEBUG) << "cryptfs_enable_inplace_f2fs success"; + return 0; } LOG(DEBUG) << "cryptfs_enable_inplace_f2fs()=" << rc_f2fs; - rc_full = cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev, - size, size_already_done, tot_size, - previously_encrypted_upto); + rc_full = + cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev, size, size_already_done, tot_size, + previously_encrypted_upto, set_progress_properties); LOG(DEBUG) << "cryptfs_enable_inplace_full()=" << rc_full; /* Hack for b/17898962, the following is the symptom... */ if (rc_ext4 == ENABLE_INPLACE_ERR_DEV && rc_f2fs == ENABLE_INPLACE_ERR_DEV && rc_full == ENABLE_INPLACE_ERR_DEV) { - return ENABLE_INPLACE_ERR_DEV; + LOG(DEBUG) << "ENABLE_INPLACE_ERR_DEV"; + return ENABLE_INPLACE_ERR_DEV; } return rc_full; } diff --git a/EncryptInplace.h b/EncryptInplace.h index de5a1c5..71644ac 100644 --- a/EncryptInplace.h +++ b/EncryptInplace.h @@ -24,9 +24,8 @@ #define RETRY_MOUNT_ATTEMPTS 10 #define RETRY_MOUNT_DELAY_SECONDS 1 -int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev, - off64_t size, off64_t *size_already_done, - off64_t tot_size, - off64_t previously_encrypted_upto); +int cryptfs_enable_inplace(char* crypto_blkdev, char* real_blkdev, off64_t size, + off64_t* size_already_done, off64_t tot_size, + off64_t previously_encrypted_upto, bool set_progress_properties); #endif diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp index 24047f9..4a847e3 100644 --- a/MetadataCrypt.cpp +++ b/MetadataCrypt.cpp @@ -31,8 +31,9 @@ #include #include +#include #include -#include +#include #include #include "EncryptInplace.h" @@ -71,26 +72,17 @@ static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) { return true; } -static bool read_key(bool create_if_absent, KeyBuffer* key) { - auto data_rec = fs_mgr_get_crypt_entry(fstab_default); - if (!data_rec) { - LOG(ERROR) << "Failed to get data_rec"; - return false; - } +static bool read_key(struct fstab_rec const* data_rec, bool create_if_absent, KeyBuffer* key) { if (!data_rec->key_dir) { LOG(ERROR) << "Failed to get key_dir"; return false; } - LOG(DEBUG) << "key_dir: " << data_rec->key_dir; - if (!android::vold::pathExists(data_rec->key_dir)) { - if (mkdir(data_rec->key_dir, 0777) != 0) { - PLOG(ERROR) << "Unable to create: " << data_rec->key_dir; - return false; - } - LOG(DEBUG) << "Created: " << data_rec->key_dir; - } std::string key_dir = data_rec->key_dir; auto dir = key_dir + "/key"; + LOG(DEBUG) << "key_dir/key: " << key; + if (!fs_mkdirs(dir.c_str(), 0700)) { + PLOG(ERROR) << "Creating directories: " << dir; + } auto temp = key_dir + "/tmp"; if (!android::vold::retrieveKey(create_if_absent, dir, temp, key)) return false; return true; @@ -103,7 +95,6 @@ static KeyBuffer default_key_params(const std::string& real_blkdev, const KeyBuf return KeyBuffer(); } auto res = KeyBuffer() + "AES-256-XTS " + hex_key + " " + real_blkdev.c_str() + " 0"; - LOG(DEBUG) << "crypt_params: " << std::string(res.data(), res.size()); return res; } @@ -211,108 +202,45 @@ static bool create_crypto_blk_dev(const std::string& dm_name, uint64_t nr_sec, return true; } -#define DATA_PREP_TIMEOUT 1000 -static bool prep_data_fs(void) -{ - // NOTE: post_fs_data results in init calling back around to vold, so all - // callers to this method must be async - - /* Do the prep of the /data filesystem */ - property_set("vold.post_fs_data_done", "0"); - property_set("vold.decrypt", "trigger_post_fs_data"); - LOG(DEBUG) << "Waiting for post_fs_data_done"; - - /* Wait a max of 50 seconds, hopefully it takes much less */ - for (int i = 0; ; i++) { - char p[PROPERTY_VALUE_MAX]; - - property_get("vold.post_fs_data_done", p, "0"); - if (*p == '1') { - LOG(INFO) << "Successful data prep"; - return true; - } - if (i + 1 == DATA_PREP_TIMEOUT) { - LOG(ERROR) << "post_fs_data timed out"; - return false; - } - usleep(50000); - } -} - -static void async_kick_off() { - LOG(DEBUG) << "Asynchronously restarting framework"; - sleep(2); // TODO: this mirrors cryptfs, but can it be made shorter? - property_set("vold.decrypt", "trigger_load_persist_props"); - if (!prep_data_fs()) return; - /* startup service classes main and late_start */ - property_set("vold.decrypt", "trigger_restart_framework"); -} - -bool e4crypt_mount_metadata_encrypted() { - LOG(DEBUG) << "e4crypt_mount_default_encrypted"; - KeyBuffer key; - if (!read_key(false, &key)) return false; - auto data_rec = fs_mgr_get_crypt_entry(fstab_default); - if (!data_rec) { - LOG(ERROR) << "Failed to get data_rec"; - return false; - } - uint64_t nr_sec; - if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false; - std::string crypto_blkdev; - if (!create_crypto_blk_dev(kDmNameUserdata, nr_sec, DEFAULT_KEY_TARGET_TYPE, - default_key_params(data_rec->blk_device, key), &crypto_blkdev)) return false; - // FIXME handle the corrupt case - - LOG(DEBUG) << "Restarting filesystem for metadata encryption"; - mount_via_fs_mgr(data_rec->mount_point, crypto_blkdev.c_str()); - std::thread(&async_kick_off).detach(); - return true; -} - -bool e4crypt_enable_crypto() { - LOG(DEBUG) << "e4crypt_enable_crypto"; - char encrypted_state[PROPERTY_VALUE_MAX]; - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "")) { +bool e4crypt_mount_metadata_encrypted(const std::string& mount_point, bool needs_encrypt) { + LOG(DEBUG) << "e4crypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt; + auto encrypted_state = android::base::GetProperty("ro.crypto.state", ""); + if (encrypted_state != "") { LOG(DEBUG) << "e4crypt_enable_crypto got unexpected starting state: " << encrypted_state; return false; } - - KeyBuffer key_ref; - if (!read_key(true, &key_ref)) return false; - - auto data_rec = fs_mgr_get_crypt_entry(fstab_default); + auto data_rec = fs_mgr_get_entry_for_mount_point(fstab_default, mount_point); if (!data_rec) { LOG(ERROR) << "Failed to get data_rec"; return false; } + KeyBuffer key; + if (!read_key(data_rec, needs_encrypt, &key)) return false; uint64_t nr_sec; if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false; - std::string crypto_blkdev; if (!create_crypto_blk_dev(kDmNameUserdata, nr_sec, DEFAULT_KEY_TARGET_TYPE, - default_key_params(data_rec->blk_device, key_ref), &crypto_blkdev)) return false; - - LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec; - off64_t size_already_done = 0; - auto rc = cryptfs_enable_inplace(const_cast(crypto_blkdev.c_str()), - data_rec->blk_device, nr_sec, &size_already_done, nr_sec, 0); - if (rc != 0) { - LOG(ERROR) << "Inplace crypto failed with code: " << rc; + default_key_params(data_rec->blk_device, key), &crypto_blkdev)) return false; + // FIXME handle the corrupt case + if (needs_encrypt) { + LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec; + off64_t size_already_done = 0; + auto rc = + cryptfs_enable_inplace(const_cast(crypto_blkdev.c_str()), data_rec->blk_device, + nr_sec, &size_already_done, nr_sec, 0, false); + if (rc != 0) { + LOG(ERROR) << "Inplace crypto failed with code: " << rc; + return false; + } + if (static_cast(size_already_done) != nr_sec) { + LOG(ERROR) << "Inplace crypto only got up to sector: " << size_already_done; + return false; + } + LOG(INFO) << "Inplace encryption complete"; } - if (static_cast(size_already_done) != nr_sec) { - LOG(ERROR) << "Inplace crypto only got up to sector: " << size_already_done; - return false; - } - LOG(INFO) << "Inplace encryption complete"; - - property_set("ro.crypto.state", "encrypted"); - property_set("ro.crypto.type", "file"); + LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point; mount_via_fs_mgr(data_rec->mount_point, crypto_blkdev.c_str()); - property_set("vold.decrypt", "trigger_reset_main"); - std::thread(&async_kick_off).detach(); return true; } diff --git a/MetadataCrypt.h b/MetadataCrypt.h index f6634ea..841dc97 100644 --- a/MetadataCrypt.h +++ b/MetadataCrypt.h @@ -17,7 +17,8 @@ #ifndef _METADATA_CRYPT_H #define _METADATA_CRYPT_H -bool e4crypt_mount_metadata_encrypted(); -bool e4crypt_enable_crypto(); +#include + +bool e4crypt_mount_metadata_encrypted(const std::string& mount_point, bool needs_encrypt); #endif diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index f7637fd..f4961ce 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -247,16 +247,6 @@ binder::Status VoldNativeService::shutdown() { return translate(VolumeManager::Instance()->shutdown()); } -binder::Status VoldNativeService::mountAll() { - ENFORCE_UID(AID_SYSTEM); - ACQUIRE_LOCK; - - struct fstab* fstab = fs_mgr_read_fstab_default(); - int res = fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT); - fs_mgr_free_fstab(fstab); - return translate(res); -} - binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) { ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; @@ -577,12 +567,12 @@ binder::Status VoldNativeService::fdeEnable(int32_t passwordType, ENFORCE_UID(AID_SYSTEM); ACQUIRE_CRYPT_LOCK; + LOG(DEBUG) << "fdeEnable(" << passwordType << ", *, " << encryptionFlags << ")"; if (e4crypt_is_native()) { - if (passwordType != PASSWORD_TYPE_DEFAULT) { - return error("Unexpected password type"); - } - return translateBool(e4crypt_enable_crypto()); + LOG(ERROR) << "e4crypt_is_native, fdeEnable invalid"; + return error("e4crypt_is_native, fdeEnable invalid"); } + LOG(DEBUG) << "!e4crypt_is_native, spawning fdeEnableInternal"; // Spawn as thread so init can issue commands back to vold without // causing deadlock, usually as a result of prep_data_fs. @@ -665,14 +655,12 @@ binder::Status VoldNativeService::mountDefaultEncrypted() { ENFORCE_UID(AID_SYSTEM); ACQUIRE_CRYPT_LOCK; - if (e4crypt_is_native()) { - return translateBool(e4crypt_mount_metadata_encrypted()); - } else { + if (!e4crypt_is_native()) { // Spawn as thread so init can issue commands back to vold without // causing deadlock, usually as a result of prep_data_fs. std::thread(&cryptfs_mount_default_encrypted).detach(); - return ok(); } + return ok(); } binder::Status VoldNativeService::initUser0() { @@ -690,6 +678,20 @@ binder::Status VoldNativeService::isConvertibleToFbe(bool* _aidl_return) { return ok(); } +binder::Status VoldNativeService::mountFstab(const std::string& mountPoint) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translateBool(e4crypt_mount_metadata_encrypted(mountPoint, false)); +} + +binder::Status VoldNativeService::encryptFstab(const std::string& mountPoint) { + ENFORCE_UID(AID_SYSTEM); + ACQUIRE_LOCK; + + return translateBool(e4crypt_mount_metadata_encrypted(mountPoint, true)); +} + binder::Status VoldNativeService::createUserKey(int32_t userId, int32_t userSerial, bool ephemeral) { ENFORCE_UID(AID_SYSTEM); diff --git a/VoldNativeService.h b/VoldNativeService.h index 1359d90..817f815 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -36,7 +36,6 @@ public: binder::Status monitor(); binder::Status reset(); binder::Status shutdown(); - binder::Status mountAll(); binder::Status onUserAdded(int32_t userId, int32_t userSerial); binder::Status onUserRemoved(int32_t userId); @@ -96,6 +95,8 @@ public: binder::Status mountDefaultEncrypted(); binder::Status initUser0(); binder::Status isConvertibleToFbe(bool* _aidl_return); + binder::Status mountFstab(const std::string& mountPoint); + binder::Status encryptFstab(const std::string& mountPoint); binder::Status createUserKey(int32_t userId, int32_t userSerial, bool ephemeral); binder::Status destroyUserKey(int32_t userId); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index 9facaf7..a664dfa 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -26,7 +26,6 @@ interface IVold { void monitor(); void reset(); void shutdown(); - void mountAll(); void onUserAdded(int userId, int userSerial); void onUserRemoved(int userId); @@ -79,6 +78,8 @@ interface IVold { void mountDefaultEncrypted(); void initUser0(); boolean isConvertibleToFbe(); + void mountFstab(@utf8InCpp String mountPoint); + void encryptFstab(@utf8InCpp String mountPoint); void createUserKey(int userId, int userSerial, boolean ephemeral); void destroyUserKey(int userId); diff --git a/cryptfs.cpp b/cryptfs.cpp index aa60541..e363835 100644 --- a/cryptfs.cpp +++ b/cryptfs.cpp @@ -1974,7 +1974,7 @@ static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr* crypt_ftr, char* cry tot_encryption_size = crypt_ftr->fs_size; rc = cryptfs_enable_inplace(crypto_blkdev, real_blkdev, crypt_ftr->fs_size, &cur_encryption_done, - tot_encryption_size, previously_encrypted_upto); + tot_encryption_size, previously_encrypted_upto, true); if (rc == ENABLE_INPLACE_ERR_DEV) { /* Hack for b/17898962 */ diff --git a/main.cpp b/main.cpp index 62ea6b7..5525e85 100644 --- a/main.cpp +++ b/main.cpp @@ -51,12 +51,14 @@ struct selabel_handle *sehandle; using android::base::StringPrintf; int main(int argc, char** argv) { + atrace_set_tracing_enabled(false); setenv("ANDROID_LOG_TAGS", "*:v", 1); android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); + LOG(INFO) << "Vold 3.0 (the awakening) firing up"; + ATRACE_BEGIN("main"); - LOG(INFO) << "Vold 3.0 (the awakening) firing up"; LOG(VERBOSE) << "Detected support for:" << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "") @@ -113,6 +115,8 @@ int main(int argc, char** argv) { } ATRACE_END(); + LOG(DEBUG) << "VoldNativeService::start() completed OK"; + ATRACE_BEGIN("NetlinkManager::start"); if (nm->start()) { PLOG(ERROR) << "Unable to start NetlinkManager"; diff --git a/vdc.cpp b/vdc.cpp index 5ae4cd9..3c449ae 100644 --- a/vdc.cpp +++ b/vdc.cpp @@ -44,7 +44,7 @@ static android::sp getServiceAggressive() { android::sp res; auto sm = android::defaultServiceManager(); auto name = android::String16("vold"); - for (int i = 0; i < 500; i++) { + for (int i = 0; i < 5000; i++) { res = sm->checkService(name); if (res) { LOG(VERBOSE) << "Waited " << (i * 10) << "ms for vold"; @@ -101,6 +101,10 @@ int main(int argc, char** argv) { checkStatus(vold->shutdown()); } else if (args[0] == "cryptfs" && args[1] == "checkEncryption" && args.size() == 3) { checkStatus(vold->checkEncryption(args[2])); + } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 3) { + checkStatus(vold->mountFstab(args[2])); + } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 3) { + checkStatus(vold->encryptFstab(args[2])); } else { LOG(ERROR) << "Raw commands are no longer supported"; exit(EINVAL);