From b92247368ae8456f0ada2c14b358500b642561e0 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 13 May 2019 13:02:54 -0700 Subject: [PATCH] Replace manual dm ioctls with libdm. This mostly 1:1 replaces manual ioctls to device-mapper with calls to libdm. There were two exceptions: (1) There is a very old table-load-retry loop to workaround issues with umount (b/7220345). This loop has been preserved, however, it now includes DM_DEV_CREATE as well as DM_TABLE_LOAD. (2) There was some ancient code to set DM_DEV_GEOMETRY for obb dm-devices. This never did anything since geometry must be set after loading a table. When setting it before (as vold was doing), the subsequent DM_TABLE_LOAD will clear it. Bug: 132206403 Test: FBE device boots FBE device w/ metadata encryption boots FDE device boots atest StorageManagerIntegrationTest Change-Id: Ib6db6b47329f093ac7084edaf604eddace8b9ac6 --- Android.bp | 1 + Devmapper.cpp | 220 +++++----------------------------------- Devmapper.h | 4 - MetadataCrypt.cpp | 99 ++++-------------- cryptfs.cpp | 252 +++++++++------------------------------------- 5 files changed, 91 insertions(+), 485 deletions(-) diff --git a/Android.bp b/Android.bp index 1045dc2..03e9a3f 100644 --- a/Android.bp +++ b/Android.bp @@ -30,6 +30,7 @@ cc_defaults { static_libs: [ "libavb", "libbootloader_message", + "libdm", "libfec", "libfec_rs", "libfs_avb", diff --git a/Devmapper.cpp b/Devmapper.cpp index b42467c..d55d92d 100644 --- a/Devmapper.cpp +++ b/Devmapper.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -32,239 +31,72 @@ #include #include #include +#include #include #include "Devmapper.h" -#define DEVMAPPER_BUFFER_SIZE 4096 - using android::base::StringPrintf; +using namespace android::dm; static const char* kVoldPrefix = "vold:"; -void Devmapper::ioctlInit(struct dm_ioctl* io, size_t dataSize, const char* name, unsigned flags) { - memset(io, 0, dataSize); - io->data_size = dataSize; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = flags; - if (name) { - size_t ret = strlcpy(io->name, name, sizeof(io->name)); - if (ret >= sizeof(io->name)) abort(); - } -} - int Devmapper::create(const char* name_raw, const char* loopFile, const char* key, unsigned long numSectors, char* ubuffer, size_t len) { + auto& dm = DeviceMapper::Instance(); auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw); - const char* name = name_string.c_str(); - char* buffer = (char*)malloc(DEVMAPPER_BUFFER_SIZE); - if (!buffer) { - PLOG(ERROR) << "Failed malloc"; + DmTable table; + table.Emplace(0, numSectors, "twofish", key, 0, loopFile, 0); + + if (!dm.CreateDevice(name_string, table)) { + LOG(ERROR) << "Failed to create device-mapper device " << name_string; return -1; } - int fd; - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - PLOG(ERROR) << "Failed open"; - free(buffer); + std::string path; + if (!dm.GetDmDevicePathByName(name_string, &path)) { + LOG(ERROR) << "Failed to get device-mapper device path for " << name_string; return -1; } - - struct dm_ioctl* io = (struct dm_ioctl*)buffer; - - // Create the DM device - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); - - if (ioctl(fd, DM_DEV_CREATE, io)) { - PLOG(ERROR) << "Failed DM_DEV_CREATE"; - free(buffer); - close(fd); - return -1; - } - - // Set the legacy geometry - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); - - char* geoParams = buffer + sizeof(struct dm_ioctl); - // bps=512 spc=8 res=32 nft=2 sec=8190 mid=0xf0 spt=63 hds=64 hid=0 bspf=8 rdcl=2 infs=1 bkbs=2 - strlcpy(geoParams, "0 64 63 0", DEVMAPPER_BUFFER_SIZE - sizeof(struct dm_ioctl)); - geoParams += strlen(geoParams) + 1; - geoParams = (char*)_align(geoParams, 8); - if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) { - PLOG(ERROR) << "Failed DM_DEV_SET_GEOMETRY"; - free(buffer); - close(fd); - return -1; - } - - // Retrieve the device number we were allocated - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); - if (ioctl(fd, DM_DEV_STATUS, io)) { - PLOG(ERROR) << "Failed DM_DEV_STATUS"; - free(buffer); - close(fd); - return -1; - } - - unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); - snprintf(ubuffer, len, "/dev/block/dm-%u", minor); - - // Load the table - struct dm_target_spec* tgt; - tgt = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)]; - - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, DM_STATUS_TABLE_FLAG); - io->target_count = 1; - tgt->status = 0; - - tgt->sector_start = 0; - tgt->length = numSectors; - - strlcpy(tgt->target_type, "crypt", sizeof(tgt->target_type)); - - char* cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - snprintf(cryptParams, - DEVMAPPER_BUFFER_SIZE - (sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec)), - "twofish %s 0 %s 0", key, loopFile); - cryptParams += strlen(cryptParams) + 1; - cryptParams = (char*)_align(cryptParams, 8); - tgt->next = cryptParams - buffer; - - if (ioctl(fd, DM_TABLE_LOAD, io)) { - PLOG(ERROR) << "Failed DM_TABLE_LOAD"; - free(buffer); - close(fd); - return -1; - } - - // Resume the new table - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); - - if (ioctl(fd, DM_DEV_SUSPEND, io)) { - PLOG(ERROR) << "Failed DM_DEV_SUSPEND"; - free(buffer); - close(fd); - return -1; - } - - free(buffer); - - close(fd); + snprintf(ubuffer, len, "%s", path.c_str()); return 0; } int Devmapper::destroy(const char* name_raw) { + auto& dm = DeviceMapper::Instance(); + auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw); - const char* name = name_string.c_str(); - - char* buffer = (char*)malloc(DEVMAPPER_BUFFER_SIZE); - if (!buffer) { - PLOG(ERROR) << "Failed malloc"; - return -1; - } - - int fd; - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - PLOG(ERROR) << "Failed open"; - free(buffer); - return -1; - } - - struct dm_ioctl* io = (struct dm_ioctl*)buffer; - - // Create the DM device - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); - - if (ioctl(fd, DM_DEV_REMOVE, io)) { + if (!dm.DeleteDevice(name_string)) { if (errno != ENXIO) { PLOG(ERROR) << "Failed DM_DEV_REMOVE"; } - free(buffer); - close(fd); return -1; } - - free(buffer); - close(fd); return 0; } int Devmapper::destroyAll() { ATRACE_NAME("Devmapper::destroyAll"); - char* buffer = (char*)malloc(1024 * 64); - if (!buffer) { - PLOG(ERROR) << "Failed malloc"; - return -1; - } - memset(buffer, 0, (1024 * 64)); - char* buffer2 = (char*)malloc(DEVMAPPER_BUFFER_SIZE); - if (!buffer2) { - PLOG(ERROR) << "Failed malloc"; - free(buffer); + auto& dm = DeviceMapper::Instance(); + std::vector devices; + if (!dm.GetAvailableDevices(&devices)) { + LOG(ERROR) << "Failed to get dm devices"; return -1; } - int fd; - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - PLOG(ERROR) << "Failed open"; - free(buffer); - free(buffer2); - return -1; - } - - struct dm_ioctl* io = (struct dm_ioctl*)buffer; - ioctlInit(io, (1024 * 64), NULL, 0); - - if (ioctl(fd, DM_LIST_DEVICES, io)) { - PLOG(ERROR) << "Failed DM_LIST_DEVICES"; - free(buffer); - free(buffer2); - close(fd); - return -1; - } - - struct dm_name_list* n = (struct dm_name_list*)(((char*)buffer) + io->data_start); - if (!n->dev) { - free(buffer); - free(buffer2); - close(fd); - return 0; - } - - unsigned nxt = 0; - do { - n = (struct dm_name_list*)(((char*)n) + nxt); - auto name = std::string(n->name); - if (android::base::StartsWith(name, kVoldPrefix)) { - LOG(DEBUG) << "Tearing down stale dm device named " << name; - - memset(buffer2, 0, DEVMAPPER_BUFFER_SIZE); - struct dm_ioctl* io2 = (struct dm_ioctl*)buffer2; - ioctlInit(io2, DEVMAPPER_BUFFER_SIZE, n->name, 0); - if (ioctl(fd, DM_DEV_REMOVE, io2)) { + for (const auto& device : devices) { + if (android::base::StartsWith(device.name(), kVoldPrefix)) { + LOG(DEBUG) << "Tearing down stale dm device named " << device.name(); + if (!dm.DeleteDevice(device.name())) { if (errno != ENXIO) { - PLOG(WARNING) << "Failed to destroy dm device named " << name; + PLOG(WARNING) << "Failed to destroy dm device named " << device.name(); } } } else { - LOG(DEBUG) << "Found unmanaged dm device named " << name; + LOG(DEBUG) << "Found unmanaged dm device named " << device.name(); } - nxt = n->next; - } while (nxt); - - free(buffer); - free(buffer2); - close(fd); + } return 0; } - -void* Devmapper::_align(void* ptr, unsigned int a) { - unsigned long agn = --a; - - return (void*)(((unsigned long)ptr + agn) & ~agn); -} diff --git a/Devmapper.h b/Devmapper.h index b1f6dfa..9d4896e 100644 --- a/Devmapper.h +++ b/Devmapper.h @@ -26,10 +26,6 @@ class Devmapper { unsigned long numSectors, char* buffer, size_t len); static int destroy(const char* name); static int destroyAll(); - - private: - static void* _align(void* ptr, unsigned int a); - static void ioctlInit(struct dm_ioctl* io, size_t data_size, const char* name, unsigned flags); }; #endif diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp index deb7194..573d4cc 100644 --- a/MetadataCrypt.cpp +++ b/MetadataCrypt.cpp @@ -23,19 +23,17 @@ #include #include -#include #include #include #include -#include - #include #include #include #include #include #include +#include #include "Checkpoint.h" #include "EncryptInplace.h" @@ -45,13 +43,12 @@ #include "Utils.h" #include "VoldUtil.h" -#define DM_CRYPT_BUF_SIZE 4096 #define TABLE_LOAD_RETRIES 10 -#define DEFAULT_KEY_TARGET_TYPE "default-key" using android::fs_mgr::FstabEntry; using android::fs_mgr::GetEntryForMountPoint; using android::vold::KeyBuffer; +using namespace android::dm; static const std::string kDmNameUserdata = "userdata"; @@ -146,16 +143,6 @@ static bool read_key(const FstabEntry& data_rec, bool create_if_absent, KeyBuffe } // namespace vold } // namespace android -static KeyBuffer default_key_params(const std::string& real_blkdev, const KeyBuffer& key) { - KeyBuffer hex_key; - if (android::vold::StrToHex(key, hex_key) != android::OK) { - LOG(ERROR) << "Failed to turn key to hex"; - return KeyBuffer(); - } - auto res = KeyBuffer() + "AES-256-XTS " + hex_key + " " + real_blkdev.c_str() + " 0"; - return res; -} - static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) { if (android::vold::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) { PLOG(ERROR) << "Unable to measure size of " << real_blkdev; @@ -164,86 +151,35 @@ static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_s return true; } -static struct dm_ioctl* dm_ioctl_init(char* buffer, size_t buffer_size, const std::string& dm_name) { - if (buffer_size < sizeof(dm_ioctl)) { - LOG(ERROR) << "dm_ioctl buffer too small"; - return nullptr; - } - - memset(buffer, 0, buffer_size); - struct dm_ioctl* io = (struct dm_ioctl*)buffer; - io->data_size = buffer_size; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = 0; - dm_name.copy(io->name, sizeof(io->name)); - return io; -} - static bool create_crypto_blk_dev(const std::string& dm_name, uint64_t nr_sec, - const std::string& target_type, const KeyBuffer& crypt_params, + const std::string& real_blkdev, const KeyBuffer& key, std::string* crypto_blkdev) { - android::base::unique_fd dm_fd( - TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC, 0))); - if (dm_fd == -1) { - PLOG(ERROR) << "Cannot open device-mapper"; - return false; - } - alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE]; - auto io = dm_ioctl_init(buffer, sizeof(buffer), dm_name); - if (!io || ioctl(dm_fd.get(), DM_DEV_CREATE, io) != 0) { - PLOG(ERROR) << "Cannot create dm-crypt device " << dm_name; + auto& dm = DeviceMapper::Instance(); + + KeyBuffer hex_key_buffer; + if (android::vold::StrToHex(key, hex_key_buffer) != android::OK) { + LOG(ERROR) << "Failed to turn key to hex"; return false; } + std::string hex_key(hex_key_buffer.data(), hex_key_buffer.size()); - // Get the device status, in particular, the name of its device file - io = dm_ioctl_init(buffer, sizeof(buffer), dm_name); - if (ioctl(dm_fd.get(), DM_DEV_STATUS, io) != 0) { - PLOG(ERROR) << "Cannot retrieve dm-crypt device status " << dm_name; - return false; - } - *crypto_blkdev = std::string() + "/dev/block/dm-" + - std::to_string((io->dev & 0xff) | ((io->dev >> 12) & 0xfff00)); - - io = dm_ioctl_init(buffer, sizeof(buffer), dm_name); - size_t paramix = io->data_start + sizeof(struct dm_target_spec); - size_t nullix = paramix + crypt_params.size(); - size_t endix = (nullix + 1 + 7) & 8; // Add room for \0 and align to 8 byte boundary - - if (endix > sizeof(buffer)) { - LOG(ERROR) << "crypt_params too big for DM_CRYPT_BUF_SIZE"; - return false; - } - - io->target_count = 1; - auto tgt = (struct dm_target_spec*)(buffer + io->data_start); - tgt->status = 0; - tgt->sector_start = 0; - tgt->length = nr_sec; - target_type.copy(tgt->target_type, sizeof(tgt->target_type)); - memcpy(buffer + paramix, crypt_params.data(), - std::min(crypt_params.size(), sizeof(buffer) - paramix)); - buffer[nullix] = '\0'; - tgt->next = endix; + DmTable table; + table.Emplace(0, nr_sec, "AES-256-XTS", hex_key, real_blkdev, 0); for (int i = 0;; i++) { - if (ioctl(dm_fd.get(), DM_TABLE_LOAD, io) == 0) { + if (dm.CreateDevice(dm_name, table)) { break; } if (i + 1 >= TABLE_LOAD_RETRIES) { - PLOG(ERROR) << "DM_TABLE_LOAD ioctl failed"; + LOG(ERROR) << "Could not create default-key device " << dm_name; return false; } - PLOG(INFO) << "DM_TABLE_LOAD ioctl failed, retrying"; + PLOG(INFO) << "Could not create default-key device, retrying"; usleep(500000); } - // Resume this device to activate it - io = dm_ioctl_init(buffer, sizeof(buffer), dm_name); - if (ioctl(dm_fd.get(), DM_DEV_SUSPEND, io)) { - PLOG(ERROR) << "Cannot resume dm-crypt device " << dm_name; + if (!dm.GetDmDevicePathByName(dm_name, crypto_blkdev)) { + LOG(ERROR) << "Cannot retrieve default-key device status " << dm_name; return false; } return true; @@ -267,8 +203,7 @@ bool fscrypt_mount_metadata_encrypted(const std::string& mount_point, bool needs 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)) + if (!create_crypto_blk_dev(kDmNameUserdata, nr_sec, data_rec->blk_device, key, &crypto_blkdev)) return false; // FIXME handle the corrupt case if (needs_encrypt) { diff --git a/cryptfs.cpp b/cryptfs.cpp index 0b7101e..c5d0307 100644 --- a/cryptfs.cpp +++ b/cryptfs.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -56,13 +57,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -78,12 +77,11 @@ extern "C" { using android::base::ParseUint; using android::base::StringPrintf; using android::fs_mgr::GetEntryForMountPoint; +using namespace android::dm; using namespace std::chrono_literals; #define UNUSED __attribute__((unused)) -#define DM_CRYPT_BUF_SIZE 4096 - #define HASH_COUNT 2000 constexpr size_t INTERMEDIATE_KEY_LEN_BYTES = 16; @@ -253,19 +251,6 @@ static void cryptfs_reboot(RebootType rt) { return; } -static void ioctl_init(struct dm_ioctl* io, size_t dataSize, const char* name, unsigned flags) { - memset(io, 0, dataSize); - io->data_size = dataSize; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = flags; - if (name) { - strlcpy(io->name, name, sizeof(io->name)); - } -} - namespace { struct CryptoType; @@ -973,109 +958,12 @@ static void convert_key_to_hex_ascii(const unsigned char* master_key, unsigned i master_key_ascii[a] = '\0'; } -static int load_crypto_mapping_table(struct crypt_mnt_ftr* crypt_ftr, - const unsigned char* master_key, const char* real_blk_name, - const char* name, int fd, const char* extra_params) { - alignas(struct dm_ioctl) char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl* io; - struct dm_target_spec* tgt; - char* crypt_params; - // We need two ASCII characters to represent each byte, and need space for - // the '\0' terminator. - char master_key_ascii[MAX_KEY_LEN * 2 + 1]; - size_t buff_offset; - int i; - - io = (struct dm_ioctl*)buffer; - - /* Load the mapping table for this device */ - tgt = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)]; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - io->target_count = 1; - tgt->status = 0; - tgt->sector_start = 0; - tgt->length = crypt_ftr->fs_size; - strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME); - - crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii); - - buff_offset = crypt_params - buffer; - SLOGI( - "Creating crypto dev \"%s\"; cipher=%s, keysize=%u, real_dev=%s, len=%llu, params=\"%s\"\n", - name, crypt_ftr->crypto_type_name, crypt_ftr->keysize, real_blk_name, tgt->length * 512, - extra_params); - snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s", - crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name, extra_params); - crypt_params += strlen(crypt_params) + 1; - crypt_params = - (char*)(((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */ - tgt->next = crypt_params - buffer; - - for (i = 0; i < TABLE_LOAD_RETRIES; i++) { - if (!ioctl(fd, DM_TABLE_LOAD, io)) { - break; - } - usleep(500000); - } - - if (i == TABLE_LOAD_RETRIES) { - /* We failed to load the table, return an error */ - return -1; - } else { - return i + 1; - } -} - -static int get_dm_crypt_version(int fd, const char* name, int* version) { - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl* io; - struct dm_target_versions* v; - - io = (struct dm_ioctl*)buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - - if (ioctl(fd, DM_LIST_VERSIONS, io)) { - return -1; - } - - /* Iterate over the returned versions, looking for name of "crypt". - * When found, get and return the version. - */ - v = (struct dm_target_versions*)&buffer[sizeof(struct dm_ioctl)]; - while (v->next) { - if (!strcmp(v->name, "crypt")) { - /* We found the crypt driver, return the version, and get out */ - version[0] = v->version[0]; - version[1] = v->version[1]; - version[2] = v->version[2]; - return 0; - } - v = (struct dm_target_versions*)(((char*)v) + v->next); - } - - return -1; -} - -static std::string extra_params_as_string(const std::vector& extra_params_vec) { - if (extra_params_vec.empty()) return ""; - std::string extra_params = std::to_string(extra_params_vec.size()); - for (const auto& p : extra_params_vec) { - extra_params.append(" "); - extra_params.append(p); - } - return extra_params; -} - /* * If the ro.crypto.fde_sector_size system property is set, append the * parameters to make dm-crypt use the specified crypto sector size and round * the crypto device size down to a crypto sector boundary. */ -static int add_sector_size_param(std::vector* extra_params_vec, - struct crypt_mnt_ftr* ftr) { +static int add_sector_size_param(DmTargetCrypt* target, struct crypt_mnt_ftr* ftr) { constexpr char DM_CRYPT_SECTOR_SIZE[] = "ro.crypto.fde_sector_size"; char value[PROPERTY_VALUE_MAX]; @@ -1089,12 +977,11 @@ static int add_sector_size_param(std::vector* extra_params_vec, return -1; } - std::string param = StringPrintf("sector_size:%u", sector_size); - extra_params_vec->push_back(std::move(param)); + target->SetSectorSize(sector_size); // With this option, IVs will match the sector numbering, instead // of being hard-coded to being based on 512-byte sectors. - extra_params_vec->emplace_back("iv_large_sectors"); + target->SetIvLargeSectors(); // Round the crypto device size down to a crypto sector boundary. ftr->fs_size &= ~((sector_size / 512) - 1); @@ -1105,112 +992,67 @@ static int add_sector_size_param(std::vector* extra_params_vec, static int create_crypto_blk_dev(struct crypt_mnt_ftr* crypt_ftr, const unsigned char* master_key, const char* real_blk_name, char* crypto_blk_name, const char* name, uint32_t flags) { - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl* io; - unsigned int minor; - int fd = 0; - int err; - int retval = -1; - int version[3]; - int load_count; - std::vector extra_params_vec; + auto& dm = DeviceMapper::Instance(); - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Cannot open device-mapper\n"); - goto errout; - } + // We need two ASCII characters to represent each byte, and need space for + // the '\0' terminator. + char master_key_ascii[MAX_KEY_LEN * 2 + 1]; + convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii); - io = (struct dm_ioctl*)buffer; + auto target = std::make_unique(0, crypt_ftr->fs_size, + (const char*)crypt_ftr->crypto_type_name, + master_key_ascii, 0, real_blk_name, 0); + target->AllowDiscards(); - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - err = ioctl(fd, DM_DEV_CREATE, io); - if (err) { - SLOGE("Cannot create dm-crypt device %s: %s\n", name, strerror(errno)); - goto errout; - } - - /* Get the device status, in particular, the name of it's device file */ - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - if (ioctl(fd, DM_DEV_STATUS, io)) { - SLOGE("Cannot retrieve dm-crypt device status\n"); - goto errout; - } - minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); - snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor); - - if (!get_dm_crypt_version(fd, name, version)) { - /* Support for allow_discards was added in version 1.11.0 */ - if ((version[0] >= 2) || ((version[0] == 1) && (version[1] >= 11))) { - extra_params_vec.emplace_back("allow_discards"); - } - } if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE) { - extra_params_vec.emplace_back("allow_encrypt_override"); + target->AllowEncryptOverride(); } - if (add_sector_size_param(&extra_params_vec, crypt_ftr)) { + if (add_sector_size_param(target.get(), crypt_ftr)) { SLOGE("Error processing dm-crypt sector size param\n"); - goto errout; + return -1; } - load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name, fd, - extra_params_as_string(extra_params_vec).c_str()); - if (load_count < 0) { + + DmTable table; + table.AddTarget(std::move(target)); + + int load_count = 1; + while (load_count < TABLE_LOAD_RETRIES) { + if (dm.CreateDevice(name, table)) { + break; + } + load_count++; + } + + if (load_count >= TABLE_LOAD_RETRIES) { SLOGE("Cannot load dm-crypt mapping table.\n"); - goto errout; - } else if (load_count > 1) { + return -1; + } + if (load_count > 1) { SLOGI("Took %d tries to load dmcrypt table.\n", load_count); } - /* Resume this device to activate it */ - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - - if (ioctl(fd, DM_DEV_SUSPEND, io)) { - SLOGE("Cannot resume the dm-crypt device\n"); - goto errout; + std::string path; + if (!dm.GetDmDevicePathByName(name, &path)) { + SLOGE("Cannot determine dm-crypt path for %s.\n", name); + return -1; } + snprintf(crypto_blk_name, MAXPATHLEN, "%s", path.c_str()); /* Ensure the dm device has been created before returning. */ if (android::vold::WaitForFile(crypto_blk_name, 1s) < 0) { // WaitForFile generates a suitable log message - goto errout; + return -1; } - - /* We made it here with no errors. Woot! */ - retval = 0; - -errout: - close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */ - - return retval; + return 0; } -static int delete_crypto_blk_dev(const char* name) { - int fd; - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl* io; - int retval = -1; - int err; - - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Cannot open device-mapper\n"); - goto errout; +static int delete_crypto_blk_dev(const std::string& name) { + auto& dm = DeviceMapper::Instance(); + if (!dm.DeleteDevice(name)) { + SLOGE("Cannot remove dm-crypt device %s: %s\n", name.c_str(), strerror(errno)); + return -1; } - - io = (struct dm_ioctl*)buffer; - - ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0); - err = ioctl(fd, DM_DEV_REMOVE, io); - if (err) { - SLOGE("Cannot remove dm-crypt device %s: %s\n", name, strerror(errno)); - goto errout; - } - - /* We made it here with no errors. Woot! */ - retval = 0; - -errout: - close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */ - - return retval; + return 0; } static int pbkdf2(const char* passwd, const unsigned char* salt, unsigned char* ikey, @@ -1924,7 +1766,7 @@ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const u * storage volume. */ int cryptfs_revert_ext_volume(const char* label) { - return delete_crypto_blk_dev((char*)label); + return delete_crypto_blk_dev(label); } int cryptfs_crypto_complete(void) {