diff --git a/.codecov.yml b/.codecov.yml index 0e6067a8a..155718e14 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -3,15 +3,14 @@ codecov: require_ci_to_pass: no coverage: + status: + project: yes + patch: no + changes: no precision: 2 round: down range: "100...100" -status: - project: yes - patch: no - changes: no - parsers: gcov: branch_detection: diff --git a/bfelf_loader/CMakeLists.txt b/bfelf_loader/CMakeLists.txt index 6e40bbc18..0abdf5a7b 100644 --- a/bfelf_loader/CMakeLists.txt +++ b/bfelf_loader/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.6) project(bfelf_loader C CXX) +set(TIDY_EXCLUSIONS ,-cppcoreguidelines-pro-type-const-cast) include(${CMAKE_INSTALL_PREFIX}/cmake/CMakeGlobal_Project.txt) # ------------------------------------------------------------------------------ diff --git a/bfelf_loader/include/bfelf_loader.h b/bfelf_loader/include/bfelf_loader.h index 741cf55ef..70b1a54db 100644 --- a/bfelf_loader/include/bfelf_loader.h +++ b/bfelf_loader/include/bfelf_loader.h @@ -919,7 +919,8 @@ private_hash(const char *name) } static inline int64_t -private_get_sym_by_hash(struct bfelf_file_t *ef, const char *name, const struct bfelf_sym **sym) +private_get_sym_by_hash( + struct bfelf_file_t *ef, const char *name, const struct bfelf_sym **sym) { bfelf64_word i = 0; unsigned long x = private_hash(name); @@ -945,7 +946,8 @@ private_get_sym_by_hash(struct bfelf_file_t *ef, const char *name, const struct } static inline int64_t -private_get_sym_by_name(struct bfelf_file_t *ef, const char *name, const struct bfelf_sym **sym) +private_get_sym_by_name( + struct bfelf_file_t *ef, const char *name, const struct bfelf_sym **sym) { bfelf64_word i = 0; @@ -973,10 +975,8 @@ private_get_sym_by_name(struct bfelf_file_t *ef, const char *name, const struct static inline int64_t private_get_sym_global( - const struct bfelf_loader_t *loader, - const char *name, - struct bfelf_file_t **ef_found, - const struct bfelf_sym **sym) + const struct bfelf_loader_t *loader, const char *name, + struct bfelf_file_t **ef_found, const struct bfelf_sym **sym) { int64_t ret = 0; bfelf64_word i = 0; @@ -1472,8 +1472,8 @@ bfelf_file_get_num_load_instrs(const struct bfelf_file_t *ef) * @return BFELF_SUCCESS on success, negative on error */ static inline int64_t -bfelf_file_get_load_instr(const struct bfelf_file_t *ef, uint64_t index, - const struct bfelf_load_instr **instr) +bfelf_file_get_load_instr( + const struct bfelf_file_t *ef, uint64_t index, const struct bfelf_load_instr **instr) { if (ef == nullptr) { return bfinvalid_argument("ef == nullptr"); @@ -1508,7 +1508,8 @@ bfelf_file_get_load_instr(const struct bfelf_file_t *ef, uint64_t index, * @return BFELF_SUCCESS on success, negative on error */ static inline int64_t -bfelf_file_get_section_info(const struct bfelf_file_t *ef, struct section_info_t *info) +bfelf_file_get_section_info( + const struct bfelf_file_t *ef, struct section_info_t *info) { bfelf64_word i = 0; @@ -1631,7 +1632,8 @@ bfelf_file_get_stack_perm(const struct bfelf_file_t *ef, bfelf64_xword *perm) * @return BFELF_SUCCESS on success, negative on error */ static inline int64_t -bfelf_file_get_relro(const struct bfelf_file_t *ef, bfelf64_addr *addr, bfelf64_xword *size) +bfelf_file_get_relro( + const struct bfelf_file_t *ef, bfelf64_addr *addr, bfelf64_xword *size) { if (ef == nullptr) { return bfinvalid_argument("ef == nullptr"); @@ -1693,7 +1695,8 @@ bfelf_file_get_num_needed(const struct bfelf_file_t *ef) * @return number of needed entries on success, negative on error */ static inline int64_t -bfelf_file_get_needed(const struct bfelf_file_t *ef, uint64_t index, const char **needed) +bfelf_file_get_needed( + const struct bfelf_file_t *ef, uint64_t index, const char **needed) { if (ef == nullptr) { return bfinvalid_argument("ef == nullptr"); @@ -1891,7 +1894,8 @@ bfelf_loader_relocate(struct bfelf_loader_t *loader) * @return BFELF_SUCCESS on success, negative on error */ static inline int64_t -bfelf_loader_resolve_symbol(const struct bfelf_loader_t *loader, const char *name, void **addr) +bfelf_loader_resolve_symbol( + const struct bfelf_loader_t *loader, const char *name, void **addr) { int64_t ret = 0; @@ -1934,7 +1938,7 @@ struct bfelf_binary_t { }; static inline int64_t -private_load_elf_binary(struct bfelf_binary_t *binary) +private_load_binary(struct bfelf_binary_t *binary) { int64_t i = 0; int64_t ret = 0; @@ -2005,19 +2009,15 @@ private_load_elf_binary(struct bfelf_binary_t *binary) } static inline int64_t -private_load_elf_binaries( - struct bfelf_binary_t *binaries, - uint64_t num_binaries, - struct bfelf_loader_t *loader) +private_relocate_binaries( + struct bfelf_binary_t *binaries, uint64_t num_binaries, struct bfelf_loader_t *loader) { uint64_t i = 0; int64_t ret = 0; for (i = 0; i < num_binaries; i++) { ret = bfelf_loader_add(loader, &binaries[i].ef, binaries[i].exec, binaries[i].exec); - if (ret != BFELF_SUCCESS) { - return ret; - } + bfignored(ret); } ret = bfelf_loader_relocate(loader); @@ -2030,9 +2030,7 @@ private_load_elf_binaries( static inline int64_t private_crt_info( - struct bfelf_binary_t *binaries, - uint64_t num_binaries, - struct crt_info_t *crt_info) + struct bfelf_binary_t *binaries, uint64_t num_binaries, struct crt_info_t *crt_info) { uint64_t i = 0; @@ -2042,9 +2040,7 @@ private_crt_info( struct section_info_t section_info = {}; ret = bfelf_file_get_section_info(&binaries[i].ef, §ion_info); - if (ret != BFELF_SUCCESS) { - return ret; - } + bfignored(ret); crt_info->info[crt_info->info_num++] = section_info; } @@ -2086,11 +2082,8 @@ private_crt_info( */ static inline int64_t bfelf_load( - struct bfelf_binary_t *binaries, - uint64_t num_binaries, - void **entry, - struct crt_info_t *crt_info, - struct bfelf_loader_t *loader) + struct bfelf_binary_t *binaries, uint64_t num_binaries, void **entry, + struct crt_info_t *crt_info, struct bfelf_loader_t *loader) { uint64_t i = 0; int64_t ret = 0; @@ -2116,21 +2109,19 @@ bfelf_load( } for (i = 0; i < num_binaries; i++) { - ret = private_load_elf_binary(&binaries[i]); + ret = private_load_binary(&binaries[i]); if (ret != BF_SUCCESS) { return ret; } } - ret = private_load_elf_binaries(binaries, num_binaries, loader); + ret = private_relocate_binaries(binaries, num_binaries, loader); if (ret != BF_SUCCESS) { return ret; } ret = private_crt_info(binaries, num_binaries, crt_info); - if (ret != BF_SUCCESS) { - return ret; - } + bfignored(ret); ret = bfelf_file_get_entry(&binaries[num_binaries - 1].ef, entry); bfignored(ret); @@ -2154,10 +2145,7 @@ bfelf_load( * @return BFELF_SUCCESS on success, negative on error */ static inline int64_t -bfelf_set_args( - struct crt_info_t *crt_info, - int argc, - const char **argv) +bfelf_set_args(struct crt_info_t *crt_info, int argc, const char **argv) { if (crt_info == nullptr) { return bfinvalid_argument("crt_info == nullptr"); @@ -2191,11 +2179,7 @@ bfelf_set_args( */ static inline int64_t bfelf_set_integer_args( - struct crt_info_t *crt_info, - uintptr_t request, - uintptr_t arg1, - uintptr_t arg2, - uintptr_t arg3) + struct crt_info_t *crt_info, uintptr_t request, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) { if (crt_info == nullptr) { return bfinvalid_argument("crt_info == nullptr"); @@ -2229,9 +2213,7 @@ bfelf_set_integer_args( inline auto private_read_binary( - gsl::not_null f, - const std::string &filename, - bfelf_binary_t &binary) + gsl::not_null f, const std::string &filename, bfelf_binary_t &binary) { auto buffer = f->read_binary(filename); @@ -2251,9 +2233,7 @@ private_get_needed_list(const bfelf_file_t &ef) const char *needed = nullptr; ret = bfelf_file_get_needed(&ef, static_cast(i), &needed); - if (ret != BFELF_SUCCESS) { - throw std::runtime_error("bfelf_file_get_needed failed: " + bfn::to_string(ret, 16)); - } + bfignored(ret); list.emplace_back(needed); } @@ -2284,11 +2264,8 @@ private_get_needed_list(const bfelf_file_t &ef) */ inline auto bfelf_read_binary_and_get_needed_list( - gsl::not_null f, - const std::string &filename, - const std::vector &paths, - bfn::buffer &buffer, - bfelf_binary_t &binary) + gsl::not_null f, const std::string &filename, + const std::vector &paths, bfn::buffer &buffer, bfelf_binary_t &binary) { buffer = private_read_binary(f, filename, binary); @@ -2330,9 +2307,7 @@ class binaries_info * @param paths a list of paths to locate the ELF binary from */ binaries_info( - gsl::not_null f, - const std::string &filename, - const std::vector &paths) + gsl::not_null f, const std::string &filename, const std::vector &paths) { bfn::buffer data; bfelf_binary_t binary = {}; @@ -2362,8 +2337,7 @@ class binaries_info * @param filenames the list of files to load */ binaries_info( - gsl::not_null f, - const std::vector &filenames) + gsl::not_null f, const std::vector &filenames) { this->init_binaries(f, filenames); @@ -2467,18 +2441,14 @@ class binaries_info private: void - push_binary( - bfn::buffer &&data, - bfelf_binary_t &&binary) + push_binary(bfn::buffer &&data, bfelf_binary_t &&binary) { m_datas.push_back(std::move(data)); m_binaries.push_back(std::move(binary)); } void - init_binaries( - gsl::not_null f, - const std::vector &filenames) + init_binaries(gsl::not_null f, const std::vector &filenames) { expects(!filenames.empty()); diff --git a/bfelf_loader/tests/CMakeLists.txt b/bfelf_loader/tests/CMakeLists.txt index 244dc51d1..5f3083b8e 100644 --- a/bfelf_loader/tests/CMakeLists.txt +++ b/bfelf_loader/tests/CMakeLists.txt @@ -17,6 +17,7 @@ macro(do_test str) add_test(bfelf_${str} test_${str}) endmacro(do_test) +do_test(binary) do_test(file_get_entry) do_test(file_get_load_instr) do_test(file_get_needed) @@ -30,9 +31,11 @@ do_test(file_get_stack_perm) do_test(file_get_total_size) do_test(file_init) do_test(helpers) -do_test(load_elf) -do_test(load_libraries) +do_test(load) do_test(loader_add) do_test(loader_relocate) do_test(loader_resolve_symbol) +do_test(read_binary_and_get_needed_list) do_test(real) +do_test(set_args) +do_test(set_integer_args) diff --git a/bfelf_loader/tests/test_binary.cpp b/bfelf_loader/tests/test_binary.cpp index 5185a4074..51bbb70f3 100644 --- a/bfelf_loader/tests/test_binary.cpp +++ b/bfelf_loader/tests/test_binary.cpp @@ -20,39 +20,49 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include +#include #include #include -TEST_CASE("bfelf_binary: invalid file") +#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT + +TEST_CASE("bfelf_binary: binary load fails") { - file *f = nullptr; - CHECK_THROWS(bfelf_binary(f, g_filenames.back())); + MockRepository mocks; + mocks.OnCallFunc(bfelf_load).Return(-1); + + file f; + CHECK_THROWS(binaries_info(&f, g_filenames.back(), {BAREFLANK_SYSROOT_PATH + "/lib/"_s})); } -TEST_CASE("bfelf_binary: invalid filename") +TEST_CASE("bfelf_binary: binary success") { - CHECK_THROWS(bfelf_binary(&g_file, "bad_filename")); + file f; + CHECK_NOTHROW(binaries_info(&f, g_filenames.back(), {BAREFLANK_SYSROOT_PATH + "/lib/"_s})); } -TEST_CASE("bfelf_binary: invalid ELF file") +TEST_CASE("bfelf_binary: module list load fails") { - auto &&filename = "test.txt"_s; - auto &&text_data = "not an ELF file"_s; + MockRepository mocks; + mocks.OnCallFunc(bfelf_load).Return(-1); - REQUIRE_NOTHROW(g_file.write_text(filename, text_data)); - CHECK_THROWS(bfelf_binary(&g_file, filename)); + file f; + CHECK_THROWS(binaries_info(&f, g_filenames)); +} - REQUIRE(std::remove(filename.c_str()) == 0); +TEST_CASE("bfelf_binary: module list success") +{ + file f; + CHECK_NOTHROW(binaries_info(&f, g_filenames)); } -TEST_CASE("bfelf_binary: success") +TEST_CASE("bfelf_binary: set args") { - auto &&binary = bfelf_binary {&g_file, g_filenames.back()}; + file f; + binaries_info info(&f, g_filenames); - CHECK(binary.filename() == BAREFLANK_SYSROOT_PATH + "/bin/dummy_main"_s); - CHECK(binary.filesize() != 0); - CHECK(!binary.filedata().empty()); - CHECK(binary.execdata()); - CHECK(binary.ef().file != nullptr); + CHECK_NOTHROW(info.set_args(0, nullptr)); } + +#endif diff --git a/bfelf_loader/tests/test_fake_elf.cpp b/bfelf_loader/tests/test_fake_elf.cpp index a79ae69f4..414cc8103 100644 --- a/bfelf_loader/tests/test_fake_elf.cpp +++ b/bfelf_loader/tests/test_fake_elf.cpp @@ -123,10 +123,10 @@ get_fake_elf() test->dynamic.init_array.d_val = offset(test->init_array, *test); test->dynamic.fini_array.d_tag = bfdt_fini_array; test->dynamic.fini_array.d_val = offset(test->fini_array, *test); - test->dynamic.init_array.d_tag = bfdt_init_arraysz; - test->dynamic.init_array.d_val = sizeof(test_init_array); - test->dynamic.fini_array.d_tag = bfdt_fini_arraysz; - test->dynamic.fini_array.d_val = sizeof(test_fini_array); + test->dynamic.init_arraysz.d_tag = bfdt_init_arraysz; + test->dynamic.init_arraysz.d_val = sizeof(test_init_array); + test->dynamic.fini_arraysz.d_tag = bfdt_fini_arraysz; + test->dynamic.fini_arraysz.d_val = sizeof(test_fini_array); test->dynamic.flags_1.d_tag = bfdt_flags_1; test->dynamic.last.d_tag = bfdt_null; diff --git a/bfelf_loader/tests/test_file_get_section_info.cpp b/bfelf_loader/tests/test_file_get_section_info.cpp index 3a3139626..e571aabf7 100644 --- a/bfelf_loader/tests/test_file_get_section_info.cpp +++ b/bfelf_loader/tests/test_file_get_section_info.cpp @@ -56,8 +56,10 @@ TEST_CASE("bfelf_file_get_section_info: expected misc resources") section_info_t info = {}; auto &dummy_main_ef = binaries.ef(); - dummy_main_ef.init = 10; - dummy_main_ef.fini = 10; + dummy_main_ef.init = 42; + dummy_main_ef.fini = 42; + dummy_main_ef.fini_array = 42; + dummy_main_ef.fini_arraysz = 42; auto ret = bfelf_file_get_section_info(&dummy_main_ef, &info); CHECK(ret == BFELF_SUCCESS); @@ -65,8 +67,8 @@ TEST_CASE("bfelf_file_get_section_info: expected misc resources") CHECK(info.init_array_addr != nullptr); CHECK(info.init_array_size != 0); - CHECK(info.fini_array_addr == nullptr); - CHECK(info.fini_array_size == 0); + CHECK(info.fini_array_addr != nullptr); + CHECK(info.fini_array_size != 0); CHECK(info.eh_frame_addr != nullptr); CHECK(info.eh_frame_size != 0); diff --git a/bfelf_loader/tests/test_load.cpp b/bfelf_loader/tests/test_load.cpp new file mode 100644 index 000000000..78399830d --- /dev/null +++ b/bfelf_loader/tests/test_load.cpp @@ -0,0 +1,172 @@ +// +// Bareflank Hypervisor +// +// Copyright (C) 2015 Assured Information Security, Inc. +// Author: Rian Quinn +// Author: Brendan Kerrigan +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include +#include + +#include +#include + +#include +#include +#include + +TEST_CASE("bfelf_load: invalid binaries") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_loader_t loader = {}; + + auto ret = bfelf_load(nullptr, 9, &entry, &info, &loader); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} + +TEST_CASE("bfelf_load: invalid num binaries") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + auto ret = bfelf_load(reinterpret_cast(binaries), 0, &entry, &info, &loader); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} + +TEST_CASE("bfelf_load: invalid entry") +{ + crt_info_t info = {}; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + auto ret = bfelf_load(reinterpret_cast(binaries), 9, nullptr, &info, &loader); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} + +TEST_CASE("bfelf_load: invalid info") +{ + void *entry = nullptr; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + auto ret = bfelf_load(reinterpret_cast(binaries), 9, &entry, nullptr, &loader); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} + +TEST_CASE("bfelf_load: invalid loader") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_binary_t binaries[9] = {}; + + auto ret = bfelf_load(reinterpret_cast(binaries), 9, &entry, &info, nullptr); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} + +TEST_CASE("bfelf_load: init fail") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + std::list files; + for (auto i = 0ULL; i < 9; i++) { + auto file = g_file.read_binary(g_filenames.at(i)); + + gsl::at(binaries, i).file = file.data(); + gsl::at(binaries, i).file_size = file.size(); + + files.emplace_back(std::move(file)); + } + + gsl::at(const_cast(gsl::at(binaries, 0).file), 16, 0) = 0; + + auto ret = bfelf_load(reinterpret_cast(binaries), 9, &entry, &info, &loader); + CHECK(ret == BFELF_ERROR_INVALID_SIGNATURE); +} + +TEST_CASE("bfelf_load: out of memory fail") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + std::list files; + for (auto i = 0ULL; i < 9; i++) { + auto file = g_file.read_binary(g_filenames.at(i)); + + gsl::at(binaries, i).file = file.data(); + gsl::at(binaries, i).file_size = file.size(); + + files.emplace_back(std::move(file)); + } + + out_of_memory = true; + auto ___ = gsl::finally([&] { + out_of_memory = false; + }); + + auto ret = bfelf_load(reinterpret_cast(binaries), 9, &entry, &info, &loader); + CHECK(ret == BFELF_ERROR_OUT_OF_MEMORY); +} + +TEST_CASE("bfelf_load: relocate fail") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + std::list files; + for (auto i = 0ULL; i < 9; i++) { + auto file = g_file.read_binary(g_filenames.at(i)); + + gsl::at(binaries, i).file = file.data(); + gsl::at(binaries, i).file_size = file.size(); + + files.emplace_back(std::move(file)); + } + + auto ret = bfelf_load(reinterpret_cast(binaries), 8, &entry, &info, &loader); + CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL); +} + +TEST_CASE("bfelf_load: success") +{ + void *entry = nullptr; + crt_info_t info = {}; + bfelf_loader_t loader = {}; + bfelf_binary_t binaries[9] = {}; + + std::list files; + for (auto i = 0ULL; i < 9; i++) { + auto file = g_file.read_binary(g_filenames.at(i)); + + gsl::at(binaries, i).file = file.data(); + gsl::at(binaries, i).file_size = file.size(); + + files.emplace_back(std::move(file)); + } + + auto ret = bfelf_load(reinterpret_cast(binaries), 9, &entry, &info, &loader); + CHECK(ret == BF_SUCCESS); +} diff --git a/bfelf_loader/tests/test_load_elf.cpp b/bfelf_loader/tests/test_load_elf.cpp deleted file mode 100644 index e79cefe04..000000000 --- a/bfelf_loader/tests/test_load_elf.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// Bareflank Hypervisor -// -// Copyright (C) 2015 Assured Information Security, Inc. -// Author: Rian Quinn -// Author: Brendan Kerrigan -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -#include -#include - -#include -#include - -#include -#include - -TEST_CASE("bfelf_load_elf: invalid file") -{ - // char *exec = nullptr; - // bfelf_file_t ef = {}; - - // auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); - // auto size = file.size(); - - // auto ret = bfelf_load_elf(nullptr, size, &ef, &exec); - // CHECK(ret == BFELF_ERROR_INVALID_ARG); -} - -// TEST_CASE("bfelf_load_elf: invalid size") -// { -// char *exec = nullptr; -// bfelf_file_t ef = {}; - -// auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); -// auto size = 0ULL; - -// auto ret = bfelf_load_elf(file.data(), size, &ef, &exec); -// CHECK(ret == BFELF_ERROR_INVALID_ARG); -// } - -// TEST_CASE("bfelf_load_elf: invalid elf") -// { -// char *exec = nullptr; - -// auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); -// auto size = file.size(); - -// auto ret = bfelf_load_elf(file.data(), size, nullptr, &exec); -// CHECK(ret == BFELF_ERROR_INVALID_ARG); -// } - -// TEST_CASE("bfelf_load_elf: invalid exec") -// { -// bfelf_file_t ef = {}; - -// auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); -// auto size = file.size(); - -// auto ret = bfelf_load_elf(file.data(), size, &ef, nullptr); -// CHECK(ret == BFELF_ERROR_INVALID_ARG); -// } - -// TEST_CASE("bfelf_load_elf: bfelf_file_init fails") -// { -// char *exec = nullptr; -// bfelf_file_t ef = {}; - -// auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); -// auto size = file.size(); - -// auto span = gsl::string_span<>(file); -// span[0] = 0; - -// auto ret = bfelf_load_elf(file.data(), size, &ef, &exec); -// CHECK(ret == BFELF_ERROR_INVALID_SIGNATURE); -// } - -// TEST_CASE("bfelf_load_elf: platform_alloc_rwe fails") -// { -// char *exec = nullptr; -// bfelf_file_t ef = {}; - -// auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); -// auto size = file.size(); - -// MockRepository mocks; -// mocks.OnCallFunc(platform_alloc_rwe).Return(nullptr); - -// auto ret = bfelf_load_elf(file.data(), size, &ef, &exec); -// CHECK(ret == BFELF_ERROR_OUT_OF_MEMORY); -// } - -// TEST_CASE("bfelf_load_elf: success") -// { -// char *exec = nullptr; -// bfelf_file_t ef = {}; - -// auto file = g_file.read_binary(BAREFLANK_SYSROOT_PATH "/bin/dummy_main"); -// auto size = file.size(); - -// auto ret = bfelf_load_elf(file.data(), size, &ef, &exec); -// CHECK(ret == BF_SUCCESS); - -// std::unique_ptr {exec, free}; -// } diff --git a/bfelf_loader/tests/test_loader_add.cpp b/bfelf_loader/tests/test_loader_add.cpp index e23322406..48a725c2b 100644 --- a/bfelf_loader/tests/test_loader_add.cpp +++ b/bfelf_loader/tests/test_loader_add.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -52,33 +53,44 @@ TEST_CASE("bfelf_loader_add: invalid addr") CHECK(ret == BFELF_ERROR_INVALID_ARG); } -// TEST_CASE("bfelf_loader_add: too many files") -// { -// int64_t ret = 0; -// bfelf_file_t ef = {}; -// bfelf_loader_t loader = {}; +TEST_CASE("bfelf_loader_add: add twice") +{ + int64_t ret = 0; + bfelf_loader_t loader = {}; + bfelf_file_t dummy_misc_ef = {}; -// auto data = get_fake_elf(); -// auto &buf = std::get<0>(data); -// auto size = std::get<1>(data); + ret = bfelf_loader_add(&loader, &dummy_misc_ef, static_cast(dummy), static_cast(dummy)); + CHECK(ret == BF_SUCCESS); -// for (auto i = 0; i < MAX_NUM_MODULES + 1; i++) { + ret = bfelf_loader_add(&loader, &dummy_misc_ef, static_cast(dummy), static_cast(dummy)); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} -// bfelf_file_t dummy_misc_ef = {}; +TEST_CASE("bfelf_loader_add: too many files") +{ + int64_t ret = 0; + bfelf_loader_t loader = {}; + std::vector efs(MAX_NUM_MODULES + 1); -// ret = bfelf_file_init(buf.get(), size, &ef); -// REQUIRE(ret == BFELF_SUCCESS); + auto data = get_fake_elf(); + auto &buf = std::get<0>(data); + auto size = std::get<1>(data); -// ret = bfelf_loader_add(&loader, &ef, dummy, dummy); + for (auto i = 0ULL; i < MAX_NUM_MODULES + 1; i++) { -// if (i < MAX_NUM_MODULES) { -// CHECK(ret == BF_SUCCESS); -// } -// else { -// CHECK(ret == BFELF_ERROR_LOADER_FULL); -// } -// } -// } + ret = bfelf_file_init(buf.get(), size, &gsl::at(efs, i)); + REQUIRE(ret == BFELF_SUCCESS); + + ret = bfelf_loader_add(&loader, &gsl::at(efs, i), static_cast(dummy), static_cast(dummy)); + + if (i < MAX_NUM_MODULES) { + CHECK(ret == BF_SUCCESS); + } + else { + CHECK(ret == BFELF_ERROR_LOADER_FULL); + } + } +} TEST_CASE("bfelf_loader_add: add fake") { diff --git a/bfelf_loader/tests/test_loader_relocate.cpp b/bfelf_loader/tests/test_loader_relocate.cpp index a319ce614..85a470d46 100644 --- a/bfelf_loader/tests/test_loader_relocate.cpp +++ b/bfelf_loader/tests/test_loader_relocate.cpp @@ -53,11 +53,34 @@ TEST_CASE("bfelf_loader_relocate: twice") CHECK(ret == BFELF_SUCCESS); } +#ifndef WIN64 + TEST_CASE("bfelf_loader_relocate: no such symbol") { - auto filenames = g_filenames; - filenames.erase(filenames.begin()); - filenames.erase(filenames.begin()); + int64_t ret = 0; + binaries_info binaries{&g_file, g_filenames}; + + binaries.ef(0) = {}; + binaries.loader().relocated = 0; - CHECK_THROWS(binaries_info(&g_file, filenames)); + ret = bfelf_loader_relocate(&binaries.loader()); + CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL); } + +TEST_CASE("bfelf_loader_relocate: no such symbol in plt") +{ + int64_t ret = 0; + binaries_info binaries{&g_file, g_filenames}; + + binaries.ef(0) = {}; + binaries.loader().relocated = 0; + + for (auto i = 0ULL; i < 9; i++) { + binaries.ef(i).relanum_dyn = 0; + } + + ret = bfelf_loader_relocate(&binaries.loader()); + CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL); +} + +#endif diff --git a/bfelf_loader/tests/test_loader_resolve_symbol.cpp b/bfelf_loader/tests/test_loader_resolve_symbol.cpp index 219928269..5699a45dd 100644 --- a/bfelf_loader/tests/test_loader_resolve_symbol.cpp +++ b/bfelf_loader/tests/test_loader_resolve_symbol.cpp @@ -30,7 +30,7 @@ TEST_CASE("bfelf_loader_resolve_symbol: invalid loader") { func_t func; - auto ret = bfelf_loader_resolve_symbol(nullptr, "abort", reinterpret_cast(&func)); + auto ret = bfelf_loader_resolve_symbol(nullptr, "lib1_foo", reinterpret_cast(&func)); CHECK(ret == BFELF_ERROR_INVALID_ARG); } @@ -47,7 +47,7 @@ TEST_CASE("bfelf_loader_resolve_symbol: invalid addr") { bfelf_loader_t loader = {}; - auto ret = bfelf_loader_resolve_symbol(&loader, "abort", nullptr); + auto ret = bfelf_loader_resolve_symbol(&loader, "lib1_foo", nullptr); CHECK(ret == BFELF_ERROR_INVALID_ARG); } @@ -61,7 +61,7 @@ TEST_CASE("bfelf_loader_resolve_symbol: no files added") func_t func; - ret = bfelf_loader_resolve_symbol(&loader, "abort", reinterpret_cast(&func)); + ret = bfelf_loader_resolve_symbol(&loader, "lib1_foo", reinterpret_cast(&func)); CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL); } @@ -83,7 +83,7 @@ TEST_CASE("bfelf_loader_resolve_symbol: success") func_t func; - ret = bfelf_loader_resolve_symbol(&binaries.loader(), "abort", reinterpret_cast(&func)); + ret = bfelf_loader_resolve_symbol(&binaries.loader(), "lib1_foo", reinterpret_cast(&func)); CHECK(ret == BFELF_SUCCESS); } @@ -111,6 +111,6 @@ TEST_CASE("bfelf_loader_resolve_symbol: success no hash") func_t func; - ret = bfelf_loader_resolve_symbol(&binaries.loader(), "abort", reinterpret_cast(&func)); + ret = bfelf_loader_resolve_symbol(&binaries.loader(), "lib1_foo", reinterpret_cast(&func)); CHECK(ret == BFELF_SUCCESS); } diff --git a/bfelf_loader/tests/test_read_binary_and_get_needed_list.cpp b/bfelf_loader/tests/test_read_binary_and_get_needed_list.cpp new file mode 100644 index 000000000..cffeccef4 --- /dev/null +++ b/bfelf_loader/tests/test_read_binary_and_get_needed_list.cpp @@ -0,0 +1,75 @@ +// +// Bareflank Hypervisor +// +// Copyright (C) 2015 Assured Information Security, Inc. +// Author: Rian Quinn +// Author: Brendan Kerrigan +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include +#include + +#include +#include + +TEST_CASE("bfelf_set_integer_args: invalid info") +{ + file f; + bfn::buffer buffer{}; + bfelf_binary_t binary{}; + std::string filename{"test.txt"}; + + REQUIRE_NOTHROW(f.write_text(filename, "not an ELF file")); + + CHECK_THROWS( + bfelf_read_binary_and_get_needed_list(&f, filename, {}, buffer, binary) + ); + + REQUIRE(std::remove(filename.c_str()) == 0); +} + +TEST_CASE("bfelf_set_integer_args: no paths") +{ + file f; + bfn::buffer buffer{}; + bfelf_binary_t binary{}; + + CHECK_THROWS( + bfelf_read_binary_and_get_needed_list(&f, g_filenames.back(), {"not a dir"}, buffer, binary) + ); +} + +TEST_CASE("bfelf_set_integer_args: invalid filename") +{ + file f; + bfn::buffer buffer{}; + bfelf_binary_t binary{}; + + CHECK_THROWS( + bfelf_read_binary_and_get_needed_list(&f, "not_a_real_file", {}, buffer, binary) + ); +} + +TEST_CASE("bfelf_set_integer_args: success") +{ + file f; + bfn::buffer buffer{}; + bfelf_binary_t binary{}; + + CHECK_NOTHROW( + bfelf_read_binary_and_get_needed_list(&f, g_filenames.back(), {BAREFLANK_SYSROOT_PATH + "/lib/"_s}, buffer, binary) + ); +} diff --git a/bfelf_loader/tests/test_real_elf.cpp b/bfelf_loader/tests/test_real_elf.cpp index b9946ee6d..90fa02f23 100644 --- a/bfelf_loader/tests/test_real_elf.cpp +++ b/bfelf_loader/tests/test_real_elf.cpp @@ -44,11 +44,16 @@ std::vector g_filenames = { }; file g_file; +bool out_of_memory = false; static std::map> g_memory; void * platform_alloc_rwe(uint64_t len) { + if (out_of_memory) { + return nullptr; + } + auto addr = aligned_alloc(0x1000, len); g_memory[addr] = std::shared_ptr(static_cast(addr), free); diff --git a/bfelf_loader/tests/test_real_elf.h b/bfelf_loader/tests/test_real_elf.h index 62238a60d..8c227913d 100644 --- a/bfelf_loader/tests/test_real_elf.h +++ b/bfelf_loader/tests/test_real_elf.h @@ -28,6 +28,7 @@ #include extern file g_file; +extern bool out_of_memory; extern std::vector g_filenames; #endif diff --git a/bfelf_loader/tests/test_load_libraries.cpp b/bfelf_loader/tests/test_set_args.cpp similarity index 53% rename from bfelf_loader/tests/test_load_libraries.cpp rename to bfelf_loader/tests/test_set_args.cpp index 3cdc649dc..b4a465c69 100644 --- a/bfelf_loader/tests/test_load_libraries.cpp +++ b/bfelf_loader/tests/test_set_args.cpp @@ -19,39 +19,27 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#include #include -#include +#include #include -TEST_CASE("bfelf_load_binaries: invalid file") +TEST_CASE("bfelf_set_args: invalid info") { - // file *f = nullptr; - // bfelf_loader_t loader = {}; + int argc = 0; + const char *argv = nullptr; - // CHECK_THROWS(bfelf_load_binaries(f, g_filenames, &loader)); + auto ret = bfelf_set_args(nullptr, argc, &argv); + CHECK(ret == BFELF_ERROR_INVALID_ARG); } -// TEST_CASE("bfelf_load_binaries: invalid loader") -// { -// bfelf_loader_t *loader = nullptr; -// CHECK_THROWS(bfelf_load_binaries(&g_file, g_filenames, loader)); -// } - -// TEST_CASE("bfelf_load_binaries: no files") -// { -// bfelf_loader_t loader = {}; -// CHECK_NOTHROW(bfelf_load_binaries(&g_file, {}, &loader)); -// } - -// TEST_CASE("bfelf_load_binaries: invalid filename") -// { -// bfelf_loader_t loader = {}; -// CHECK_THROWS(bfelf_load_binaries(&g_file, {"bad_file_name"_s}, &loader)); -// } +TEST_CASE("bfelf_set_args: success") +{ + int argc = 0; + crt_info_t info = {}; + const char *argv = nullptr; -// TEST_CASE("bfelf_load_binaries: success") -// { -// bfelf_loader_t loader = {}; -// CHECK_NOTHROW(bfelf_load_binaries(&g_file, g_filenames, &loader)); -// } + auto ret = bfelf_set_args(&info, argc, &argv); + CHECK(ret == BF_SUCCESS); +} diff --git a/bfelf_loader/tests/test_set_integer_args.cpp b/bfelf_loader/tests/test_set_integer_args.cpp new file mode 100644 index 000000000..706ac48b5 --- /dev/null +++ b/bfelf_loader/tests/test_set_integer_args.cpp @@ -0,0 +1,40 @@ +// +// Bareflank Hypervisor +// +// Copyright (C) 2015 Assured Information Security, Inc. +// Author: Rian Quinn +// Author: Brendan Kerrigan +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include +#include + +#include +#include + +TEST_CASE("bfelf_set_integer_args: invalid info") +{ + auto ret = bfelf_set_integer_args(nullptr, 0, 0, 0, 0); + CHECK(ret == BFELF_ERROR_INVALID_ARG); +} + +TEST_CASE("bfelf_set_integer_args: success") +{ + crt_info_t info = {}; + + auto ret = bfelf_set_integer_args(&info, 0, 0, 0, 0); + CHECK(ret == BF_SUCCESS); +} diff --git a/bfsdk/cmake/CMakeGlobal_Project.txt b/bfsdk/cmake/CMakeGlobal_Project.txt index 5843b1f49..72f264f82 100644 --- a/bfsdk/cmake/CMakeGlobal_Project.txt +++ b/bfsdk/cmake/CMakeGlobal_Project.txt @@ -142,6 +142,7 @@ execute_process(COMMAND uname -o OUTPUT_VARIABLE UNAME OUTPUT_STRIP_TRAILING_WHI if(UNAME STREQUAL "Cygwin" OR WIN32) set(OSTYPE "WIN64") set(ABITYPE "MS64") + set(WIN64 ON) else() set(OSTYPE "UNIX") set(ABITYPE "SYSV") diff --git a/bfsdk/scripts/bareflank_astyle_format.sh b/bfsdk/scripts/bareflank_astyle_format.sh index 5a30312b9..3b78572ec 100755 --- a/bfsdk/scripts/bareflank_astyle_format.sh +++ b/bfsdk/scripts/bareflank_astyle_format.sh @@ -42,7 +42,7 @@ fi if [[ "$1" == "all" ]]; then files=$(git ls-files | grep -Ee "\.(cpp|h|c)$" || true) else - files=$(git diff --relative --name-only --diff-filter=ACM HEAD^ $PWD | grep -Ee "\.(cpp|h|c)$" || true) + files=$(git diff --relative --name-only HEAD $PWD | grep -Ee "\.(cpp|h|c)$" || true) echo "Files undergoing astyle checks:" for f in $files; do diff --git a/bfsdk/scripts/bareflank_clang_tidy.sh b/bfsdk/scripts/bareflank_clang_tidy.sh index 654e59354..a8cff8387 100755 --- a/bfsdk/scripts/bareflank_clang_tidy.sh +++ b/bfsdk/scripts/bareflank_clang_tidy.sh @@ -74,7 +74,7 @@ get_changed_files() { if [[ "$1" == "all" ]]; then files=$(git ls-files | grep -Ee "\.(cpp|h|c)$" || true) else - files=$(git diff --relative --name-only --diff-filter=ACM HEAD^ $PWD | grep -Ee "\.(cpp|h|c)$" || true) + files=$(git diff --relative --name-only HEAD $PWD | grep -Ee "\.(cpp|h|c)$" || true) fi popd > /dev/null } diff --git a/bfsysroot/bfsupport/dummy_lib1/CMakeLists.txt b/bfsysroot/bfsupport/dummy_lib1/CMakeLists.txt index 834526663..dd566cc97 100644 --- a/bfsysroot/bfsupport/dummy_lib1/CMakeLists.txt +++ b/bfsysroot/bfsupport/dummy_lib1/CMakeLists.txt @@ -11,6 +11,10 @@ include(${CMAKE_INSTALL_PREFIX}/cmake/CMakeGlobal_Includes.txt) add_library(dummy_lib1 SHARED dummy_lib1.cpp) target_compile_definitions(dummy_lib1 PRIVATE SHARED_DUMMY) +if(NOT WIN64) + set(CMAKE_SHARED_LINKER_FLAGS "--fuse-ld=gold") +endif() + # ------------------------------------------------------------------------------ # Install # ------------------------------------------------------------------------------ diff --git a/bfsysroot/bfsupport/dummy_lib1/dummy_lib1.cpp b/bfsysroot/bfsupport/dummy_lib1/dummy_lib1.cpp index f30567ef2..7f1c4b2b7 100644 --- a/bfsysroot/bfsupport/dummy_lib1/dummy_lib1.cpp +++ b/bfsysroot/bfsupport/dummy_lib1/dummy_lib1.cpp @@ -19,15 +19,21 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +#include #include +EXPORT_SYM extern "C" int +lib1_foo() +{ return 1; } + derived1::derived1() noexcept - : m_member(1000) { + global_var++; } derived1::~derived1() { + global_var--; m_member = 0; } diff --git a/bfsysroot/bfsupport/dummy_lib2/CMakeLists.txt b/bfsysroot/bfsupport/dummy_lib2/CMakeLists.txt index 960f5568d..a331dfaff 100644 --- a/bfsysroot/bfsupport/dummy_lib2/CMakeLists.txt +++ b/bfsysroot/bfsupport/dummy_lib2/CMakeLists.txt @@ -11,6 +11,10 @@ include(${CMAKE_INSTALL_PREFIX}/cmake/CMakeGlobal_Includes.txt) add_library(dummy_lib2 SHARED dummy_lib2.cpp) target_compile_definitions(dummy_lib2 PRIVATE SHARED_DUMMY) +if(NOT WIN64) + set(CMAKE_SHARED_LINKER_FLAGS "--fuse-ld=gold") +endif() + # ------------------------------------------------------------------------------ # Install # ------------------------------------------------------------------------------ diff --git a/bfsysroot/bfsupport/dummy_lib2/dummy_lib2.cpp b/bfsysroot/bfsupport/dummy_lib2/dummy_lib2.cpp index 98beee144..3d40f9361 100644 --- a/bfsysroot/bfsupport/dummy_lib2/dummy_lib2.cpp +++ b/bfsysroot/bfsupport/dummy_lib2/dummy_lib2.cpp @@ -21,13 +21,16 @@ #include +extern "C" int lib1_foo(); + derived2::derived2() noexcept - : m_member(2000) { + global_var += lib1_foo(); } derived2::~derived2() { + global_var -= lib1_foo(); m_member = 0; } diff --git a/bfsysroot/bfsupport/dummy_main/dummy_main.cpp b/bfsysroot/bfsupport/dummy_main/dummy_main.cpp index 816c4784d..694b82f0f 100644 --- a/bfsysroot/bfsupport/dummy_main/dummy_main.cpp +++ b/bfsysroot/bfsupport/dummy_main/dummy_main.cpp @@ -32,6 +32,8 @@ derived1 g_derived1; derived2 g_derived2; +EXPORT_SYM int global_var = 0; + int main(int argc, char *argv[]) { diff --git a/bfsysroot/bfsupport/include/dummy_libs.h b/bfsysroot/bfsupport/include/dummy_libs.h index a69a4ae2b..6b4a31555 100644 --- a/bfsysroot/bfsupport/include/dummy_libs.h +++ b/bfsysroot/bfsupport/include/dummy_libs.h @@ -51,6 +51,8 @@ /* @cond */ +extern int global_var; + class EXPORT_DUMMY base { public: @@ -74,7 +76,7 @@ class EXPORT_DUMMY derived1 : public base foo(int arg) noexcept override; private: - int m_member; + int m_member{1000}; }; class EXPORT_DUMMY derived2 : public base @@ -87,7 +89,7 @@ class EXPORT_DUMMY derived2 : public base foo(int arg) noexcept override; private: - int m_member; + int m_member{2000}; }; /* @endcond */