Remove dependency of ext2fs, com_err from fota tizen_5.5_tv accepted/tizen/5.5/unified/20200101.002929 submit/tizen_5.5/20191227.074621 submit/tizen_5.5/20191230.014825 submit/tizen_5.5/20191230.093352
authors414.kim <s414.kim@samsung.com>
Fri, 27 Dec 2019 07:37:47 +0000 (16:37 +0900)
committers414.kim <s414.kim@samsung.com>
Fri, 27 Dec 2019 07:37:47 +0000 (16:37 +0900)
This is a patch for hot fix. It will be refactored later.

Change-Id: I03d5b19f0468f9754a35cebf3ac2aa33e27f00df
Signed-off-by: s414.kim <s414.kim@samsung.com>
fota/CMakeLists.txt
fota/fota.cpp

index 340f9b3..4a4dffa 100755 (executable)
 
 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")
index a81cfa3..80617fa 100644 (file)
@@ -13,6 +13,9 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
+
+#include <linux/dm-ioctl.h>
+#include <sys/mount.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <strings.h>
 #include <blkid.h>
-
+#include <string.h>
+#include <iomanip>
 #include <string>
+#include <sstream>
 #include <iostream>
+#include <memory>
 
+#include <klay/error.h>
+#include <klay/exception.h>
 #include <klay/audit/dlog-sink.h>
 
 #include <upgrade-support.h>
-#include <internal-encryption-common.h>
-#include <engine/encryption/dmcrypt-engine.h>
+#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<int, void(*)(int*)> 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<size_t>(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 {