From 6940fb52bb586832dacaeaa80e259b4a22bbcb70 Mon Sep 17 00:00:00 2001 From: "s414.kim" Date: Fri, 27 Dec 2019 16:37:47 +0900 Subject: [PATCH] Remove dependency of ext2fs, com_err from fota This is a patch for hot fix. It will be refactored later. Change-Id: I03d5b19f0468f9754a35cebf3ac2aa33e27f00df Signed-off-by: s414.kim --- fota/CMakeLists.txt | 5 +- fota/fota.cpp | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 210 insertions(+), 12 deletions(-) diff --git a/fota/CMakeLists.txt b/fota/CMakeLists.txt index 340f9b3..4a4dffa 100755 --- a/fota/CMakeLists.txt +++ b/fota/CMakeLists.txt @@ -16,14 +16,11 @@ SET(PROJECT_NAME "ode-fota") -PKG_CHECK_MODULES(FOTA_DEPS REQUIRED klay-static blkid ext2fs com_err) +PKG_CHECK_MODULES(FOTA_DEPS REQUIRED klay-static blkid) SET(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/fota.cpp ${ODE_SERVER}/upgrade-support.cpp - ${ODE_SERVER}/ext4-tool.cpp ${ODE_SERVER}/misc.cpp - ${ODE_SERVER}/engine/encryption/dmcrypt-engine.cpp - ${ODE_SERVER}/internal-encryption-common.cpp ) SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") diff --git a/fota/fota.cpp b/fota/fota.cpp index a81cfa3..80617fa 100644 --- a/fota/fota.cpp +++ b/fota/fota.cpp @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ + +#include +#include #include #include #include @@ -20,20 +23,31 @@ #include #include #include - +#include +#include #include +#include #include +#include +#include +#include #include #include -#include -#include +#include "progress-bar.h" + +#define DM_MAX_BUFFER_SIZE 4096 +#define DM_KEY_MIN_LEN_BYTE 32 +#define DM_DEFAULT_LABEL_NAME "userdata" +#define DM_DEFAULT_CRYPTO_NAME "aes-cbc-essiv:sha256" audit::LogSink *SINK = nullptr; namespace ode { +const char *INTERNAL_PATH = "/opt/usr"; + struct AbstractDevice { AbstractDevice() {} virtual ~AbstractDevice() {} @@ -112,6 +126,196 @@ ProgressBar::~ProgressBar() {} void ProgressBar::update(unsigned) {} void ProgressBar::done(void) {} +//Hot fix for urgent issue - start, TODO : It should be removed. +unsigned long getBlockCount(const std::string &src) +{ + int fd = open(src.c_str(), O_RDONLY); + if (fd < 0) + return 0; + + unsigned long size = 0; + if ((ioctl(fd, BLKGETSIZE, &size)) == -1) + size = 0; + close(fd); + + return size; +} + +const std::string convertToHex(const BinaryData &binary) +{ + std::stringstream hex; + + hex << std::hex << std::setfill('0'); + for (unsigned int byte : binary) { + hex << std::setw(2) << byte; + } + return hex.str(); +} + +void initDMIoctl(char *buf, size_t size, const std::string &name, unsigned flags) +{ + struct dm_ioctl *io = (struct dm_ioctl *)buf; + + ::memset(io, 0, size); + io->data_size = size; + io->data_start = sizeof(struct dm_ioctl); + io->version[0] = 4; + io->version[1] = 0; + io->version[2] = 0; + io->flags = flags; + ::memset(io->name, 0, sizeof(io->name)); + ::strncpy(io->name, name.c_str(), sizeof(io->name) - 1); +} + +BinaryData sanitizeKey(const BinaryData &key) +{ + if (key.size() < DM_KEY_MIN_LEN_BYTE) + throw runtime::Exception("Size of key smaller than minimum 32B"); + BinaryData sanitized(key); + sanitized.resize(DM_KEY_MIN_LEN_BYTE); + return sanitized; +} + +const std::string createCryptoBlkDev(const std::string &realBlkDev, + const std::string &mountName, + const BinaryData &key, + std::string cryptoTypeName) +{ + auto blockCount = getBlockCount(realBlkDev); + std::string cryptoBlkDev; + int fd = -1; + + /* + * dmBuf |-------------------------------------------------| DM_MAX_BUFFER_SIZE(4096) + */ + char dmBuf[DM_MAX_BUFFER_SIZE]; // first: for dm_io, dm_ts + + // Open dm control IOCTL + if ((fd = open("/dev/mapper/control", O_RDWR)) < 0) { + throw runtime::Exception("Cannot open device-mapper"); + } + + std::unique_ptr fdPtr(&fd, [](int* fd){ if (fd) ::close(*fd); }); + + /* + * dmBuf |-------------------------------------------------| DM_MAX_BUFFER_SIZE(4096) + * dmIo |----------| size of dm_ioctl + */ + auto dmIo = (struct dm_ioctl *)dmBuf; + + // Create Device (mount_name) + initDMIoctl(dmBuf, DM_MAX_BUFFER_SIZE, mountName, 0); + if (ioctl(fd, DM_DEV_CREATE, dmBuf) && errno != EBUSY) { + throw runtime::Exception("Cannot create dm-crypt device"); + } + + // Get the device status, in particular, the mount_name of it's device file + initDMIoctl(dmBuf, DM_MAX_BUFFER_SIZE, mountName, 0); + if (ioctl(fd, DM_DEV_STATUS, dmBuf)) { + throw runtime::Exception("Cannot retrieve dm-crypt device status"); + } + + // Store created device into crypto_blkdev + unsigned int dmMinor = (dmIo->dev & 0xff) | ((dmIo->dev >> 12) & 0xfff00); + cryptoBlkDev = "/dev/dm-" + std::to_string(dmMinor); + + /* + * dmBuf |-------------------------------------------------| DM_MAX_BUFFER_SIZE(4096) + * dmIo |----------| size of dm_ioctl + * dmTs |--------------| size of dm_target_spec + */ + auto dmTs = (struct dm_target_spec *)(dmBuf + sizeof(struct dm_ioctl)); + + // Load the mapping table for this device + + // Force clean-up whole dm_buffer + initDMIoctl(dmBuf, DM_MAX_BUFFER_SIZE, mountName, 0); + dmIo->target_count = 1; + dmTs->status = 0; + dmTs->sector_start = 0; + dmTs->length = blockCount; + ::memset(dmTs->target_type, 0, sizeof(dmTs->target_type)); + ::strncpy(dmTs->target_type, "crypt", sizeof(dmTs->target_type) - 1); + + /* + * dmBuf |-------------------------------------------------| DM_MAX_BUFFER_SIZE(4096) + * dmIo |----------| size of dm_ioctl + * dmTs |--------------| size of dm_target_spec + * cryptParams |---------------------| + */ + char *cryptParams = dmBuf + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); + + // Store cryptParams + size_t cryptParamsSize = DM_MAX_BUFFER_SIZE - (cryptParams - dmBuf); + std::string keyHex = convertToHex(key); + int ret = snprintf(cryptParams, + cryptParamsSize, + "%s %s 0 %s 0", + cryptoTypeName.c_str(), + keyHex.c_str(), + realBlkDev.c_str()); + if (ret < 0) { + throw runtime::Exception("snprintf() failed"); + } + if (static_cast(ret) >= cryptParamsSize) { + throw runtime::Exception("Crypto params didn't fit the device mapper buffer"); + } + + cryptParams += strlen(cryptParams) + 1; + // Align to an 8 byte boundary + cryptParams = (char *)(((unsigned long)cryptParams + 7) & ~8); + dmTs->next = cryptParams - dmBuf; + + // Table load + if (ioctl(fd, DM_TABLE_LOAD, dmBuf) < 0) { + throw runtime::Exception("Cannot load dm-crypt mapping table."); + } + + // Resume this device to activate it + initDMIoctl(dmBuf, DM_MAX_BUFFER_SIZE, mountName, 0); + if (ioctl(fd, DM_DEV_SUSPEND, dmBuf)) { + throw runtime::Exception("Cannot resume the dm-crypt device"); + } + + return cryptoBlkDev; +} + +void destroyCryptoBlkDev(const std::string &cryptoBlkDev) +{ + char buf[DM_MAX_BUFFER_SIZE]; + int fd, ret; + + if ((fd = open("/dev/mapper/control", O_RDWR)) < 0) + throw runtime::Exception("Cannot open device-mapper"); + + initDMIoctl(buf, sizeof(buf), cryptoBlkDev, 0); + ret = ioctl(fd, DM_DEV_REMOVE, buf); + int err = errno; + close(fd); + + if (ret != 0 && err != ENXIO) { + throw runtime::Exception("Cannot remove dm-crypt device"); + } +} + +void DMCryptMount(const std::string &source, const std::string &destination, const BinaryData &key, unsigned int options) +{ + // create crypto type device mapping layer to mount the encrypted partition. + auto cryptoBlkDev = createCryptoBlkDev(source, DM_DEFAULT_LABEL_NAME, sanitizeKey(key), DM_DEFAULT_CRYPTO_NAME); + + if (::mount(cryptoBlkDev.c_str(), destination.c_str(), "ext4", 0, 0) < 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); +} + +void DMCryptUmount(const std::string &destination) +{ + if (::umount(destination.c_str()) && errno != EINVAL && errno != ENOENT) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + + destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME); +} +//Hot fix - end + } // namespace ode namespace { @@ -152,18 +356,15 @@ int main(int argc, char* argv[]) if (argc == 3) path = argv[2]; - DMCryptEngine dmcrypt(devpath, path, ProgressBar([](unsigned){})); - // mount options are ignored by mount() - dmcrypt.mount(masterKey, 0); + DMCryptMount(devpath, path, masterKey, 0); UpgradeSupport::createUpgradeFlag(); } else if (UMOUNT == argv[1]) { std::string path = INTERNAL_PATH; if (argc == 3) path = argv[2]; - DMCryptEngine dmcrypt(devpath, path, ProgressBar([](int){})); - dmcrypt.umount(); + DMCryptUmount(path); } else if (REMOVE == argv[1]) { UpgradeSupport::removeMasterKey(devpath); } else { -- 2.7.4