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
server.cpp
ext4-tool.cpp
secure-erase.cpp
+ block-device.cpp
internal-encryption.cpp
external-encryption.cpp
engine/ext4-engine.cpp
--- /dev/null
+/*
+ * 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 <string.h>
+
+#include <klay/filesystem.h>
+#include <klay/exception.h>
+
+#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
--- /dev/null
+/*
+ * 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 <unordered_map>
+#include <fstream>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <linux/fs.h>
+
+#include <klay/filesystem.h>
+
+namespace ode {
+
+class Block {
+public:
+ template <typename OffsetType, typename LengthType>
+ 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<std::string, std::string> 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__ */
* See the License for the specific language governing permissions and
* limitations under the License
*/
+#include <fstream>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/fs.h>
+#include <linux/fiemap.h>
+
+#include <klay/exception.h>
#include <klay/filesystem.h>
#include <klay/audit/logger.h>
#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));
{
}
-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