ProgressBar::ProgressBar(UpdateFunc const&) : updateValue(0) {}
ProgressBar::~ProgressBar() {}
-void ProgressBar::update(int) {}
-void ProgressBar::update(int, int, int) {}
+void ProgressBar::update(unsigned) {}
void ProgressBar::done(void) {}
} // namespace ode
if (MOUNT == argv[1]) {
auto masterKey = UpgradeSupport::loadMasterKey(DEV_PATH);
- DMCryptEngine dmcrypt(DEV_PATH, INTERNAL_PATH, ProgressBar([](int){}));
+ DMCryptEngine dmcrypt(DEV_PATH, INTERNAL_PATH, ProgressBar([](unsigned){}));
// mount options are ignored by mount()
dmcrypt.mount(masterKey, 0);
namespace {
-blkcnt_t getBlockCount(const std::string &src)
+unsigned long getBlockCount(const std::string &src)
{
int fd = open(src.c_str(), O_RDONLY);
if (fd < 0)
return 0;
- unsigned long long size = 0;
+ unsigned long size = 0;
if ((ioctl(fd, BLKGETSIZE, &size)) == -1)
size = 0;
close(fd);
- return (blkcnt_t)size;
+ return size;
}
const std::string convertToHex(const BinaryData &binary)
}
void copyInPlace(const std::string &source, const std::string &destination,
- const std::function<bool(blkcnt_t)> &isTarget,
- const std::function<void(int, int)> &addProgress)
+ unsigned int options,
+ ProgressBar& progress)
{
Ext4Tool ext4tool(source);
- const blksize_t srcBlockSize = ext4tool.getBlockSize();
- const blkcnt_t srcTotalBlockCount = ext4tool.getTotalBlockCount();
+ const uint32_t srcBlockSize = ext4tool.getBlockSize();
+ const uint32_t srcTotalBlockCount = ext4tool.getTotalBlockCount();
char buf[srcBlockSize];
+ bool fastEncryption = true;
+
+ if (!(options & OPTION_INCLUDE_UNUSED_REGION)) {
+ INFO(SINK, "FastEncryption: Disabled");
+ fastEncryption = false;
+ } else {
+ INFO(SINK, "FastEncryption: Enabled");
+ }
runtime::File src(source, O_RDONLY);
runtime::File dst(destination, O_WRONLY);
off_t pos = 0;
- for (blkcnt_t n = 0; n < srcTotalBlockCount; n++, pos += srcBlockSize) {
- if (!isTarget(n)) {
+ for (uint32_t n = 0; n < srcTotalBlockCount; n++, pos += srcBlockSize) {
+ if (!fastEncryption && !ext4tool.isUsedBlock(n)) {
continue;
}
src.read(buf, srcBlockSize);
dst.write(buf, srcBlockSize);
- addProgress(n, srcTotalBlockCount);
+ progress.update(n, srcTotalBlockCount);
}
}
// should be encrypted here.
auto cryptoBlkDev = createCryptoBlkDev(source, DM_DEFAULT_LABEL_NAME, sanitizeKey(key), DM_DEFAULT_CRYPTO_NAME);
- std::function<bool(blkcnt_t)> isTarget;
- if (!(options & OPTION_INCLUDE_UNUSED_REGION)) {
- INFO(SINK, "FastEncryption: Disabled");
- isTarget = std::bind(&Ext4Tool::isUsedBlock, &ext4Source, _1);
- } else {
- INFO(SINK, "FastEncryption: Enabled");
- isTarget = [](unsigned int n) {
- return true;
- };
- }
-
// We always do In-place encryption
- copyInPlace(source, cryptoBlkDev, isTarget,
- std::bind((void(ProgressBar::*)(int, int, int))&ProgressBar::update,
- &progress, _1, _2, 1));
+ copyInPlace(source, cryptoBlkDev, options, progress);
// remove crypto type device mapper
destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME);
break;
}
- std::function<bool(blkcnt_t)> isTarget;
- if (!(options & OPTION_INCLUDE_UNUSED_REGION)) {
- INFO(SINK, "FastEncryption: Disabled");
- isTarget = std::bind(&Ext4Tool::isUsedBlock, &ext4CryptoBlkDev, _1);
- } else {
- INFO(SINK, "FastEncryption: Enabled");
- isTarget = [](unsigned int n) {
- return true;
- };
- }
-
// We always do In-place decryption
- copyInPlace(cryptoBlkDev, source, isTarget,
- std::bind((void(ProgressBar::*)(int, int, int))&ProgressBar::update,
- &progress, _1, _2, 1));
+ copyInPlace(cryptoBlkDev, source, options, progress);
// remove crypto type device mapper
destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME);
return true;
},
[¤t, &totalSize, this](off_t size) {
+ if (current > std::numeric_limits<decltype(current)>::max() - size)
+ throw runtime::Exception("Offset too big");
current += size;
- this->progress.update(current * 100 / totalSize);
+ this->progress.update(current, totalSize);
});
}
copyInPlace(tempMountpoint.getPath(), source,
tempDir.getPath(), wasEncrypted,
[¤t, &totalSize, this](off_t size) {
+ if (current > std::numeric_limits<decltype(current)>::max() - size)
+ throw runtime::Exception("Offset too big");
current += size;
- this->progress.update(current * 100 / totalSize);
+ this->progress.update(current, totalSize);
});
ecryptfsUmount(tempMountpoint.getPath());
off_t totalSize = getUsedSpace(source), current = 0;
copyInPlace(destination, encrypted.getPath(),
[¤t, &totalSize, this](off_t size) {
+ if (current > std::numeric_limits<decltype(current)>::max() - size)
+ throw runtime::Exception("Offset too big");
current += size;
- this->progress.update(current, totalSize, 1);
+ this->progress.update(current, totalSize);
});
if (::mount(encrypted.getPath().c_str(), destination.c_str(), NULL, MS_BIND, 0) < 0) {
off_t totalSize = getUsedSpace(source), current = 0;
copyInPlace(encrypted.getPath(), destination,
[¤t, &totalSize, this](off_t size) {
+ if (current > std::numeric_limits<decltype(current)>::max() - size)
+ throw runtime::Exception("Offset too big");
current += size;
- this->progress.update(current, totalSize, 1);
+ this->progress.update(current, totalSize);
});
encrypted.remove(true);
*/
#include "erase-engine.h"
+#include <limits>
+
#define ERASE_SIZE 4096
namespace ode {
{
}
-void EraseEngine::discardBlock(unsigned long long offset, blksize_t size)
+void EraseEngine::discardBlock(uint64_t offset, uint32_t size)
{
char zero[ERASE_SIZE] = {};
if (size > ERASE_SIZE) {
throw runtime::Exception("[eraseBlock] : size is too big");
}
+ if (offset > std::numeric_limits<off_t>::max()) {
+ throw runtime::Exception("[eraseBlock] : offset is too big");
+ }
runtime::File device(target);
device.open(O_WRONLY);
void EraseEngine::cleanDevice(const std::string &path)
{
- blkcnt_t totalBlockCount = 0;
- blksize_t blockSize = 0;
- unsigned long long offset = 0;
+ uint32_t totalBlockCount = 0;
+ uint32_t blockSize = 0;
+ uint64_t offset = 0;
target = path;
Ext4Tool ext4Tool(target);
- totalBlockCount = (blkcnt_t)ext4Tool.getTotalBlockCount();
- blockSize = (blksize_t)ext4Tool.getBlockSize();
+ totalBlockCount = ext4Tool.getTotalBlockCount();
+ blockSize = ext4Tool.getBlockSize();
- for (blkcnt_t i = 0; i < totalBlockCount; i++) {
+ for (uint32_t i = 0; i < totalBlockCount; i++) {
if (!ext4Tool.isUsedBlock(i)) {
- offset = (unsigned long long)i * (unsigned long long)blockSize;
+ offset = static_cast<uint64_t>(i) * blockSize;
discardBlock(offset, blockSize);
}
- progressBar.update(i, totalBlockCount, 1);
+ progressBar.update(i, totalBlockCount);
}
progressBar.done();
}
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
+#include <cstdint>
#include <vconf.h>
#include <klay/filesystem.h>
#include <klay/exception.h>
void cleanDevice(const std::string &path);
private:
- void discardBlock(unsigned long long offset, blksize_t size);
+ void discardBlock(uint64_t offset, uint32_t size);
private:
ProgressBar progressBar;
std::string target;
return;
}
-void MMCEraseEngine::discardBlock(unsigned long long offset, blksize_t size)
+void MMCEraseEngine::discardBlock(uint64_t offset, uint64_t size)
{
int descriptor = 0, ret = 0;
- unsigned long long range[2] = {0, };
+ uint64_t range[2] = {0, };
descriptor = ::open(target.c_str(), O_WRONLY);
if (descriptor < 0) {
}
range[0] = offset;
- range[1] = (unsigned long long)size;
+ range[1] = size;
ret = ::ioctl(descriptor, BLKDISCARD, &range);
::close(descriptor);
void MMCEraseEngine::cleanDevice(const std::string &path)
{
- blkcnt_t totalBlockCount = 0;
- blksize_t blockSize = 0;
- unsigned long long offset = 0;
+ uint32_t totalBlockCount = 0;
+ uint32_t blockSize = 0;
+ uint64_t offset = 0;
target.append(path);
Ext4Tool ext4Tool(target);
- totalBlockCount = (blkcnt_t)ext4Tool.getTotalBlockCount();
- blockSize = (blksize_t)ext4Tool.getBlockSize();
+ totalBlockCount = ext4Tool.getTotalBlockCount();
+ blockSize = ext4Tool.getBlockSize();
- for (blkcnt_t i = 0; i < totalBlockCount; i++) {
+ for (uint32_t i = 0; i < totalBlockCount; i++) {
if (!ext4Tool.isUsedBlock(i)) {
- offset = (unsigned long long)i * (unsigned long long)blockSize;
+ offset = static_cast<uint64_t>(i) * blockSize;
discardBlock(offset, blockSize);
}
- progressBar.update(i, totalBlockCount, 1);
+ progressBar.update(i, totalBlockCount);
}
progressBar.done();
synchronization();
#define __MMC_ERASE_ENGINE_H__
#include <fstream>
+#include <cstdint>
#include <fcntl.h>
#include <unistd.h>
void cleanDevice(const std::string &target);
private:
void synchronization(void);
- void discardBlock(unsigned long long offset, blksize_t size);
+ void discardBlock(uint64_t offset, uint64_t size);
private:
ProgressBar progressBar;
std::string target;
#include <string>
#include <vector>
+#include <limits>
#include <klay/filesystem.h>
#include <klay/process.h>
namespace {
-unsigned int divCeilSafely(unsigned int a, unsigned int b)
+uint32_t divCeilSafely(uint32_t a, uint32_t b)
{
if (!a)
return 0;
void Ext4Tool::readInfo()
{
- unsigned int firstDataBlock = 0;
- unsigned int blocksPerGroup = 0;
- unsigned int clustersPerGroup = 0;
- unsigned short descSize = 0;
+ // TODO this function should be rewritten
+ uint32_t firstDataBlock = 0;
+ uint32_t blocksPerGroup = 0;
+ uint32_t clustersPerGroup = 0;
+ uint16_t descSize = 0;
runtime::File device(source);
if (!device.exists())
// read totalBlockCount
device.lseek(ODE_SUPERBLOCK_OFFSET + 4, SEEK_SET);
- device.read(&totalBlockCount, 4);
+ device.read(&totalBlockCount, sizeof(totalBlockCount));
// read firstDataBlock
device.lseek(ODE_SUPERBLOCK_OFFSET + 20, SEEK_SET);
- device.read(&firstDataBlock, 4);
+ device.read(&firstDataBlock, sizeof(firstDataBlock));
// read blockSize
device.lseek(ODE_SUPERBLOCK_OFFSET + 24, SEEK_SET);
- device.read(&blockSize, 4);
+ device.read(&blockSize, sizeof(blockSize));
+ if ((std::numeric_limits<decltype(blockSize)>::max() >> blockSize) < ODE_EXT2_MIN_BLOCK_SIZE)
+ throw runtime::Exception("Block size too big"); // blockSize must be <= 21
blockSize = (ODE_EXT2_MIN_BLOCK_SIZE << blockSize);
// read blocksPerGroup
device.lseek(ODE_SUPERBLOCK_OFFSET + 32, SEEK_SET);
- device.read(&blocksPerGroup, 4);
+ device.read(&blocksPerGroup, sizeof(blocksPerGroup));
// read clustersPerGroup
device.lseek(ODE_SUPERBLOCK_OFFSET + 36, SEEK_SET);
- device.read(&clustersPerGroup, 4);
+ device.read(&clustersPerGroup, sizeof(clustersPerGroup));
// read descSize
device.lseek(ODE_SUPERBLOCK_OFFSET + 0xFE, SEEK_SET);
- device.read(&descSize, 2);
+ device.read(&descSize, sizeof(descSize));
if (descSize < ODE_EXT2_MIN_DESC_SIZE) {
descSize = ODE_EXT2_MIN_DESC_SIZE;
}
- unsigned int groupDescCount = divCeilSafely(totalBlockCount - firstDataBlock, blocksPerGroup);
- int blockNbytes = clustersPerGroup / 8;
+ if (firstDataBlock >= totalBlockCount)
+ throw runtime::Exception("Invalid block info");
+ uint32_t groupDescCount = divCeilSafely(totalBlockCount - firstDataBlock, blocksPerGroup);
// read group_desc
- unsigned int descPerBlock = blockSize / descSize;
- unsigned int descBlockCount = divCeilSafely(groupDescCount, descPerBlock);
+ uint32_t descPerBlock = blockSize / descSize;
+ uint32_t descBlockCount = divCeilSafely(groupDescCount, descPerBlock);
// read first meta block
+ if (descBlockCount > std::numeric_limits<BinaryData::size_type>::max() / blockSize)
+ throw runtime::Exception("Size too big for BinaryData");
BinaryData group_desc(descBlockCount * blockSize);
+ // firstDataBlock < totalBlockCount so no overflow is possible
device.lseek((firstDataBlock + 1) * blockSize, SEEK_SET);
- device.read(group_desc.data(), (descBlockCount * blockSize));
+ device.read(group_desc.data(), group_desc.size());
- unsigned int cnt = blockNbytes << 3;
- unsigned int blkItr = firstDataBlock;
+ uint32_t blkItr = firstDataBlock;
// this structure just is used for easy type-casting.
struct odeExtGroupDesc {
- unsigned int blockBitmap; /* Blocks bitmap block */
+ uint32_t blockBitmap; /* Blocks bitmap block */
/* skip other member */
};
// read bitmap
{
- unsigned int start = firstDataBlock;
- unsigned int real_end = blocksPerGroup * groupDescCount - 1 + start;
- size_t size = (size_t) (((real_end - start) / 8) + 1);
+ uint32_t start = firstDataBlock;
+ uint32_t real_end = totalBlockCount - 1;
+
+ uint32_t size = (real_end - start) / 8 + 1;
size = (size + 7) & ~3;
+ if (std::numeric_limits<size_t>::max() <= size)
+ throw runtime::Exception("Bitmap size too big");
+
bitmap.resize(size);
}
- for (unsigned int i = 0; i < groupDescCount; i++) {
- unsigned int blk = (((struct odeExtGroupDesc *)(((unsigned char *)(group_desc.data())) + i * descSize))->blockBitmap);
+ if (groupDescCount >= group_desc.size() / descSize)
+ throw runtime::Exception("Group descriptors buffer too small");
+
+ if (blockSize > std::numeric_limits<size_t>::max())
+ throw runtime::Exception("Block size too big");
+
+ if (clustersPerGroup > std::numeric_limits<size_t>::max() - 7)
+ throw runtime::Exception("Too many clusters per group");
+
+ if (groupDescCount > (std::numeric_limits<decltype(blkItr)>::max() - blkItr) / clustersPerGroup + 1)
+ throw runtime::Exception("Block iterator may get too big");
+
+ if (((blkItr + clustersPerGroup * (groupDescCount - 1)) >> 3) + ((clustersPerGroup + 7) >> 3) > bitmap.size())
+ throw runtime::Exception("Bitmap size too small");
+
+ for (uint32_t i = 0; i < groupDescCount; i++) {
+ uint32_t blk = reinterpret_cast<odeExtGroupDesc*>(group_desc.data() + i * descSize)->blockBitmap;
try {
BinaryData block_bitmap(blockSize);
+
+ if (blk > std::numeric_limits<off_t>::max() / blockSize)
+ throw runtime::Exception("Block bitmap index too big");
+
device.lseek(blk * blockSize, SEEK_SET);
device.read(block_bitmap.data(), blockSize);
- memcpy(bitmap.data() + (blkItr >> 3), block_bitmap.data(), (cnt + 7) >> 3);
+ memcpy(bitmap.data() + (blkItr >> 3), block_bitmap.data(), (clustersPerGroup + 7) >> 3);
} catch (runtime::Exception &e) {
WARN(SINK, "Block " + std::to_string(blk) + " is missing");
- memset(bitmap.data() + (blkItr >> 3), 0, (cnt + 7) >> 3);
+ memset(bitmap.data() + (blkItr >> 3), 0, (clustersPerGroup + 7) >> 3);
}
- blkItr += cnt;
+ blkItr += clustersPerGroup;
}
device.close();
}
-unsigned int Ext4Tool::getBlockSize()
+uint32_t Ext4Tool::getBlockSize()
{
return blockSize;
}
-unsigned int Ext4Tool::getTotalBlockCount()
+uint32_t Ext4Tool::getTotalBlockCount()
{
return totalBlockCount;
}
-bool Ext4Tool::isUsedBlock(unsigned int blockIndex)
+bool Ext4Tool::isUsedBlock(uint32_t blockIndex)
{
unsigned char *addr = (bitmap.data() + (blockIndex >> 3));
- int mask = 1 << (blockIndex & 0x07);
+ unsigned char mask = 1 << (blockIndex & 0x07);
if (mask & *addr)
return true;
#ifndef __EXT4_TOOL_H__
#define __EXT4_TOOL_H__
+#include <cstdint>
+
#include <string>
#include <klay/filesystem.h>
Ext4Tool &operator=(const Ext4Tool &) = delete;
Ext4Tool &operator=(Ext4Tool &&) = delete;
- unsigned int getBlockSize();
- unsigned int getTotalBlockCount();
- bool isUsedBlock(unsigned int blockIndex);
+ uint32_t getBlockSize();
+ uint32_t getTotalBlockCount();
+ bool isUsedBlock(uint32_t blockIndex);
void forceCleanUp();
static bool isExt(const std::string &src);
private:
void readInfo();
std::string source;
- unsigned int blockSize, totalBlockCount;
+ uint32_t blockSize, totalBlockCount;
BinaryData bitmap;
};
engine.reset(new EXTERNAL_ENGINE(
EXTERNAL_PATH, EXTERNAL_PATH,
- ProgressBar([](int v) {
+ ProgressBar([](unsigned v) {
::vconf_set_str(VCONFKEY_SDE_ENCRYPT_PROGRESS,
std::to_string(v).c_str());
})
engine.reset(new INTERNAL_ENGINE(
source, INTERNAL_PATH,
- ProgressBar([](int v) {
+ ProgressBar([](unsigned v) {
::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS,
std::to_string(v).c_str());
})
{
}
-void ProgressBar::update(int value)
+void ProgressBar::update(unsigned value)
{
if (updateValue != value) {
updateValue = value;
}
}
-void ProgressBar::update(int curCount, int totalCount, int unit)
-{
- update(((curCount * 100) / totalCount) * unit);
-}
-
void ProgressBar::done(void)
{
updateValue = 100;
#define __ODE_PROGRESS_BAR_H__
#include <functional>
+#include <limits>
+#include <cassert>
namespace ode {
class ProgressBar {
public:
- typedef std::function<void(int)> UpdateFunc;
+ typedef std::function<void(unsigned)> UpdateFunc;
ProgressBar() = delete;
- ProgressBar(UpdateFunc const &updater);
+ explicit ProgressBar(UpdateFunc const &updater);
~ProgressBar();
- void update(int value);
- void update(int count, int totalCount, int unit);
+ void update(unsigned value);
+
+ template <typename T>
+ void update(T count, T totalCount);
+
void done(void);
private:
UpdateFunc updater;
- int updateValue;
+ unsigned updateValue;
};
+
+template <typename T>
+void ProgressBar::update(T count, T totalCount)
+{
+ assert(count <= totalCount);
+ assert(totalCount > 0);
+
+ if (count > std::numeric_limits<T>::max() / 100)
+ update(count / (totalCount / 100));
+ else
+ update((count * 100) / totalCount);
+}
+
+
} // namespace ode
#endif //__ODE_PROGRESS_BAR_H__
{
server.expose(this, PRIVILEGE_PLATFORM, (int)(SecureEraseServer::clean)(std::string));
- engine.reset(new ERASE_ENGINE(ProgressBar([](int v) {
+ engine.reset(new ERASE_ENGINE(ProgressBar([](unsigned v) {
::vconf_set_str(VCONFKEY_ODE_ERASE_PROGRESS, std::to_string(v).c_str());
}))
);
namespace {
-ProgressBar progress([](int v) {});
+ProgressBar progress([](unsigned) {});
}
TESTCASE(EcryptfsGetPathTest)
{
try {
- ode::ProgressBar progress([](int v) {});
+ ode::ProgressBar progress([](unsigned v) {});
ode::EcryptfsEngine engine("/dev/mmcblkp0", "/opt/usr", progress);
if (engine.getSource() != "/dev/mmcblkp0") {
throw runtime::Exception("Source doen't match");
TESTCASE(Ext4GetPathTest)
{
try {
- ode::ProgressBar progress([](int v) {});
+ ode::ProgressBar progress([](unsigned v) {});
ode::Ext4Engine engine("/dev/mmcblkp0", "/opt/usr", progress);
if (engine.getSource() != "/dev/mmcblkp0") {
throw runtime::Exception("Source doen't match");