diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index e3d4f870c..61c9cd788 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -721,6 +721,12 @@ static bool needs_block_encryption(const struct fstab_rec* rec) return false; } +static bool should_use_metadata_encryption(const struct fstab_rec* rec) { + if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false; + if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false; + return true; +} + // Check to see if a mountable volume has encryption requirements static int handle_encryptable(const struct fstab_rec* rec) { @@ -733,8 +739,14 @@ static int handle_encryptable(const struct fstab_rec* rec) << " - allow continue unencrypted"; return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; } + } else if (should_use_metadata_encryption(rec)) { + if (umount(rec->mount_point) == 0) { + return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION; + } else { + PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt"; + return FS_MGR_MNTALL_FAIL; + } } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) { - // Deal with file level encryption LINFO << rec->mount_point << " is file encrypted"; return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED; } else if (fs_mgr_is_encryptable(rec)) { @@ -900,7 +912,6 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) continue; } - /* mount(2) returned an error, handle the encryptable/formattable case */ bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); bool crypt_footer = false; if (mret && mount_errno != EBUSY && mount_errno != EACCES && @@ -940,6 +951,8 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) continue; } } + + /* mount(2) returned an error, handle the encryptable/formattable case */ if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if (wiped) { @@ -965,6 +978,9 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; + } else if (mret && mount_errno != EBUSY && mount_errno != EACCES && + should_use_metadata_encryption(&fstab->recs[attempted_idx])) { + encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED; } else { if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) { PERROR << "Ignoring failure to mount an un-encryptable or wiped partition on" @@ -1256,48 +1272,46 @@ int fs_mgr_swapon_all(struct fstab *fstab) return ret; } -/* - * key_loc must be at least PROPERTY_VALUE_MAX bytes long - * - * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long - */ -int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size) -{ - int i = 0; +struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) { + int i; if (!fstab) { - return -1; - } - /* Initialize return values to null strings */ - if (key_loc) { - *key_loc = '\0'; - } - if (real_blk_device) { - *real_blk_device = '\0'; + return NULL; } /* Look for the encryptable partition to find the data */ for (i = 0; i < fstab->num_entries; i++) { /* Don't deal with vold managed enryptable partitions here */ - if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { - continue; + if (!(fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) && + (fstab->recs[i].fs_mgr_flags & + (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE | MF_FILEENCRYPTION))) { + return &fstab->recs[i]; } - if (!(fstab->recs[i].fs_mgr_flags - & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE))) { - continue; - } - - /* We found a match */ - if (key_loc) { - strlcpy(key_loc, fstab->recs[i].key_loc, size); - } - if (real_blk_device) { - strlcpy(real_blk_device, fstab->recs[i].blk_device, size); - } - break; } + return NULL; +} - return 0; +/* + * key_loc must be at least PROPERTY_VALUE_MAX bytes long + * + * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long + */ +void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size) { + struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab); + if (key_loc) { + if (rec) { + strlcpy(key_loc, rec->key_loc, size); + } else { + *key_loc = '\0'; + } + } + if (real_blk_device) { + if (rec) { + strlcpy(real_blk_device, rec->blk_device, size); + } else { + *real_blk_device = '\0'; + } + } } bool fs_mgr_load_verity_state(int* mode) { diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 0a694c145..e43eb7a56 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -31,6 +31,7 @@ struct fs_mgr_flag_values { char *key_loc; + char* key_dir; char *verity_loc; long long part_length; char *label; @@ -70,34 +71,35 @@ static struct flag_list mount_flags[] = { }; static struct flag_list fs_mgr_flags[] = { - { "wait", MF_WAIT }, - { "check", MF_CHECK }, - { "encryptable=", MF_CRYPT }, - { "forceencrypt=", MF_FORCECRYPT }, - { "fileencryption=", MF_FILEENCRYPTION }, - { "forcefdeorfbe=", MF_FORCEFDEORFBE }, - { "nonremovable", MF_NONREMOVABLE }, - { "voldmanaged=", MF_VOLDMANAGED}, - { "length=", MF_LENGTH }, - { "recoveryonly", MF_RECOVERYONLY }, - { "swapprio=", MF_SWAPPRIO }, - { "zramsize=", MF_ZRAMSIZE }, - { "max_comp_streams=", MF_MAX_COMP_STREAMS }, - { "verifyatboot", MF_VERIFYATBOOT }, - { "verify", MF_VERIFY }, - { "avb", MF_AVB }, - { "noemulatedsd", MF_NOEMULATEDSD }, - { "notrim", MF_NOTRIM }, - { "formattable", MF_FORMATTABLE }, - { "slotselect", MF_SLOTSELECT }, - { "nofail", MF_NOFAIL }, - { "latemount", MF_LATEMOUNT }, - { "reservedsize=", MF_RESERVEDSIZE }, - { "quota", MF_QUOTA }, - { "eraseblk=", MF_ERASEBLKSIZE }, - { "logicalblk=", MF_LOGICALBLKSIZE }, - { "defaults", 0 }, - { 0, 0 }, + {"wait", MF_WAIT}, + {"check", MF_CHECK}, + {"encryptable=", MF_CRYPT}, + {"forceencrypt=", MF_FORCECRYPT}, + {"fileencryption=", MF_FILEENCRYPTION}, + {"forcefdeorfbe=", MF_FORCEFDEORFBE}, + {"keydirectory=", MF_KEYDIRECTORY}, + {"nonremovable", MF_NONREMOVABLE}, + {"voldmanaged=", MF_VOLDMANAGED}, + {"length=", MF_LENGTH}, + {"recoveryonly", MF_RECOVERYONLY}, + {"swapprio=", MF_SWAPPRIO}, + {"zramsize=", MF_ZRAMSIZE}, + {"max_comp_streams=", MF_MAX_COMP_STREAMS}, + {"verifyatboot", MF_VERIFYATBOOT}, + {"verify", MF_VERIFY}, + {"avb", MF_AVB}, + {"noemulatedsd", MF_NOEMULATEDSD}, + {"notrim", MF_NOTRIM}, + {"formattable", MF_FORMATTABLE}, + {"slotselect", MF_SLOTSELECT}, + {"nofail", MF_NOFAIL}, + {"latemount", MF_LATEMOUNT}, + {"reservedsize=", MF_RESERVEDSIZE}, + {"quota", MF_QUOTA}, + {"eraseblk=", MF_ERASEBLKSIZE}, + {"logicalblk=", MF_LOGICALBLKSIZE}, + {"defaults", 0}, + {0, 0}, }; #define EM_AES_256_XTS 1 @@ -266,6 +268,11 @@ static int parse_flags(char *flags, struct flag_list *fl, } else { flag_vals->file_names_mode = EM_AES_256_CTS; } + } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) { + /* The metadata flag is followed by an = and the + * directory for the keys. Get it and return it. + */ + flag_vals->key_dir = strdup(strchr(p, '=') + 1); } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { /* The length flag is followed by an = and the * size of the partition. Get it and return it. @@ -557,6 +564,7 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &flag_vals, NULL, 0); fstab->recs[cnt].key_loc = flag_vals.key_loc; + fstab->recs[cnt].key_dir = flag_vals.key_dir; fstab->recs[cnt].verity_loc = flag_vals.verity_loc; fstab->recs[cnt].length = flag_vals.part_length; fstab->recs[cnt].label = flag_vals.label; @@ -716,6 +724,7 @@ void fs_mgr_free_fstab(struct fstab *fstab) free(fstab->recs[i].fs_type); free(fstab->recs[i].fs_options); free(fstab->recs[i].key_loc); + free(fstab->recs[i].key_dir); free(fstab->recs[i].label); } diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index c985462af..3ca507b8b 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -107,6 +107,7 @@ #define MF_ERASEBLKSIZE 0x800000 #define MF_LOGICALBLKSIZE 0X1000000 #define MF_AVB 0X2000000 +#define MF_KEYDIRECTORY 0X4000000 #define DM_BUF_SIZE 4096 diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index fd63dfd38..26ae48aa9 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -72,6 +72,7 @@ struct fstab_rec { char *fs_options; int fs_mgr_flags; char *key_loc; + char* key_dir; char *verity_loc; long long length; char *label; @@ -95,6 +96,8 @@ struct fstab *fs_mgr_read_fstab_dt(); struct fstab *fs_mgr_read_fstab(const char *fstab_path); void fs_mgr_free_fstab(struct fstab *fstab); +#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7 +#define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6 #define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5 #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 4 #define FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION 3 @@ -112,8 +115,8 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, int fs_mgr_do_mount_one(struct fstab_rec *rec); int fs_mgr_do_tmpfs_mount(const char *n_name); int fs_mgr_unmount_all(struct fstab *fstab); -int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, - char *real_blk_device, int size); +struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab); +void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size); bool fs_mgr_load_verity_state(int* mode); bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback); int fs_mgr_add_entry(struct fstab *fstab, diff --git a/init/builtins.cpp b/init/builtins.cpp index 43eb42075..f687b6ca3 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -481,6 +481,23 @@ static int queue_fs_event(int code) { // Although encrypted, we have device key, so we do not need to // do anything different from the nonencrypted case. ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); + } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) { + if (e4crypt_install_keyring()) { + return -1; + } + property_set("ro.crypto.state", "encrypted"); + property_set("ro.crypto.type", "file"); + + // defaultcrypto detects file/block encryption. init flow is same for each. + ActionManager::GetInstance().QueueEventTrigger("defaultcrypto"); + } else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) { + if (e4crypt_install_keyring()) { + return -1; + } + property_set("ro.crypto.type", "file"); + + // encrypt detects file/block encryption. init flow is same for each. + ActionManager::GetInstance().QueueEventTrigger("encrypt"); } else if (code > 0) { PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << code; }