From: seolheui,kim Date: Wed, 23 Nov 2016 08:58:35 +0000 (+0900) Subject: Add secure-erase X-Git-Tag: submit/tizen/20170213.020148~34 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F67%2F99567%2F18;p=platform%2Fcore%2Fsecurity%2Fode.git Add secure-erase Change-Id: I383d341a158049689b4bcc39e2bf7b5af4f1421c Signed-off-by: seolheui,kim --- diff --git a/rmi/secure-erase.h b/rmi/secure-erase.h index 2eb4735..48facda 100644 --- a/rmi/secure-erase.h +++ b/rmi/secure-erase.h @@ -33,8 +33,13 @@ public: int erase(const std::string& name); int clean(const std::string& name); +private: + int fileErase(const std::string& name); + int directoryErase(const std::string& name); + void dropCachePage(); private: ODEControlContext& context; + std::string devicePath; }; } // namespace ode diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 94a688d..e32abb2 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -17,6 +17,7 @@ SET(SERVER_SRCS main.cpp server.cpp ext4-tool.cpp secure-erase.cpp + block-device.cpp internal-encryption.cpp external-encryption.cpp engine/ext4-engine.cpp diff --git a/server/block-device.cpp b/server/block-device.cpp new file mode 100644 index 0000000..184ef88 --- /dev/null +++ b/server/block-device.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include +#include + +#include "block-device.h" + +namespace ode { + +BlockDevice::BlockDevice(const std::string &path) : name("") +{ + int ret = 0; + runtime::File file(path); + if (!file.exists()) { + throw runtime::Exception("target doesn't exist"); + } + + if (!file.isDevice()) { + createDeviceList(); + evaluateDevice(path); + } else { + name = path; + } + + if (name != "") { + int descriptor = ::open(name.c_str(), O_RDONLY); + if (descriptor > 0) { + ret = ::ioctl(descriptor, FIGETBSZ, &blockSize); + if (ret < 0) { + ::close(descriptor); + throw runtime::Exception("Failed to get block size"); + } + } + ::close(descriptor); + } else { + throw runtime::Exception("Cannot find device name"); + } +} + +BlockDevice::~BlockDevice() +{ +} + +int BlockDevice::open(int flags) +{ + int descriptor = 0; + + if (name != "") { + descriptor = ::open(name.c_str(), flags); + return descriptor; + } + + return -1; +} + +void BlockDevice::close(int descriptor) +{ + int ret = 0; + + ret = ::close(descriptor); + if (ret < 0) { + throw runtime::Exception("Cannot close descriptor"); + } + return; +} + +int BlockDevice::discard(const Block &block) +{ + int devFd = 0; + unsigned long long range[2]; + + devFd = BlockDevice::open(O_WRONLY); + if (devFd < 0) { + return -1; + } + + range[0] = block.physicalOffset; + range[1] = block.length; + + int ret = ::ioctl(devFd, BLKDISCARD, &range); + + BlockDevice::close(devFd); + + return ret; +} + +int BlockDevice::secDiscard(const Block &block) +{ + int devFd = 0; + unsigned long long range[2]; + + devFd = BlockDevice::open(O_WRONLY); + if (devFd < 0) { + return -1; + } + + range[0] = block.physicalOffset; + range[1] = block.length; + + int ret = ::ioctl(devFd, BLKSECDISCARD, &range); + + BlockDevice::close(devFd); + + return ret; +} + +const std::string &BlockDevice::getName() const +{ + if (name == "") { + throw runtime::Exception("Cannot get device name"); + } + return name; +} + +int BlockDevice::getSize() +{ + if (name == "") { + throw runtime::Exception("Cannot get device name"); + } + return blockSize; +} + +void BlockDevice::createDeviceList() +{ + char deviceName[PATH_MAX] = ""; + char source[PATH_MAX] = ""; + char filesystemType[PATH_MAX] = ""; + std::string deviceInfo = ""; + + std::ifstream file("/etc/mtab"); + if (file.fail()) { + throw runtime::Exception("/etc/mtab doesn't exist"); + } + + while (std::getline(file, deviceInfo)) { + if (::sscanf(deviceInfo.c_str(), "%s %s %s %*s %*d %*d", + deviceName, source, filesystemType) == 3) { + int fd = ::open(deviceName, O_WRONLY); + if (fd < 0) { + continue; + } + + if (strcmp(filesystemType, "ext2") && strcmp(filesystemType, "ext3") + && strcmp(filesystemType, "ext4")) { + ::close(fd); + continue; + } + + runtime::File device(deviceName); + if (!device.exists()) { + ::close(fd); + continue; + } + + if (device.isDevice()) { + deviceList.insert(std::make_pair(source, deviceName)); + } + ::close(fd); + } + } + + return; +} + +void BlockDevice::evaluateDevice(const std::string &path) +{ + DeviceListIterator matchedDevice = deviceList.find(path); + const std::string &subStr = path; + std::size_t pos = subStr.size(); + + if (matchedDevice != deviceList.end()) { + name = matchedDevice->second; + return; + } + + while ((pos = subStr.rfind('/', pos - 1)) != std::string::npos && pos != 0) { + std::string subPath = subStr.substr(0, pos); + matchedDevice = deviceList.find(subPath); + if (matchedDevice != deviceList.end()) { + name = matchedDevice->second; + return; + } + } +} + +} //namespace ode diff --git a/server/block-device.h b/server/block-device.h new file mode 100644 index 0000000..095da51 --- /dev/null +++ b/server/block-device.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __BLOCK_DEVICE_H__ +#define __BLOCK_DEVICE_H__ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace ode { + +class Block { +public: + template + Block(OffsetType offset, LengthType len) : physicalOffset(offset), length(len) {} + ~Block() {} + + unsigned long long physicalOffset; + unsigned long long length; +}; + +class BlockDevice final { +public: + typedef std::unordered_map DeviceList; + typedef DeviceList::const_iterator DeviceListIterator; + + BlockDevice(const std::string &path); + BlockDevice(const BlockDevice &) = delete; + BlockDevice(BlockDevice &&) = delete; + ~BlockDevice(); + + BlockDevice &operator=(const BlockDevice &) = delete; + BlockDevice &operator=(BlockDevice &&) = delete; + + int open(int flags); + void close(int descriptor); + + int discard(const Block &block); + int secDiscard(const Block &block); + + const std::string &getName() const; + int getSize(); + +private: + void createDeviceList(); + void evaluateDevice(const std::string &path); + +private: + std::string name; + int blockSize; + + DeviceList deviceList; +}; + +} // namespace ode + +#endif /* __BLOCK_DEVICE_H__ */ diff --git a/server/secure-erase.cpp b/server/secure-erase.cpp index a0afbec..ab10b28 100644 --- a/server/secure-erase.cpp +++ b/server/secure-erase.cpp @@ -13,15 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License */ +#include + +#include +#include +#include +#include + +#include #include #include #include "rmi/secure-erase.h" +#include "block-device.h" +#include "ext4-tool.h" namespace ode { -SecureErase::SecureErase(ODEControlContext& ctx) : - context(ctx) +SecureErase::SecureErase(ODEControlContext &ctx) : + context(ctx), devicePath("") { context.registerParametricMethod(this, "", (int)(SecureErase::erase)(std::string)); context.registerParametricMethod(this, "", (int)(SecureErase::clean)(std::string)); @@ -31,16 +41,160 @@ SecureErase::~SecureErase() { } -int SecureErase::erase(const std::string& name) +int SecureErase::erase(const std::string &name) +{ + int ret = -1; + try { + runtime::File file(name); + if (!file.exists()) { + return -1; + } + + BlockDevice blockDevice(name); + devicePath = blockDevice.getName(); + + if (file.isFile()) { + /* TBD */ + ret = fileErase(name); + } else if (file.isDirectory()) { + /* TBD */ + ret = directoryErase(name); + } else if (file.isDevice()) { + Ext4Tool ext4Tool(name); + unsigned int i, totalBlock = ext4Tool.getTotalBlockCount(); + unsigned int blockSize = (unsigned int)blockDevice.getSize(); + + for (i = 0; i < totalBlock; i++) { + Block block(i*blockSize, blockSize); + ret = blockDevice.discard(block); + if (ret != 0) { + return -1; + } + } + } + + dropCachePage(); + } catch (runtime::Exception &e) {} + + return ret; +} + +int SecureErase::clean(const std::string &name) +{ + int ret = -1; + try { + BlockDevice blockDevice(name); + runtime::File file(name, O_WRONLY); + if (!file.exists() || !file.isDevice()) { + return -1; + } + + Ext4Tool ext4Tool(name); + unsigned int i, totalBlock = ext4Tool.getTotalBlockCount(); + unsigned int blockSize = (unsigned int) blockDevice.getSize(); + + for (i = 0; i < totalBlock; i++) { + if (!ext4Tool.isUsedBlock(i)) { + Block block(i*blockSize, blockSize); + ret = blockDevice.discard(block); + if (ret != 0) { + return -1; + } + } + } + + dropCachePage(); + } catch (runtime::Exception &e) {} + + return ret; +} + +int SecureErase::fileErase(const std::string &name) { - return -1; + int ret = 0, fd = 0; + int extentBlockCount = 0; + char buf[4096] = ""; + struct fiemap *fmap = (struct fiemap *)buf; + struct fiemap_extent *fm_ext = NULL; + int count = (sizeof(buf) - sizeof(*fmap)) / sizeof(struct fiemap_extent); + + /* [TBD] stop the related process */ + + BlockDevice blockDevice(devicePath); + + ::memset(fmap, 0, sizeof(struct fiemap)); + + fd = ::open(name.c_str(), O_RDONLY); + if (fd < 0) { + return -1; + } + + fmap->fm_length = ~0ULL; + fmap->fm_flags = 0; + fmap->fm_extent_count = count; + + ret = ::ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fmap); + if (ret < 0) { + ::close(fd); + return -1; + } + + ::close(fd); + + fm_ext = &fmap->fm_extents[0]; + extentBlockCount = (int)fmap->fm_mapped_extents; + + for (int i = 0; i < extentBlockCount; i++) { + Block block(fm_ext[i].fe_physical, fm_ext[i].fe_length); + ret = blockDevice.secDiscard(block); + if (ret < 0) { + return -1; + } + } + + return ret; } -int SecureErase::clean(const std::string& name) +int SecureErase::directoryErase(const std::string &name) { - return -1; + int ret = 0; + + runtime::DirectoryIterator iter(name), end; + while (iter != end) { + std::string next = name + "/" + iter->getName(); + runtime::File file(next); + if (!file.exists()) { + return -1; + } + + if (file.isFile()) { + fileErase(next); + ::remove(next.c_str()); + } else if (file.isDirectory()) { + directoryErase(next); + } + ++iter; + } + + fileErase(name); + ::rmdir(name.c_str()); + + return ret; } +void SecureErase::dropCachePage() +{ + std::ofstream file; + + file.open("/proc/sys/vm/drop_caches"); + if (file.fail()) { + throw runtime::Exception("Failed to access drop_caches file"); + } + file << "3\n"; + file.close(); + ::sync(); + return; +} } // namespace ode