Add some overflow checks to FS

This commit is contained in:
Gary Talent 2018-01-29 21:56:19 -06:00
parent 04e5af6fe6
commit 3600d88987
7 changed files with 122 additions and 47 deletions

2
deps/ox/.liccor.yml vendored
View File

@ -2,7 +2,7 @@
source: source:
- src - src
copyright_notice: |- copyright_notice: |-
Copyright 2015 - 2017 gtalent2@gmail.com Copyright 2015 - 2018 gtalent2@gmail.com
This Source Code Form is subject to the terms of the Mozilla Public This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this License, v. 2.0. If a copy of the MPL was not distributed with this

View File

@ -10,6 +10,10 @@
#include <ox/std/std.hpp> #include <ox/std/std.hpp>
#include <iostream>
using std::cout;
using std::endl;
namespace ox { namespace ox {
template<typename FsT, typename InodeId> template<typename FsT, typename InodeId>
@ -801,6 +805,7 @@ void *FileStore<Header>::alloc(typename Header::FsSize_t size) {
compact(); compact();
next = nextInodeAddr(); next = nextInodeAddr();
if ((next + size) > ptr(end())) { if ((next + size) > ptr(end())) {
cout << "alloc returning nullptr\n";
return nullptr; return nullptr;
} }
} }
@ -818,6 +823,7 @@ void *FileStore<Header>::alloc(typename Header::FsSize_t size) {
template<typename Header> template<typename Header>
void FileStore<Header>::compact() { void FileStore<Header>::compact() {
cout << "FileStore::compact\n";
auto dest = ptr<Inode*>(firstInode()); auto dest = ptr<Inode*>(firstInode());
auto current = ptr<Inode*>(firstInode()); auto current = ptr<Inode*>(firstInode());
while (current->getNext() > firstInode() && current->getNext() < ptr(end())) { while (current->getNext() > firstInode() && current->getNext() < ptr(end())) {

View File

@ -60,10 +60,7 @@ FileSystem *expandCopy(FileSystem *fs, size_t size) {
FileSystem *expandCopyCleanup(FileSystem *fs, size_t size) { FileSystem *expandCopyCleanup(FileSystem *fs, size_t size) {
auto out = expandCopy(fs, size); auto out = expandCopy(fs, size);
if (out) { if (!out) {
delete[] fs->buff();
delete fs;
} else {
out = fs; out = fs;
} }

View File

@ -5,6 +5,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#pragma once #pragma once
#include <ox/std/std.hpp> #include <ox/std/std.hpp>
@ -25,10 +26,10 @@ enum FileType {
}; };
struct FileStat { struct FileStat {
uint64_t inode; uint64_t inode = 0;
uint64_t links; uint64_t links = 0;
uint64_t size; uint64_t size = 0;
uint8_t fileType; uint8_t fileType = 0;
}; };
template<typename String> template<typename String>
@ -50,29 +51,39 @@ bool operator<(const DirectoryListing<String> &a, const DirectoryListing<String>
template<typename InodeId_t> template<typename InodeId_t>
struct __attribute__((packed)) DirectoryEntry { struct __attribute__((packed)) DirectoryEntry {
InodeId_t inode;
char *getName() { public:
return (char*) (this + 1); InodeId_t inode = 0;
}
void setName(const char *name) { private:
auto data = getName(); uint32_t m_nameLen = 0;
auto nameLen = ox_strlen(name);
ox_memcpy(data, name, nameLen);
data[nameLen] = 0;
}
static uint64_t spaceNeeded(const char *fileName) { public:
return sizeof(DirectoryEntry) + ox_strlen(fileName) + 1; void *end() {
} return ((uint8_t*) this) + size();
}
/** char *getName() {
* The size in bytes. return (char*) (this + 1);
*/ }
uint64_t size() {
return spaceNeeded(getName()); void setName(const char *name) {
} auto data = getName();
m_nameLen = ox_strlen(name);
ox_memcpy(data, name, m_nameLen);
data[m_nameLen] = 0;
}
static uint64_t spaceNeeded(const char *fileName) {
return sizeof(DirectoryEntry) + ox_strlen(fileName) + 1;
}
/**
* The size in bytes.
*/
uint64_t size() {
return sizeof(DirectoryEntry) + m_nameLen + 1;
}
}; };
template<typename InodeId_t, typename FsSize_t> template<typename InodeId_t, typename FsSize_t>
@ -87,6 +98,8 @@ struct __attribute__((packed)) Directory {
return size ? (DirectoryEntry<InodeId_t>*) (this + 1) : nullptr; return size ? (DirectoryEntry<InodeId_t>*) (this + 1) : nullptr;
} }
void *end();
uint64_t getFileInode(const char *name); uint64_t getFileInode(const char *name);
int getChildrenInodes(InodeId_t *inodes, size_t inodesLen); int getChildrenInodes(InodeId_t *inodes, size_t inodesLen);
@ -99,6 +112,11 @@ struct __attribute__((packed)) Directory {
int ls(List *list); int ls(List *list);
}; };
template<typename InodeId_t, typename FsSize_t>
void *Directory<InodeId_t, FsSize_t>::end() {
return ((int8_t*) this) + size;
}
template<typename InodeId_t, typename FsSize_t> template<typename InodeId_t, typename FsSize_t>
uint64_t Directory<InodeId_t, FsSize_t>::getFileInode(const char *name) { uint64_t Directory<InodeId_t, FsSize_t>::getFileInode(const char *name) {
uint64_t inode = 0; uint64_t inode = 0;
@ -172,16 +190,19 @@ int Directory<InodeId_t, FsSize_t>::copy(Directory<uint64_t, uint64_t> *dirOut)
if (current) { if (current) {
for (uint64_t i = 0; i < this->children; i++) { for (uint64_t i = 0; i < this->children; i++) {
auto entry = (DirectoryEntry<uint64_t>*) dirOutBuff; auto entry = (DirectoryEntry<uint64_t>*) dirOutBuff;
if (this->end() < current->end()) {
return 1;
}
entry->inode = current->inode; entry->inode = current->inode;
entry->setName(current->getName()); entry->setName(current->getName());
current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size()); current = (DirectoryEntry<InodeId_t>*) (((uint8_t*) current) + current->size());
dirOutBuff += entry->size(); dirOutBuff += entry->size();
} }
return 0;
} else { } else {
return 1; return 2;
} }
return 0;
} }
template<typename InodeId_t, typename FsSize_t> template<typename InodeId_t, typename FsSize_t>
@ -207,7 +228,7 @@ class FileSystem {
virtual int stripDirectories() = 0; virtual int stripDirectories() = 0;
virtual int mkdir(const char *path) = 0; virtual int mkdir(const char *path, bool recursive = false) = 0;
/** /**
* Moves an entry from one directory to another. * Moves an entry from one directory to another.
@ -257,13 +278,16 @@ class FileSystem {
template<typename List> template<typename List>
int FileSystem::ls(const char *path, List *list) { int FileSystem::ls(const char *path, List *list) {
typedef Directory<uint64_t, uint64_t> Dir;
int err = 0; int err = 0;
auto s = stat(path); auto s = stat(path);
if (s.fileType == FileType_Directory) { if (s.fileType == FileType_Directory) {
uint8_t dirBuff[s.size * 4]; uint8_t dirBuff[max(static_cast<size_t>(s.size), sizeof(Dir)) * 4];
auto dir = (Directory<uint64_t, uint64_t>*) dirBuff; auto dir = (Directory<uint64_t, uint64_t>*) dirBuff;
err = readDirectory(path, dir); err |= readDirectory(path, dir);
err |= dir->ls(list); if (!err) {
err |= dir->ls(list);
}
} }
return err; return err;
} }
@ -300,7 +324,7 @@ class FileSystemTemplate: public FileSystem {
int stripDirectories() override; int stripDirectories() override;
int mkdir(const char *path) override; int mkdir(const char *path, bool recursive = false) override;
int read(const char *path, void *buffer, size_t buffSize) override; int read(const char *path, void *buffer, size_t buffSize) override;
@ -384,20 +408,35 @@ int FileSystemTemplate<FileStore, FS_TYPE>::stripDirectories() {
} }
template<typename FileStore, FsType FS_TYPE> template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *pathIn) { int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *pathIn, bool recursive) {
if (!findInodeOf(pathIn)) { if (!findInodeOf(pathIn)) {
auto pathLen = ox_strlen(pathIn); auto pathLen = ox_strlen(pathIn);
char path[pathLen + 1]; char path[pathLen + 1];
ox_memcpy(path, pathIn, pathLen + 1); ox_memcpy(path, pathIn, pathLen + 1);
// make sure last character does not end with / // make sure last character does not end with /
if (pathLen >= 1 && path[pathLen - 1] == '/') { if (pathLen >= 1 && path[pathLen - 1] == '/') {
path[pathLen - 1] = 0; path[pathLen - 1] = 0;
pathLen--; pathLen--;
} }
char dirPath[pathLen];
PathIterator pathReader(path, pathLen);
auto err = pathReader.dirPath(dirPath, pathLen);
if (err) {
return err;
}
// make sure parent directory exists if recursive
if (recursive and !findInodeOf(dirPath)) {
err |= mkdir(dirPath, recursive);
if (err) {
return err;
}
}
Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t> dir; Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t> dir;
auto err = write(path, &dir, sizeof(dir), FileType::FileType_Directory); err |= write(path, &dir, sizeof(dir), FileType::FileType_Directory);
if (err) { if (err) {
return err; return err;
} }
@ -411,10 +450,7 @@ int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *pathIn) {
} }
// add .. entry for parent // add .. entry for parent
char dirPath[pathLen]; err |= insertDirectoryEntry(path, "..", findInodeOf(dirPath));
PathIterator pathReader(path, pathLen);
err |= pathReader.dirPath(dirPath, pathLen);
err = insertDirectoryEntry(path, "..", findInodeOf(dirPath));
if (err) { if (err) {
remove(inode); remove(inode);
return err; return err;
@ -846,14 +882,14 @@ int FileSystemTemplate<FileStore, FS_TYPE>::rmDirectoryEntry(const char *path) {
template<typename FileStore, FsType FS_TYPE> template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::readDirectory(const char *path, Directory<uint64_t, uint64_t> *dirOut) { int FileSystemTemplate<FileStore, FS_TYPE>::readDirectory(const char *path, Directory<uint64_t, uint64_t> *dirOut) {
typedef Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t> Dir;
int err = 0; int err = 0;
auto inode = findInodeOf(path); auto dirStat = stat(path);
auto dirStat = stat(inode); auto dirBuffLen = ox::max(static_cast<size_t>(dirStat.size), sizeof(Dir));
auto dirBuffLen = dirStat.size;
uint8_t dirBuff[dirBuffLen]; uint8_t dirBuff[dirBuffLen];
auto dir = (Directory<typename FileStore::InodeId_t, typename FileStore::FsSize_t>*) dirBuff; auto dir = (Dir*) dirBuff;
err = read(dirStat.inode, dirBuff, dirBuffLen); err |= read(dirStat.inode, dirBuff, dirBuffLen);
if (!err) { if (!err) {
return dir->copy(dirOut); return dir->copy(dirOut);
} else { } else {

11
deps/ox/src/ox/fs/fs.hpp vendored Normal file
View File

@ -0,0 +1,11 @@
/*
* Copyright 2015 - 2017 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "filesystem.hpp"

23
deps/ox/src/ox/std/math.hpp vendored Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright 2015 - 2017 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
namespace ox {
template<typename T>
inline const T &min(const T &a, const T &b) {
return a < b ? a : b;
}
template<typename T>
inline const T &max(const T &a, const T &b) {
return a > b ? a : b;
}
}

View File

@ -5,10 +5,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#pragma once #pragma once
#include "bitops.hpp" #include "bitops.hpp"
#include "byteswap.hpp" #include "byteswap.hpp"
#include "math.hpp"
#include "memops.hpp" #include "memops.hpp"
#include "random.hpp" #include "random.hpp"
#include "strops.hpp" #include "strops.hpp"