Bareflank 3.0 Initial Upload

This patch provides the initial upload for Bareflank 3.0.
It should be noted that this initial upload does not contain
all of the intended features for 3.0, and instead provides
a starting point for further development and review.
This commit is contained in:
Rian Quinn 2021-01-29 08:01:19 -07:00
parent d2203d8fa4
commit 7e3f101819
1193 changed files with 65421 additions and 144010 deletions

View file

@ -1,92 +0,0 @@
# Change Log
## [1.1.0] - 2017-28-04
### Added
- New GDT class that provides a cleaner abstraction of the GDT
- New IDT class that provides a cleaner abstraction of the IDT
- New Page Table class that provides a cleaner abstraction of the Page Tables
- New VMCS state classes that organize the creation of the VMM's state, as
well as the Host VM's state.
- New state save logic for the exit handler to support multi-core. The state
save area is placed in "GS" allowing the exit handler to access CPU specific
state logic in a reentrant, thread-safe manner without the need for lookups
or APIC logic.
- Added TSS structure to intrinsics code. This structure is used by the
custom GDT for the VMM, but is not actually used.
- The VMM now uses it's own GDT instead of the GDT provided by the Host OS.
- The VMM now uses it's own IDT instead of the IDT provided by the Host OS.
- The VMM now uses it's own CR0 instead of the CR0 provided by the Host OS.
- The VMM now uses it's own CR3 instead of the CR3 provided by the Host OS.
- The VMM now uses it's own CR4 instead of the CR4 provided by the Host OS.
- The VMM now uses it's own RFLAGS instead of the RFLAGS provided by the Host OS.
- The VMM now uses it's own EFER MSR instead of the EFER MSR provided by the Host OS.
- New vCPU APIs that provide that ability to pass around a "user_data *" for extension
support
- Support for "-O3" optimizations
- Support for SSE/AVX code in the VMM
- Offical Windows 10 and Windows 8.1 Support
- Offical OpenSUSE support
- DWARF Expression support
- Multi-Core support
- Posix Mutex support (provides std::mutex)
- Coveralls support
- Coverity support
- AppVeyor support
- Clang Tidy 3.8 support
- Clang / LLVM 3.8, 3.9, and 4.0 support
- libc / libcxx / libcxxabi / bfcrt / bfunwind all loaded as shared libraries
- VMCS unit tests
- Intrinsics / VMCS namespace logic that provides useful functions / definitions
found in the Intel manual
- Libcxx unit tests
- VMCall support
### Changed
- The VMCS state classes are now shared by pointer (i.e. shared_ptr)
instead of my reference. This was done to support inheritance.
- The build system has been completely redone to provide both out-of-tree
compilation, but also to provide support for docker. With this new system,
it is possible to stand up the hypervisor in less than 10 minutes from start
to finish, while also maintaining multiple build systems for testing
- A lot of source code has been changed to address findings from Coverity
and Clang-Tidy
### Fixed
- If a VM-entry failure occurred, the exit handler would incorrectly read
the error as unknown because it was not filtering the VM-entry failure
bit
- Some of the macros in the intrinsics file were causing unsigned integers
because they hit touched bit 31. The macros have been expanded to 64 bits
to prevent this
- CPU-z support has been added via a Read MSR quirk.
### Removed
- The old GDT logic that was in the intrinsics_x64 has been removed. Please
use the new GDT class as it has the same functionality, but more.
- The old IDT logic that was in the intrinsics_x64 has been removed. Please
use the new IDT class as it has the same functionality, but more.
- The old vmcs_intel_x64_state class has been removed in favor of inheritance
to better support different state types (VMM, Host VM and Guest VM). Please
use the subclasses instead, or inherit manually
- The vCPU dispatch, halt and promote functions have been removed as they
were specific to Intel.
- GCC 5.x support for cross compilation (native still supported)
## [1.0.0] - 2016-27-04
### Added
- Linux support
- Single core support (core 0)
- Custom C runtime library for constructor / destructor support and registering
exception handlers
- Custom driver entry logic for loading the VMM
- Custom ELF loader for loading the VMM modules
- User-space management application (BFM) for starting / stopping the
hypervisor
- Custom kernel-safe unwind library for adding exception support to the VMM
- Basic VMM with support for Intel x86_64. The VMM places the Host OS into
a virtual machine and back out. Currently can be extended to provide
additional functionality
- Custom build environment
- Complete set of unit tests
- Documentation
- Scripts for setting up Ubuntu, Debian and Fedora build environments.

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
# Copyright (C) 2020 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@ -20,201 +20,24 @@
# SOFTWARE.
cmake_minimum_required(VERSION 3.13)
project(hypervisor)
project(hypervisor CXX)
# ------------------------------------------------------------------------------
# Modules
# ------------------------------------------------------------------------------
include(${CMAKE_CURRENT_LIST_DIR}/cmake/init_build.cmake)
include(ProcessorCount)
include(ExternalProject)
# ------------------------------------------------------------------------------
# Configs
# ------------------------------------------------------------------------------
include(${CMAKE_CURRENT_LIST_DIR}/scripts/cmake/config/default.cmake)
include_external_config()
# ------------------------------------------------------------------------------
# Macros
# ------------------------------------------------------------------------------
include(${SOURCE_CMAKE_DIR}/macros.cmake)
# ------------------------------------------------------------------------------
# Testing
# ------------------------------------------------------------------------------
if(ENABLE_BUILD_TEST)
include(CTest)
enable_testing(true)
if(HYPERVISOR_BUILD_LOADER)
add_subdirectory(loader)
endif()
# ------------------------------------------------------------------------------
# Sub-project includes
# ------------------------------------------------------------------------------
add_project_include(${SOURCE_CMAKE_DIR}/macros.cmake)
# ------------------------------------------------------------------------------
# BFM VMM
# ------------------------------------------------------------------------------
set_bfm_vmm(${DEFAULT_VMM} DEFAULT TARGET bfvmm)
message(STATUS "Bareflank Manager VMM")
message(STATUS " vmm: ${BFM_VMM}")
message(STATUS " target: ${BFM_VMM_TARGET}")
# ------------------------------------------------------------------------------
# Targets
# ------------------------------------------------------------------------------
include(${SOURCE_CMAKE_DIR}/targets.cmake)
# ------------------------------------------------------------------------------
# General Dependencies
# ------------------------------------------------------------------------------
include_dependency(SOURCE_DEPENDS_DIR gsl)
include_dependency(SOURCE_DEPENDS_DIR cxxopts)
include_dependency(SOURCE_DEPENDS_DIR json)
include_dependency(SOURCE_DEPENDS_DIR astyle)
include_dependency(SOURCE_DEPENDS_DIR clang_tidy)
include_dependency(SOURCE_DEPENDS_DIR catch)
include_dependency(SOURCE_DEPENDS_DIR hippomocks)
# ------------------------------------------------------------------------------
# Package File
# ------------------------------------------------------------------------------
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${EXPORT_DIR})
file(APPEND ${PKG_FILE} "")
# ------------------------------------------------------------------------------
# Root Targets
# ------------------------------------------------------------------------------
add_subproject(bfroot vmm SOURCE_DIR ${SOURCE_CMAKE_DIR})
add_subproject(bfroot efi SOURCE_DIR ${SOURCE_CMAKE_DIR})
add_subproject(bfroot test SOURCE_DIR ${SOURCE_CMAKE_DIR} DEPENDS catch)
add_subproject(bfroot userspace SOURCE_DIR ${SOURCE_CMAKE_DIR})
# ------------------------------------------------------------------------------
# VMM Components
# ------------------------------------------------------------------------------
include_dependency(SOURCE_DEPENDS_DIR binutils)
include_dependency(SOURCE_DEPENDS_DIR newlib)
include_dependency(SOURCE_DEPENDS_DIR llvm)
include_dependency(SOURCE_DEPENDS_DIR libcxxabi)
include_dependency(SOURCE_DEPENDS_DIR libcxx)
add_subproject(bfsdk vmm DEPENDS bfroot)
if(ENABLE_BUILD_VMM OR (ENABLE_BUILD_TEST AND NOT WIN32))
add_subproject(bfruntime vmm DEPENDS gsl libcxx bfroot)
add_subproject(bfunwind vmm DEPENDS bfruntime)
if(HYPERVISOR_BUILD_VMMCTL)
add_subdirectory(vmmctl)
endif()
if(ENABLE_BUILD_VMM)
add_subproject(bfintrinsics vmm DEPENDS bfruntime)
add_subproject(bfvmm vmm DEPENDS bfunwind bfintrinsics bfsdk)
endif()
# ------------------------------------------------------------------------------
# Unit Tests
# ------------------------------------------------------------------------------
if(ENABLE_BUILD_TEST)
add_subproject(bfsdk test DEPENDS gsl json hippomocks bfroot)
endif()
if(ENABLE_BUILD_TEST AND NOT WIN32)
add_subproject(bfdummy vmm DEPENDS bfunwind)
add_subproject(bfdriver test DEPENDS bfsdk)
endif()
if(ENABLE_BUILD_TEST)
add_subproject(bfm test DEPENDS bfsdk)
add_subproject(bfruntime test DEPENDS bfsdk)
add_subproject(bfvmm test DEPENDS bfsdk)
endif()
# ------------------------------------------------------------------------------
# Userspace Components
# ------------------------------------------------------------------------------
if(ENABLE_BUILD_USERSPACE)
add_subproject(bfsdk userspace DEPENDS bfroot)
add_subproject(bfintrinsics userspace DEPENDS gsl json bfroot)
add_subproject(bfm userspace DEPENDS gsl json cxxopts bfroot)
add_subproject(bfack userspace DEPENDS bfintrinsics)
endif()
# ------------------------------------------------------------------------------
# External Components
# ------------------------------------------------------------------------------
list(APPEND EXTENSION ${SOURCE_EXAMPLES_DIR}/cpuidcount)
list(APPEND EXTENSION ${SOURCE_EXAMPLES_DIR}/hook)
list(APPEND EXTENSION ${SOURCE_EXAMPLES_DIR}/rdtsc)
list(APPEND EXTENSION ${SOURCE_EXAMPLES_DIR}/vpid)
include_external_extensions()
# ------------------------------------------------------------------------------
# EFI Components
# ------------------------------------------------------------------------------
if(ENABLE_BUILD_EFI AND NOT WIN32)
include_dependency(SOURCE_DEPENDS_DIR gnuefi)
add_subproject(bfdriver efi DEPENDS bfroot gnuefi ${BFM_VMM_TARGET})
endif()
# ------------------------------------------------------------------------------
# Force Rebuild
# ------------------------------------------------------------------------------
get_property(FORCE_REBUILD GLOBAL PROPERTY "FORCE_REBUILD")
if(FORCE_REBUILD STREQUAL "ON")
set_property(GLOBAL PROPERTY "FORCE_REBUILD" "OFF")
file(REMOVE_RECURSE ${DEPENDS_DIR})
file(REMOVE_RECURSE ${PREFIXES_DIR})
message(FATAL_ERROR "${Yellow}dependencies updated, rebuild is required. Rerun cmake${ColorReset}")
endif()
# TODO:
#
# Detect if the flags have changed, delete the depends and prefixes, and then
# tell the user that cmake needs to be run again as a rebuild is required.
# ------------------------------------------------------------------------------
# Validate Build
# ------------------------------------------------------------------------------
include(scripts/cmake/validate.cmake)
validate_build()
# ------------------------------------------------------------------------------
# Banners
# ------------------------------------------------------------------------------
print_banner()
print_usage()
# ------------------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------------------
git_dir_script()
# ------------------------------------------------------------------------------
# Info
# ------------------------------------------------------------------------------
if(NOT WIN32)
add_custom_command(TARGET info COMMAND ${CMAKE_COMMAND} -E cmake_echo_color " ")
hypervisor_add_mk_cross_compile(cmake/mk_cross_compile)
hypervisor_add_ext_cross_compile(cmake/ext_cross_compile)
if(NOT DEFINED FIRST_TIME)
message(STATUS "${BF_COLOR_YLW}-----------------------------------------${BF_COLOR_RST}")
message(STATUS "run '${BF_COLOR_MAG}make info${BF_COLOR_RST}' for configuration details")
message(STATUS "${BF_COLOR_YLW}-----------------------------------------${BF_COLOR_RST}")
set(FIRST_TIME ON)
endif()

21
LICENSE
View file

@ -1,21 +0,0 @@
MIT License
Copyright (C) 2019 Assured Information Security, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

23
LICENSE.md Normal file
View file

@ -0,0 +1,23 @@
# **License**
**MIT License**
Copyright © 2016 - 2019 Martin Donath
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
# Copyright (C) 2020 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@ -19,37 +19,26 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
if(ENABLE_BUILD_VMM OR ENABLE_BUILD_USERSPACE OR ENABLE_BUILD_TEST)
message(STATUS "Including dependency: json")
download_dependency(
json
URL ${JSON_URL}
URL_MD5 ${JSON_URL_MD5}
)
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Windows)
find_program(HYPERVISOR_NINJA "ninja")
if(NOT HYPERVISOR_NINJA)
message(FATAL_ERROR "Unable to find ninja")
endif()
set(CMAKE_GENERATOR "Ninja" CACHE INTERNAL "")
endif()
list(APPEND JSON_CONFIGURE_FLAGS
-DJSON_BuildTests=OFF
)
if(ENABLE_BUILD_VMM)
add_dependency(
json vmm
CMAKE_ARGS ${JSON_CONFIGURE_FLAGS}
)
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Darwin)
set(HAVE_FLAG_SEARCH_PATHS_FIRST 0 CACHE INTERNAL "")
endif()
if(ENABLE_BUILD_USERSPACE)
add_dependency(
json userspace
CMAKE_ARGS ${JSON_CONFIGURE_FLAGS}
)
endif()
if(ENABLE_BUILD_TEST)
add_dependency(
json test
CMAKE_ARGS ${JSON_CONFIGURE_FLAGS}
)
if(NOT DEFINED CMAKE_CXX_COMPILER)
if(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin)
set(CMAKE_CXX_COMPILER llvm-clang++ CACHE INTERNAL "")
else()
set(CMAKE_CXX_COMPILER clang++ CACHE INTERNAL "")
endif()
find_program(CMAKE_CXX_COMPILER ${CMAKE_CXX_COMPILER})
if(NOT CMAKE_CXX_COMPILER)
message(FATAL_ERROR "Unable to find a default C++ compiler")
endif()
endif()

321
README.md
View file

@ -1,95 +1,42 @@
![Bareflank](https://github.com/Bareflank/hypervisor/raw/gh-pages/logo.png)
<br>
[![GitHub Version](https://badge.fury.io/gh/bareflank%2Fhypervisor.svg)](https://badge.fury.io/gh/bareflank%2Fhypervisor)
[![Build Status](https://travis-ci.org/Bareflank/hypervisor.svg?branch=master)](https://travis-ci.org/Bareflank/hypervisor)
[![Build Status](https://ci.appveyor.com/api/projects/status/r82c37nc634tnsv9/branch/master?svg=true)](https://ci.appveyor.com/project/rianquinn/hypervisor-13oyg/branch/master)
[![Codacy Status](https://api.codacy.com/project/badge/Grade/28ec616803cb4800a4b727b70a3b112f)](https://www.codacy.com/app/rianquinn/hypervisor?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=Bareflank/hypervisor&amp;utm_campaign=Badge_Grade)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/325/badge)](https://bestpractices.coreinfrastructure.org/projects/325)
[![Join the chat](https://img.shields.io/badge/chat-on%20Slack-brightgreen.svg)](https://bareflank.herokuapp.com/)
## Description
The Bareflank Hypervisor is an open source, hypervisor Software Development Toolkit (SDK), led by
Assured Information Security, Inc. (AIS), that provides a set of APIs needed to
rapidly prototype and create new hypervisors. To ease development, Bareflank
is written in C/C++, and includes support for C++ exceptions, JSON, the GSL and the C++ Standard
Template Library (STL).
The Bareflank Hypervisor is an open source hypervisor Software Development Toolkit (SDK), led by Assured Information Security, Inc. (AIS), that provides the tools needed to rapidly prototype and create your own hypervisor.
The Bareflank Hypervisor uses a layered, modular approach.
- [hypervisor](https://github.com/Bareflank/hypervisor): provides the base SDK, hypervisor
implementation, the build system, and architecture specific intrinsics.
- [boxy](https://github.com/Bareflank/boxy): leverages the Bareflank SDK to provide a
fully functional hypervisor with guest support.
Most people think that hypervisors are meant to virtualize servers and provide a means to run Windows on a Mac, but there is a whole field of research where hypervisors are used without guest virtual machines. Since a hypervisor is capable of controlling the host OS running underneath it (so-called "ring -1"), host-only hypervisors support introspection, reverse engineering, anti-virus, containerization, diversity, and even architectural research like [MoRE](https://github.com/ainfosec/MoRE). All of these use cases start the same way, by spending months standing up the hypervisor itself before you can start working on your actual project. Existing open source hypervisors are burdened with legacy support, only support a single operating system or contain unnecessary complexity that make them painful to work with when conducting hypervisor research.
To support Bareflank's design approach, the hypervisor is licensed
under MIT, specifically
enabling users of the project to both contribute back to the project, but
also create proprietary versions of the hypervisor if so desired.
Instead, Bareflank uses a layered, modular approach, that lets you pick just how much complexity you need in your project:
- [BSL](https://github.com/Bareflank/bsl): provides a header-only, AUTOSAR compliant implementation of a subset of the C++ Standard Library, used to implement Bareflank's C++ components ensuring Bareflank and projects built using Bareflank can support critical systems applications like Automotive.
- [LLVM](https://github.com/Bareflank/llvm-project): provides our custom implementation of the LLVM Clang compiler and associated tools including additional static analysis checks in Clang Tidy to ensure compliance with AUTOSAR.
- [PAL](https://github.com/Bareflank/pal): provides auto-generated intrinsics APIs for Intel, AMD and ARM on any combination of OS (e.g., Windows and Linux), ABI (e.g., SysV and MS64) and programming language (e.g., C, C++ and Python).
- [hypervisor](https://github.com/Bareflank/hypervisor): provides the base SDK including the loader, the Bareflank microkernel and support applications. If all you need is host-only hypervisor support, this is the project to start with.
- [MicroV](https://github.com/Bareflank/microv): provides support for guest VMs, allowing the user to create an execute additional virtual machines. If you need guest VM support, this is the project to start with.
In addition, the project comes complete with a set of unit tests to validate
that the provided SDK works as expected. Furthermore,
[Travis CI](https://travis-ci.org/Bareflank/hypervisor) has been set up to
test source code formatting via
[Astyle](http://astyle.sourceforge.net), and static / dynamic analysis
via
[Clang Tidy](http://clang.llvm.org/extra/clang-tidy/),
[Codacy](https://www.codacy.com),
and
[Google's Sanitizers](https://github.com/google/sanitizers). Finally, we adhere
to the
[CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/325),
the
[High Integrity C++ Guidelines](http://www.codingstandard.com/)
and the
[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
including support for the
[Guideline Support Library](https://github.com/Microsoft/GSL).
To support Bareflank's ecosystem, the hypervisor SDK is licensed under MIT, specifically enabling users of the project to both contribute back to the project, but also create proprietary, closed source products that use the Bareflank SDK as their foundation. Feel free to use Bareflank to create your commercial products. All we ask is that if you find a bug or add a feature to the SDK that you consider contributing your changes back to the project.
Currently, we have support for the following 64bit host operating systems on
Intel _Sandy Bridge_ and above hardware:
- Arch Linux
- Ubuntu 17.10+
- Windows 10
- Windows 7
- UEFI
## **Quick start**
In the future, we would also like to support:
- macOS
- BSD
- ARM64 (still under development)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/bareflank/hypervisor?color=brightgreen)
## Motivation
Get the latest version of the Bareflank Hypervisor SDK from GitHub:
Most people think that hypervisors are meant to virtualize servers and provide a means to run Windows on a Mac, but there is a whole field of research where hypervisors are used without guest virtual machines. Since a hypervisor is capable of controlling the host OS running underneath it (so-called "ring -1"), host-only hypervisors support introspection, reverse engineering, anti-virus, containerization, diversity, and even architectural research like [MoRE](https://github.com/ainfosec/MoRE). All of these use cases start the same way, by spending months standing up the hypervisor itself before you can start working on your actual project. Existing open source hypervisors are burdened with legacy support and unnecessary complexity that make them painful to work with when conducting hypervisor research.
``` bash
git clone https://github.com/bareflank/hypervisor
mkdir bsl/build && cd bsl/build
cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" ..
ninja
```
## Links
[Bareflank Hypervisor Website](http://bareflank.github.io/hypervisor/) <br>
[Bareflank Hypervisor API Documentation](http://bareflank.github.io/hypervisor/html/)
## Demo
Check out the latest demo for how to compile and use the Bareflank Hypervisor on Ubuntu 18.04:
[![Bareflank Demonstration Video](http://img.youtube.com/vi/fNLXxtdkhLg/maxresdefault.jpg)](https://www.youtube.com/watch?v=fNLXxtdkhLg)
## Additional Videos
Checkout our [YouTube Channel](https://www.youtube.com/channel/UCH-7Pw96K5V1RHAPn5-cmYA) for more great content as well as
the following videos at [CppCon](https://www.youtube.com/user/CppCon) below:
[![CppCon 2019](https://i.imgur.com/hjZg0pf.png)](https://www.youtube.com/watch?v=bKPN-CGhEC0)
[![CppCon 2017](https://i.imgur.com/nBFD6uA.png)](https://www.youtube.com/watch?v=KdJhQuycD78)
[![CppCon 2016](https://i.imgur.com/fwmlOiJ.png)](https://www.youtube.com/watch?v=uQSQy-7lveQ)
Enjoy:
```
ninja driver_quick
ninja start
ninja dump
```
## Interested In Working For AIS?
Check out our [Can You Hack It?®](https://www.canyouhackit.com) challenge
and test your skills! Submit your score to show us what youve got. We have
offices across the country and offer competitive pay and outstanding
benefits. Join a team that is not only committed to the future of cyberspace,
but to our employees success as well.
Check out our [Can You Hack It?®](https://www.canyouhackit.com) challenge and test your skills! Submit your score to show us what youve got. We have offices across the country and offer competitive pay and outstanding benefits. Join a team that is not only committed to the future of cyberspace, but to our employees success as well.
<p align="center">
<a href="https://www.ainfosec.com/">
@ -97,179 +44,117 @@ the following videos at [CppCon](https://www.youtube.com/user/CppCon) below:
</a>
</p>
## Dependencies
## Demo
Although Bareflank can be made to run on most systems, the following are the
supported platforms and their dependencies:
Check out the latest demo for how to compile and use the Bareflank Hypervisor on Ubuntu 20.04:
#### Arch Linux:
```
sudo pacman -S git base-devel linux-headers nasm clang cmake
## Additional Videos
Check out our [YouTube Channel](https://www.youtube.com/channel/UCH-7Pw96K5V1RHAPn5-cmYA) for more great content as well as
the following videos at [CppCon](https://www.youtube.com/user/CppCon) below:
[![CppCon 2019](https://i.imgur.com/hjZg0pf.png)](https://www.youtube.com/watch?v=bKPN-CGhEC0)
[![CppCon 2017](https://i.imgur.com/nBFD6uA.png)](https://www.youtube.com/watch?v=KdJhQuycD78)
[![CppCon 2016](https://i.imgur.com/fwmlOiJ.png)](https://www.youtube.com/watch?v=uQSQy-7lveQ)
## **Build Requirements**
Currently, the Bareflank hypervisor only supports the Clang/LLVM 11+ compiler. This, however, ensures the hypervisor can be natively compiled on Windows including support for cross-compiling. Support for other C++20 compilers can be added if needed, just let us know if that is something you need.
### **Windows**
To compile Bareflank on Windows, you must first install the following:
- [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=16) (Enable "Desktop development with C++")
- [LLVM 11+](https://github.com/llvm/llvm-project/releases)
- [CMake 3.16+](https://cmake.org/download/)
- [Ninja](https://github.com/ninja-build/ninja/releases)
Visual Studio is needed as it contains Windows specific libraries that are needed during compilation. Instead of using the Clang/LLVM project that natively ships with Visual Studio, we use the standard Clang/LLVM binaries provided by the LLVM project which ensures we get all of the tools including LLD, Clang Tidy and Clang Format. Also note that you must put Ninja somewhere
in your path (we usually drop into CMake's bin folder).
To compile use the following:
``` bash
git clone https://github.com/bareflank/hypervisor
mkdir hypervisor/build && cd hypervisor/build
cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON ..
ninja info
ninja
```
#### Ubuntu 17.10 (or Higher):
```
sudo apt-get install git build-essential linux-headers-$(uname -r) nasm clang cmake libelf-dev
### **Ubuntu Linux**
To compile Bareflank on Ubuntu, you must install the following:
- [LLVM 11+](https://apt.llvm.org/)
- [CMake 3.16+](https://cmake.org/download/)
Once you have the above setup, you can install all dependencies using the following command
```bash
sudo apt-get install -y clang-11 build-essential git ninja-build
```
#### Windows (Visual Studio):
- [Visual Studio 2019 / WDK 10](https://docs.microsoft.com/en-us/windows-hardware/drivers/)
- Check "Desktop development with C++"
- Check "C++ CLI / Support"
- Check "VC++ 2019 version xxx Libs for Spectre (x86 and x64)"
After installing the above packages, you must enable test signing mode. This can be done from a
command prompt with admin privileges:
You might also have to update your build environment to point to the new version of LLVM as follows:
```
bcdedit.exe /set testsigning ON
<reboot>
sudo update-alternatives --remove-all clang++
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-11 100
```
#### Windows (Cygwin):
- All of the Windows (Visual Studio) instructions
- [Cygwin](https://www.cygwin.com/setup-x86_64.exe)
To install Cygwin, simply install using all default settings, and then copy
setup-x86\_64.exe to C:\\cygwin64\\bin. From there, open a Cygwin terminal and
run the following:
To compile use the following:
``` bash
git clone https://github.com/bareflank/hypervisor
mkdir hypervisor/build && cd hypervisor/build
cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON ..
ninja info
ninja
```
setup-x86_64.exe -q -P git,make,gcc-core,gcc-g++,nasm,clang,clang++,cmake,python,gettext,bash-completion,flex,bison,texinfo
```
This build environment provides a complete toolchain for building and running Bareflank. Most
developers using Bareflank on Windows will need Cygwin for this reason. The remaining compilation
instructions follow below.
## Compilation Instructions
To compile with default settings for your host environment, run the following commands:
```
git clone https://github.com/bareflank/hypervisor.git
mkdir build; cd build
cmake ../hypervisor
make -j<# cores + 1>
```
For more detailed build instructions, see the
[detailed build instructions](scripts/docs/build_instructions.md).
For instructions on building and creating Bareflank extensions, see the
[extension build instructions](scripts/docs/extension_instructions.md)
## Usage Instructions
To use the hypervisor, run the following commands:
```
make driver_quick
make quick
ninja driver_quick
ninja start
```
to get status information, use the following:
to get debug information, use the following:
```
make status
make dump
ninja dump
```
to reverse this:
```
make unload
make driver_unload
```
to clean up:
```
make distclean
```
## Example Extensions
As stated above, the Bareflank Hypervisor is an SDK to create your own, more complicated
hypervisors. One example of an extension is the [boxy](https://github.com/Bareflank/boxy)
hypervisor, which provides support for Linux based guest virtual machines. There are
several other examples in our [examples](https://github.com/Bareflank/hypervisor/tree/master/examples)
folder.
To use one of these examples, you must tell the build system which Virtual Machine
Monitor (VMM) you wish to use. By default, the build system will use "bfvmm", but
you can override this by defining DEFAULT_VMM variable when running cmake. Each
example has its own VMM target. For example, the CPUID count example's VMM is
"example_cpuidcount_vmm" which can be seen in the following
[CMakeLists.txt](https://github.com/Bareflank/hypervisor/blob/master/examples/cpuidcount/CMakeLists.txt)
file. So for example, to compile Bareflank and test out the CPUID count example,
you would configure Bareflank using the following:
```
cmake -DDEFAULT_VMM=example_cpuidcount_vmm ..
ninja stop
ninja driver_unload
```
In addition to setting the DEFAULT_VMM, if you are using the
[example_config.cmake](https://github.com/Bareflank/hypervisor/blob/master/scripts/cmake/config/example_config.cmake)
config file you would set the OVERRIDE_VMM variable which will set the DEFAULT_VMM for you.
## **Resources**
Finally, if you are creating your own out-of-tree extension, you must tell the build system
where your extension is located so that it can include it when building the hypervisor.
To do this, you must define the EXTENSION variable. So for example, if you are creating your
own extension, with your own VMM target, you would use the following when configuring
cmake:
[![Join the chat](https://img.shields.io/badge/chat-on%20Slack-brightgreen.svg)](https://bareflank.herokuapp.com/)
```
cmake -DDEFAULT_VMM=<vmm target name> -DEXTENSION=<path to extension> ..
```
The Bareflank Support Library provides a ton of useful resources to learn how to use the library including:
## UEFI:
A UEFI application version of Bareflank may be compiled on Linux and used to boot
both Linux and Windows The following
describes how to build and execute Bareflank with EFI. For additional information,
please see the following YouTube [video](https://www.youtube.com/watch?v=FuEyjDqA53M&t=4s)
- **Documentation**: <https://bareflank.github.io/hypervisor/>
- **Examples**: <https://github.com/Bareflank/hypervisor/tree/master/examples>
- **Unit Tests**: <https://github.com/Bareflank/hypervisor/tree/master/tests>
To compile for UEFI, add the following to CMake when configuring:
```
-DENABLE_BUILD_EFI=ON
```
It should be noted that unit tests must be disabled, and static builds are currently
required (the example config provides an example of how to configure Bareflank as
needed for more complex builds).
If you have any questions, bugs, or feature requests, please feel free to ask on any of the following:
To boot Windows or Linux you will need to provide your own
extension that enables EPT. To see an example of this type of extension, please
see the following integration test:
```
https://github.com/Bareflank/hypervisor/blob/master/bfvmm/integration/arch/intel_x64/efi/test_efi.cpp
```
Once you have your own extension, the example config is required to tell the build
system which VMM and target to use. The example config can be found here:
```
https://github.com/Bareflank/hypervisor/blob/master/scripts/cmake/config/example_config.cmake
```
Our front page video on YouTube explains how to use this config, and the instructions
are also in the config itself. To enable EFI, turn on the EFI
flag. You will also need to set the following:
```
set(OVERRIDE_VMM <name>)
set(OVERRIDE_VMM_TARGET <name>)
```
If for example, you are using the integration test listed above, these setting would
be as follows:
```
set(OVERRIDE_VMM integration_intel_x64_efi_test_efi)
set(OVERRIDE_VMM_TARGET integration)
```
The first variable defines the VMM's name and the second variable defines the target
that builds this VMM (which tells the build system what dependency EFI has). From
there build as normal.
- **Slack**: <https://bareflank.herokuapp.com/>
- **Issue Tracker**: <https://github.com/Bareflank/hypervisor/issues>
The resulting UEFI application can be found here:
```
build/prefixes/x86_64-efi-pe/bin/bareflank.efi
```
Place this binary in your EFI partition (e.g., on Ubuntu this is
/boot/efi/EFI/BOOT/bareflank.efi) and execute it like any other EFI application.
Once Bareflank is running, you can start Windows or Linux if you included the
above. Also note that utilities like "make dump" do not work when using EFI as
the driver doesn't have access to the debug ring. You can, however, use
"make ack" to get the hypervisor to say "hi".
And as always, we are always looking for more help:
- **Pull Requests**: <https://github.com/Bareflank/hypervisor/pulls>
- **Contributing Guidelines**: <https://github.com/Bareflank/hypervisor/blob/master/contributing.md>
## **Testing**
The Bareflank hypervisor leverages the following tools to ensure the highest possible code quality. Each pull request undergoes the following rigorous testing and review:
- **Static Analysis:** [Clang Tidy](https://github.com/Bareflank/llvm-project)
- **Dynamic Analysis:** Google's ASAN and UBSAN
- **Code Coverage:** Code Coverage with CodeCov
- **Coding Standards**: [AUTOSAR C++14](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/17-03/AUTOSAR_RS_CPP14Guidelines.pdf) and [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
- **Style**: Clang Format
- **Documentation**: Doxygen
## Serial Instructions

0
SUPPORT.md Normal file
View file

33
Vagrantfile vendored
View file

@ -1,33 +0,0 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
Vagrant.configure(2) do |config|
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
end
config.vm.define "ubuntu17_10", primary: true do |ubuntu17_10|
ubuntu17_10.vm.box = "ubuntu/artful64"
ubuntu17_10.vm.provision "shell",
path: "scripts/vagrant/provision_ubuntu17_10.sh"
end
end

View file

@ -1,33 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bfack.h>
#include <iostream>
int main()
{
if (bfack() != 0) {
std::clog << "ack: success" << '\n';
}
else {
std::clog << "ack: failure" << '\n';
}
}

View file

@ -1,109 +0,0 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.13)
project(bfdriver C CXX)
init_project(bfdriver INTERFACE)
target_link_libraries(bfdriver INTERFACE ${PREFIX}::bfroot)
# ------------------------------------------------------------------------------
# Generator expressions
# ------------------------------------------------------------------------------
set(C $<COMPILE_LANGUAGE:C>)
set(CXX $<COMPILE_LANGUAGE:CXX>)
set(BUILD $<BOOL:$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>>)
set(BUILD_INCLUDE $<AND:$<OR:${C},${CXX}>,${BUILD}>)
set(BUILD_INCLUDE_CXX $<AND:${CXX},${BUILD}>)
# ------------------------------------------------------------------------------
# EFI
# ------------------------------------------------------------------------------
if(${PREFIX} STREQUAL efi)
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/vmm.h
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${BFM_VMM_BIN_PATH}/${BFM_VMM} vmm
COMMAND xxd
ARGS -i vmm > ${CMAKE_BINARY_DIR}/vmm.h
DEPENDS ${BFM_VMM_BIN_PATH}/${BFM_VMM}
COMMENT " EFI VMM: ${BFM_VMM_BIN_PATH}/${BFM_VMM}"
)
add_custom_target(
bareflank_xxd
DEPENDS ${CMAKE_BINARY_DIR}/vmm.h
)
add_library(bareflank SHARED)
add_dependencies(bareflank bareflank_xxd)
target_link_libraries(bareflank PRIVATE bfdriver)
target_include_directories(bareflank PRIVATE
$<${BUILD_INCLUDE}:${CMAKE_CURRENT_LIST_DIR}/include>
$<${BUILD_INCLUDE}:${CMAKE_CURRENT_LIST_DIR}/../bfsdk/include>
$<${BUILD_INCLUDE}:${CMAKE_CURRENT_LIST_DIR}/../bfelf_loader/include>
$<${BUILD_INCLUDE}:${CMAKE_BINARY_DIR}>
)
target_sources(bareflank PRIVATE
src/platform/efi/entry.c
src/platform/efi/platform.c
src/platform/efi/platform.asm
src/common.c
${EFI_EXTENSION_SOURCES}
)
add_custom_command(
TARGET bareflank
POST_BUILD
COMMAND ${CMAKE_OBJCOPY}
ARGS -j .text -j .sdata -j .data -j .dynamic -j .dynsym
ARGS -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc
ARGS --target efi-app-${BUILD_TARGET_ARCH} libbareflank.so ${CMAKE_BINARY_DIR}/bareflank.efi
)
install(FILES ${CMAKE_BINARY_DIR}/bareflank.efi DESTINATION bin)
endif()
# ------------------------------------------------------------------------------
# Test
# ------------------------------------------------------------------------------
if(${PREFIX} STREQUAL test)
target_include_directories(bfdriver INTERFACE
$<${BUILD_INCLUDE}:${CMAKE_CURRENT_LIST_DIR}/include>
$<${BUILD_INCLUDE}:${CMAKE_CURRENT_LIST_DIR}/../bfsdk/include>
$<${BUILD_INCLUDE}:${CMAKE_CURRENT_LIST_DIR}/../bfelf_loader/include>
)
target_compile_definitions(bfdriver INTERFACE
$<${BUILD_INCLUDE_CXX}:VMM_PREFIX_PATH=\"${VMM_PREFIX_PATH}\">
)
add_library(support)
target_link_libraries(support PRIVATE bfdriver)
target_sources(support PRIVATE
tests/test_support.cpp
src/common.c
src/platform/test/platform.c
)
endif()
fini_project()

View file

@ -1,179 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef COMMON_H
#define COMMON_H
#include <bftypes.h>
#include <bferrorcodes.h>
#include <bfelf_loader.h>
#include <bfdebugringinterface.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* VMM Status
*
* @return returns the current status of the VMM.
*/
int64_t
common_vmm_status(void);
/**
* Reset
*
* This function should not be called directly. Instead, use common_unload.
* This is only exposed publically for unit testing.
*/
void
common_reset(void);
/**
* Initialize Driver Entry
*
* This code should be run as part of the driver entry's init code. This
* sets up some resources that are needed throughout the lifetime of the
* driver entry.
*/
int64_t
common_init(void);
/**
* Finalize Driver Entry
*
* This code should be run as part of the driver entry's fini code. This
* cleans up some resources that were needed throughout the lifetime of the
* driver entry.
*
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_fini(void);
/**
* Add Module
*
* Add's a module into memory to be executed once start_vmm is run. This
* function uses the platform functions to allocate memory for the executable.
* The file that is provided should not be removed until after stop_vmm is
* run. Removing the file from memory could cause a crash, as the start_vmm
* function uses the file that is being added to search for symbols that are
* needed, as well as the stop_vmm function. Once stop_vmm is run, it's safe
* to remove the files. Also, this function cannot be run if the vmm has
* already been started.
*
* @param file the file to add to memory
* @param fsize the size of the file in bytes
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_add_module(const char *file, uint64_t fsize);
/**
* Load VMM
*
* This function loads the vmm (assuming that the modules that were
* loaded are actually a vmm). Once a VMM is loaded, it is placed in memory,
* and all of the modules are properly reloacted such that, code within each
* module is now capable of executing.
*
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_load_vmm(void);
/**
* Unload VMM
*
* This function unloads the vmm. Once the VMM is unloaded, all of the symbols
* for the VMM are removed from memory, and are no longer accessible. The VMM
* cannot be unloaded unless the VMM is already loaded, but is not running.
*
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_unload_vmm(void);
/**
* Start VMM
*
* This function starts the vmm. Before the VMM can be started, it must first
* be loaded.
*
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_start_vmm(void);
/**
* Stop VMM
*
* This function stops the vmm. Before a VMM can be stopped, it must first be
* loaded, and running.
*
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_stop_vmm(void);
/**
* Dump VMM
*
* This grabs the conents of the debug ring, and dumps the contents to the
* driver entry's console. This is one of a couple of ways to get feedback
* from the VMM. Note that the VMM must at least be loaded for this function
* to work as it has to do a symbol lookup
*
* @param drr a pointer to the drr provided by the user
* @param vcpuid indicates which drr to get as each vcpu has its own drr
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_dump_vmm(struct debug_ring_resources_t **drr, uint64_t vcpuid);
/**
* Call VMM
*
* Executes the VMM. The VMM has a single entry point, with a switch statement
* that executes the provided "request". When this occurs, arg1 and arg2 are
* provided to the requested function. Note that the first arg takes a cpuid,
* which is the core number you are currently executing on. This is needed
* because this function needs to set up the proper stack before executing
* the VMM, and it needs to know which core you are on to use the proper stack
* which in turn also executes with the proper TLS region.
*
* @param cpuid the core id this code is currently being executed on
* @param request the requested function in the VMM to execute
* @param arg1 arg #1
* @param arg2 arg #2
* @return BF_SUCCESS on success, negative error code on failure
*/
int64_t
common_call_vmm(uint64_t cpuid, uint64_t request, uintptr_t arg1, uintptr_t arg2);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,524 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <common.h>
#include <bftypes.h>
#include <bfdebug.h>
#include <bfmemory.h>
#include <bfplatform.h>
#include <bfconstants.h>
#include <bfthreadcontext.h>
#include <bfdriverinterface.h>
/* -------------------------------------------------------------------------- */
/* Global */
/* -------------------------------------------------------------------------- */
int64_t g_num_modules = 0;
struct bfelf_binary_t g_modules[MAX_NUM_MODULES];
_start_t _start_func = 0;
struct crt_info_t g_info;
struct bfelf_loader_t g_loader;
int64_t g_num_cpus_started = 0;
int64_t g_vmm_status = VMM_UNLOADED;
void *g_tls = 0;
void *g_stack = 0;
uint64_t g_tls_size = 0;
uint64_t g_stack_size = 0;
uint64_t g_stack_top = 0;
void *g_rsdp = 0;
/* -------------------------------------------------------------------------- */
/* Helpers */
/* -------------------------------------------------------------------------- */
int64_t
private_setup_stack(void)
{
g_stack_size = STACK_SIZE * 2;
g_stack = platform_alloc_rw(g_stack_size);
if (g_stack == 0) {
return BF_ERROR_OUT_OF_MEMORY;
}
g_stack_top = (uint64_t)g_stack + g_stack_size;
g_stack_top = (g_stack_top & ~(STACK_SIZE - 1)) - 1;
platform_memset(g_stack, 0, g_stack_size);
return BF_SUCCESS;
}
int64_t
private_setup_tls(void)
{
g_tls_size = THREAD_LOCAL_STORAGE_SIZE * (uint64_t)platform_num_cpus();
g_tls = platform_alloc_rw(g_tls_size);
if (g_tls == 0) {
return BF_ERROR_OUT_OF_MEMORY;
}
platform_memset(g_tls, 0, g_tls_size);
return BF_SUCCESS;
}
int64_t
private_setup_rsdp(void)
{
g_rsdp = platform_get_rsdp();
return BF_SUCCESS;
}
int64_t
private_add_raw_md_to_memory_manager(uint64_t virt, uint64_t type)
{
int64_t ret = 0;
struct memory_descriptor md = {0, 0, 0};
md.virt = virt;
md.phys = (uint64_t)platform_virt_to_phys((void *)md.virt);
md.type = type;
ret = platform_call_vmm_on_core(
0, BF_REQUEST_ADD_MDL, (uintptr_t)&md, 0);
if (ret != MEMORY_MANAGER_SUCCESS) {
return ret;
}
return BF_SUCCESS;
}
int64_t
private_add_md_to_memory_manager(struct bfelf_binary_t *module)
{
bfelf64_word s = 0;
for (s = 0; s < bfelf_file_get_num_load_instrs(&module->ef); s++) {
int64_t ret = 0;
uint64_t exec_s = 0;
uint64_t exec_e = 0;
const struct bfelf_load_instr *instr = 0;
ret = bfelf_file_get_load_instr(&module->ef, s, &instr);
bfignored(ret);
exec_s = (uint64_t)module->exec + instr->mem_offset;
exec_e = (uint64_t)module->exec + instr->mem_offset + instr->memsz;
exec_s &= ~(BAREFLANK_PAGE_SIZE - 1);
exec_e &= ~(BAREFLANK_PAGE_SIZE - 1);
for (; exec_s <= exec_e; exec_s += BAREFLANK_PAGE_SIZE) {
if ((instr->perm & bfpf_x) != 0) {
ret = private_add_raw_md_to_memory_manager(
exec_s, MEMORY_TYPE_R | MEMORY_TYPE_E);
}
else {
ret = private_add_raw_md_to_memory_manager(
exec_s, MEMORY_TYPE_R | MEMORY_TYPE_W);
}
if (ret != MEMORY_MANAGER_SUCCESS) {
return ret;
}
}
}
return BF_SUCCESS;
}
int64_t
private_add_tss_mdl(void)
{
uint64_t i = 0;
for (i = 0; i < g_tls_size; i += BAREFLANK_PAGE_SIZE) {
int64_t ret = private_add_raw_md_to_memory_manager(
(uint64_t)g_tls + i, MEMORY_TYPE_R | MEMORY_TYPE_W);
if (ret != BF_SUCCESS) {
return ret;
}
}
return BF_SUCCESS;
}
int64_t
private_add_modules_mdl(void)
{
int64_t i = 0;
for (i = 0; i < g_num_modules; i++) {
int64_t ret = private_add_md_to_memory_manager(&g_modules[i]);
if (ret != BF_SUCCESS) {
return ret;
}
}
return BF_SUCCESS;
}
/* -------------------------------------------------------------------------- */
/* Implementation */
/* -------------------------------------------------------------------------- */
int64_t
common_vmm_status(void)
{ return g_vmm_status; }
void
common_reset(void)
{
int64_t i;
for (i = 0; i < g_num_modules; i++) {
if (g_modules[i].exec != 0) {
platform_free_rwe(g_modules[i].exec, g_modules[i].exec_size);
}
}
platform_memset(&g_modules, 0, sizeof(g_modules));
platform_memset(&g_loader, 0, sizeof(struct bfelf_loader_t));
platform_memset(&g_info, 0, sizeof(struct crt_info_t));
platform_memset(&g_loader, 0, sizeof(struct bfelf_loader_t));
_start_func = 0;
g_num_modules = 0;
g_num_cpus_started = 0;
g_vmm_status = VMM_UNLOADED;
if (g_tls != 0) {
platform_free_rw(g_tls, g_tls_size);
}
if (g_stack != 0) {
platform_free_rw(g_stack, g_stack_size);
}
g_tls = 0;
g_stack = 0;
g_stack_top = 0;
g_rsdp = 0;
}
int64_t
common_init(void)
{
int64_t ret = platform_init();
if (ret != BF_SUCCESS) {
return ret;
}
common_reset();
return BF_SUCCESS;
}
int64_t
common_fini(void)
{
if (common_vmm_status() == VMM_RUNNING) {
if (common_stop_vmm() != BF_SUCCESS) {
BFALERT("common_fini: failed to stop vmm\n");
}
}
if (common_vmm_status() == VMM_LOADED) {
if (common_unload_vmm() != BF_SUCCESS) {
BFALERT("common_fini: failed to unload vmm\n");
}
}
if (common_vmm_status() == VMM_CORRUPT) {
return BF_ERROR_VMM_CORRUPTED;
}
if (g_num_modules > 0) {
common_reset();
}
return BF_SUCCESS;
}
int64_t
common_add_module(const char *file, uint64_t fsize)
{
if (file == 0 || fsize == 0) {
return BF_ERROR_INVALID_ARG;
}
switch (common_vmm_status()) {
case VMM_CORRUPT:
return BF_ERROR_VMM_CORRUPTED;
case VMM_LOADED:
return BF_ERROR_VMM_INVALID_STATE;
case VMM_RUNNING:
return BF_ERROR_VMM_INVALID_STATE;
default:
break;
}
if (g_num_modules >= MAX_NUM_MODULES) {
return BF_ERROR_MAX_MODULES_REACHED;
}
g_modules[g_num_modules].file = file;
g_modules[g_num_modules].file_size = fsize;
g_num_modules++;
return BF_SUCCESS;
}
int64_t
common_load_vmm(void)
{
int64_t ret = 0;
int64_t ignore_ret = 0;
switch (common_vmm_status()) {
case VMM_CORRUPT:
return BF_ERROR_VMM_CORRUPTED;
case VMM_LOADED:
return BF_SUCCESS;
case VMM_RUNNING:
return BF_ERROR_VMM_INVALID_STATE;
default:
break;
}
if (g_num_modules == 0) {
return BF_ERROR_NO_MODULES_ADDED;
}
ret = private_setup_stack();
if (ret != BF_SUCCESS) {
goto failure;
}
ret = private_setup_tls();
if (ret != BF_SUCCESS) {
goto failure;
}
ret = private_setup_rsdp();
if (ret != BF_SUCCESS) {
goto failure;
}
ret = bfelf_load(g_modules, (uint64_t)g_num_modules, (void **)&_start_func, &g_info, &g_loader);
if (ret != BF_SUCCESS) {
goto failure;
}
ret = platform_call_vmm_on_core(0, BF_REQUEST_INIT, 0, 0);
if (ret != BF_SUCCESS) {
goto failure;
}
ret = platform_call_vmm_on_core(0, BF_REQUEST_SET_RSDP, (uint64_t)g_rsdp, 0);
if (ret != BF_SUCCESS) {
goto failure;
}
ret = private_add_modules_mdl();
if (ret != BF_SUCCESS) {
goto failure;
}
ret = private_add_tss_mdl();
if (ret != BF_SUCCESS) {
goto failure;
}
g_vmm_status = VMM_LOADED;
return BF_SUCCESS;
failure:
ignore_ret = common_unload_vmm();
bfignored(ignore_ret);
return ret;
}
int64_t
common_unload_vmm(void)
{
int64_t ret = 0;
switch (common_vmm_status()) {
case VMM_CORRUPT:
return BF_ERROR_VMM_CORRUPTED;
case VMM_RUNNING:
return BF_ERROR_VMM_INVALID_STATE;
case VMM_UNLOADED:
goto unloaded;
default:
break;
}
ret = platform_call_vmm_on_core(0, BF_REQUEST_FINI, 0, 0);
if (ret != BF_SUCCESS) {
goto corrupted;
}
unloaded:
common_reset();
g_vmm_status = VMM_UNLOADED;
return BF_SUCCESS;
corrupted:
g_vmm_status = VMM_CORRUPT;
return ret;
}
int64_t
common_start_vmm(void)
{
int64_t ret = 0;
int64_t cpuid = 0;
int64_t ignore_ret = 0;
switch (common_vmm_status()) {
case VMM_CORRUPT:
return BF_ERROR_VMM_CORRUPTED;
case VMM_RUNNING:
return BF_SUCCESS;
case VMM_UNLOADED:
return BF_ERROR_VMM_INVALID_STATE;
default:
break;
}
for (cpuid = 0, g_num_cpus_started = 0; cpuid < platform_num_cpus(); cpuid++) {
ret = platform_call_vmm_on_core(
(uint64_t)cpuid, BF_REQUEST_VMM_INIT, (uint64_t)cpuid, 0);
if (ret != BF_SUCCESS) {
goto failure;
}
g_num_cpus_started++;
}
g_vmm_status = VMM_RUNNING;
return BF_SUCCESS;
failure:
ignore_ret = common_stop_vmm();
bfignored(ignore_ret);
return ret;
}
int64_t
common_stop_vmm(void)
{
int64_t ret = 0;
int64_t cpuid = 0;
switch (common_vmm_status()) {
case VMM_CORRUPT:
return BF_ERROR_VMM_CORRUPTED;
case VMM_UNLOADED:
return BF_ERROR_VMM_INVALID_STATE;
default:
break;
}
for (cpuid = g_num_cpus_started - 1; cpuid >= 0 ; cpuid--) {
ret = platform_call_vmm_on_core(
(uint64_t)cpuid, BF_REQUEST_VMM_FINI, (uint64_t)cpuid, 0);
if (ret != BFELF_SUCCESS) {
goto corrupted;
}
g_num_cpus_started--;
}
g_vmm_status = VMM_LOADED;
return BF_SUCCESS;
corrupted:
g_vmm_status = VMM_CORRUPT;
return ret;
}
int64_t
common_dump_vmm(struct debug_ring_resources_t **drr, uint64_t vcpuid)
{
int64_t ret = 0;
if (drr == 0) {
return BF_ERROR_INVALID_ARG;
}
if (common_vmm_status() == VMM_UNLOADED) {
return BF_ERROR_VMM_INVALID_STATE;
}
ret = platform_call_vmm_on_core(
0, BF_REQUEST_GET_DRR, (uint64_t)vcpuid, (uint64_t)drr);
if (ret != BFELF_SUCCESS) {
return ret;
}
return BF_SUCCESS;
}
typedef struct thread_context_t tc_t;
int64_t
common_call_vmm(
uint64_t cpuid, uint64_t request, uintptr_t arg1, uintptr_t arg2)
{
int64_t ignored_ret = 0;
tc_t *tc = (tc_t *)(g_stack_top - sizeof(tc_t));
ignored_ret = bfelf_set_integer_args(&g_info, request, arg1, arg2, 0);
bfignored(ignored_ret);
tc->cpuid = cpuid;
tc->tlsptr = (uint64_t *)((uint64_t)g_tls + (THREAD_LOCAL_STORAGE_SIZE * (uint64_t)cpuid));
return _start_func((void *)(g_stack_top - sizeof(tc_t) - 1), &g_info);
}

View file

@ -1,626 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// This file describes the EFI MP Services Protocol. This protocol is not mentioned in the base
// EFI specification (2.6), but an exceedingly similar protocol is described in the EFI platform
// initialization specification (http://www.uefi.org/sites/default/files/resources/PI_Spec_1_6.pdf)
#ifndef _MP_SERVICE_PROTOCOL_H_
#define _MP_SERVICE_PROTOCOL_H_
///
/// Global ID for the EFI_MP_SERVICES_PROTOCOL.
///
#define EFI_MP_SERVICES_PROTOCOL_GUID \
{ \
0x3fdda605, 0xa76e, 0x4f46, {0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08} \
}
///
/// Forward declaration for the EFI_MP_SERVICES_PROTOCOL.
///
typedef struct _EFI_MP_SERVICES_PROTOCOL EFI_MP_SERVICES_PROTOCOL;
///
/// Terminator for a list of failed CPUs returned by StartAllAPs().
///
#define END_OF_CPU_LIST 0xffffffff
///
/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and
/// indicates whether the processor is playing the role of BSP. If the bit is 1,
/// then the processor is BSP. Otherwise, it is AP.
///
#define PROCESSOR_AS_BSP_BIT 0x00000001
///
/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and
/// indicates whether the processor is enabled. If the bit is 1, then the
/// processor is enabled. Otherwise, it is disabled.
///
#define PROCESSOR_ENABLED_BIT 0x00000002
///
/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and
/// indicates whether the processor is healthy. If the bit is 1, then the
/// processor is healthy. Otherwise, some fault has been detected for the processor.
///
#define PROCESSOR_HEALTH_STATUS_BIT 0x00000004
///
/// Structure that describes the pyhiscal location of a logical CPU.
///
typedef struct {
///
/// Zero-based physical package number that identifies the cartridge of the processor.
///
UINT32 Package;
///
/// Zero-based physical core number within package of the processor.
///
UINT32 Core;
///
/// Zero-based logical thread number within core of the processor.
///
UINT32 Thread;
} EFI_CPU_PHYSICAL_LOCATION;
///
/// Structure that describes information about a logical CPU.
///
typedef struct {
///
/// The unique processor ID determined by system hardware. For IA32 and X64,
/// the processor ID is the same as the Local APIC ID. Only the lower 8 bits
/// are used, and higher bits are reserved. For IPF, the lower 16 bits contains
/// id/eid, and higher bits are reserved.
///
UINT64 ProcessorId;
///
/// Flags indicating if the processor is BSP or AP, if the processor is enabled
/// or disabled, and if the processor is healthy. Bits 3..31 are reserved and
/// must be 0.
///
/// <pre>
/// BSP ENABLED HEALTH Description
/// === ======= ====== ===================================================
/// 0 0 0 Unhealthy Disabled AP.
/// 0 0 1 Healthy Disabled AP.
/// 0 1 0 Unhealthy Enabled AP.
/// 0 1 1 Healthy Enabled AP.
/// 1 0 0 Invalid. The BSP can never be in the disabled state.
/// 1 0 1 Invalid. The BSP can never be in the disabled state.
/// 1 1 0 Unhealthy Enabled BSP.
/// 1 1 1 Healthy Enabled BSP.
/// </pre>
///
UINT32 StatusFlag;
///
/// The physical location of the processor, including the physical package number
/// that identifies the cartridge, the physical core number within package, and
/// logical thread number within core.
///
EFI_CPU_PHYSICAL_LOCATION Location;
} EFI_PROCESSOR_INFORMATION;
/**
The function prototype for invoking a function on an Application Processor.
This definition is used by the UEFI MP Serices Protocol, and the
PI SMM System Table.
@param[in,out] Buffer The pointer to private data buffer.
**/
typedef
VOID
(EFIAPI *EFI_AP_PROCEDURE)(
IN OUT VOID *Buffer
);
/**
This service retrieves the number of logical processor in the platform
and the number of those logical processors that are enabled on this boot.
This service may only be called from the BSP.
This function is used to retrieve the following information:
- The number of logical processors that are present in the system.
- The number of enabled logical processors in the system at the instant
this call is made.
Because MP Service Protocol provides services to enable and disable processors
dynamically, the number of enabled logical processors may vary during the
course of a boot session.
If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
is returned in NumberOfProcessors, the number of currently enabled processor
is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
instance.
@param[out] NumberOfProcessors Pointer to the total number of logical
processors in the system, including the BSP
and disabled APs.
@param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical
processors that exist in system, including
the BSP.
@retval EFI_SUCCESS The number of logical processors and enabled
logical processors was retrieved.
@retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
@retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS)(
IN EFI_MP_SERVICES_PROTOCOL *This,
OUT UINTN *NumberOfProcessors,
OUT UINTN *NumberOfEnabledProcessors
);
/**
Gets detailed MP-related information on the requested processor at the
instant this call is made. This service may only be called from the BSP.
This service retrieves detailed MP-related information about any processor
on the platform. Note the following:
- The processor information may change during the course of a boot session.
- The information presented here is entirely MP related.
Information regarding the number of caches and their sizes, frequency of operation,
slot numbers is all considered platform-related information and is not provided
by this service.
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
instance.
@param[in] ProcessorNumber The handle number of processor.
@param[out] ProcessorInfoBuffer A pointer to the buffer where information for
the requested processor is deposited.
@retval EFI_SUCCESS Processor information was returned.
@retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
@retval EFI_NOT_FOUND The processor with the handle specified by
ProcessorNumber does not exist in the platform.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_GET_PROCESSOR_INFO)(
IN EFI_MP_SERVICES_PROTOCOL *This,
IN UINTN ProcessorNumber,
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
);
/**
This service executes a caller provided function on all enabled APs. APs can
run either simultaneously or one at a time in sequence. This service supports
both blocking and non-blocking requests. The non-blocking requests use EFI
events so the BSP can detect when the APs have finished. This service may only
be called from the BSP.
This function is used to dispatch all the enabled APs to the function specified
by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
immediately and Procedure is not started on any AP.
If SingleThread is TRUE, all the enabled APs execute the function specified by
Procedure one by one, in ascending order of processor handle number. Otherwise,
all the enabled APs execute the function specified by Procedure simultaneously.
If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all
APs finish or TimeoutInMicroSecs expires. Otherwise, execution is in non-blocking
mode, and the BSP returns from this service without waiting for APs. If a
non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
is signaled, then EFI_UNSUPPORTED must be returned.
If the timeout specified by TimeoutInMicroseconds expires before all APs return
from Procedure, then Procedure on the failed APs is terminated. All enabled APs
are always available for further calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
and EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its
content points to the list of processor handle numbers in which Procedure was
terminated.
Note: It is the responsibility of the consumer of the EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
to make sure that the nature of the code that is executed on the BSP and the
dispatched APs is well controlled. The MP Services Protocol does not guarantee
that the Procedure function is MP-safe. Hence, the tasks that can be run in
parallel are limited to certain independent tasks and well-controlled exclusive
code. EFI services and protocols may not be called by APs unless otherwise
specified.
In blocking execution mode, BSP waits until all APs finish or
TimeoutInMicroSeconds expires.
In non-blocking execution mode, BSP is freed to return to the caller and then
proceed to the next task without having to wait for APs. The following
sequence needs to occur in a non-blocking execution mode:
-# The caller that intends to use this MP Services Protocol in non-blocking
mode creates WaitEvent by calling the EFI CreateEvent() service. The caller
invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent
is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests
the function specified by Procedure to be started on all the enabled APs,
and releases the BSP to continue with other tasks.
-# The caller can use the CheckEvent() and WaitForEvent() services to check
the state of the WaitEvent created in step 1.
-# When the APs complete their task or TimeoutInMicroSecondss expires, the MP
Service signals WaitEvent by calling the EFI SignalEvent() function. If
FailedCpuList is not NULL, its content is available when WaitEvent is
signaled. If all APs returned from Procedure prior to the timeout, then
FailedCpuList is set to NULL. If not all APs return from Procedure before
the timeout, then FailedCpuList is filled in with the list of the failed
APs. The buffer is allocated by MP Service Protocol using AllocatePool().
It is the caller's responsibility to free the buffer with FreePool() service.
-# This invocation of SignalEvent() function informs the caller that invoked
EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed
the specified task or a timeout occurred. The contents of FailedCpuList
can be examined to determine which APs did not complete the specified task
prior to the timeout.
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
instance.
@param[in] Procedure A pointer to the function to be run on
enabled APs of the system. See type
EFI_AP_PROCEDURE.
@param[in] SingleThread If TRUE, then all the enabled APs execute
the function specified by Procedure one by
one, in ascending order of processor handle
number. If FALSE, then all the enabled APs
execute the function specified by Procedure
simultaneously.
@param[in] WaitEvent The event created by the caller with CreateEvent()
service. If it is NULL, then execute in
blocking mode. BSP waits until all APs finish
or TimeoutInMicroSeconds expires. If it's
not NULL, then execute in non-blocking mode.
BSP requests the function specified by
Procedure to be started on all the enabled
APs, and go on executing immediately. If
all return from Procedure, or TimeoutInMicroSeconds
expires, this event is signaled. The BSP
can use the CheckEvent() or WaitForEvent()
services to check the state of event. Type
EFI_EVENT is defined in CreateEvent() in
the Unified Extensible Firmware Interface
Specification.
@param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for
APs to return from Procedure, either for
blocking or non-blocking mode. Zero means
infinity. If the timeout expires before
all APs return from Procedure, then Procedure
on the failed APs is terminated. All enabled
APs are available for next function assigned
by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
If the timeout expires in blocking mode,
BSP returns EFI_TIMEOUT. If the timeout
expires in non-blocking mode, WaitEvent
is signaled with SignalEvent().
@param[in] ProcedureArgument The parameter passed into Procedure for
all APs.
@param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,
if all APs finish successfully, then its
content is set to NULL. If not all APs
finish before timeout expires, then its
content is set to address of the buffer
holding handle numbers of the failed APs.
The buffer is allocated by MP Service Protocol,
and it's the caller's responsibility to
free the buffer with FreePool() service.
In blocking mode, it is ready for consumption
when the call returns. In non-blocking mode,
it is ready when WaitEvent is signaled. The
list of failed CPU is terminated by
END_OF_CPU_LIST.
@retval EFI_SUCCESS In blocking mode, all APs have finished before
the timeout expired.
@retval EFI_SUCCESS In non-blocking mode, function has been dispatched
to all enabled APs.
@retval EFI_UNSUPPORTED A non-blocking mode request was made after the
UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
signaled.
@retval EFI_DEVICE_ERROR Caller processor is AP.
@retval EFI_NOT_STARTED No enabled APs exist in the system.
@retval EFI_NOT_READY Any enabled APs are busy.
@retval EFI_TIMEOUT In blocking mode, the timeout expired before
all enabled APs have finished.
@retval EFI_INVALID_PARAMETER Procedure is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_STARTUP_ALL_APS)(
IN EFI_MP_SERVICES_PROTOCOL *This,
IN EFI_AP_PROCEDURE Procedure,
IN BOOLEAN SingleThread,
IN EFI_EVENT WaitEvent OPTIONAL,
IN UINTN TimeoutInMicroSeconds,
IN VOID *ProcedureArgument OPTIONAL,
OUT UINTN **FailedCpuList OPTIONAL
);
/**
This service lets the caller get one enabled AP to execute a caller-provided
function. The caller can request the BSP to either wait for the completion
of the AP or just proceed with the next task by using the EFI event mechanism.
See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking
execution support. This service may only be called from the BSP.
This function is used to dispatch one enabled AP to the function specified by
Procedure passing in the argument specified by ProcedureArgument. If WaitEvent
is NULL, execution is in blocking mode. The BSP waits until the AP finishes or
TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.
BSP proceeds to the next task without waiting for the AP. If a non-blocking mode
is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,
then EFI_UNSUPPORTED must be returned.
If the timeout specified by TimeoutInMicroseconds expires before the AP returns
from Procedure, then execution of Procedure by the AP is terminated. The AP is
available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and
EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL
instance.
@param[in] Procedure A pointer to the function to be run on the
designated AP of the system. See type
EFI_AP_PROCEDURE.
@param[in] ProcessorNumber The handle number of the AP. The range is
from 0 to the total number of logical
processors minus 1. The total number of
logical processors can be retrieved by
EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
@param[in] WaitEvent The event created by the caller with CreateEvent()
service. If it is NULL, then execute in
blocking mode. BSP waits until this AP finish
or TimeoutInMicroSeconds expires. If it's
not NULL, then execute in non-blocking mode.
BSP requests the function specified by
Procedure to be started on this AP,
and go on executing immediately. If this AP
return from Procedure or TimeoutInMicroSeconds
expires, this event is signaled. The BSP
can use the CheckEvent() or WaitForEvent()
services to check the state of event. Type
EFI_EVENT is defined in CreateEvent() in
the Unified Extensible Firmware Interface
Specification.
@param[in] TimeoutInMicrosecsond Indicates the time limit in microseconds for
this AP to finish this Procedure, either for
blocking or non-blocking mode. Zero means
infinity. If the timeout expires before
this AP returns from Procedure, then Procedure
on the AP is terminated. The
AP is available for next function assigned
by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs()
or EFI_MP_SERVICES_PROTOCOL.StartupThisAP().
If the timeout expires in blocking mode,
BSP returns EFI_TIMEOUT. If the timeout
expires in non-blocking mode, WaitEvent
is signaled with SignalEvent().
@param[in] ProcedureArgument The parameter passed into Procedure on the
specified AP.
@param[out] Finished If NULL, this parameter is ignored. In
blocking mode, this parameter is ignored.
In non-blocking mode, if AP returns from
Procedure before the timeout expires, its
content is set to TRUE. Otherwise, the
value is set to FALSE. The caller can
determine if the AP returned from Procedure
by evaluating this value.
@retval EFI_SUCCESS In blocking mode, specified AP finished before
the timeout expires.
@retval EFI_SUCCESS In non-blocking mode, the function has been
dispatched to specified AP.
@retval EFI_UNSUPPORTED A non-blocking mode request was made after the
UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
signaled.
@retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_TIMEOUT In blocking mode, the timeout expired before
the specified AP has finished.
@retval EFI_NOT_READY The specified AP is busy.
@retval EFI_NOT_FOUND The processor with the handle specified by
ProcessorNumber does not exist.
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.
@retval EFI_INVALID_PARAMETER Procedure is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_STARTUP_THIS_AP)(
IN EFI_MP_SERVICES_PROTOCOL *This,
IN EFI_AP_PROCEDURE Procedure,
IN UINTN ProcessorNumber,
IN EFI_EVENT WaitEvent OPTIONAL,
IN UINTN TimeoutInMicroseconds,
IN VOID *ProcedureArgument OPTIONAL,
OUT BOOLEAN *Finished OPTIONAL
);
/**
This service switches the requested AP to be the BSP from that point onward.
This service changes the BSP for all purposes. This call can only be performed
by the current BSP.
This service switches the requested AP to be the BSP from that point onward.
This service changes the BSP for all purposes. The new BSP can take over the
execution of the old BSP and continue seamlessly from where the old one left
off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
is signaled.
If the BSP cannot be switched prior to the return from this service, then
EFI_UNSUPPORTED must be returned.
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
@param[in] ProcessorNumber The handle number of AP that is to become the new
BSP. The range is from 0 to the total number of
logical processors minus 1. The total number of
logical processors can be retrieved by
EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
@param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an
enabled AP. Otherwise, it will be disabled.
@retval EFI_SUCCESS BSP successfully switched.
@retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
this service returning.
@retval EFI_UNSUPPORTED Switching the BSP is not supported.
@retval EFI_SUCCESS The calling processor is an AP.
@retval EFI_NOT_FOUND The processor with the handle specified by
ProcessorNumber does not exist.
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
a disabled AP.
@retval EFI_NOT_READY The specified AP is busy.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_SWITCH_BSP)(
IN EFI_MP_SERVICES_PROTOCOL *This,
IN UINTN ProcessorNumber,
IN BOOLEAN EnableOldBSP
);
/**
This service lets the caller enable or disable an AP from this point onward.
This service may only be called from the BSP.
This service allows the caller enable or disable an AP from this point onward.
The caller can optionally specify the health status of the AP by Health. If
an AP is being disabled, then the state of the disabled AP is implementation
dependent. If an AP is enabled, then the implementation must guarantee that a
complete initialization sequence is performed on the AP, so the AP is in a state
that is compatible with an MP operating system. This service may not be supported
after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
If the enable or disable AP operation cannot be completed prior to the return
from this service, then EFI_UNSUPPORTED must be returned.
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
@param[in] ProcessorNumber The handle number of AP.
The range is from 0 to the total number of
logical processors minus 1. The total number of
logical processors can be retrieved by
EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
@param[in] EnableAP Specifies the new state for the processor for
enabled, FALSE for disabled.
@param[in] HealthFlag If not NULL, a pointer to a value that specifies
the new health status of the AP. This flag
corresponds to StatusFlag defined in
EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
the PROCESSOR_HEALTH_STATUS_BIT is used. All other
bits are ignored. If it is NULL, this parameter
is ignored.
@retval EFI_SUCCESS The specified AP was enabled or disabled successfully.
@retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed
prior to this service returning.
@retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.
@retval EFI_DEVICE_ERROR The calling processor is an AP.
@retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber
does not exist.
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_ENABLEDISABLEAP)(
IN EFI_MP_SERVICES_PROTOCOL *This,
IN UINTN ProcessorNumber,
IN BOOLEAN EnableAP,
IN UINT32 *HealthFlag OPTIONAL
);
/**
This return the handle number for the calling processor. This service may be
called from the BSP and APs.
This service returns the processor handle number for the calling processor.
The returned value is in the range from 0 to the total number of logical
processors minus 1. The total number of logical processors can be retrieved
with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
is returned. Otherwise, the current processors handle number is returned in
ProcessorNumber, and EFI_SUCCESS is returned.
@param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
@param[in] ProcessorNumber Pointer to the handle number of AP.
The range is from 0 to the total number of
logical processors minus 1. The total number of
logical processors can be retrieved by
EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors().
@retval EFI_SUCCESS The current processor handle number was returned
in ProcessorNumber.
@retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_MP_SERVICES_WHOAMI)(
IN EFI_MP_SERVICES_PROTOCOL *This,
OUT UINTN *ProcessorNumber
);
///
/// When installed, the MP Services Protocol produces a collection of services
/// that are needed for MP management.
///
/// Before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, the module
/// that produces this protocol is required to place all APs into an idle state
/// whenever the APs are disabled or the APs are not executing code as requested
/// through the StartupAllAPs() or StartupThisAP() services. The idle state of
/// an AP before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled is
/// implementation dependent.
///
/// After the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, all the APs
/// must be placed in the OS compatible CPU state as defined by the UEFI
/// Specification. Implementations of this protocol may use the UEFI event
/// EFI_EVENT_GROUP_READY_TO_BOOT to force APs into the OS compatible state as
/// defined by the UEFI Specification. Modules that use this protocol must
/// guarantee that all non-blocking mode requests on all APs have been completed
/// before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled. Since the
/// order that event notification functions in the same event group are executed
/// is not deterministic, an event of type EFI_EVENT_GROUP_READY_TO_BOOT cannot
/// be used to guarantee that APs have completed their non-blocking mode requests.
///
/// When the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, the StartAllAPs()
/// and StartupThisAp() services must no longer support non-blocking mode requests.
/// The support for SwitchBSP() and EnableDisableAP() may no longer be supported
/// after this event is signaled. Since UEFI Applications and UEFI OS Loaders
/// execute after the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, these
/// UEFI images must be aware that the functionality of this protocol may be reduced.
///
struct _EFI_MP_SERVICES_PROTOCOL {
EFI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors;
EFI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo;
EFI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs;
EFI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP;
EFI_MP_SERVICES_SWITCH_BSP SwitchBSP;
EFI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP;
EFI_MP_SERVICES_WHOAMI WhoAmI;
};
#endif

View file

@ -1,262 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <efi.h>
#include <efilib.h>
#include <vmm.h>
#include <common.h>
#include <bfdebug.h>
#include <bftypes.h>
#include <bfconstants.h>
#include <bfdriverinterface.h>
/* -------------------------------------------------------------------------- */
/* Global */
/* -------------------------------------------------------------------------- */
uint64_t g_vcpuid = 0;
struct pmodule_t {
char *data;
uint64_t size;
};
uint64_t g_num_pmodules = 0;
struct pmodule_t pmodules[MAX_NUM_MODULES] = {{0}};
/* -------------------------------------------------------------------------- */
/* Misc Device */
/* -------------------------------------------------------------------------- */
static int64_t
ioctl_add_module(const char *file, uint64_t len)
{
char *buf;
int64_t ret;
if (g_num_pmodules >= MAX_NUM_MODULES) {
BFALERT("IOCTL_ADD_MODULE: too many modules have been loaded\n");
return BF_IOCTL_FAILURE;
}
buf = platform_alloc_rw(len);
if (buf == NULL) {
BFALERT("IOCTL_ADD_MODULE: failed to allocate memory for the module\n");
return BF_IOCTL_FAILURE;
}
gBS->CopyMem(buf, (void *)file, len);
ret = common_add_module(buf, len);
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_ADD_MODULE: common_add_module failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto failed;
}
pmodules[g_num_pmodules].data = buf;
pmodules[g_num_pmodules].size = len;
g_num_pmodules++;
return BF_IOCTL_SUCCESS;
failed:
platform_free_rw(buf, len);
BFALERT("IOCTL_ADD_MODULE: failed\n");
return BF_IOCTL_FAILURE;
}
static long
ioctl_load_vmm(void)
{
int64_t ret;
ret = common_load_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_LOAD_VMM: common_load_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto failure;
}
return BF_IOCTL_SUCCESS;
failure:
BFDEBUG("IOCTL_LOAD_VMM: failed\n");
return BF_IOCTL_FAILURE;
}
static long
ioctl_start_vmm(void)
{
int64_t ret;
ret = common_start_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_START_VMM: common_start_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto failure;
}
return BF_IOCTL_SUCCESS;
failure:
BFDEBUG("IOCTL_START_VMM: failed\n");
return BF_IOCTL_FAILURE;
}
/* -------------------------------------------------------------------------- */
/* Load / Image */
/* -------------------------------------------------------------------------- */
/**
* TODO
*
* Instead of loading the OS, we need to actually load a EFI/BOOT/chain.efi
* file which is the previous EFI/BOOT/boot64.efi. This will allow us to
* support the different types of loaders that are instealled regardless of
* which one is actually installed.
*/
static long
load_start_vm(EFI_HANDLE ParentImage)
{
/**
* TODO
*
* Need to check to see if there are deallocate functions for a lot of
* these functions as they are returning pointers.
*/
EFI_STATUS status;
UINTN i;
UINTN NumberFileSystemHandles = 0;
EFI_HANDLE *FileSystemHandles = NULL;
status =
gBS->LocateHandleBuffer(
ByProtocol,
&gEfiBlockIoProtocolGuid,
NULL,
&NumberFileSystemHandles,
&FileSystemHandles
);
if (EFI_ERROR(status)) {
BFALERT("LocateHandleBuffer failed\n");
return EFI_ABORTED;
}
for (i = 0; i < NumberFileSystemHandles; ++i) {
EFI_DEVICE_PATH_PROTOCOL *FilePath = NULL;
EFI_BLOCK_IO *BlkIo = NULL;
EFI_HANDLE ImageHandle = NULL;
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo = NULL;
status =
gBS->HandleProtocol(
FileSystemHandles[i],
&gEfiBlockIoProtocolGuid,
(VOID **) &BlkIo
);
if (EFI_ERROR(status)) {
continue;
}
FilePath = FileDevicePath(FileSystemHandles[i], L"\\EFI\\BOOT\\bootx64.efi");
status =
gBS->LoadImage(
FALSE,
ParentImage,
FilePath,
NULL,
0,
&ImageHandle
);
gBS->FreePool(FilePath);
if (EFI_ERROR(status)) {
continue;
}
status =
gBS->HandleProtocol(
ImageHandle,
&gEfiLoadedImageProtocolGuid,
(VOID **) &ImageInfo
);
if (EFI_ERROR(status)) {
continue;
}
if (ImageInfo->ImageCodeType != EfiLoaderCode) {
continue;
}
gBS->StartImage(ImageHandle, NULL, NULL);
break;
}
BFALERT("Unable to locate EFI bootloader\n");
return EFI_ABORTED;
}
/* -------------------------------------------------------------------------- */
/* Entry / Exit */
/* -------------------------------------------------------------------------- */
EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
InitializeLib(image, systab);
Print(L"\n");
Print(L" ___ __ _ _ \n");
Print(L" | _ ) __ _ _ _ ___ / _| |__ _ _ _ | |__\n");
Print(L" | _ \\/ _` | '_/ -_) _| / _` | ' \\| / /\n");
Print(L" |___/\\__,_|_| \\___|_| |_\\__,_|_||_|_\\_\\\n");
Print(L"\n");
Print(L" Please give us a star on: https://github.com/Bareflank/hypervisor\n");
Print(L"\n");
if (common_init() != BF_SUCCESS) {
return EFI_ABORTED;
}
ioctl_add_module((char *)vmm, vmm_len);
ioctl_load_vmm();
ioctl_start_vmm();
load_start_vm(image);
return EFI_SUCCESS;
}

View file

@ -1,33 +0,0 @@
;
; Copyright (C) 2019 Assured Information Security, Inc.
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
bits 64
default rel
section .text
global _set_ne
_set_ne:
mov rax, cr0
or rax, 0x20
mov cr0, rax
ret

View file

@ -1,232 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <bfarch.h>
#include <bftypes.h>
#include <bfdebug.h>
#include <bfplatform.h>
#include <bfelf_loader.h>
#include <common.h>
#include <efi.h>
#include <efilib.h>
#include "MpService.h"
EFI_MP_SERVICES_PROTOCOL *g_mp_services = nullptr;
void _set_ne(void);
int64_t
platform_init(void)
{
EFI_STATUS status;
EFI_GUID gEfiMpServiceProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID;
status =
gBS->LocateProtocol(
&gEfiMpServiceProtocolGuid,
nullptr,
(VOID **)&g_mp_services
);
if (EFI_ERROR(status)) {
BFALERT("locate_mp_services_protocol: LocateProtocol failed: %r\n", status);
return -1;
}
_set_ne();
return BF_SUCCESS;
}
void *
platform_alloc_rw(uint64_t len)
{
EFI_STATUS status;
EFI_PHYSICAL_ADDRESS addr = 0;
if (len == 0) {
BFALERT("platform_alloc_rw: invalid length\n");
return (void *)addr;
}
status = gBS->AllocatePages(
AllocateAnyPages, EfiRuntimeServicesData, (len / EFI_PAGE_SIZE) + 1, &addr
);
if (EFI_ERROR(status)) {
BFALERT("platform_alloc_rw: AllocatePages failed: %lld\n", len);
}
return (void *)addr;
}
void *
platform_alloc_rwe(uint64_t len)
{
EFI_STATUS status;
EFI_PHYSICAL_ADDRESS addr = 0;
if (len == 0) {
BFALERT("platform_alloc_rw: invalid length\n");
return (void *)addr;
}
status = gBS->AllocatePages(
AllocateAnyPages, EfiRuntimeServicesCode, (len / EFI_PAGE_SIZE) + 1, &addr
);
if (EFI_ERROR(status)) {
BFALERT("platform_alloc_rw: AllocatePages failed: %lld\n", len);
}
return (void *)addr;
}
void
platform_free_rw(void *addr, uint64_t len)
{
if (addr == nullptr) {
BFALERT("platform_free_rw: invalid address %p\n", addr);
return;
}
gBS->FreePages(
(EFI_PHYSICAL_ADDRESS) addr, (len / EFI_PAGE_SIZE) + 1
);
}
void
platform_free_rwe(void *addr, uint64_t len)
{
if (addr == nullptr) {
BFALERT("platform_free_rw: invalid address %p\n", addr);
return;
}
gBS->FreePages(
(EFI_PHYSICAL_ADDRESS) addr, (len / EFI_PAGE_SIZE) + 1
);
}
void *
platform_virt_to_phys(void *virt)
{
return virt;
}
void *
platform_memset(void *ptr, char value, uint64_t num)
{
gBS->SetMem(ptr, num, value);
return ptr;
}
int64_t
platform_memcpy(
void *dst, uint64_t dst_size, const void *src, uint64_t src_size, uint64_t num)
{
if (dst == 0 || src == 0) {
BFALERT("platform_memcpy: invalid dst or src\n");
return FAILURE;
}
if (num > dst_size || num > src_size) {
BFALERT("platform_memcpy: num out of range\n");
return FAILURE;
}
gBS->CopyMem((VOID *)dst, (VOID *)src, num);
return SUCCESS;
}
int64_t
platform_num_cpus(void)
{
UINTN NumberOfProcessors;
UINTN NumberOfEnabledProcessors;
EFI_STATUS status =
g_mp_services->GetNumberOfProcessors(
g_mp_services,
&NumberOfProcessors,
&NumberOfEnabledProcessors
);
if (EFI_ERROR(status)) {
BFALERT("platform_num_cpus: GetNumberOfProcessors failed\n");
return 0;
}
return (int64_t)NumberOfProcessors;
}
struct call_vmm_args {
uint64_t cpuid;
uint64_t request;
uintptr_t arg1;
uintptr_t arg2;
int64_t ret;
};
EFI_FUNCTION static void
call_vmm(struct call_vmm_args *args)
{
_set_ne();
args->ret =
common_call_vmm(args->cpuid, args->request, args->arg1, args->arg2);
}
int64_t
platform_call_vmm_on_core(
uint64_t cpuid, uint64_t request, uintptr_t arg1, uintptr_t arg2)
{
struct call_vmm_args args = {
cpuid, request, arg1, arg2, 0
};
if (cpuid == 0) {
return common_call_vmm(cpuid, request, arg1, arg2);
}
EFI_STATUS status =
g_mp_services->StartupThisAP(
g_mp_services,
(EFI_AP_PROCEDURE)call_vmm,
cpuid,
nullptr,
0,
&args,
nullptr
);
if (EFI_ERROR(status)) {
BFALERT("platform_num_cpus: StartupThisAP failed\n");
return -1;
}
return args.ret;
}
void *
platform_get_rsdp(void)
{ return 0; }

View file

@ -1,538 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/kallsyms.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/suspend.h>
#include <common.h>
#include <bfdebug.h>
#include <bftypes.h>
#include <bfconstants.h>
#include <bfdriverinterface.h>
uint64_t _vmcall(uint64_t r1, uint64_t r2, uint64_t r3, uint64_t r4);
/* -------------------------------------------------------------------------- */
/* Global */
/* -------------------------------------------------------------------------- */
static uint64_t g_vcpuid = 0;
static uint64_t g_module_length = 0;
struct pmodule_t {
char *data;
int64_t size;
};
uint64_t g_num_pmodules = 0;
struct pmodule_t pmodules[MAX_NUM_MODULES] = { 0 };
/* -------------------------------------------------------------------------- */
/* Status */
/* -------------------------------------------------------------------------- */
static int g_status = 0;
#define STATUS_STOPPED 0
#define STATUS_RUNNING 1
#define STATUS_SUSPEND 2
DEFINE_MUTEX(g_status_mutex);
/* -------------------------------------------------------------------------- */
/* Misc Device */
/* -------------------------------------------------------------------------- */
static int
dev_open(struct inode *inode, struct file *file)
{ return 0; }
static int
dev_release(struct inode *inode, struct file *file)
{ return 0; }
static long
ioctl_add_module(const char *file)
{
char *buf;
int64_t ret;
if (g_num_pmodules >= MAX_NUM_MODULES) {
BFALERT("IOCTL_ADD_MODULE: too many modules have been loaded\n");
return BF_IOCTL_FAILURE;
}
buf = platform_alloc_rw(g_module_length);
if (buf == NULL) {
BFALERT("IOCTL_ADD_MODULE: failed to allocate memory for the module\n");
return BF_IOCTL_FAILURE;
}
ret = copy_from_user(buf, file, g_module_length);
if (ret != 0) {
BFALERT("IOCTL_ADD_MODULE: failed to copy memory from userspace\n");
goto IOCTL_FAILURE;
}
ret = common_add_module(buf, g_module_length);
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_ADD_MODULE: common_add_module failed: %p - %s\n", \
(void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
pmodules[g_num_pmodules].data = buf;
pmodules[g_num_pmodules].size = g_module_length;
g_num_pmodules++;
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
platform_free_rw(buf, g_module_length);
return BF_IOCTL_FAILURE;
}
static long
ioctl_add_module_length(uint64_t *len)
{
int64_t ret;
if (len == 0) {
BFALERT("IOCTL_ADD_MODULE_LENGTH: failed with len == NULL\n");
return BF_IOCTL_FAILURE;
}
ret = copy_from_user(&g_module_length, len, sizeof(uint64_t));
if (ret != 0) {
BFALERT("IOCTL_ADD_MODULE_LENGTH: failed to copy memory from userspace\n");
return BF_IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
}
static long
ioctl_unload_vmm(void)
{
int i;
int64_t ret;
ret = common_unload_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_UNLOAD_VMM: common_unload_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
for (i = 0; i < g_num_pmodules; i++) {
platform_free_rw(pmodules[i].data, pmodules[i].size);
}
g_num_pmodules = 0;
platform_memset(&pmodules, 0, sizeof(pmodules));
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
return BF_IOCTL_FAILURE;
}
static long
ioctl_load_vmm(void)
{
int64_t ret;
ret = common_load_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_LOAD_VMM: common_load_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
ioctl_unload_vmm();
return BF_IOCTL_FAILURE;
}
static long
ioctl_stop_vmm(void)
{
int64_t ret;
mutex_lock(&g_status_mutex);
ret = common_stop_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_STOP_VMM: common_stop_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
g_status = STATUS_STOPPED;
mutex_unlock(&g_status_mutex);
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
mutex_unlock(&g_status_mutex);
return BF_IOCTL_FAILURE;
}
static long
ioctl_start_vmm(void)
{
int64_t ret;
mutex_lock(&g_status_mutex);
ret = common_start_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_START_VMM: common_start_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
g_status = STATUS_RUNNING;
mutex_unlock(&g_status_mutex);
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
common_stop_vmm();
mutex_unlock(&g_status_mutex);
return BF_IOCTL_FAILURE;
}
static long
ioctl_dump_vmm(struct debug_ring_resources_t *user_drr)
{
int64_t ret;
struct debug_ring_resources_t *drr = 0;
ret = common_dump_vmm(&drr, g_vcpuid);
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_DUMP_VMM: common_dump_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
return BF_IOCTL_FAILURE;
}
ret = copy_to_user(user_drr, drr, sizeof(struct debug_ring_resources_t));
if (ret != 0) {
BFALERT("IOCTL_DUMP_VMM: failed to copy memory from userspace\n");
return BF_IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
}
static long
ioctl_vmm_status(int64_t *status)
{
int64_t ret;
int64_t vmm_status = common_vmm_status();
if (status == 0) {
BFALERT("IOCTL_VMM_STATUS: common_vmm_status failed: NULL\n");
return BF_IOCTL_FAILURE;
}
ret = copy_to_user(status, &vmm_status, sizeof(int64_t));
if (ret != 0) {
BFALERT("IOCTL_VMM_STATUS: failed to copy memory from userspace\n");
return BF_IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
}
static long
ioctl_set_vcpuid(uint64_t *vcpuid)
{
int64_t ret;
if (vcpuid == 0) {
BFALERT("IOCTL_SET_VCPUID: failed with vcpuid == NULL\n");
return BF_IOCTL_FAILURE;
}
ret = copy_from_user(&g_vcpuid, vcpuid, sizeof(uint64_t));
if (ret != 0) {
BFALERT("IOCTL_SET_VCPUID: failed to copy memory from userspace\n");
return BF_IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
}
static long
ioctl_vmcall(struct ioctl_vmcall_args_t *user_args)
{
int64_t ret;
struct ioctl_vmcall_args_t args;
if (user_args == 0) {
BFALERT("IOCTL_CALL: failed with args == NULL\n");
return BF_IOCTL_FAILURE;
}
ret = copy_from_user(&args, user_args, sizeof(struct ioctl_vmcall_args_t));
if (ret != 0) {
BFALERT("IOCTL_CALL: failed to copy memory from userspace\n");
return BF_IOCTL_FAILURE;
}
mutex_lock(&g_status_mutex);
switch (g_status) {
case STATUS_RUNNING:
args.reg1 = _vmcall(args.reg1, args.reg2, args.reg3, args.reg4);
break;
case STATUS_SUSPEND:
args.reg1 = SUSPEND;
break;
default:
args.reg1 = FAILURE;
break;
};
mutex_unlock(&g_status_mutex);
args.reg2 = 0;
args.reg3 = 0;
args.reg4 = 0;
ret = copy_to_user(user_args, &args, sizeof(struct ioctl_vmcall_args_t));
if (ret != 0) {
BFALERT("IOCTL_CALL: failed to copy memory from userspace\n");
return BF_IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
}
static long
dev_unlocked_ioctl(
struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case IOCTL_ADD_MODULE:
return ioctl_add_module((char *)arg);
case IOCTL_ADD_MODULE_LENGTH:
return ioctl_add_module_length((uint64_t *)arg);
case IOCTL_LOAD_VMM:
return ioctl_load_vmm();
case IOCTL_UNLOAD_VMM:
return ioctl_unload_vmm();
case IOCTL_START_VMM:
return ioctl_start_vmm();
case IOCTL_STOP_VMM:
return ioctl_stop_vmm();
case IOCTL_DUMP_VMM:
return ioctl_dump_vmm((struct debug_ring_resources_t *)arg);
case IOCTL_VMM_STATUS:
return ioctl_vmm_status((int64_t *)arg);
case IOCTL_SET_VCPUID:
return ioctl_set_vcpuid((uint64_t *)arg);
case IOCTL_VMCALL:
return ioctl_vmcall((struct ioctl_vmcall_args_t *)arg);
default:
return -EINVAL;
}
}
static struct file_operations fops = {
.open = dev_open,
.release = dev_release,
.unlocked_ioctl = dev_unlocked_ioctl,
};
static struct miscdevice bareflank_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = BAREFLANK_NAME,
.fops = &fops,
.mode = 0666
};
/* -------------------------------------------------------------------------- */
/* Entry / Exit */
/* -------------------------------------------------------------------------- */
int
dev_reboot(
struct notifier_block *nb, unsigned long code, void *unused)
{
mutex_lock(&g_status_mutex);
common_fini();
g_status = STATUS_STOPPED;
mutex_unlock(&g_status_mutex);
return NOTIFY_DONE;
}
static int
resume(void)
{
mutex_lock(&g_status_mutex);
if (g_status != STATUS_SUSPEND) {
mutex_unlock(&g_status_mutex);
return NOTIFY_DONE;
}
if (common_start_vmm() != BF_SUCCESS) {
common_fini();
g_status = STATUS_STOPPED;
mutex_unlock(&g_status_mutex);
return -EPERM;
}
g_status = STATUS_RUNNING;
mutex_unlock(&g_status_mutex);
return NOTIFY_DONE;
}
static int
suspend(void)
{
mutex_lock(&g_status_mutex);
if (g_status != STATUS_RUNNING) {
mutex_unlock(&g_status_mutex);
return NOTIFY_DONE;
}
if (common_stop_vmm() != BF_SUCCESS) {
common_fini();
g_status = STATUS_STOPPED;
mutex_unlock(&g_status_mutex);
return -EPERM;
}
g_status = STATUS_SUSPEND;
mutex_unlock(&g_status_mutex);
return NOTIFY_DONE;
}
int
dev_pm(
struct notifier_block *nb, unsigned long code, void *unused)
{
switch (code) {
case PM_SUSPEND_PREPARE:
case PM_HIBERNATION_PREPARE:
case PM_RESTORE_PREPARE:
return suspend();
case PM_POST_SUSPEND:
case PM_POST_HIBERNATION:
case PM_POST_RESTORE:
return resume();
default:
break;
}
return NOTIFY_DONE;
}
static struct notifier_block reboot_notifier_block = {
.notifier_call = dev_reboot
};
static struct notifier_block pm_notifier_block = {
.notifier_call = dev_pm
};
int
dev_init(void)
{
register_reboot_notifier(&reboot_notifier_block);
register_pm_notifier(&pm_notifier_block);
if (misc_register(&bareflank_dev) != 0) {
BFALERT("misc_register failed\n");
goto INIT_FAILURE;
}
if (common_init() != 0) {
BFALERT("common_init failed\n");
goto INIT_FAILURE;
}
g_status = STATUS_STOPPED;
mutex_init(&g_status_mutex);
return 0;
INIT_FAILURE:
return -EPERM;
}
void
dev_exit(void)
{
mutex_lock(&g_status_mutex);
common_fini();
g_status = STATUS_STOPPED;
misc_deregister(&bareflank_dev);
unregister_pm_notifier(&pm_notifier_block);
unregister_reboot_notifier(&reboot_notifier_block);
mutex_unlock(&g_status_mutex);
return;
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");

View file

@ -1,199 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <bfarch.h>
#include <bfdebug.h>
#include <bfplatform.h>
#include <common.h>
#include <asm/io.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/version.h>
#include <linux/cpumask.h>
#include <linux/sched.h>
#include <linux/kallsyms.h>
#if defined(BF_AARCH64)
# include <asm/io.h>
#endif
typedef long (*set_affinity_fn)(pid_t, const struct cpumask *);
set_affinity_fn set_cpu_affinity = nullptr;
int64_t
platform_init(void)
{
set_cpu_affinity = (set_affinity_fn)kallsyms_lookup_name("sched_setaffinity");
if (set_cpu_affinity == nullptr) {
BFALERT("Failed to locate sched_setaffinity\n");
return -1;
}
return BF_SUCCESS;
}
void *
platform_alloc_rw(uint64_t len)
{
void *addr = nullptr;
if (len == 0) {
BFALERT("platform_alloc_rw: invalid length\n");
return addr;
}
addr = vmalloc(len);
if (addr == nullptr) {
BFALERT("platform_alloc_rw: failed to vmalloc rw mem: %lld\n", len);
}
return addr;
}
void *
platform_alloc_rwe(uint64_t len)
{
void *addr = nullptr;
if (len == 0) {
BFALERT("platform_alloc_rwe: invalid length\n");
return addr;
}
addr = __vmalloc(len, GFP_KERNEL, PAGE_KERNEL_EXEC);
if (addr == nullptr) {
BFALERT("platform_alloc_rwe: failed to vmalloc rwe mem: %lld\n", len);
}
return addr;
}
void
platform_free_rw(void *addr, uint64_t len)
{
bfignored(len);
if (addr == nullptr) {
BFALERT("platform_free_rw: invalid address %p\n", addr);
return;
}
vfree(addr);
}
void
platform_free_rwe(void *addr, uint64_t len)
{
bfignored(len);
if (addr == nullptr) {
BFALERT("platform_free_rwe: invalid address %p\n", addr);
return;
}
vfree(addr);
}
void *
platform_virt_to_phys(void *virt)
{
if (is_vmalloc_addr(virt)) {
return (void *)page_to_phys(vmalloc_to_page(virt));
}
else {
return (void *)virt_to_phys(virt);
}
}
void *
platform_memset(void *ptr, char value, uint64_t num)
{
if (!ptr) {
return nullptr;
}
return memset(ptr, value, num);
}
int64_t
platform_memcpy(
void *dst, uint64_t dst_size, const void *src, uint64_t src_size, uint64_t num)
{
if (dst == 0 || src == 0) {
BFALERT("platform_memcpy: invalid dst or src\n");
return FAILURE;
}
if (num > dst_size || num > src_size) {
BFALERT("platform_memcpy: num out of range\n");
return FAILURE;
}
memcpy(dst, src, num);
return SUCCESS;
}
int64_t
platform_num_cpus(void)
{
int64_t num_cpus = num_online_cpus();
if (num_cpus < 0) {
return 0;
}
return num_cpus;
}
int64_t
platform_call_vmm_on_core(
uint64_t cpuid, uint64_t request, uintptr_t arg1, uintptr_t arg2)
{
int64_t ret = 0;
if (set_cpu_affinity(current->pid, cpumask_of(cpuid)) != 0) {
return BF_ERROR_UNKNOWN;
}
if (request == BF_REQUEST_VMM_FINI) {
load_direct_gdt(raw_smp_processor_id());
}
ret = common_call_vmm(cpuid, request, arg1, arg2);
if (request == BF_REQUEST_VMM_FINI) {
load_fixmap_gdt(raw_smp_processor_id());
}
return ret;
}
void *
platform_get_rsdp(void)
{ return 0; }

View file

@ -1,119 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <common.h>
#include <bfplatform.h>
#include <bfconstants.h>
#ifdef WIN64
#include <windows.h>
#else
#include <sys/mman.h>
#endif
int platform_info_should_fail = 0;
#define PAGE_ROUND_UP(x) ( (((uintptr_t)(x)) + BAREFLANK_PAGE_SIZE-1) & (~(BAREFLANK_PAGE_SIZE-1)) )
int64_t
platform_init(void)
{ return BF_SUCCESS; }
void *
platform_alloc_rw(uint64_t len)
{ return malloc(len); }
void *
platform_alloc_rwe(uint64_t len)
{
void *addr = 0;
#ifdef WIN64
DWORD oldProtect;
#else
int ret;
#endif
len = PAGE_ROUND_UP(len);
addr = aligned_alloc(BAREFLANK_PAGE_SIZE, len);
#ifdef WIN64
VirtualProtect(addr, len, PAGE_EXECUTE_READWRITE, &oldProtect);
#else
ret = mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC);
bfignored(ret);
#endif
return addr;
}
void
platform_free_rw(void *addr, uint64_t len)
{
bfignored(len);
free(addr);
}
void
platform_free_rwe(void *addr, uint64_t len)
{
bfignored(len);
free(addr);
}
void *
platform_virt_to_phys(void *virt)
{ return virt; }
void *
platform_memset(void *ptr, char value, uint64_t num)
{ return memset(ptr, value, num); }
int64_t
platform_memcpy(
void *dst, uint64_t dst_size, const void *src, uint64_t src_size, uint64_t num)
{
bfignored(dst_size);
bfignored(src_size);
memcpy(dst, src, num);
return SUCCESS;
}
int64_t
platform_num_cpus(void)
{ return 1; }
int64_t
platform_call_vmm_on_core(
uint64_t cpuid, uint64_t request, uintptr_t arg1, uintptr_t arg2)
{
return common_call_vmm(cpuid, request, arg1, arg2);
}
void *
platform_get_rsdp(void)
{ return 0; }

View file

@ -1,99 +0,0 @@
;
; Copyright (C) 2019 Assured Information Security, Inc.
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
;
; bareflank.inf
;
[Version]
Signature="$WINDOWS NT$"
Class=System
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider=%ManufacturerName%
CatalogFile=bareflank.cat
DriverVer=
[DestinationDirs]
DefaultDestDir = 12
bareflank_Device_CoInstaller_CopyFiles = 11
; ================= Class section =====================
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
bareflank.sys = 1,,
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1
;*****************************************
; Install Section
;*****************************************
[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$
[Standard.NT$ARCH$]
%bareflank.DeviceDesc%=bareflank_Device, Root\bareflank
[bareflank_Device.NT]
CopyFiles=Drivers_Dir
[Drivers_Dir]
bareflank.sys
;-------------- Service installation
[bareflank_Device.NT.Services]
AddService = bareflank,%SPSVCINST_ASSOCSERVICE%, bareflank_Service_Inst
; -------------- bareflank driver install sections
[bareflank_Service_Inst]
DisplayName = %bareflank.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\bareflank.sys
;
;--- bareflank_Device Coinstaller installation ------
;
[bareflank_Device.NT.CoInstallers]
AddReg=bareflank_Device_CoInstaller_AddReg
CopyFiles=bareflank_Device_CoInstaller_CopyFiles
[bareflank_Device_CoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
[bareflank_Device_CoInstaller_CopyFiles]
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
[bareflank_Device.NT.Wdf]
KmdfService = bareflank, bareflank_wdfsect
[bareflank_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
ManufacturerName="Assured Information Security, Inc."
DiskName = "Bareflank Installation Disk"
bareflank.DeviceDesc = "Bareflank Device"
bareflank.SVCDESC = "Bareflank Service"

View file

@ -1,48 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2008
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bareflank", "bareflank.vcxproj", "{9299115C-8A76-408B-B25B-BB3571EA196A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9299115C-8A76-408B-B25B-BB3571EA196A}.Debug|x64.ActiveCfg = Debug|x64
{9299115C-8A76-408B-B25B-BB3571EA196A}.Debug|x64.Build.0 = Debug|x64
{9299115C-8A76-408B-B25B-BB3571EA196A}.Debug|x64.Deploy.0 = Debug|x64
{9299115C-8A76-408B-B25B-BB3571EA196A}.Release|x64.ActiveCfg = Release|x64
{9299115C-8A76-408B-B25B-BB3571EA196A}.Release|x64.Build.0 = Release|x64
{9299115C-8A76-408B-B25B-BB3571EA196A}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5BB3266F-C8ED-491E-8FBD-B31BB90A5319}
EndGlobalSection
EndGlobal

View file

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Visual Studio 15
-->
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<Inf Include="bareflank.inf" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9299115C-8A76-408B-B25B-BB3571EA196A}</ProjectGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<RootNamespace>bareflank</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>..\..\..\..\bfsdk\include;..\..\..\..\bfelf_loader\include;..\..\..\include;.;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<IncludePath>..\..\..\..\bfsdk\include;..\..\..\..\bfelf_loader\include;..\..\..\include;.;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>KERNEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>KERNEL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\common.c" />
<ClCompile Include="device.c" />
<ClCompile Include="driver.c" />
<ClCompile Include="platform.c" />
<ClCompile Include="queue.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="device.h" />
<ClInclude Include="driver.h" />
<ClInclude Include="queue.h" />
</ItemGroup>
<ItemGroup>
<MASM Include="intrinsics.asm" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Visual Studio 15
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Inf Include="bareflank.inf" />
</ItemGroup>
<ItemGroup>
<Filter Include="Sources">
<UniqueIdentifier>{01371a61-2ed2-4da4-9ef8-a45467279dda}</UniqueIdentifier>
<Extensions>*.c</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="device.h" />
<ClInclude Include="driver.h" />
<ClInclude Include="queue.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\common.c" />
<ClCompile Include="device.c" />
<ClCompile Include="driver.c" />
<ClCompile Include="platform.c" />
<ClCompile Include="queue.c" />
</ItemGroup>
<ItemGroup>
<MASM Include="intrinsics.asm" />
</ItemGroup>
</Project>

View file

@ -1,156 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <driver.h>
extern int g_status;
extern FAST_MUTEX g_status_mutex;
/* -------------------------------------------------------------------------- */
/* Driver */
/* -------------------------------------------------------------------------- */
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = bareflankEvtDriverContextCleanup;
WDF_DRIVER_CONFIG_INIT(&config, bareflankEvtDeviceAdd);
status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
return status;
}
return STATUS_SUCCESS;
}
NTSTATUS
bareflankEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
UNREFERENCED_PARAMETER(Driver);
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDeviceD0Entry = bareflankEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = bareflankEvtDeviceD0Exit;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
status = bareflankCreateDevice(DeviceInit);
if (!NT_SUCCESS(status)) {
return status;
}
return STATUS_SUCCESS;
}
VOID
bareflankEvtDriverContextCleanup(
_In_ WDFOBJECT DriverObject
)
{
UNREFERENCED_PARAMETER(DriverObject);
ExAcquireFastMutex(&g_status_mutex);
common_fini();
g_status = STATUS_STOPPED;
ExReleaseFastMutex(&g_status_mutex);
}
static int g_sleeping = 0;
NTSTATUS
bareflankEvtDeviceD0Entry(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE PreviousState
)
{
UNREFERENCED_PARAMETER(Device);
UNREFERENCED_PARAMETER(PreviousState);
ExAcquireFastMutex(&g_status_mutex);
if (g_status != STATUS_SUSPEND) {
ExReleaseFastMutex(&g_status_mutex);
return STATUS_SUCCESS;
}
if (common_start_vmm() != BF_SUCCESS) {
common_fini();
g_status = STATUS_STOPPED;
ExReleaseFastMutex(&g_status_mutex);
return STATUS_UNSUCCESSFUL;
}
g_status = STATUS_RUNNING;
ExReleaseFastMutex(&g_status_mutex);
return STATUS_SUCCESS;
}
NTSTATUS
bareflankEvtDeviceD0Exit(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE TargetState
)
{
UNREFERENCED_PARAMETER(Device);
UNREFERENCED_PARAMETER(TargetState);
ExAcquireFastMutex(&g_status_mutex);
if (g_status != STATUS_RUNNING) {
ExReleaseFastMutex(&g_status_mutex);
return STATUS_SUCCESS;
}
if (common_stop_vmm() != BF_SUCCESS) {
common_fini();
g_status = STATUS_STOPPED;
ExReleaseFastMutex(&g_status_mutex);
return STATUS_UNSUCCESSFUL;
}
g_status = STATUS_SUSPEND;
ExReleaseFastMutex(&g_status_mutex);
return STATUS_SUCCESS;
}

View file

@ -1,40 +0,0 @@
;
; Copyright (C) 2019 Assured Information Security, Inc.
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
.code
_vmcall PROC
push rbx
mov rax, rcx
mov rbx, rdx
mov rcx, r8
mov rdx, r9
vmcall
pop rbx
ret
_vmcall ENDP
end

View file

@ -1,158 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <ntddk.h>
#include <bfdebug.h>
#include <bfplatform.h>
#include <common.h>
#define BF_TAG 'BFLK'
#define BF_NX_TAG 'BFNX'
int64_t
platform_init(void)
{ return BF_SUCCESS; }
void *
platform_alloc_rw(uint64_t len)
{
void *addr = nullptr;
if (len == 0) {
BFALERT("platform_alloc: invalid length\n");
return addr;
}
addr = ExAllocatePoolWithTag(NonPagedPool, len, BF_TAG);
if (addr == nullptr) {
BFALERT("platform_alloc_rw: failed to ExAllocatePoolWithTag mem: %lld\n", len);
}
return addr;
}
void *
platform_alloc_rwe(uint64_t len)
{
void *addr = nullptr;
if (len == 0) {
BFALERT("platform_alloc: invalid length\n");
return addr;
}
addr = ExAllocatePoolWithTag(NonPagedPoolExecute, len, BF_TAG);
if (addr == nullptr) {
BFALERT("platform_alloc_rw: failed to ExAllocatePoolWithTag mem: %lld\n", len);
}
return addr;
}
void *
platform_virt_to_phys(void *virt)
{
PHYSICAL_ADDRESS addr = MmGetPhysicalAddress(virt);
return (void *)addr.QuadPart;
}
void
platform_free_rw(void *addr, uint64_t len)
{
(void) len;
if (addr == nullptr) {
BFALERT("platform_free_rw: invalid address %p\n", addr);
return;
}
ExFreePoolWithTag(addr, BF_TAG);
}
void
platform_free_rwe(void *addr, uint64_t len)
{
(void) len;
if (addr == nullptr) {
BFALERT("platform_free_rw: invalid address %p\n", addr);
return;
}
ExFreePoolWithTag(addr, BF_TAG);
}
void *
platform_memset(void *ptr, char value, uint64_t num)
{
if (ptr == nullptr) {
return nullptr;
}
RtlFillMemory(ptr, num, value);
return ptr;
}
int64_t
platform_memcpy(
void *dst, uint64_t dst_size, const void *src, uint64_t src_size, uint64_t num)
{
if (dst == 0 || src == 0) {
BFALERT("platform_memcpy: invalid dst or src\n");
return FAILURE;
}
if (num > dst_size || num > src_size) {
BFALERT("platform_memcpy: num out of range\n");
return FAILURE;
}
RtlCopyMemory(dst, src, num);
return SUCCESS;
}
int64_t
platform_num_cpus()
{
KAFFINITY k_affin;
return (int64_t)KeQueryActiveProcessorCount(&k_affin);
}
int64_t
platform_call_vmm_on_core(
uint64_t cpuid, uint64_t request, uintptr_t arg1, uintptr_t arg2)
{
int64_t ret;
KAFFINITY old = KeSetSystemAffinityThreadEx(1ULL << cpuid);
ret = common_call_vmm(cpuid, request, arg1, arg2);
KeRevertToUserAffinityThreadEx(old);
return ret;
}
void *
platform_get_rsdp(void)
{ return 0; }

View file

@ -1,411 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <driver.h>
uint64_t _vmcall(uint64_t r1, uint64_t r2, uint64_t r3, uint64_t r4);
/* -------------------------------------------------------------------------- */
/* Status */
/* -------------------------------------------------------------------------- */
int g_status = 0;
FAST_MUTEX g_status_mutex;
/* -------------------------------------------------------------------------- */
/* Global */
/* -------------------------------------------------------------------------- */
static uint64_t g_vcpuid = 0;
struct pmodule_t {
char *data;
int64_t size;
};
static uint64_t g_num_pmodules = 0;
static struct pmodule_t pmodules[MAX_NUM_MODULES] = { 0 };
/* -------------------------------------------------------------------------- */
/* Misc Device */
/* -------------------------------------------------------------------------- */
static int64_t
ioctl_add_module(const char *file, int64_t len)
{
char *buf;
int64_t ret;
if (g_num_pmodules >= MAX_NUM_MODULES) {
BFALERT("IOCTL_ADD_MODULE: too many modules have been loaded\n");
return BF_IOCTL_FAILURE;
}
buf = platform_alloc_rw(len);
if (buf == NULL) {
BFALERT("IOCTL_ADD_MODULE: failed to allocate memory for the module\n");
return BF_IOCTL_FAILURE;
}
RtlCopyMemory(buf, file, len);
ret = common_add_module(buf, len);
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_ADD_MODULE: common_add_module failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
pmodules[g_num_pmodules].data = buf;
pmodules[g_num_pmodules].size = len;
g_num_pmodules++;
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
platform_free_rw(buf, len);
return BF_IOCTL_FAILURE;
}
static long
ioctl_unload_vmm(void)
{
int i;
int64_t ret;
ret = common_unload_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_UNLOAD_VMM: common_unload_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
for (i = 0; i < g_num_pmodules; i++) {
platform_free_rw(pmodules[i].data, pmodules[i].size);
}
g_num_pmodules = 0;
platform_memset(&pmodules, 0, sizeof(pmodules));
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
return BF_IOCTL_FAILURE;
}
static long
ioctl_load_vmm(void)
{
int64_t ret;
ret = common_load_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_LOAD_VMM: common_load_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
ioctl_unload_vmm();
return BF_IOCTL_FAILURE;
}
static long
ioctl_stop_vmm(void)
{
int64_t ret;
ExAcquireFastMutex(&g_status_mutex);
ret = common_stop_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_STOP_VMM: common_stop_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
g_status = STATUS_STOPPED;
ExReleaseFastMutex(&g_status_mutex);
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
ExReleaseFastMutex(&g_status_mutex);
return BF_IOCTL_FAILURE;
}
static long
ioctl_start_vmm(void)
{
int64_t ret;
ExAcquireFastMutex(&g_status_mutex);
ret = common_start_vmm();
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_START_VMM: common_start_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
goto IOCTL_FAILURE;
}
g_status = STATUS_RUNNING;
ExReleaseFastMutex(&g_status_mutex);
return BF_IOCTL_SUCCESS;
IOCTL_FAILURE:
common_stop_vmm();
ExReleaseFastMutex(&g_status_mutex);
return BF_IOCTL_FAILURE;
}
static long
ioctl_dump_vmm(struct debug_ring_resources_t *user_drr)
{
int64_t ret;
struct debug_ring_resources_t *drr = 0;
ret = common_dump_vmm(&drr, g_vcpuid);
if (ret != BF_SUCCESS) {
BFALERT("IOCTL_DUMP_VMM: common_dump_vmm failed: %p - %s\n", (void *)ret, ec_to_str(ret));
return BF_IOCTL_FAILURE;
}
RtlCopyMemory(user_drr, drr, sizeof(struct debug_ring_resources_t));
return BF_IOCTL_SUCCESS;
}
static long
ioctl_vmm_status(int64_t *status)
{
int64_t vmm_status = common_vmm_status();
if (status == 0) {
BFALERT("IOCTL_VMM_STATUS: common_vmm_status failed: NULL\n");
return BF_IOCTL_FAILURE;
}
*status = vmm_status;
return BF_IOCTL_SUCCESS;
}
static long
ioctl_set_vcpuid(uint64_t *vcpuid)
{
if (vcpuid == 0) {
BFALERT("IOCTL_SET_VCPUID: failed with vcpuid == NULL\n");
return BF_IOCTL_FAILURE;
}
g_vcpuid = *vcpuid;
return BF_IOCTL_SUCCESS;
}
static long
ioctl_vmcall(struct ioctl_vmcall_args_t *args_in, struct ioctl_vmcall_args_t *args_out)
{
struct ioctl_vmcall_args_t args = {0};
if (args_in == 0) {
BFALERT("IOCTL_VMCALL: failed with args in == NULL\n");
return BF_IOCTL_FAILURE;
}
if (args_out == 0) {
BFALERT("IOCTL_VMCALL: failed with args out == NULL\n");
return BF_IOCTL_FAILURE;
}
RtlCopyMemory(&args, args_in, sizeof(struct ioctl_vmcall_args_t));
ExAcquireFastMutex(&g_status_mutex);
switch (g_status) {
case STATUS_RUNNING:
args.reg1 = _vmcall(args.reg1, args.reg2, args.reg3, args.reg4);
break;
case STATUS_SUSPEND:
args.reg1 = SUSPEND;
break;
default:
args.reg1 = FAILURE;
break;
};
ExReleaseFastMutex(&g_status_mutex);
args.reg2 = 0;
args.reg3 = 0;
args.reg4 = 0;
RtlCopyMemory(args_out, &args, sizeof(struct ioctl_vmcall_args_t));
return BF_IOCTL_SUCCESS;
}
NTSTATUS
bareflankQueueInitialize(
_In_ WDFDEVICE Device
)
{
WDFQUEUE queue;
NTSTATUS status;
WDF_IO_QUEUE_CONFIG queueConfig;
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
&queueConfig,
WdfIoQueueDispatchParallel
);
queueConfig.EvtIoStop = bareflankEvtIoStop;
queueConfig.EvtIoDeviceControl = bareflankEvtIoDeviceControl;
status = WdfIoQueueCreate(Device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
if (!NT_SUCCESS(status)) {
BFALERT("WdfIoQueueCreate failed\n");
goto INIT_FAILURE;
}
if (common_init() != 0) {
BFALERT("common_init failed\n");
goto INIT_FAILURE;
}
g_status = STATUS_STOPPED;
ExInitializeFastMutex(&g_status_mutex);
return STATUS_SUCCESS;
INIT_FAILURE:
return STATUS_UNSUCCESSFUL;
}
VOID
bareflankEvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
{
PVOID in = 0;
PVOID out = 0;
size_t in_size = 0;
size_t out_size = 0;
int64_t ret = 0;
NTSTATUS status;
UNREFERENCED_PARAMETER(Queue);
if (InputBufferLength != 0) {
status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &in, &in_size);
if (!NT_SUCCESS(status)) {
goto IOCTL_FAILURE;
}
}
if (OutputBufferLength != 0) {
status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &out, &out_size);
if (!NT_SUCCESS(status)) {
goto IOCTL_FAILURE;
}
}
switch (IoControlCode) {
case IOCTL_ADD_MODULE:
ret = ioctl_add_module((char *)in, (int64_t)in_size);
break;
case IOCTL_LOAD_VMM:
ret = ioctl_load_vmm();
break;
case IOCTL_UNLOAD_VMM:
ret = ioctl_unload_vmm();
break;
case IOCTL_START_VMM:
ret = ioctl_start_vmm();
break;
case IOCTL_STOP_VMM:
ret = ioctl_stop_vmm();
break;
case IOCTL_DUMP_VMM:
ret = ioctl_dump_vmm((struct debug_ring_resources_t *)out);
break;
case IOCTL_VMM_STATUS:
ret = ioctl_vmm_status((int64_t *)out);
break;
case IOCTL_SET_VCPUID:
ret = ioctl_set_vcpuid((uint64_t *)in);
break;
case IOCTL_VMCALL:
ret = ioctl_vmcall((struct ioctl_vmcall_args_t *)in, (struct ioctl_vmcall_args_t *)out);
break;
default:
goto IOCTL_FAILURE;
}
if (OutputBufferLength != 0) {
WdfRequestSetInformation(Request, out_size);
}
if (ret != BF_IOCTL_SUCCESS) {
goto IOCTL_FAILURE;
}
WdfRequestComplete(Request, STATUS_SUCCESS);
return;
IOCTL_FAILURE:
WdfRequestComplete(Request, STATUS_ACCESS_DENIED);
return;
}
VOID
bareflankEvtIoStop(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG ActionFlags
)
{
UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(ActionFlags);
WdfRequestComplete(Request, STATUS_SUCCESS);
return;
}

View file

@ -1,100 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
TEST_CASE("common_add_module: invalid file")
{
CHECK(common_add_module(nullptr, 42) == BF_ERROR_INVALID_ARG);
}
TEST_CASE("common_add_module: invalid size")
{
binaries_info info{&g_file, g_filenames_success, false};
CHECK(common_add_module(info.back().file, 0) == BF_ERROR_INVALID_ARG);
}
TEST_CASE("common_add_module: success")
{
binaries_info info{&g_file, g_filenames_success, false};
CHECK(common_add_module(info.back().file, info.back().file_size) == BF_SUCCESS);
REQUIRE(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_add_module: already loaded")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_add_module(info.front().file, info.front().file_size) == BF_ERROR_VMM_INVALID_STATE); \
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_add_module: already running")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_add_module(info.front().file, info.front().file_size) == BF_ERROR_VMM_INVALID_STATE);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_add_module: corrupt")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
CHECK(common_add_module(info.front().file, info.front().file_size) == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_add_module: too many modules")
{
binaries_info info{&g_file, g_filenames_success, false};
for (auto i = 0; i < MAX_NUM_MODULES; i++) {
CHECK(common_add_module(info.back().file, info.back().file_size) == BF_SUCCESS);
}
CHECK(common_add_module(info.front().file, info.front().file_size) == BF_ERROR_MAX_MODULES_REACHED);
REQUIRE(common_fini() == BF_SUCCESS);
}

View file

@ -1,66 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <bfdriverinterface.h>
#include <bfdebugringinterface.h>
#include <common.h>
#include <test_support.h>
debug_ring_resources_t *g_drr;
TEST_CASE("common_add_module: invalid drr")
{
CHECK(common_dump_vmm(nullptr, 0) == BF_ERROR_INVALID_ARG);
}
TEST_CASE("common_add_module: unloaded")
{
CHECK(common_dump_vmm(&g_drr, 0) == BF_ERROR_VMM_INVALID_STATE);
}
TEST_CASE("common_add_module: get drr fails")
{
binaries_info info{&g_file, g_filenames_get_drr_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_dump_vmm(&g_drr, 0) == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_add_module: success")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_dump_vmm(&g_drr, 0) == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}

View file

@ -1,111 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
TEST_CASE("common_fini: unloaded")
{
CHECK(common_fini() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_fini: add module")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_fini: load")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_fini: start")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_fini: corrupt")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_fini: unload fails")
{
binaries_info info{&g_file, g_filenames_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_fini: stop fails")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
}

View file

@ -1,45 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <hippomocks.h>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT
TEST_CASE("run init")
{
CHECK(common_init() == BF_SUCCESS);
}
TEST_CASE("failure")
{
MockRepository mocks;
mocks.OnCallFunc(platform_init).Return(BF_ERROR_UNKNOWN);
CHECK(common_init() == BF_ERROR_UNKNOWN);
}
#endif

View file

@ -1,208 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <hippomocks.h>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT
extern "C" int64_t private_setup_rsdp(void);
extern "C" int64_t private_add_modules_mdl(void);
TEST_CASE("common_load_vmm: success")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: already loaded")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: already running")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_load_vmm() == BF_ERROR_VMM_INVALID_STATE);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: corrupt")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
CHECK(common_load_vmm() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_load_vmm: alloc stack fails")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
MockRepository mocks;
mocks.ExpectCallFunc(platform_alloc_rw).Return(nullptr);
CHECK(common_load_vmm() == BF_ERROR_OUT_OF_MEMORY);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: alloc tss fails")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
MockRepository mocks;
mocks.ExpectCallFunc(platform_alloc_rw).Do(malloc);
mocks.ExpectCallFunc(platform_alloc_rw).Return(nullptr);
CHECK(common_load_vmm() == BF_ERROR_OUT_OF_MEMORY);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: rsdp fails")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
MockRepository mocks;
mocks.ExpectCallFunc(private_setup_rsdp).Return(-1);
CHECK(common_load_vmm() == -1);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: missing symbols")
{
auto filenames = g_filenames_success;
filenames.pop_back();
binaries_info info{&g_file, filenames, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BFELF_ERROR_NO_SUCH_SYMBOL);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: no modules added")
{
CHECK(common_load_vmm() == BF_ERROR_NO_MODULES_ADDED);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: init fails")
{
binaries_info info{&g_file, g_filenames_init_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: set rsdp fails")
{
binaries_info info{&g_file, g_filenames_set_rsdp_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: add modules mdl fails")
{
binaries_info info{&g_file, g_filenames_add_mdl_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_load_vmm: add tss mdl fails")
{
binaries_info info{&g_file, g_filenames_add_mdl_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
MockRepository mocks;
mocks.OnCallFunc(private_add_modules_mdl).Return(BF_SUCCESS);
CHECK(common_load_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_SUCCESS);
}
#endif

View file

@ -1,119 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <hippomocks.h>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT
TEST_CASE("common_start_vmm: success")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_start_vmm: unloaded")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_start_vmm() == BF_ERROR_VMM_INVALID_STATE);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_start_vmm: already running")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_start_vmm: corrupt")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
CHECK(common_start_vmm() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_start_vmm: start fails")
{
binaries_info info{&g_file, g_filenames_vmm_init_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_start_vmm: set affinity fails")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
{
MockRepository mocks;
mocks.OnCallFunc(platform_call_vmm_on_core).Return(BF_ERROR_UNKNOWN);
CHECK(common_start_vmm() == BF_ERROR_UNKNOWN);
}
CHECK(common_fini() == BF_SUCCESS);
}
#endif

View file

@ -1,140 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <hippomocks.h>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT
TEST_CASE("common_stop_vmm: success")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_stop_vmm: unloaded")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_stop_vmm() == BF_ERROR_VMM_INVALID_STATE);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_stop_vmm: not running")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_stop_vmm: already stopped")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_stop_vmm: corrupt")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
CHECK(common_stop_vmm() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_start_vmm: stop fails")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_stop_vmm: set affinity fails")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
{
MockRepository mocks;
mocks.OnCallFunc(platform_call_vmm_on_core).Return(BF_ERROR_UNKNOWN);
CHECK(common_stop_vmm() == BF_ERROR_UNKNOWN);
}
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
#endif

View file

@ -1,120 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <hippomocks.h>
#include <bfdriverinterface.h>
#include <common.h>
#include <test_support.h>
#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT
TEST_CASE("common_unload_vmm: success")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == BF_SUCCESS);
CHECK(common_unload_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_unload_vmm: already unloaded")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_unload_vmm() == BF_SUCCESS);
CHECK(common_unload_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_unload_vmm: loaded")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_unload_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_unload_vmm: running")
{
binaries_info info{&g_file, g_filenames_success, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_unload_vmm() == BF_ERROR_VMM_INVALID_STATE);
CHECK(common_fini() == BF_SUCCESS);
}
TEST_CASE("common_unload_vmm: corrupt")
{
binaries_info info{&g_file, g_filenames_vmm_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
CHECK(common_unload_vmm() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
TEST_CASE("common_start_vmm: unload fails")
{
binaries_info info{&g_file, g_filenames_fini_fails, false};
for (const auto &binary : info.binaries()) {
REQUIRE(common_add_module(binary.file, binary.file_size) == BF_SUCCESS);
}
CHECK(common_load_vmm() == BF_SUCCESS);
CHECK(common_start_vmm() == BF_SUCCESS);
CHECK(common_stop_vmm() == BF_SUCCESS);
CHECK(common_unload_vmm() == ENTRY_ERROR_UNKNOWN);
CHECK(common_fini() == BF_ERROR_VMM_CORRUPTED);
common_reset();
}
#endif

View file

@ -1,124 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cert-err58-cpp
//
// Reason:
// The operator+ may throw an exception, and since these vectors
// have static storage, tidy raises this error. This is unlikely to happen,
// and if it does, it will only happen in the bfdriver unittests
//
#include <vector>
#include <string>
#include <bffile.h>
#include <bfelf_loader.h>
file g_file;
std::vector<std::string> g_filenames_success = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main"_s,
};
std::vector<std::string> g_filenames_init_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_init_fails"_s,
};
std::vector<std::string> g_filenames_fini_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_fini_fails"_s,
};
std::vector<std::string> g_filenames_add_mdl_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_add_mdl_fails"_s,
};
std::vector<std::string> g_filenames_get_drr_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_get_drr_fails"_s,
};
std::vector<std::string> g_filenames_set_rsdp_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_set_rsdp_fails"_s,
};
std::vector<std::string> g_filenames_vmm_init_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_vmm_init_fails"_s,
};
std::vector<std::string> g_filenames_vmm_fini_fails = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libc.a"_s,
VMM_PREFIX_PATH + "/lib/libc++abi.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main_vmm_fini_fails"_s,
};

View file

@ -1,35 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef TEST_SUPPORT_H
#define TEST_SUPPORT_H
extern file g_file;
extern std::vector<std::string> g_filenames_success;
extern std::vector<std::string> g_filenames_init_fails;
extern std::vector<std::string> g_filenames_fini_fails;
extern std::vector<std::string> g_filenames_add_mdl_fails;
extern std::vector<std::string> g_filenames_get_drr_fails;
extern std::vector<std::string> g_filenames_set_rsdp_fails;
extern std::vector<std::string> g_filenames_vmm_init_fails;
extern std::vector<std::string> g_filenames_vmm_fini_fails;
#endif

View file

@ -1,97 +0,0 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.13)
project(bfdummy C CXX)
init_project(bfdummy INTERFACE)
target_include_directories(bfdummy INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)
target_link_libraries(bfdummy INTERFACE
--whole-archive -lbfcrt -lbfdso --no-whole-archive
${CMAKE_INSTALL_PREFIX}/lib/libc++.a
${CMAKE_INSTALL_PREFIX}/lib/libc++abi.a
vmm::bfpthread
vmm::bfunwind
${CMAKE_INSTALL_PREFIX}/lib/libm.a
${CMAKE_INSTALL_PREFIX}/lib/libc.a
vmm::bfsyscall
)
#------------------------------------------------------------------------------
# Libraries
#------------------------------------------------------------------------------
add_library(dummy_lib1 src/libs/dummy_lib1.cpp)
add_library(dummy_lib2 src/libs/dummy_lib2.cpp)
target_link_libraries(dummy_lib1 PUBLIC bfdummy)
target_link_libraries(dummy_lib2 PUBLIC bfdummy)
set_target_properties(dummy_lib1 PROPERTIES LINKER_LANGUAGE C)
set_target_properties(dummy_lib2 PROPERTIES LINKER_LANGUAGE C)
install(TARGETS dummy_lib1 DESTINATION lib EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_lib2 DESTINATION lib EXPORT bfdummy-vmm-targets)
#------------------------------------------------------------------------------
# Executables
#------------------------------------------------------------------------------
add_executable(dummy_main src/main/dummy_main.cpp)
add_executable(dummy_main_init_fails src/main/dummy_main.cpp)
add_executable(dummy_main_fini_fails src/main/dummy_main.cpp)
add_executable(dummy_main_add_mdl_fails src/main/dummy_main.cpp)
add_executable(dummy_main_get_drr_fails src/main/dummy_main.cpp)
add_executable(dummy_main_set_rsdp_fails src/main/dummy_main.cpp)
add_executable(dummy_main_vmm_init_fails src/main/dummy_main.cpp)
add_executable(dummy_main_vmm_fini_fails src/main/dummy_main.cpp)
target_link_libraries(dummy_main PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_init_fails PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_fini_fails PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_add_mdl_fails PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_get_drr_fails PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_set_rsdp_fails PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_vmm_init_fails PRIVATE dummy_lib1 dummy_lib2)
target_link_libraries(dummy_main_vmm_fini_fails PRIVATE dummy_lib1 dummy_lib2)
target_compile_definitions(dummy_main_init_fails PRIVATE REQUEST_INIT_FAILS)
target_compile_definitions(dummy_main_fini_fails PRIVATE REQUEST_FINI_FAILS)
target_compile_definitions(dummy_main_add_mdl_fails PRIVATE REQUEST_ADD_MDL_FAILS)
target_compile_definitions(dummy_main_get_drr_fails PRIVATE REQUEST_GET_DRR_FAILS)
target_compile_definitions(dummy_main_set_rsdp_fails PRIVATE REQUEST_SET_RSDP_FAILS)
target_compile_definitions(dummy_main_vmm_init_fails PRIVATE REQUEST_VMM_INIT_FAILS)
target_compile_definitions(dummy_main_vmm_fini_fails PRIVATE REQUEST_VMM_FINI_FAILS)
install(TARGETS dummy_main DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_init_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_fini_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_add_mdl_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_get_drr_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_set_rsdp_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_vmm_init_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
install(TARGETS dummy_main_vmm_fini_fails DESTINATION bin EXPORT bfdummy-vmm-targets)
fini_project()

View file

@ -1,77 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef DUMMY_LIBS_H
#define DUMMY_LIBS_H
#include <stddef.h>
#include <stdint.h>
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
/* @cond */
extern int global_var;
class base
{
public:
base() noexcept = default;
virtual ~base() = default;
virtual int
foo(int) noexcept
{
return 0;
}
};
class derived1 : public base
{
public:
derived1() noexcept;
~derived1() override;
int
foo(int arg) noexcept override;
private:
int m_member{1000};
};
class derived2 : public base
{
public:
derived2() noexcept;
~derived2() override;
int
foo(int arg) noexcept override;
private:
int m_member{2000};
};
/* @endcond */
#endif

View file

@ -1,44 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <bfexports.h>
#include <dummy_libs.h>
extern "C" int
lib1_foo()
{ return 1; }
derived1::derived1() noexcept
{
global_var++;
}
derived1::~derived1()
{
global_var--;
m_member = 0;
}
int
derived1::foo(int arg) noexcept
{
return arg + m_member;
}

View file

@ -1,41 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <dummy_libs.h>
extern "C" int lib1_foo();
derived2::derived2() noexcept
{
global_var += lib1_foo();
}
derived2::~derived2()
{
global_var -= lib1_foo();
m_member = 0;
}
int
derived2::foo(int arg) noexcept
{
return arg + m_member;
}

View file

@ -1,224 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cppcoreguidelines-pro*
//
// Reason:
// Although written in C++, this code needs to implement C specific logic
// that by its very definition will not adhere to the core guidelines
// similar to libc which is needed by all C++ implementations.
//
#ifndef REQUEST_INIT_FAILS
#define REQUEST_INIT_RETURN ENTRY_SUCCESS
#else
#define REQUEST_INIT_RETURN ENTRY_ERROR_UNKNOWN
#endif
#ifndef REQUEST_FINI_FAILS
#define REQUEST_FINI_RETURN ENTRY_SUCCESS
#else
#define REQUEST_FINI_RETURN ENTRY_ERROR_UNKNOWN
#endif
#ifndef REQUEST_ADD_MDL_FAILS
#define REQUEST_ADD_MDL_RETURN ENTRY_SUCCESS
#else
#define REQUEST_ADD_MDL_RETURN ENTRY_ERROR_UNKNOWN
#endif
#ifndef REQUEST_GET_DRR_FAILS
#define REQUEST_GET_DRR_RETURN ENTRY_SUCCESS
#else
#define REQUEST_GET_DRR_RETURN ENTRY_ERROR_UNKNOWN
#endif
#ifndef REQUEST_SET_RSDP_FAILS
#define REQUEST_SET_RSDP_RETURN ENTRY_SUCCESS
#else
#define REQUEST_SET_RSDP_RETURN ENTRY_ERROR_UNKNOWN
#endif
#ifndef REQUEST_VMM_INIT_FAILS
#define REQUEST_VMM_INIT_RETURN ENTRY_SUCCESS
#else
#define REQUEST_VMM_INIT_RETURN ENTRY_ERROR_UNKNOWN
#endif
#ifndef REQUEST_VMM_FINI_FAILS
#define REQUEST_VMM_FINI_RETURN ENTRY_SUCCESS
#else
#define REQUEST_VMM_FINI_RETURN ENTRY_ERROR_UNKNOWN
#endif
#include <bfgsl.h>
#include <bftypes.h>
#include <bfexports.h>
#include <bfsupport.h>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <dummy_libs.h>
int g_errno;
int *__errno() { return &g_errno; }
derived1 g_derived1;
derived2 g_derived2;
int global_var = 0;
int
main(int argc, char *argv[])
{
if (argc != 2) {
return -1;
}
try {
throw std::runtime_error("test exceptions");
}
catch (std::exception &) {
auto view = gsl::make_span(argv, argc);
return g_derived1.foo(gsl::narrow_cast<int>(strtol(view[0], nullptr, 10))) +
g_derived2.foo(gsl::narrow_cast<int>(strtol(view[1], nullptr, 10)));
}
return 0;
}
extern "C" int64_t
bfmain(uintptr_t request, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
{
bfignored(arg1);
bfignored(arg2);
bfignored(arg3);
switch (request) {
case BF_REQUEST_INIT:
return REQUEST_INIT_RETURN;
case BF_REQUEST_FINI:
return REQUEST_FINI_RETURN;
case BF_REQUEST_ADD_MDL:
return REQUEST_ADD_MDL_RETURN;
case BF_REQUEST_GET_DRR:
return REQUEST_GET_DRR_RETURN;
case BF_REQUEST_VMM_INIT:
return REQUEST_VMM_INIT_RETURN;
case BF_REQUEST_VMM_FINI:
return REQUEST_VMM_FINI_RETURN;
case BF_REQUEST_SET_RSDP:
return REQUEST_SET_RSDP_RETURN;
default:
break;
}
return ENTRY_ERROR_UNKNOWN;
}
// -----------------------------------------------------------------------------
// Missing C Functions
// -----------------------------------------------------------------------------
int g_cursor = 0;
char g_memory[0x100000] = {};
extern "C" int
write(int file, const void *buffer, size_t count)
{
bfignored(file);
bfignored(buffer);
bfignored(count);
return 0;
}
extern "C" uint64_t
unsafe_write_cstr(const char *cstr, size_t len)
{
bfignored(cstr);
bfignored(len);
return 0;
}
extern "C" void *
_malloc_r(struct _reent *ent, size_t size)
{
bfignored(ent);
auto addr = &gsl::at(g_memory, g_cursor);
g_cursor += size;
return addr;
}
extern "C" void
_free_r(struct _reent *ent, void *ptr)
{
bfignored(ent);
bfignored(ptr);
}
extern "C" void *
_calloc_r(struct _reent *ent, size_t nmemb, size_t size)
{
bfignored(ent);
if (auto ptr = _malloc_r(nullptr, nmemb * size)) {
return memset(ptr, 0, nmemb * size);
}
return nullptr;
}
extern "C" void *
_realloc_r(struct _reent *ent, void *ptr, size_t size)
{
bfignored(ent);
bfignored(ptr);
bfignored(size);
return nullptr;
}
extern "C" uint64_t *
thread_context_tlsptr(void)
{
static uint64_t s_tls[0x1000] = {};
return s_tls;
}
extern "C" uint64_t
thread_context_cpuid(void)
{
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,266 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @file bfelf_loader_reloc_aarch64.h
*/
/*
* AArch64 Relocations
*
* The following is defined in the "ELF for the ARM 64-bit architecture"
* specification:
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
*
* @cond
*/
/* ---------------------------------------------------------------------------------------------- */
/* Miscellaneous relocations */
/* ---------------------------------------------------------------------------------------------- */
#define BFR_AARCH64_NONE bfscast(bfelf64_xword, 0)
/* ---------------------------------------------------------------------------------------------- */
/* Static data relocations */
/* ---------------------------------------------------------------------------------------------- */
/* Data relocations */
#define BFR_AARCH64_ABS64 bfscast(bfelf64_xword, 257)
#define BFR_AARCH64_ABS32 bfscast(bfelf64_xword, 258)
#define BFR_AARCH64_ABS16 bfscast(bfelf64_xword, 259)
#define BFR_AARCH64_PREL64 bfscast(bfelf64_xword, 260)
#define BFR_AARCH64_PREL32 bfscast(bfelf64_xword, 261)
#define BFR_AARCH64_PREL16 bfscast(bfelf64_xword, 262)
/* ---------------------------------------------------------------------------------------------- */
/* Static AArch64 relocations */
/* ---------------------------------------------------------------------------------------------- */
/* Group relocations to create an unsigned data value or address inline */
#define BFR_AARCH64_MOVW_UABS_G0 bfscast(bfelf64_xword, 263)
#define BFR_AARCH64_MOVW_UABS_G0_NC bfscast(bfelf64_xword, 264)
#define BFR_AARCH64_MOVW_UABS_G1 bfscast(bfelf64_xword, 265)
#define BFR_AARCH64_MOVW_UABS_G1_NC bfscast(bfelf64_xword, 266)
#define BFR_AARCH64_MOVW_UABS_G2 bfscast(bfelf64_xword, 267)
#define BFR_AARCH64_MOVW_UABS_G2_NC bfscast(bfelf64_xword, 268)
#define BFR_AARCH64_MOVW_UABS_G3 bfscast(bfelf64_xword, 269)
/* Group relocations to create a signed data or offset value inline */
#define BFR_AARCH64_MOVW_SABS_G0 bfscast(bfelf64_xword, 270)
#define BFR_AARCH64_MOVW_SABS_G1 bfscast(bfelf64_xword, 271)
#define BFR_AARCH64_MOVW_SABS_G2 bfscast(bfelf64_xword, 272)
/* Relocations to generate PC-relative addresses */
#define BFR_AARCH64_LD_PREL_LO19 bfscast(bfelf64_xword, 273)
#define BFR_AARCH64_ADR_PREL_LO21 bfscast(bfelf64_xword, 274)
#define BFR_AARCH64_ADR_PREL_PG_HI21 bfscast(bfelf64_xword, 275)
#define BFR_AARCH64_ADR_PREL_PG_HI21_NC bfscast(bfelf64_xword, 276)
#define BFR_AARCH64_ADD_ABS_LO12_NC bfscast(bfelf64_xword, 277)
#define BFR_AARCH64_LDST8_ABS_LO12_NC bfscast(bfelf64_xword, 278)
#define BFR_AARCH64_LDST16_ABS_LO12_NC bfscast(bfelf64_xword, 284)
#define BFR_AARCH64_LDST32_ABS_LO12_NC bfscast(bfelf64_xword, 285)
#define BFR_AARCH64_LDST64_ABS_LO12_NC bfscast(bfelf64_xword, 286)
#define BFR_AARCH64_LDST128_ABS_LO12_NC bfscast(bfelf64_xword, 299)
/* Relocations for control-flow instructions */
#define BFR_AARCH64_TSTBR14 bfscast(bfelf64_xword, 279)
#define BFR_AARCH64_CONDBR19 bfscast(bfelf64_xword, 280)
#define BFR_AARCH64_JUMP26 bfscast(bfelf64_xword, 282)
#define BFR_AARCH64_CALL26 bfscast(bfelf64_xword, 283)
/* Group relocations to create a PC-relative offset inline */
#define BFR_AARCH64_MOVW_PREL_G0 bfscast(bfelf64_xword, 287)
#define BFR_AARCH64_MOVW_PREL_G0_NC bfscast(bfelf64_xword, 288)
#define BFR_AARCH64_MOVW_PREL_G1 bfscast(bfelf64_xword, 289)
#define BFR_AARCH64_MOVW_PREL_G1_NC bfscast(bfelf64_xword, 290)
#define BFR_AARCH64_MOVW_PREL_G2 bfscast(bfelf64_xword, 291)
#define BFR_AARCH64_MOVW_PREL_G2_NC bfscast(bfelf64_xword, 292)
#define BFR_AARCH64_MOVW_PREL_G3 bfscast(bfelf64_xword, 293)
/* Group relocations to create a GOT-relative offset inline */
#define BFR_AARCH64_MOVW_GOTOFF_G0 bfscast(bfelf64_xword, 300)
#define BFR_AARCH64_MOVW_GOTOFF_G0_NC bfscast(bfelf64_xword, 301)
#define BFR_AARCH64_MOVW_GOTOFF_G1 bfscast(bfelf64_xword, 302)
#define BFR_AARCH64_MOVW_GOTOFF_G1_NC bfscast(bfelf64_xword, 303)
#define BFR_AARCH64_MOVW_GOTOFF_G2 bfscast(bfelf64_xword, 304)
#define BFR_AARCH64_MOVW_GOTOFF_G2_NC bfscast(bfelf64_xword, 305)
#define BFR_AARCH64_MOVW_GOTOFF_G3 bfscast(bfelf64_xword, 306)
/* GOT-relative data relocations */
#define BFR_AARCH64_GOTREL64 bfscast(bfelf64_xword, 307)
#define BFR_AARCH64_GOTREL32 bfscast(bfelf64_xword, 308)
/* GOT-relative instruction relocations */
#define BFR_AARCH64_GOT_LD_PREL19 bfscast(bfelf64_xword, 309)
#define BFR_AARCH64_LD64_GOTOFF_LO15 bfscast(bfelf64_xword, 310)
#define BFR_AARCH64_ADR_GOT_PAGE bfscast(bfelf64_xword, 311)
#define BFR_AARCH64_LD64_GOT_LO12_NC bfscast(bfelf64_xword, 312)
#define BFR_AARCH64_LD64_GOTPAGE_LO15 bfscast(bfelf64_xword, 313)
/* ---------------------------------------------------------------------------------------------- */
/* Relocations for thread-local storage */
/* ---------------------------------------------------------------------------------------------- */
/* General dynamic TLS relocations */
#define BFR_AARCH64_TLSGD_ADR_PREL21 bfscast(bfelf64_xword, 512)
#define BFR_AARCH64_TLSGD_ADR_PAGE21 bfscast(bfelf64_xword, 513)
#define BFR_AARCH64_TLSGD_ADD_LO12_NC bfscast(bfelf64_xword, 514)
#define BFR_AARCH64_TLSGD_MOVW_G1 bfscast(bfelf64_xword, 515)
#define BFR_AARCH64_TLSGD_MOVW_G0_NC bfscast(bfelf64_xword, 516)
/* Local dynamic TLS relocations */
#define BFR_AARCH64_TLSLD_ADR_PREL21 bfscast(bfelf64_xword, 517)
#define BFR_AARCH64_TLSLD_ADR_PAGE21 bfscast(bfelf64_xword, 518)
#define BFR_AARCH64_TLSLD_ADD_LO12_NC bfscast(bfelf64_xword, 519)
#define BFR_AARCH64_TLSLD_MOVW_G1 bfscast(bfelf64_xword, 520)
#define BFR_AARCH64_TLSLD_MOVW_G0_NC bfscast(bfelf64_xword, 521)
#define BFR_AARCH64_TLSLD_LD_PREL19 bfscast(bfelf64_xword, 522)
#define BFR_AARCH64_TLSLD_MOVW_DTPREL_G2 bfscast(bfelf64_xword, 523)
#define BFR_AARCH64_TLSLD_MOVW_DTPREL_G1 bfscast(bfelf64_xword, 524)
#define BFR_AARCH64_TLSLD_MOVW_DTPREL_G1_NC bfscast(bfelf64_xword, 525)
#define BFR_AARCH64_TLSLD_MOVW_DTPREL_G0 bfscast(bfelf64_xword, 526)
#define BFR_AARCH64_TLSLD_MOVW_DTPREL_G0_NC bfscast(bfelf64_xword, 527)
#define BFR_AARCH64_TLSLD_ADD_DTPREL_HI12 bfscast(bfelf64_xword, 528)
#define BFR_AARCH64_TLSLD_ADD_DTPREL_LO12 bfscast(bfelf64_xword, 529)
#define BFR_AARCH64_TLSLD_ADD_DTPREL_LO12_NC bfscast(bfelf64_xword, 530)
#define BFR_AARCH64_TLSLD_LDST8_DTPREL_LO12 bfscast(bfelf64_xword, 531)
#define BFR_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC bfscast(bfelf64_xword, 532)
#define BFR_AARCH64_TLSLD_LDST16_DTPREL_LO12 bfscast(bfelf64_xword, 533)
#define BFR_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC bfscast(bfelf64_xword, 534)
#define BFR_AARCH64_TLSLD_LDST32_DTPREL_LO12 bfscast(bfelf64_xword, 535)
#define BFR_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC bfscast(bfelf64_xword, 536)
#define BFR_AARCH64_TLSLD_LDST64_DTPREL_LO12 bfscast(bfelf64_xword, 537)
#define BFR_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC bfscast(bfelf64_xword, 538)
#define BFR_AARCH64_TLSLD_LDST128_DTPREL_LO12 bfscast(bfelf64_xword, 572)
#define BFR_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC bfscast(bfelf64_xword, 573)
/* Initial exec TLS relocations */
#define BFR_AARCH64_TLSIE_MOVW_GOTTPREP_G1 bfscast(bfelf64_xword, 539)
#define BFR_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC bfscast(bfelf64_xword, 540)
#define BFR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 bfscast(bfelf64_xword, 541)
#define BFR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC bfscast(bfelf64_xword, 542)
#define BFR_AARCH64_TLSIE_LD_GOTTPREL_PREL19 bfscast(bfelf64_xword, 543)
/* Local exec TLS relocations */
#define BFR_AARCH64_TLSLE_MOVW_TPREL_G2 bfscast(bfelf64_xword, 544)
#define BFR_AARCH64_TLSLE_MOVW_TPREL_G1 bfscast(bfelf64_xword, 545)
#define BFR_AARCH64_TLSLE_MOVW_TPREL_G1_NC bfscast(bfelf64_xword, 546)
#define BFR_AARCH64_TLSLE_MOVW_TPREL_G0 bfscast(bfelf64_xword, 547)
#define BFR_AARCH64_TLSLE_MOVW_TPREL_G0_NC bfscast(bfelf64_xword, 548)
#define BFR_AARCH64_TLSLE_ADD_TPREL_HI12 bfscast(bfelf64_xword, 549)
#define BFR_AARCH64_TLSLE_ADD_TPREL_LO12 bfscast(bfelf64_xword, 550)
#define BFR_AARCH64_TLSLE_ADD_TPREL_LO12_NC bfscast(bfelf64_xword, 551)
#define BFR_AARCH64_TLSLE_LDST8_TPREL_LO12 bfscast(bfelf64_xword, 552)
#define BFR_AARCH64_TLSLE_LDST8_TPREL_LO12_NC bfscast(bfelf64_xword, 553)
#define BFR_AARCH64_TLSLE_LDST16_TPREL_LO12 bfscast(bfelf64_xword, 554)
#define BFR_AARCH64_TLSLE_LDST16_TPREL_LO12_NC bfscast(bfelf64_xword, 555)
#define BFR_AARCH64_TLSLE_LDST32_TPREL_LO12 bfscast(bfelf64_xword, 556)
#define BFR_AARCH64_TLSLE_LDST32_TPREL_LO12_NC bfscast(bfelf64_xword, 557)
#define BFR_AARCH64_TLSLE_LDST64_TPREL_LO12 bfscast(bfelf64_xword, 558)
#define BFR_AARCH64_TLSLE_LDST64_TPREL_LO12_NC bfscast(bfelf64_xword, 559)
#define BFR_AARCH64_TLSLE_LDST128_TPREL_LO12 bfscast(bfelf64_xword, 570)
#define BFR_AARCH64_TLSLE_LDST128_TPREL_LO12_NC bfscast(bfelf64_xword, 571)
/* TLS descriptor relocations */
#define BFR_AARCH64_TLSDESC_LD_PREL19 bfscast(bfelf64_xword, 560)
#define BFR_AARCH64_TLSDESC_ADR_PREL21 bfscast(bfelf64_xword, 561)
#define BFR_AARCH64_TLSDESC_ADR_PAGE21 bfscast(bfelf64_xword, 562)
#define BFR_AARCH64_TLSDESC_LD64_LO12 bfscast(bfelf64_xword, 563)
#define BFR_AARCH64_TLSDESC_ADD_LO12 bfscast(bfelf64_xword, 564)
#define BFR_AARCH64_TLSDESC_OFF_G1 bfscast(bfelf64_xword, 656)
#define BFR_AARCH64_TLSDESC_OFF_G0_NC bfscast(bfelf64_xword, 566)
#define BFR_AARCH64_TLSDESC_LDR bfscast(bfelf64_xword, 567)
#define BFR_AARCH64_TLSDESC_ADD bfscast(bfelf64_xword, 568)
#define BFR_AARCH64_TLSDESC_CALL bfscast(bfelf64_xword, 569)
/* ---------------------------------------------------------------------------------------------- */
/* Dynamic relocations */
/* ---------------------------------------------------------------------------------------------- */
#define BFR_AARCH64_COPY bfscast(bfelf64_xword, 1024)
#define BFR_AARCH64_GLOB_DAT bfscast(bfelf64_xword, 1025)
#define BFR_AARCH64_JUMP_SLOT bfscast(bfelf64_xword, 1026)
#define BFR_AARCH64_RELATIVE bfscast(bfelf64_xword, 1027)
#define BFR_AARCH64_TLS_DTPREL64 bfscast(bfelf64_xword, 1028)
#define BFR_AARCH64_TLS_DTPMOD64 bfscast(bfelf64_xword, 1029)
#define BFR_AARCH64_TLS_TPREL64 bfscast(bfelf64_xword, 1030)
#define BFR_AARCH64_TLSDESC bfscast(bfelf64_xword, 1031)
#define BFR_AARCH64_IRELATIVE bfscast(bfelf64_xword, 1032)
/* @endcond */
/* ---------------------------------------------------------------------------------------------- */
/* ELF Relocations Implementation */
/* ---------------------------------------------------------------------------------------------- */
/* @cond */
static inline int64_t
private_relocate_symbol(
struct bfelf_loader_t *loader, struct bfelf_file_t *ef, const struct bfelf_rela *rela)
{
const char *str = nullptr;
const struct bfelf_sym *found_sym = nullptr;
struct bfelf_file_t *found_ef = ef;
bfelf64_addr *ptr = bfrcast(bfelf64_addr *, ef->exec_addr + rela->r_offset - ef->start_addr);
if (BFELF_REL_TYPE(rela->r_info) == BFR_AARCH64_RELATIVE) {
*ptr = bfrcast(bfelf64_addr, ef->exec_virt + rela->r_addend);
return BFELF_SUCCESS;
}
found_sym = &(ef->symtab[BFELF_REL_SYM(rela->r_info)]);
if (BFELF_SYM_BIND(found_sym->st_info) == bfstb_weak) {
found_ef = nullptr;
}
if (found_sym->st_value == 0 || found_ef == nullptr) {
int64_t ret;
str = &(ef->strtab[found_sym->st_name]);
ret = private_get_sym_global(loader, str, &found_ef, &found_sym);
if (ret != BFELF_SUCCESS) {
return ret;
}
}
switch (BFELF_REL_TYPE(rela->r_info)) {
case BFR_AARCH64_GLOB_DAT:
case BFR_AARCH64_JUMP_SLOT:
case BFR_AARCH64_ABS64:
*ptr = bfrcast(bfelf64_addr, found_ef->exec_virt + found_sym->st_value);
break;
case BFR_AARCH64_ABS32:
*(uint32_t *) ptr = bfrcast(uint32_t, found_ef->exec_virt + found_sym->st_value);
break;
case BFR_AARCH64_ABS16:
*(uint16_t *) ptr = bfrcast(uint16_t, found_ef->exec_virt + found_sym->st_value);
break;
default:
return bfunsupported_rel(str);
}
return BFELF_SUCCESS;
}
/* @endcond */

View file

@ -1,96 +0,0 @@
/*
* Copyright (C) 2019 Assured Information Security, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @file bfelf_loader_reloc_x64.h
*/
/*
* System V ABI 64bit Relocations
*
* The following is defined in the ELF 64bit file format specification:
* http://www.x86-64.org/documentation/abi.pdf, page 71
*
* @cond
*/
#define BFR_X86_64_64 bfscast(bfelf64_xword, 1)
#define BFR_X86_64_GLOB_DAT bfscast(bfelf64_xword, 6)
#define BFR_X86_64_JUMP_SLOT bfscast(bfelf64_xword, 7)
#define BFR_X86_64_RELATIVE bfscast(bfelf64_xword, 8)
/* @endcond */
/* ---------------------------------------------------------------------------------------------- */
/* ELF Relocations Implementation */
/* ---------------------------------------------------------------------------------------------- */
/* @cond */
static inline int64_t
private_relocate_symbol(
struct bfelf_loader_t *loader, struct bfelf_file_t *ef, const struct bfelf_rela *rela)
{
const char *str = nullptr;
const struct bfelf_sym *found_sym = nullptr;
struct bfelf_file_t *found_ef = ef;
bfelf64_addr *ptr = bfrcast(bfelf64_addr *, ef->exec_addr + rela->r_offset - ef->start_addr);
if (BFELF_REL_TYPE(rela->r_info) == BFR_X86_64_RELATIVE) {
*ptr = bfrcast(bfelf64_addr, ef->exec_virt + rela->r_addend);
return BFELF_SUCCESS;
}
found_sym = &(ef->symtab[BFELF_REL_SYM(rela->r_info)]);
if (BFELF_SYM_BIND(found_sym->st_info) == bfstb_weak) {
found_ef = nullptr;
}
if (found_sym->st_value == 0 || found_ef == nullptr) {
int64_t ret = 0;
str = &(ef->strtab[found_sym->st_name]);
ret = private_get_sym_global(loader, str, &found_ef, &found_sym);
if (ret != BFELF_SUCCESS) {
return ret;
}
}
*ptr = bfrcast(bfelf64_addr, found_ef->exec_virt + found_sym->st_value);
switch (BFELF_REL_TYPE(rela->r_info)) {
case BFR_X86_64_64:
*ptr += bfscast(bfelf64_addr, rela->r_addend);
break;
case BFR_X86_64_GLOB_DAT:
case BFR_X86_64_JUMP_SLOT:
break;
default:
return bfunsupported_rel(str);
}
return BFELF_SUCCESS;
}
/* @endcond */

View file

@ -1,139 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <hippomocks.h>
#include <test_real_elf.h>
#ifdef _HIPPOMOCKS__ENABLE_CFUNC_MOCKING_SUPPORT
TEST_CASE("bfelf_binary: binary load fails")
{
MockRepository mocks;
mocks.OnCallFunc(bfelf_load).Return(-1);
file f;
CHECK_THROWS(binaries_info(&f, g_filenames.back(), {VMM_PREFIX_PATH + "/lib/"_s}));
}
TEST_CASE("bfelf_binary: binary success")
{
file f;
CHECK_NOTHROW(binaries_info(&f, g_filenames.back(), {VMM_PREFIX_PATH + "/lib/"_s}));
}
TEST_CASE("bfelf_binary: module list load fails")
{
MockRepository mocks;
mocks.OnCallFunc(bfelf_load).Return(-1);
file f;
CHECK_THROWS(binaries_info(&f, g_filenames));
}
TEST_CASE("bfelf_binary: module list success")
{
file f;
CHECK_NOTHROW(binaries_info(&f, g_filenames));
}
TEST_CASE("bfelf_binary: set args")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.set_args(0, nullptr));
}
TEST_CASE("bfelf_binary: ef")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.ef());
}
TEST_CASE("bfelf_binary: ef index")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.ef(0));
}
TEST_CASE("bfelf_binary: at")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.at(0));
}
TEST_CASE("bfelf_binary: front")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.front());
}
TEST_CASE("bfelf_binary: back")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.back());
}
TEST_CASE("bfelf_binary: binaries")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.binaries());
}
TEST_CASE("bfelf_binary: info")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.info());
}
TEST_CASE("bfelf_binary: entry")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.entry());
}
TEST_CASE("bfelf_binary: loader")
{
file f;
binaries_info info(&f, g_filenames);
CHECK_NOTHROW(info.loader());
}
#endif

View file

@ -1,162 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cppcoreguidelines-pro-type-reinterpret-cast
//
// Reason:
// Although in general this is a good rule, for hypervisor level code that
// interfaces with the kernel, and raw hardware, this rule is
// impractical.
//
#include <cstdint>
#include <cstring>
#include <test_fake_elf.h>
#define offset(a, b) ((reinterpret_cast<uintptr_t>(&(a))) - (reinterpret_cast<uintptr_t>(&(b))))
std::pair<std::unique_ptr<char[]>, uint64_t>
get_fake_elf()
{
auto &&size = sizeof(bfelf_test);
auto &&buff = std::make_unique<char[]>(size);
auto &&test = reinterpret_cast<bfelf_test *>(buff.get());
test->header.e_ident[bfei_mag0] = 0x7F;
test->header.e_ident[bfei_mag1] = 'E';
test->header.e_ident[bfei_mag2] = 'L';
test->header.e_ident[bfei_mag3] = 'F';
test->header.e_ident[bfei_class] = bfelfclass64;
test->header.e_ident[bfei_data] = bfelfdata2lsb;
test->header.e_ident[bfei_version] = bfev_current;
test->header.e_ident[bfei_osabi] = bfelfosabi_sysv;
test->header.e_ident[bfei_abiversion] = 0;
test->header.e_type = bfet_dyn;
test->header.e_machine = bfem_x86_64;
test->header.e_version = bfev_current;
test->header.e_entry = 0x150;
test->header.e_phoff = offset(test->phdrtab, *test);
test->header.e_shoff = offset(test->shdrtab, *test);
test->header.e_flags = 0;
test->header.e_ehsize = sizeof(bfelf_ehdr);
test->header.e_phentsize = sizeof(bfelf_phdr);
test->header.e_phnum = sizeof(test_phdrtab) / sizeof(bfelf_phdr);
test->header.e_shentsize = sizeof(bfelf_shdr);
test->header.e_shnum = sizeof(test_shdrtab) / sizeof(bfelf_shdr);
test->header.e_shstrndx = 2;
test->phdrtab.re_segment.p_type = bfpt_load;
test->phdrtab.re_segment.p_flags = bfpf_r | bfpf_x;
test->phdrtab.re_segment.p_offset = 0;
test->phdrtab.re_segment.p_vaddr = 0;
test->phdrtab.re_segment.p_paddr = 0;
test->phdrtab.re_segment.p_filesz = 0x500;
test->phdrtab.re_segment.p_memsz = 0x500;
test->phdrtab.re_segment.p_align = 0x1000;
test->phdrtab.rw_segment.p_type = bfpt_load;
test->phdrtab.rw_segment.p_flags = bfpf_r | bfpf_w;
test->phdrtab.rw_segment.p_offset = 0x500;
test->phdrtab.rw_segment.p_vaddr = 0x500;
test->phdrtab.rw_segment.p_paddr = 0x500;
test->phdrtab.rw_segment.p_filesz = 0x500;
test->phdrtab.rw_segment.p_memsz = 0x500;
test->phdrtab.rw_segment.p_align = 0x1000;
test->phdrtab.dyn_segment.p_type = bfpt_dynamic;
test->phdrtab.dyn_segment.p_flags = bfpf_r | bfpf_w;
test->phdrtab.dyn_segment.p_offset = offset(test->dynamic, *test);
test->phdrtab.dyn_segment.p_vaddr = 0x0;
test->phdrtab.dyn_segment.p_paddr = 0x0;
test->phdrtab.dyn_segment.p_filesz = sizeof(test_dynamic);
test->phdrtab.dyn_segment.p_memsz = sizeof(test_dynamic);
test->phdrtab.dyn_segment.p_align = 0x1000;
test->phdrtab.stack_segment.p_type = bfpt_gnu_stack;
test->phdrtab.stack_segment.p_flags = bfpf_r | bfpf_w;
test->phdrtab.stack_segment.p_offset = 0x0;
test->phdrtab.stack_segment.p_vaddr = 0x0;
test->phdrtab.stack_segment.p_paddr = 0x0;
test->phdrtab.stack_segment.p_filesz = 0x0;
test->phdrtab.stack_segment.p_memsz = 0x0;
test->phdrtab.stack_segment.p_align = 0x0;
test->phdrtab.relro_segment.p_type = bfpt_gnu_relro;
test->phdrtab.relro_segment.p_flags = bfpf_r;
test->phdrtab.relro_segment.p_offset = 0x0;
test->phdrtab.relro_segment.p_vaddr = 0x0;
test->phdrtab.relro_segment.p_paddr = 0x0;
test->phdrtab.relro_segment.p_filesz = 0x500;
test->phdrtab.relro_segment.p_memsz = 0x500;
test->phdrtab.relro_segment.p_align = 0x1000;
test->dynamic.needed1.d_tag = bfdt_needed;
test->dynamic.needed2.d_tag = bfdt_needed;
test->dynamic.pltgot.d_tag = bfdt_pltgot;
test->dynamic.strtab.d_tag = bfdt_strtab;
test->dynamic.strtab.d_val = offset(test->dynstr, *test);
test->dynamic.symtab.d_tag = bfdt_symtab;
test->dynamic.symtab.d_val = offset(test->dynsym, *test);
test->dynamic.rela.d_tag = bfdt_rela;
test->dynamic.rela.d_val = offset(test->relatab, *test);
test->dynamic.relasz.d_tag = bfdt_relasz;
test->dynamic.relasz.d_val = sizeof(test_relatab);
test->dynamic.relaent.d_tag = bfdt_relaent;
test->dynamic.relaent.d_val = sizeof(bfelf_rela);
test->dynamic.strsz.d_tag = bfdt_strsz;
test->dynamic.strsz.d_val = sizeof(test_dynstr);
test->dynamic.init.d_tag = bfdt_init;
test->dynamic.init.d_val = offset(test->init_array, *test);
test->dynamic.fini.d_tag = bfdt_fini;
test->dynamic.fini.d_val = offset(test->fini_array, *test);
test->dynamic.init_array.d_tag = bfdt_init_array;
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_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;
test->shdrtab.eh_frame.sh_name = 0x0;
test->shdrtab.eh_frame.sh_type = bfsht_strtab;
test->shdrtab.eh_frame.sh_flags = 0;
test->shdrtab.eh_frame.sh_addr = 0x250;
test->shdrtab.eh_frame.sh_offset = offset(test->eh_frame, *test);
test->shdrtab.eh_frame.sh_size = sizeof(test_eh_frame);
test->shdrtab.eh_frame.sh_link = 0;
test->shdrtab.eh_frame.sh_addralign = 1;
test->shdrtab.eh_frame.sh_entsize = 0;
test->shdrtab.dynstr.sh_offset = offset(test->dynstr, *test);
test->shdrtab.eh_frame.sh_name = 10;
test->shdrtab.ctors.sh_name = 20;
test->shdrtab.dtors.sh_name = 30;
strncpy(static_cast<char *>(test->dynstr.str2), ".eh_frame", 10);
strncpy(static_cast<char *>(test->dynstr.str3), ".ctors", 10);
strncpy(static_cast<char *>(test->dynstr.str4), ".dtors", 10);
return {std::move(buff), size};
}

View file

@ -1,136 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef TEST_FAKE_ELF_H
#define TEST_FAKE_ELF_H
#include <memory>
#include <bfelf_loader.h>
std::pair<std::unique_ptr<char[]>, uint64_t>
get_fake_elf();
#pragma pack(push, 1)
#ifdef __cplusplus
extern "C" {
#endif
struct test_phdrtab {
bfelf_phdr re_segment;
bfelf_phdr rw_segment;
bfelf_phdr dyn_segment;
bfelf_phdr stack_segment;
bfelf_phdr relro_segment;
};
struct test_hash {
bfelf64_word nbucket;
bfelf64_word nchain;
bfelf64_word index1;
bfelf64_word index2;
bfelf64_word hash1;
bfelf64_word hash2;
};
struct test_dynsym {
bfelf_sym syms[2];
};
struct test_dynstr {
char str1[10];
char str2[10];
char str3[10];
char str4[10];
};
struct test_relatab {
struct bfelf_rela relas[2];
};
struct test_eh_frame {
const char *reserved[10];
};
struct test_init_array {
const char *reserved[10];
};
struct test_fini_array {
const char *reserved[10];
};
struct test_dynamic {
struct bfelf_dyn needed1;
struct bfelf_dyn needed2;
struct bfelf_dyn pltgot;
struct bfelf_dyn strtab;
struct bfelf_dyn symtab;
struct bfelf_dyn rela;
struct bfelf_dyn relasz;
struct bfelf_dyn relaent;
struct bfelf_dyn strsz;
struct bfelf_dyn init;
struct bfelf_dyn fini;
struct bfelf_dyn init_array;
struct bfelf_dyn fini_array;
struct bfelf_dyn init_arraysz;
struct bfelf_dyn fini_arraysz;
struct bfelf_dyn flags_1;
struct bfelf_dyn last;
};
struct test_shdrtab {
bfelf_shdr hash;
bfelf_shdr dynsym;
bfelf_shdr dynstr;
bfelf_shdr relatab;
bfelf_shdr eh_frame;
bfelf_shdr init_array;
bfelf_shdr fini_array;
bfelf_shdr dynamic;
bfelf_shdr ctors;
bfelf_shdr dtors;
};
struct bfelf_test {
bfelf_ehdr header;
test_phdrtab phdrtab;
test_dynsym dynsym;
test_dynstr dynstr;
test_hash hash;
test_relatab relatab;
test_eh_frame eh_frame;
test_init_array init_array;
test_fini_array fini_array;
test_dynamic dynamic;
test_shdrtab shdrtab;
};
#ifdef __cplusplus
}
#endif
#pragma pack(pop)
#endif

View file

@ -1,77 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_fake_elf.h>
#include <test_real_elf.h>
TEST_CASE("bfelf_file_get_entry: invalid elf file")
{
void *addr = nullptr;
auto ret = bfelf_file_get_entry(nullptr, &addr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_entry: invalid addr")
{
int64_t ret = 0;
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_file_get_entry(&ef, nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_entry: not added to loader")
{
int64_t ret = 0;
void *addr = nullptr;
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_file_get_entry(&ef, &addr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_entry: success")
{
int64_t ret = 0;
void *addr = nullptr;
binaries_info binaries{&g_file, g_filenames};
ret = bfelf_file_get_entry(&binaries.ef(), &addr);
CHECK(ret == BFELF_SUCCESS);
}

View file

@ -1,81 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_fake_elf.h>
TEST_CASE("bfelf_file_get_load_instr: invalid elf file")
{
const bfelf_load_instr *instr = nullptr;
auto ret = bfelf_file_get_load_instr(nullptr, 0, &instr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_load_instr: include index")
{
int64_t ret = 0;
bfelf_file_t ef = {};
const bfelf_load_instr *instr = nullptr;
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_file_get_load_instr(&ef, 10, &instr);
CHECK(ret == BFELF_ERROR_INVALID_INDEX);
}
TEST_CASE("bfelf_file_get_load_instr: invalid instr")
{
int64_t ret = 0;
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_file_get_load_instr(&ef, 0, nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_load_instr: success")
{
int64_t ret = 0;
bfelf_file_t ef = {};
const bfelf_load_instr *instr = nullptr;
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_file_get_load_instr(&ef, 0, &instr);
CHECK(ret == BFELF_SUCCESS);
}

View file

@ -1,61 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_real_elf.h>
TEST_CASE("bfelf_file_get_needed: invalid elf file")
{
uint64_t index = 0;
const char *needed = nullptr;
auto ret = bfelf_file_get_needed(nullptr, index, &needed);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_needed: index")
{
uint64_t index = 0;
bfelf_file_t ef = {};
const char *needed = nullptr;
auto ret = bfelf_file_get_needed(&ef, index, &needed);
CHECK(ret == BFELF_ERROR_INVALID_INDEX);
}
TEST_CASE("bfelf_file_get_needed: invalid size")
{
uint64_t index = 0;
bfelf_file_t ef = {};
auto ret = bfelf_file_get_needed(&ef, index, nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_needed: success")
{
uint64_t index = 0;
const char *needed = nullptr;
binaries_info binaries{&g_file, g_filenames};
auto ret = bfelf_file_get_needed(&binaries.ef(), index, &needed);
CHECK(ret == BFELF_SUCCESS);
}

View file

@ -1,53 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_fake_elf.h>
TEST_CASE("bfelf_file_get_num_load_instrs: invalid elf file")
{
auto ret = bfelf_file_get_num_load_instrs(nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_num_load_instrs: uninitialized")
{
bfelf_file_t ef = {};
auto ret = bfelf_file_get_num_load_instrs(&ef);
CHECK(ret == 0);
}
TEST_CASE("bfelf_file_get_num_load_instrs: success")
{
int64_t ret = 0;
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_file_get_num_load_instrs(&ef);
CHECK(ret > 0);
}

View file

@ -1,37 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <bfelf_loader.h>
TEST_CASE("bfelf_file_get_num_needed: invalid elf file")
{
auto ret = bfelf_file_get_num_needed(nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_num_needed: success")
{
bfelf_file_t ef = {};
auto ret = bfelf_file_get_num_needed(&ef);
CHECK(ret == 0);
}

View file

@ -1,37 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <bfelf_loader.h>
TEST_CASE("bfelf_file_get_pic_pie: invalid elf file")
{
auto ret = bfelf_file_get_pic_pie(nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_pic_pie: success")
{
bfelf_file_t ef = {};
auto ret = bfelf_file_get_pic_pie(&ef);
CHECK(ret == 1);
}

View file

@ -1,73 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_real_elf.h>
TEST_CASE("bfelf_file_get_section_info: invalid elf")
{
section_info_t info = {};
auto ret = bfelf_file_get_section_info(nullptr, &info);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_section_info: invalid info")
{
bfelf_file_t ef = {};
auto ret = bfelf_file_get_section_info(&ef, nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_section_info: not added to loader")
{
bfelf_file_t ef = {};
section_info_t info = {};
auto ret = bfelf_file_get_section_info(&ef, &info);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_get_section_info: expected misc resources")
{
binaries_info binaries{&g_file, g_filenames};
section_info_t info = {};
auto &dummy_main_ef = binaries.ef();
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);
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.eh_frame_addr != nullptr);
CHECK(info.eh_frame_size != 0);
}

View file

@ -1,37 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <bfelf_loader.h>
TEST_CASE("bfelf_file_get_total_size: invalid elf file")
{
auto ret = bfelf_file_get_total_size(nullptr);
CHECK(ret == 0);
}
TEST_CASE("bfelf_file_get_total_size: success")
{
bfelf_file_t ef = {};
auto ret = bfelf_file_get_total_size(&ef);
CHECK(ret == 0);
}

View file

@ -1,254 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cppcoreguidelines-pro-type-reinterpret-cast
//
// Reason:
// Although in general this is a good rule, for hypervisor level code that
// interfaces with the kernel, and raw hardware, this rule is
// impractical.
//
#include <catch/catch.hpp>
#include <test_fake_elf.h>
TEST_CASE("bfelf_file_init: success")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
}
TEST_CASE("bfelf_file_init: invalid file arg")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto size = std::get<1>(data);
auto ret = bfelf_file_init(nullptr, size, &ef);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_init: invalid size arg")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto ret = bfelf_file_init(buf.get(), 0, &ef);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_init: invalid elf file")
{
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto ret = bfelf_file_init(buf.get(), size, nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_file_init: invalid magic 0")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_mag0] = 0;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_INVALID_SIGNATURE);
}
TEST_CASE("bfelf_file_init: invalid magic 1")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_mag1] = 0;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_INVALID_SIGNATURE);
}
TEST_CASE("bfelf_file_init: invalid magic 2")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_mag2] = 0;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_INVALID_SIGNATURE);
}
TEST_CASE("bfelf_file_init: invalid magic 3")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_mag3] = 0;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_INVALID_SIGNATURE);
}
TEST_CASE("bfelf_file_init: invalid class")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_class] = 0x4;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid data")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_data] = 0x8;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid ident version")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_version] = 0x15;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid osabi")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_osabi] = 0x16;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid abiversion")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_ident[bfei_abiversion] = 0x23;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid type")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_type = 0xDEAD;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid machine")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_machine = 0xDEAD;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid version")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_version = 0xDEAD;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}
TEST_CASE("bfelf_file_init: invalid flags")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto test = reinterpret_cast<bfelf_test *>(buf.get());
test->header.e_flags = 0xDEAD;
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_ERROR_UNSUPPORTED_FILE);
}

View file

@ -1,76 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_fake_elf.h>
#include <test_real_elf.h>
TEST_CASE("private_hash: strange characters")
{
auto str = "strange char here: \200";
CHECK(private_hash(static_cast<const char *>(str)) != 0);
}
TEST_CASE("private_relocate_symbol: invalid relocation")
{
bfelf_loader_t loader = {};
bfelf_file_t ef = {};
bfelf_rela rela = {};
bfelf_sym symtab[1] = {};
auto file = "hello";
auto exec = std::make_unique<char[]>(100);
ef.exec_addr = exec.get();
ef.exec_virt = exec.get();
ef.file = file;
ef.symtab = static_cast<bfelf_sym *>(symtab);
ef.symnum = 1;
rela.r_info = 0xFFFFFFFF;
rela.r_offset = 0x0;
gsl::at(symtab, 0).st_name = 0xFFFFF;
gsl::at(symtab, 0).st_value = 0x1;
CHECK(private_relocate_symbol(&loader, &ef, &rela) == BFELF_ERROR_UNSUPPORTED_RELA);
}
TEST_CASE("private_process_dynamic_section: test all")
{
bfelf_file_t ef = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
auto ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
private_process_dynamic_section(&ef);
ef.dynnum = 0;
private_process_dynamic_section(&ef);
ef.dynoff = 0;
private_process_dynamic_section(&ef);
}

View file

@ -1,188 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cppcoreguidelines-pro-type-reinterpret-cast
//
// Reason:
// Although in general this is a good rule, for hypervisor level code that
// interfaces with the kernel, and raw hardware, this rule is
// impractical.
//
// TIDY_EXCLUSION=-cppcoreguidelines-pro-type-const-cast
//
// Reason:
// This is test code, and we need to use const_cast so that we can modify
// our ELF file so that it looks bad. This can safely be ignored.
//
#include <hippomocks.h>
#include <catch/catch.hpp>
#include <bfgsl.h>
#include <bfplatform.h>
#include <list>
#include <test_real_elf.h>
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<bfelf_binary_t *>(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<bfelf_binary_t *>(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<bfelf_binary_t *>(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<bfelf_binary_t *>(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<bfn::buffer> files;
for (auto i = 0ULL; i < 9; i++) {
auto file = g_file.read_binary(g_filenames.at(i));
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file = file.data();
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file_size = file.size();
files.emplace_back(std::move(file));
}
auto view = gsl::make_span(const_cast<char *>(gsl::at(binaries, 0).file), 16);
view[0] = 0;
auto ret = bfelf_load(reinterpret_cast<bfelf_binary_t *>(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<bfn::buffer> files;
for (auto i = 0ULL; i < 9; i++) {
auto file = g_file.read_binary(g_filenames.at(i));
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file = file.data();
gsl::at(binaries, static_cast<std::ptrdiff_t>(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<bfelf_binary_t *>(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<bfn::buffer> files;
for (auto i = 0ULL; i < 9; i++) {
auto file = g_file.read_binary(g_filenames.at(i));
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file = file.data();
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file_size = file.size();
files.emplace_back(std::move(file));
}
auto ret = bfelf_load(reinterpret_cast<bfelf_binary_t *>(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[10] = {};
std::list<bfn::buffer> files;
for (auto i = 0ULL; i < 10; i++) {
auto file = g_file.read_binary(g_filenames.at(i));
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file = file.data();
gsl::at(binaries, static_cast<std::ptrdiff_t>(i)).file_size = file.size();
files.emplace_back(std::move(file));
}
auto ret = bfelf_load(reinterpret_cast<bfelf_binary_t *>(binaries), 10, &entry, &info, &loader);
CHECK(ret == BF_SUCCESS);
}

View file

@ -1,115 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <list>
#include <test_real_elf.h>
#include <test_fake_elf.h>
char dummy[10];
TEST_CASE("bfelf_loader_add: invalid loader")
{
bfelf_file_t dummy_misc_ef = {};
auto ret = bfelf_loader_add(nullptr, &dummy_misc_ef, static_cast<char *>(dummy), static_cast<char *>(dummy));
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_add: invalid elf file")
{
bfelf_loader_t loader = {};
auto ret = bfelf_loader_add(&loader, nullptr, static_cast<char *>(dummy), static_cast<char *>(dummy));
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_add: invalid addr")
{
bfelf_loader_t loader = {};
bfelf_file_t dummy_misc_ef = {};
auto ret = bfelf_loader_add(&loader, &dummy_misc_ef, nullptr, static_cast<char *>(dummy));
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_add: add twice")
{
int64_t ret = 0;
bfelf_loader_t loader = {};
bfelf_file_t dummy_misc_ef = {};
ret = bfelf_loader_add(&loader, &dummy_misc_ef, static_cast<char *>(dummy), static_cast<char *>(dummy));
CHECK(ret == BF_SUCCESS);
ret = bfelf_loader_add(&loader, &dummy_misc_ef, static_cast<char *>(dummy), static_cast<char *>(dummy));
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_add: too many files")
{
bfelf_loader_t loader = {};
std::vector<bfelf_file_t> efs(MAX_NUM_MODULES + 1);
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
for (auto i = 0ULL; i < MAX_NUM_MODULES + 1; i++) {
int64_t ret = 0;
ret = bfelf_file_init(buf.get(), size, &gsl::at(efs, static_cast<std::ptrdiff_t>(i)));
REQUIRE(ret == BFELF_SUCCESS);
ret = bfelf_loader_add(
&loader,
&gsl::at(efs, static_cast<std::ptrdiff_t>(i)),
static_cast<char *>(dummy),
static_cast<char *>(dummy)
);
if (i < MAX_NUM_MODULES) {
CHECK(ret == BF_SUCCESS);
}
else {
CHECK(ret == BFELF_ERROR_LOADER_FULL);
}
}
}
TEST_CASE("bfelf_loader_add: add fake")
{
int64_t ret = 0;
bfelf_file_t ef = {};
bfelf_loader_t loader = {};
auto data = get_fake_elf();
auto &buf = std::get<0>(data);
auto size = std::get<1>(data);
ret = bfelf_file_init(buf.get(), size, &ef);
CHECK(ret == BFELF_SUCCESS);
ret = bfelf_loader_add(&loader, &ef, static_cast<char *>(dummy), static_cast<char *>(dummy));
CHECK(ret == BFELF_SUCCESS);
}

View file

@ -1,83 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <catch/catch.hpp>
#include <test_real_elf.h>
TEST_CASE("bfelf_loader_relocate: invalid loader")
{
auto ret = bfelf_loader_relocate(nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_relocate: no files added")
{
bfelf_loader_t loader = {};
auto ret = bfelf_loader_relocate(&loader);
CHECK(ret == BFELF_SUCCESS);
}
TEST_CASE("bfelf_loader_relocate: success")
{
binaries_info binaries{&g_file, g_filenames};
}
TEST_CASE("bfelf_loader_relocate: twice")
{
int64_t ret = 0;
binaries_info binaries{&g_file, g_filenames};
ret = bfelf_loader_relocate(&binaries.loader());
CHECK(ret == BFELF_SUCCESS);
}
#ifndef WIN64
TEST_CASE("bfelf_loader_relocate: no such symbol")
{
int64_t ret = 0;
binaries_info binaries{&g_file, g_filenames};
binaries.ef(0) = {};
binaries.loader().relocated = 0;
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

View file

@ -1,122 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cppcoreguidelines-pro-type-reinterpret-cast
//
// Reason:
// Although in general this is a good rule, for hypervisor level code that
// interfaces with the kernel, and raw hardware, this rule is
// impractical.
//
#include <catch/catch.hpp>
#include <test_real_elf.h>
using func_t = void (*)();
TEST_CASE("bfelf_loader_resolve_symbol: invalid loader")
{
func_t func;
auto ret = bfelf_loader_resolve_symbol(nullptr, "lib1_foo", reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_resolve_symbol: invalid name")
{
func_t func;
bfelf_loader_t loader = {};
auto ret = bfelf_loader_resolve_symbol(&loader, nullptr, reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_resolve_symbol: invalid addr")
{
bfelf_loader_t loader = {};
auto ret = bfelf_loader_resolve_symbol(&loader, "lib1_foo", nullptr);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_loader_resolve_symbol: no files added")
{
int64_t ret = 0;
bfelf_loader_t loader = {};
ret = bfelf_loader_relocate(&loader);
CHECK(ret == BFELF_SUCCESS);
func_t func;
ret = bfelf_loader_resolve_symbol(&loader, "lib1_foo", reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL);
}
TEST_CASE("bfelf_loader_resolve_symbol: no such symbol")
{
int64_t ret = 0;
binaries_info binaries{&g_file, g_filenames};
func_t func;
ret = bfelf_loader_resolve_symbol(&binaries.loader(), "invalid_sym", reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL);
}
TEST_CASE("bfelf_loader_resolve_symbol: success")
{
int64_t ret = 0;
binaries_info binaries{&g_file, g_filenames};
func_t func;
ret = bfelf_loader_resolve_symbol(&binaries.loader(), "lib1_foo", reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_SUCCESS);
}
TEST_CASE("bfelf_loader_resolve_symbol: no such symbol no hash")
{
int64_t ret = 0;
binaries_info binaries{&g_file, g_filenames};
binaries.ef(0).hash = nullptr;
binaries.ef(1).hash = nullptr;
func_t func;
ret = bfelf_loader_resolve_symbol(&binaries.loader(), "invalid_sym", reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_ERROR_NO_SUCH_SYMBOL);
}
TEST_CASE("bfelf_loader_resolve_symbol: success no hash")
{
int64_t ret = 0;
binaries_info binaries{&g_file, g_filenames};
binaries.ef(0).hash = nullptr;
binaries.ef(1).hash = nullptr;
func_t func;
ret = bfelf_loader_resolve_symbol(&binaries.loader(), "lib1_foo", reinterpret_cast<void **>(&func));
CHECK(ret == BFELF_SUCCESS);
}

View file

@ -1,75 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <hippomocks.h>
#include <catch/catch.hpp>
#include <bfgsl.h>
#include <test_real_elf.h>
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(), {VMM_PREFIX_PATH + "/lib/"_s}, buffer, binary)
);
}

View file

@ -1,55 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cppcoreguidelines-pro-type-reinterpret-cast
//
// Reason:
// Although in general this is a good rule, for hypervisor level code that
// interfaces with the kernel, and raw hardware, this rule is
// impractical.
//
#include <catch/catch.hpp>
#include <test_real_elf.h>
std::array<char, 0x8000>fake_stack{};
TEST_CASE("bfelf_loader_resolve_symbol: real test (list)")
{
binaries_info binaries{&g_file, g_filenames};
std::array<const char *, 2> argv{{"1000", "2000"}};
binaries.set_args(gsl::narrow_cast<int>(argv.size()), argv.data());
auto func = reinterpret_cast<_start_t>(binaries.entry());
CHECK(func(&fake_stack.at(0x7999), &binaries.info()) == 6000);
}
TEST_CASE("bfelf_loader_resolve_symbol: real test (needed)")
{
binaries_info binaries{&g_file, g_filenames.back(), {VMM_PREFIX_PATH + "/lib/"_s}};
std::array<const char *, 2> argv{{"1000", "2000"}};
binaries.set_args(gsl::narrow_cast<int>(argv.size()), argv.data());
auto func = reinterpret_cast<_start_t>(binaries.entry());
CHECK(func(&fake_stack.at(0x7999), &binaries.info()) == 6000);
}

View file

@ -1,101 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// TIDY_EXCLUSION=-cert-err58-cpp
//
// Reason:
// This triggers on g_filenames which is only used for testing. This
// is not a false positive, but it can be safely ignored.
//
// TIDY_EXCLUSION=-cppcoreguidelines-owning-memory
//
// Reason:
// This triggers during the allocation which is part of the test harness
// so this can be safely ignored.
//
#include <test_real_elf.h>
#include <map>
#include <list>
#include <vector>
#ifdef WIN64
#include <windows.h>
#else
#include <sys/mman.h>
#endif
std::vector<std::string> g_filenames = {
VMM_PREFIX_PATH + "/lib/libdummy_lib1.a"_s,
VMM_PREFIX_PATH + "/lib/libdummy_lib2.a"_s,
VMM_PREFIX_PATH + "/lib/libbfpthread.a"_s,
VMM_PREFIX_PATH + "/lib/libbfsyscall.a"_s,
VMM_PREFIX_PATH + "/lib/libbfunwind.a"_s,
VMM_PREFIX_PATH + "/bin/dummy_main"_s
};
file g_file;
bool out_of_memory = false;
static std::map<const void *, std::shared_ptr<char>> g_memory;
extern "C" 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<char>(static_cast<char *>(addr), free);
#ifdef WIN64
DWORD oldProtect;
VirtualProtect(addr, len, PAGE_EXECUTE_READWRITE, &oldProtect);
#else
mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
return addr;
}
extern "C" void
platform_free_rwe(void *addr, uint64_t len)
{
bfignored(len);
g_memory.erase(addr);
}
extern "C" void *
platform_memset(void *ptr, char value, uint64_t num)
{ return memset(ptr, value, num); }
extern "C" int64_t
platform_memcpy(
void *dst, uint64_t dst_size, const void *src, uint64_t src_size, uint64_t num)
{
bfignored(dst_size);
bfignored(src_size);
memcpy(dst, src, num);
return SUCCESS;
}

View file

@ -1,33 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef TEST_REAL_ELF_H
#define TEST_REAL_ELF_H
#include <bfgsl.h>
#include <bffile.h>
#include <bfelf_loader.h>
extern file g_file;
extern bool out_of_memory;
extern std::vector<std::string> g_filenames;
#endif

View file

@ -1,45 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <hippomocks.h>
#include <catch/catch.hpp>
#include <bfgsl.h>
#include <test_real_elf.h>
TEST_CASE("bfelf_set_args: invalid info")
{
int argc = 0;
const char *argv = nullptr;
auto ret = bfelf_set_args(nullptr, argc, &argv);
CHECK(ret == BFELF_ERROR_INVALID_ARG);
}
TEST_CASE("bfelf_set_args: success")
{
int argc = 0;
crt_info_t info = {};
const char *argv = nullptr;
auto ret = bfelf_set_args(&info, argc, &argv);
CHECK(ret == BF_SUCCESS);
}

View file

@ -1,40 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <hippomocks.h>
#include <catch/catch.hpp>
#include <bfgsl.h>
#include <test_real_elf.h>
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);
}

View file

@ -1,54 +0,0 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
cmake_minimum_required(VERSION 3.13)
project(bfintrinsics C CXX)
init_project(bfintrinsics)
set(X64 $<STREQUAL:${BUILD_TARGET_ARCH},x86_64>)
target_link_libraries(bfintrinsics PUBLIC ${PREFIX}::bfroot)
target_sources(bfintrinsics PRIVATE
$<${X64}:src/arch/x64/cache.asm>
$<${X64}:src/arch/x64/cpuid.asm>
$<${X64}:src/arch/x64/gdt.asm>
$<${X64}:src/arch/x64/idt.asm>
$<${X64}:src/arch/x64/msrs.asm>
$<${X64}:src/arch/x64/pm.asm>
$<${X64}:src/arch/x64/portio.asm>
$<${X64}:src/arch/x64/rdtsc.asm>
$<${X64}:src/arch/x64/rflags.asm>
$<${X64}:src/arch/x64/srs.asm>
$<${X64}:src/arch/x64/tlb.asm>
$<${X64}:src/arch/intel_x64/barrier.asm>
$<${X64}:src/arch/intel_x64/bit.asm>
$<${X64}:src/arch/intel_x64/crs.asm>
$<${X64}:src/arch/intel_x64/drs.asm>
$<${X64}:src/arch/intel_x64/pause.asm>
$<${X64}:src/arch/intel_x64/vmx.asm>
)
if(PREFIX STREQUAL vmm)
install(DIRECTORY include/ DESTINATION include)
endif()
fini_project()

View file

@ -1,424 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef IOAPIC_INTEL_X64_H
#define IOAPIC_INTEL_X64_H
#include <cstdint>
#include <bfdebug.h>
#include <bfbitmanip.h>
#include "lapic.h"
// *INDENT-OFF*
namespace intel_x64
{
/// IOAPIC intrinsics
///
/// The IOAPIC is memory-mapped to 0xFEC0000 by default, though
/// it may be relocated. Like the xAPIC, it is accessed in 32-bit
/// loads and stores.
///
/// Each data register is identified by a positive 8-bit id
/// (called its offset). To read/write a data register, its
/// id is written to the IOREGSEL control register. Once written,
/// its data may be accessed through the IOREGWIN control register.
///
/// Note that IOREGSEL and IOREGWIN are the only IOAPIC registers directly
/// accessible from software - all other registers are accessed through
/// these two.
///
/// See chapter 3 of the IOAPIC spec for more details
///
namespace ioapic
{
/// @cond
using offset_t = uint8_t;
using value_t = uint32_t;
using base_t = uintptr_t;
using rte_t = uint64_t;
/// First RTE index
constexpr const auto rte_begin = 0x10U;
/// One-past-the-end of last RTE index
constexpr const auto rte_end = 0x40U;
/// Align an arbitrary address to 16 bytes, which is
/// required of ioapic base addresses
inline auto align_base(const base_t addr)
{ return addr & 0xFFFFFFFFFFFFFFF0ULL; }
namespace id
{
constexpr const auto offset = 0U;
constexpr const auto default_val = 0U;
constexpr const auto mask = 0x0F000000U;
constexpr const auto from = 24U;
constexpr const auto name = "id";
inline value_t get(value_t reg)
{ return get_bits(reg, mask) >> from; }
inline void set(value_t &reg, value_t id)
{ reg = set_bits(reg, mask, (id << from)); }
inline void dump(int level, value_t &reg, std::string *msg = nullptr)
{ bfdebug_subnhex(level, name, get(reg), msg); }
}
namespace ver
{
constexpr const auto offset = 1U;
constexpr const auto default_val = 0x00170011U;
constexpr const auto name = "ver";
namespace version
{
constexpr const auto mask = 0xFFU;
constexpr const auto from = 0U;
constexpr const auto name = "version";
inline value_t get(value_t reg)
{ return get_bits(reg, mask) >> from; }
inline void set(value_t &reg, value_t ver)
{ reg = set_bits(reg, mask, (ver << from)); }
inline void dump(int level, value_t &reg, std::string *msg = nullptr)
{ bfdebug_subndec(level, name, get(reg), msg); }
}
namespace max_rte_number
{
constexpr const auto mask = 0xFF0000U;
constexpr const auto from = 16U;
constexpr const auto name = "max_rte_number";
inline value_t get(value_t reg)
{ return get_bits(reg, mask) >> from; }
inline void set(value_t &reg, value_t ver)
{ reg = set_bits(reg, mask, (ver << from)); }
inline void dump(int level, value_t &reg, std::string *msg = nullptr)
{ bfdebug_subndec(level, name, get(reg), msg); }
}
inline void dump(int level, value_t &reg, std::string *msg = nullptr)
{
version::dump(level, reg, msg);
max_rte_number::dump(level, reg, msg);
}
}
namespace arb
{
constexpr const auto offset = 2U;
constexpr const auto default_val = 0x0U;
constexpr const auto name = "arb";
namespace id
{
constexpr const auto mask = 0x0F000000U;
constexpr const auto from = 24U;
constexpr const auto name = "id";
inline value_t get(value_t reg)
{ return get_bits(reg, mask) >> from; }
inline void set(value_t &reg, value_t arb)
{ reg = set_bits(reg, mask, (arb << from)); }
inline void dump(int level, value_t &reg, std::string *msg = nullptr)
{ bfdebug_subndec(level, name, get(reg), msg); }
}
inline void dump(int level, value_t &reg, std::string *msg = nullptr)
{ id::dump(level, reg, msg); }
}
namespace rte
{
constexpr const auto name = "rte";
constexpr const auto count = 24U;
namespace vector
{
constexpr const auto mask = 0x00000000000000FFULL;
constexpr const auto from = 0U;
constexpr const auto name = "vector";
constexpr const auto min = 0x10U;
constexpr const auto max = 0xFEU;
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{ bfdebug_subnhex(lev, name, get(val), msg); }
}
namespace delivery_mode
{
constexpr const auto mask = 0x0000000000000700ULL;
constexpr const auto from = 8U;
constexpr const auto name = "delivery_mode";
constexpr const auto fixed = 0U;
constexpr const auto lowest_priority = 1U;
constexpr const auto smi = 2U;
constexpr const auto nmi = 4U;
constexpr const auto init = 5U;
constexpr const auto extint = 7U;
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{
const auto mode = get(val);
if (mode == lowest_priority) {
bfdebug_subtext(lev, name, "lowest_priority", msg);
return;
}
::intel_x64::lapic::dump_lvt_delivery_mode(lev, get(val), msg);
}
}
namespace destination_mode
{
constexpr const auto mask = 0x0000000000000800ULL;
constexpr const auto from = 11U;
constexpr const auto name = "destination_mode";
constexpr const auto physical = 0U;
constexpr const auto logical = 1U;
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{
if (get(val) == physical) {
bfdebug_subtext(lev, name, "physical", msg);
return;
}
bfdebug_subtext(lev, name, "logical", msg);
}
}
namespace delivery_status
{
constexpr const auto mask = 0x0000000000001000ULL;
constexpr const auto from = 12U;
constexpr const auto name = "delivery_status";
constexpr const auto idle = 0U;
constexpr const auto send_pending = 1U;
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{ ::intel_x64::lapic::dump_delivery_status(lev, get(val), msg); }
}
namespace polarity
{
constexpr const auto mask = 0x0000000000002000ULL;
constexpr const auto from = 13U;
constexpr const auto name = "polarity";
constexpr const auto active_high = 0U;
constexpr const auto active_low = 1U;
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{
if (get(val) == active_high) {
bfdebug_subtext(lev, name, "active_high", msg);
return;
}
bfdebug_subtext(lev, name, "active_low", msg);
}
}
namespace remote_irr
{
constexpr const auto mask = 0x0000000000004000ULL;
constexpr const auto from = 14U;
constexpr const auto name = "remote_irr";
inline auto is_enabled(rte_t val)
{ return is_bit_set(val, from); }
inline auto is_disabled(rte_t val)
{ return is_bit_cleared(val, from); }
inline void enable(rte_t &val)
{ val = set_bit(val, from); }
inline void disable(rte_t &val)
{ val = clear_bit(val, from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{ bfdebug_subbool(lev, name, is_enabled(val), msg); }
}
namespace trigger_mode
{
constexpr const auto mask = 0x0000000000008000ULL;
constexpr const auto from = 15U;
constexpr const auto name = "trigger_mode";
constexpr const auto edge = 0U;
constexpr const auto level = 1U;
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{
if (get(val) == edge) {
bfdebug_subtext(lev, name, "edge", msg);
return;
}
bfdebug_subtext(lev, name, "level", msg);
}
}
namespace mask_bit
{
constexpr const auto mask = 0x0000000000010000ULL;
constexpr const auto from = 16U;
constexpr const auto name = "mask_bit";
inline auto is_enabled(rte_t val)
{ return is_bit_set(val, from); }
inline auto is_disabled(rte_t val)
{ return is_bit_cleared(val, from); }
inline void enable(rte_t &val)
{ val = set_bit(val, from); }
inline void disable(rte_t &val)
{ val = clear_bit(val, from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{ bfdebug_subbool(lev, name, is_enabled(val), msg); }
}
namespace logical_destination
{
constexpr const auto mask = 0xFF00000000000000ULL;
constexpr const auto from = 56U;
constexpr const auto name = "logical_destination";
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{ bfdebug_subnhex(lev, name, get(val), msg); }
}
namespace physical_destination
{
constexpr const auto mask = 0x0F00000000000000ULL;
constexpr const auto from = 56U;
constexpr const auto name = "physical_destination";
inline auto get(rte_t val) noexcept
{ return get_bits(val, mask) >> from; }
inline void set(rte_t &reg, rte_t val) noexcept
{ reg = set_bits(reg, mask, val << from); }
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{ bfdebug_subnhex(lev, name, get(val), msg); }
}
inline void dump(int lev, rte_t &val, std::string *msg = nullptr)
{
bfdebug_nhex(lev, name, val, msg);
vector::dump(lev, val, msg);
delivery_status::dump(lev, val, msg);
polarity::dump(lev, val, msg);
remote_irr::dump(lev, val, msg);
trigger_mode::dump(lev, val, msg);
mask_bit::dump(lev, val, msg);
logical_destination::dump(lev, val, msg);
physical_destination::dump(lev, val, msg);
}
}
inline bool exists(const offset_t offset)
{ return (offset < 0x3U) || (offset >= rte_begin && offset < rte_end); }
inline bool is_read_only(const offset_t offset)
{ return offset == ver::offset || offset == arb::offset; }
inline bool is_read_write(const offset_t offset)
{ return exists(offset) && !is_read_only(offset); }
inline bool is_readable(const offset_t offset)
{ return is_read_write(offset) || is_read_only(offset); }
inline bool is_writable(const offset_t offset)
{ return is_read_write(offset); }
/// @endcond
}
}
// *INDENT-ON*
#endif

View file

@ -1,282 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef INTRINSICS_LAPIC_INTEL_X64_H
#define INTRINSICS_LAPIC_INTEL_X64_H
#include <arch/intel_x64/msrs.h>
#include <arch/intel_x64/cpuid.h>
// *INDENT-OFF*
namespace intel_x64
{
using value_type = ::x64::msrs::value_type;
namespace msrs
{
namespace ia32_apic_base
{
constexpr const auto addr = 0x0000001BU;
constexpr const auto name = "ia32_apic_base";
inline auto get() noexcept
{ return _read_msr(addr); }
inline void set(value_type val) noexcept
{ _write_msr(addr, val); }
namespace bsp
{
constexpr const auto mask = 0x0000000000000100ULL;
constexpr const auto from = 8ULL;
constexpr const auto name = "bsp";
inline auto is_enabled()
{ return is_bit_set(_read_msr(addr), from); }
inline auto is_enabled(value_type msr)
{ return is_bit_set(msr, from); }
inline auto is_disabled()
{ return is_bit_cleared(_read_msr(addr), from); }
inline auto is_disabled(value_type msr)
{ return is_bit_cleared(msr, from); }
inline void enable()
{ _write_msr(addr, set_bit(_read_msr(addr), from)); }
inline void enable(value_type &msr)
{ msr = set_bit(msr, from); }
inline void disable()
{ _write_msr(addr, clear_bit(_read_msr(addr), from)); }
inline void disable(value_type &msr)
{ msr = clear_bit(msr, from); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_subbool(level, name, is_enabled(), msg); }
inline void dump(int level, value_type val, std::string *msg = nullptr)
{ bfdebug_subbool(level, name, is_enabled(val), msg); }
}
namespace extd
{
constexpr const auto mask = 0x0000000000000400ULL;
constexpr const auto from = 10ULL;
constexpr const auto name = "extd";
inline auto is_enabled()
{ return is_bit_set(_read_msr(addr), from); }
inline auto is_enabled(value_type msr)
{ return is_bit_set(msr, from); }
inline auto is_disabled()
{ return is_bit_cleared(_read_msr(addr), from); }
inline auto is_disabled(value_type msr)
{ return is_bit_cleared(msr, from); }
inline void enable()
{ _write_msr(addr, set_bit(_read_msr(addr), from)); }
inline void enable(value_type &msr)
{ msr = set_bit(msr, from); }
inline void disable()
{ _write_msr(addr, clear_bit(_read_msr(addr), from)); }
inline void disable(value_type &msr)
{ msr = clear_bit(msr, from); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_subbool(level, name, is_enabled(), msg); }
inline void dump(int level, value_type val, std::string *msg = nullptr)
{ bfdebug_subbool(level, name, is_enabled(val), msg); }
}
namespace en
{
constexpr const auto mask = 0x0000000000000800ULL;
constexpr const auto from = 11ULL;
constexpr const auto name = "en";
inline auto is_enabled()
{ return is_bit_set(_read_msr(addr), from); }
inline auto is_enabled(value_type msr)
{ return is_bit_set(msr, from); }
inline auto is_disabled()
{ return is_bit_cleared(_read_msr(addr), from); }
inline auto is_disabled(value_type msr)
{ return is_bit_cleared(msr, from); }
inline void enable()
{ _write_msr(addr, set_bit(_read_msr(addr), from)); }
inline void enable(value_type &msr)
{ msr = set_bit(msr, from); }
inline void disable()
{ _write_msr(addr, clear_bit(_read_msr(addr), from)); }
inline void disable(value_type &msr)
{ msr = clear_bit(msr, from); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_subbool(level, name, is_enabled(), msg); }
inline void dump(int level, value_type val, std::string *msg = nullptr)
{ bfdebug_subbool(level, name, is_enabled(val), msg); }
}
///
/// NOTE: `state` is a combination field of `extd` and `en` to facilitate
/// atomic apic state changes and to provide a simplified interface
///
namespace state
{
constexpr const auto mask = 0xC00ULL;
constexpr const auto from = 10ULL;
constexpr const auto name = "state";
constexpr const auto disabled = 0x0ULL;
constexpr const auto invalid = 0x1ULL;
constexpr const auto xapic = 0x2ULL;
constexpr const auto x2apic = 0x3ULL;
inline auto get() noexcept
{ return get_bits(_read_msr(addr), mask) >> from; }
inline auto get(value_type msr) noexcept
{ return get_bits(msr, mask) >> from; }
inline void set(value_type val) noexcept
{ _write_msr(addr, set_bits(_read_msr(addr), mask, val << from)); }
inline void set(value_type &msr, value_type val) noexcept
{ msr = set_bits(msr, mask, val << from); }
inline void enable_x2apic() noexcept
{ set(x2apic); }
inline void enable_x2apic(value_type &msr) noexcept
{ msr = set_bits(msr, mask, x2apic << from); }
inline void enable_xapic() noexcept
{ set(xapic); }
inline void enable_xapic(value_type &msr) noexcept
{ msr = set_bits(msr, mask, xapic << from); }
inline void disable() noexcept
{ set(disabled); }
inline void disable(value_type &msr) noexcept
{ msr = set_bits(msr, mask, disabled << from); }
inline void dump(int level, value_type val, std::string *msg = nullptr)
{
switch (val) {
case x2apic:
bfdebug_subtext(level, name, "x2apic", msg);
return;
case xapic:
bfdebug_subtext(level, name, "xapic", msg);
return;
case disabled:
bfdebug_subtext(level, name, "disabled", msg);
return;
case invalid:
bfdebug_subtext(level, name, "invalid", msg);
return;
}
}
inline void dump(int level, std::string *msg = nullptr)
{ dump(level, get(), msg); }
}
namespace apic_base
{
constexpr const auto mask = 0x0000000FFFFFF000ULL;
constexpr const auto from = 12ULL;
constexpr const auto name = "apic_base";
inline auto get() noexcept
{ return get_bits(_read_msr(addr), mask); }
inline auto get(value_type msr) noexcept
{ return get_bits(msr, mask); }
inline void set(value_type val) noexcept
{ _write_msr(addr, set_bits(_read_msr(addr), mask, val)); }
inline void set(value_type &msr, value_type val) noexcept
{ msr = set_bits(msr, mask, val); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_subnhex(level, name, get(), msg); }
inline void dump(int level, value_type val, std::string *msg = nullptr)
{ bfdebug_subnhex(level, name, val, msg); }
}
inline void dump(int level, value_type val, std::string *msg = nullptr)
{
bfdebug_nhex(level, name, val, msg);
bsp::dump(level, val, msg);
extd::dump(level, val, msg);
en::dump(level, val, msg);
state::dump(level, val, msg);
apic_base::dump(level, val, msg);
}
}
}
namespace lapic
{
/// Is present
///
/// @expects
/// @ensures
///
/// @return true if a LAPIC is available on the platform
/// @return false if a LAPIC is not available on the platform
///
inline auto is_present() noexcept
{ return ::intel_x64::cpuid::feature_information::edx::apic::is_enabled(); }
}
}
// *INDENT-ON*
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,49 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef BARRIER_INTEL_X64_H
#define BARRIER_INTEL_X64_H
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" void _rmb(void) noexcept;
extern "C" void _wmb(void) noexcept;
extern "C" void _mb(void) noexcept;
// *INDENT-OFF*
namespace intel_x64::barrier
{
inline void rmb() noexcept
{ _rmb(); }
inline void wmb() noexcept
{ _wmb(); }
inline void mb() noexcept
{ _mb(); }
}
// *INDENT-ON*
#endif

View file

@ -1,53 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef BIT_INTEL_X64_H
#define BIT_INTEL_X64_H
#include <cstdint>
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" uint64_t _bsf(uint64_t value) noexcept;
extern "C" uint64_t _bsr(uint64_t value) noexcept;
extern "C" uint64_t _popcnt(uint64_t value) noexcept;
// *INDENT-OFF*
namespace intel_x64
{
namespace bit
{
inline uint64_t bsf(uint64_t value) noexcept
{ return _bsf(value); }
inline uint64_t bsr(uint64_t value) noexcept
{ return _bsr(value); }
inline uint64_t popcnt(uint64_t value) noexcept
{ return _popcnt(value); }
}
}
// *INDENT-ON*
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,50 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef DRS_INTEL_X64_H
#define DRS_INTEL_X64_H
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" uint64_t _read_dr7(void) noexcept;
extern "C" void _write_dr7(uint64_t val) noexcept;
// *INDENT-OFF*
namespace intel_x64
{
namespace dr7
{
using value_type = uint64_t;
inline auto get() noexcept
{ return _read_dr7(); }
inline void set(value_type val) noexcept
{ _write_dr7(val); }
}
}
// *INDENT-ON*
#endif

View file

@ -1,890 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef EPT_INTEL_X64_H
#define EPT_INTEL_X64_H
#include <bfdebug.h>
#include <bfbitmanip.h>
// *INDENT-OFF*
namespace intel_x64
{
namespace ept
{
namespace pml4
{
constexpr const auto num_entries = 512;
constexpr const auto from = 39U;
constexpr const auto size = num_entries * sizeof(uintptr_t);
inline auto index(uintptr_t virt)
{
return gsl::narrow_cast<std::ptrdiff_t>(
(virt & ((0x1FFULL) << from)) >> from
);
}
template<
typename T,
typename = std::enable_if<std::is_pointer<T>::value >
>
auto index(T virt)
{ return index(reinterpret_cast<uintptr_t>(virt)); }
namespace entry
{
using value_type = uint64_t;
namespace read_access
{
constexpr const auto mask = 0x0000000000000001ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "read_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace write_access
{
constexpr const auto mask = 0x0000000000000002ULL;
constexpr const auto from = 1ULL;
constexpr const auto name = "write_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access
{
constexpr const auto mask = 0x0000000000000004ULL;
constexpr const auto from = 2ULL;
constexpr const auto name = "execute_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace accessed_flag
{
constexpr const auto mask = 0x0000000000000100ULL;
constexpr const auto from = 8ULL;
constexpr const auto name = "accessed_flag";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access_user
{
constexpr const auto mask = 0x0000000000000400ULL;
constexpr const auto from = 10ULL;
constexpr const auto name = "execute_access_user";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace phys_addr
{
constexpr const auto mask = 0x0000FFFFFFFFF000ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "phys_addr";
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace suppress_ve
{
constexpr const auto mask = 0x8000000000000000ULL;
constexpr const auto from = 63ULL;
constexpr const auto name = "suppress_ve";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
}
}
namespace pdpt
{
constexpr const auto num_entries = 512;
constexpr const auto from = 30U;
constexpr const auto size = num_entries * sizeof(uintptr_t);
constexpr const auto page_size = 0x40000000ULL;
inline auto index(uintptr_t virt)
{
return gsl::narrow_cast<std::ptrdiff_t>(
(virt & ((0x1FFULL) << from)) >> from
);
}
template<
typename T,
typename = std::enable_if<std::is_pointer<T>::value >
>
auto index(T virt)
{ return index(reinterpret_cast<uintptr_t>(virt)); }
namespace entry
{
using value_type = uint64_t;
namespace read_access
{
constexpr const auto mask = 0x0000000000000001ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "read_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace write_access
{
constexpr const auto mask = 0x0000000000000002ULL;
constexpr const auto from = 1ULL;
constexpr const auto name = "write_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access
{
constexpr const auto mask = 0x0000000000000004ULL;
constexpr const auto from = 2ULL;
constexpr const auto name = "execute_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace memory_type
{
constexpr const auto mask = 0x0000000000000038ULL;
constexpr const auto from = 3ULL;
constexpr const auto name = "memory_type";
constexpr const auto uncacheable = 0x0ULL;
constexpr const auto write_combining = 0x1ULL;
constexpr const auto write_through = 0x4ULL;
constexpr const auto write_protected = 0x5ULL;
constexpr const auto write_back = 0x6ULL;
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace ignore_pat
{
constexpr const auto mask = 0x0000000000000040ULL;
constexpr const auto from = 6ULL;
constexpr const auto name = "ignore_pat";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace ps
{
constexpr const auto mask = 0x0000000000000080ULL;
constexpr const auto from = 7ULL;
constexpr const auto name = "ps";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace accessed_flag
{
constexpr const auto mask = 0x0000000000000100ULL;
constexpr const auto from = 8ULL;
constexpr const auto name = "accessed_flag";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace dirty
{
constexpr const auto mask = 0x0000000000000200ULL;
constexpr const auto from = 9ULL;
constexpr const auto name = "dirty";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access_user
{
constexpr const auto mask = 0x0000000000000400ULL;
constexpr const auto from = 10ULL;
constexpr const auto name = "execute_access_user";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace phys_addr
{
constexpr const auto mask = 0x0000FFFFFFFFF000ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "phys_addr";
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace suppress_ve
{
constexpr const auto mask = 0x8000000000000000ULL;
constexpr const auto from = 63ULL;
constexpr const auto name = "suppress_ve";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
}
}
namespace pd
{
constexpr const auto num_entries = 512;
constexpr const auto from = 21U;
constexpr const auto size = num_entries * sizeof(uintptr_t);
constexpr const auto page_size = 0x200000ULL;
inline auto index(uintptr_t virt)
{
return gsl::narrow_cast<std::ptrdiff_t>(
(virt & ((0x1FFULL) << from)) >> from
);
}
template<
typename T,
typename = std::enable_if<std::is_pointer<T>::value >
>
auto index(T virt)
{ return index(reinterpret_cast<uintptr_t>(virt)); }
namespace entry
{
using value_type = uint64_t;
namespace read_access
{
constexpr const auto mask = 0x0000000000000001ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "read_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace write_access
{
constexpr const auto mask = 0x0000000000000002ULL;
constexpr const auto from = 1ULL;
constexpr const auto name = "write_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access
{
constexpr const auto mask = 0x0000000000000004ULL;
constexpr const auto from = 2ULL;
constexpr const auto name = "execute_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace memory_type
{
constexpr const auto mask = 0x0000000000000038ULL;
constexpr const auto from = 3ULL;
constexpr const auto name = "memory_type";
constexpr const auto uncacheable = 0x0ULL;
constexpr const auto write_combining = 0x1ULL;
constexpr const auto write_through = 0x4ULL;
constexpr const auto write_protected = 0x5ULL;
constexpr const auto write_back = 0x6ULL;
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace ignore_pat
{
constexpr const auto mask = 0x0000000000000040ULL;
constexpr const auto from = 6ULL;
constexpr const auto name = "ignore_pat";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace ps
{
constexpr const auto mask = 0x0000000000000080ULL;
constexpr const auto from = 7ULL;
constexpr const auto name = "ps";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace accessed_flag
{
constexpr const auto mask = 0x0000000000000100ULL;
constexpr const auto from = 8ULL;
constexpr const auto name = "accessed_flag";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace dirty
{
constexpr const auto mask = 0x0000000000000200ULL;
constexpr const auto from = 9ULL;
constexpr const auto name = "dirty";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access_user
{
constexpr const auto mask = 0x0000000000000400ULL;
constexpr const auto from = 10ULL;
constexpr const auto name = "execute_access_user";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace phys_addr
{
constexpr const auto mask = 0x0000FFFFFFFFF000ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "phys_addr";
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace suppress_ve
{
constexpr const auto mask = 0x8000000000000000ULL;
constexpr const auto from = 63ULL;
constexpr const auto name = "suppress_ve";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
}
}
namespace pt
{
constexpr const auto num_entries = 512;
constexpr const auto from = 12U;
constexpr const auto size = num_entries * sizeof(uintptr_t);
constexpr const auto page_size = 0x1000ULL;
inline auto index(uintptr_t virt)
{
return gsl::narrow_cast<std::ptrdiff_t>(
(virt & ((0x1FFULL) << from)) >> from
);
}
template<
typename T,
typename = std::enable_if<std::is_pointer<T>::value >
>
auto index(T virt)
{ return index(reinterpret_cast<uintptr_t>(virt)); }
namespace entry
{
using value_type = uint64_t;
namespace read_access
{
constexpr const auto mask = 0x0000000000000001ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "read_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace write_access
{
constexpr const auto mask = 0x0000000000000002ULL;
constexpr const auto from = 1ULL;
constexpr const auto name = "write_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access
{
constexpr const auto mask = 0x0000000000000004ULL;
constexpr const auto from = 2ULL;
constexpr const auto name = "execute_access";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace memory_type
{
constexpr const auto mask = 0x0000000000000038ULL;
constexpr const auto from = 3ULL;
constexpr const auto name = "memory_type";
constexpr const auto uncacheable = 0x0ULL;
constexpr const auto write_combining = 0x1ULL;
constexpr const auto write_through = 0x4ULL;
constexpr const auto write_protected = 0x5ULL;
constexpr const auto write_back = 0x6ULL;
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace ignore_pat
{
constexpr const auto mask = 0x0000000000000040ULL;
constexpr const auto from = 6ULL;
constexpr const auto name = "ignore_pat";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace ps
{
constexpr const auto mask = 0x0000000000000080ULL;
constexpr const auto from = 7ULL;
constexpr const auto name = "ps";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace accessed_flag
{
constexpr const auto mask = 0x0000000000000100ULL;
constexpr const auto from = 8ULL;
constexpr const auto name = "accessed_flag";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace dirty
{
constexpr const auto mask = 0x0000000000000200ULL;
constexpr const auto from = 9ULL;
constexpr const auto name = "dirty";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace execute_access_user
{
constexpr const auto mask = 0x0000000000000400ULL;
constexpr const auto from = 10ULL;
constexpr const auto name = "execute_access_user";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
namespace phys_addr
{
constexpr const auto mask = 0x0000FFFFFFFFF000ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "phys_addr";
inline auto get(value_type &entry) noexcept
{ return get_bits(entry, mask) >> from; }
inline void set(value_type &entry, value_type val) noexcept
{ entry = set_bits(entry, mask, val << from); }
}
namespace suppress_ve
{
constexpr const auto mask = 0x8000000000000000ULL;
constexpr const auto from = 63ULL;
constexpr const auto name = "suppress_ve";
inline auto is_enabled(value_type &entry) noexcept
{ return is_bit_set(entry, from); }
inline auto is_disabled(value_type &entry) noexcept
{ return !is_bit_set(entry, from); }
inline void enable(value_type &entry) noexcept
{ entry = set_bit(entry, from); }
inline void disable(value_type &entry) noexcept
{ entry = clear_bit(entry, from); }
}
}
}
}
}
// *INDENT-ON*
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,49 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef PAUSE_INTEL_X64_H
#define PAUSE_INTEL_X64_H
#include <atomic>
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" void _pause(void) noexcept;
// *INDENT-OFF*
namespace intel_x64
{
inline auto pause() noexcept
{ _pause(); }
inline void spin_until_true(std::atomic<bool> &flag) noexcept
{ while (!flag) { pause(); } }
inline void spin_until_false(std::atomic<bool> &flag) noexcept
{ while (flag) { pause(); } }
}
// *INDENT-ON*
#endif

View file

@ -1,124 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_16BIT_CONTROL_FIELDS_H
#define VMCS_INTEL_X64_16BIT_CONTROL_FIELDS_H
#include <arch/intel_x64/vmcs/helpers.h>
/// Intel x86_64 VMCS 16-Bit Control Fields
///
/// The following provides the interface for the 16-bit control VMCS
/// fields as defined in Appendix B.1.1, Vol. 3 of the Intel Software Developer's
/// Manual.
///
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
namespace virtual_processor_identifier
{
constexpr const auto addr = 0x0000000000000000ULL;
constexpr const auto name = "virtual_processor_identifier";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_vpid::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace posted_interrupt_notification_vector
{
constexpr const auto addr = 0x0000000000000002ULL;
constexpr const auto name = "posted_interrupt_notification_vector";
inline bool exists()
{ return msrs::ia32_vmx_true_pinbased_ctls::process_posted_interrupts::is_allowed1(); }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace eptp_index
{
constexpr const auto addr = 0x0000000000000004ULL;
constexpr const auto name = "eptp_index";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::ept_violation_ve::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
}
}
// *INDENT-ON*
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,70 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_32BIT_HOST_STATE_FIELD_H
#define VMCS_INTEL_X64_32BIT_HOST_STATE_FIELD_H
#include <arch/intel_x64/vmcs/helpers.h>
/// Intel x86_64 VMCS 32-bit Host-State Data Fields
///
/// The following provides the interface for the 32-bit host-state VMCS
/// fields as defined in Appendix B.3.4, Vol. 3 of the Intel Software Developer's
/// Manual.
///
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
namespace host_ia32_sysenter_cs
{
constexpr const auto addr = 0x0000000000004C00ULL;
constexpr const auto name = "host_ia32_sysenter_cs";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
}
}
// *INDENT-ON*
#endif

View file

@ -1,957 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_64BIT_CONTROL_FIELDS_H
#define VMCS_INTEL_X64_64BIT_CONTROL_FIELDS_H
#include <arch/intel_x64/vmcs/helpers.h>
/// Intel x86_64 VMCS 64-bit Control Fields
///
/// The following provides the interface for the 64-bit control VMCS
/// fields as defined in Appendix B.2.1, Vol. 3 of the Intel Software Developer's
/// Manual.
///
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
namespace address_of_io_bitmap_a
{
constexpr const auto addr = 0x0000000000002000ULL;
constexpr const auto name = "address_of_io_bitmap_a";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace address_of_io_bitmap_b
{
constexpr const auto addr = 0x0000000000002002ULL;
constexpr const auto name = "address_of_io_bitmap_b";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace address_of_msr_bitmap
{
constexpr const auto addr = 0x0000000000002004ULL;
constexpr const auto name = "address_of_msr_bitmap";
inline bool exists()
{ return msrs::ia32_vmx_true_procbased_ctls::use_msr_bitmap::is_allowed1(); }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace vm_exit_msr_store_address
{
constexpr const auto addr = 0x0000000000002006ULL;
constexpr const auto name = "vm_exit_msr_store_address";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace vm_exit_msr_load_address
{
constexpr const auto addr = 0x0000000000002008ULL;
constexpr const auto name = "vm_exit_msr_load_address";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace vm_entry_msr_load_address
{
constexpr const auto addr = 0x000000000000200AULL;
constexpr const auto name = "vm_entry_msr_load_address";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace executive_vmcs_pointer
{
constexpr const auto addr = 0x000000000000200CULL;
constexpr const auto name = "executive_vmcs_pointer";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace pml_address
{
constexpr const auto addr = 0x000000000000200EULL;
constexpr const auto name = "pml_address";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_pml::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace tsc_offset
{
constexpr const auto addr = 0x0000000000002010ULL;
constexpr const auto name = "tsc_offset";
inline bool exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace virtual_apic_address
{
constexpr const auto addr = 0x0000000000002012ULL;
constexpr const auto name = "virtual_apic_address";
inline bool exists()
{ return msrs::ia32_vmx_true_procbased_ctls::use_tpr_shadow::is_allowed1(); }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace apic_access_address
{
constexpr const auto addr = 0x0000000000002014ULL;
constexpr const auto name = "apic_access_address";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::virtualize_apic_accesses::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace posted_interrupt_descriptor_address
{
constexpr const auto addr = 0x0000000000002016ULL;
constexpr const auto name = "posted_interrupt_descriptor_address";
inline bool exists()
{ return msrs::ia32_vmx_true_pinbased_ctls::process_posted_interrupts::is_allowed1(); }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace vm_function_controls
{
constexpr const auto addr = 0x0000000000002018ULL;
constexpr const auto name = "vm_function_controls";
constexpr const auto msr_addr = 0x00000491U;
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_vm_functions::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
namespace eptp_switching
{
constexpr const auto mask = 0x0000000000000001ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "eptp_switching";
inline auto is_enabled()
{ return is_bit_set(get_vmcs_field(addr, name, exists()), from); }
inline auto is_enabled(value_type field)
{ return is_bit_set(field, from); }
inline auto is_enabled_if_exists(bool verbose = false)
{ return is_bit_set(get_vmcs_field_if_exists(addr, name, verbose, exists()), from); }
inline auto is_disabled()
{ return is_bit_cleared(get_vmcs_field(addr, name, exists()), from); }
inline auto is_disabled(value_type field)
{ return is_bit_cleared(field, from); }
inline auto is_disabled_if_exists(bool verbose = false)
{ return is_bit_cleared(get_vmcs_field_if_exists(addr, name, verbose, exists()), from); }
inline void enable()
{ set_vmcs_field_bit(addr, from, name, exists()); }
inline void enable(value_type &field)
{ field = set_bit(field, from); }
inline void enable_if_exists(bool verbose = false)
{ set_vmcs_field_bit_if_exists(addr, from, name, verbose, exists()); }
inline void disable()
{ clear_vmcs_field_bit(addr, from, name, exists()); }
inline void disable(value_type &field)
{ field = clear_bit(field, from); }
inline void disable_if_exists(bool verbose = false)
{ clear_vmcs_field_bit_if_exists(addr, from, name, verbose, exists()); }
inline void set(bool val)
{ val ? enable() : disable(); }
inline void set(value_type &field, bool val)
{ val ? enable(field) : disable(field); }
inline void set_if_exists(bool val, bool verbose = false)
{ val ? enable_if_exists(verbose) : disable_if_exists(verbose); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subbool(level, msg); }
}
namespace reserved
{
constexpr const auto mask = 0xFFFFFFFFFFFFFFFEULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "reserved";
inline auto get()
{ return get_bits(get_vmcs_field(addr, name, exists()), mask) >> from; }
inline auto get(value_type field)
{ return get_bits(field, mask) >> from; }
inline auto get_if_exists(bool verbose = false)
{ return get_bits(get_vmcs_field_if_exists(addr, name, verbose, exists()), mask) >> from; }
inline void set(value_type val)
{ set_vmcs_field_bits(val, addr, mask, from, name, exists()); }
inline void set(value_type &field, value_type val)
{ field = set_bits(field, mask, (val << from)); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_bits_if_exists(val, addr, mask, from, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subnhex(level, msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
dump_vmcs_nhex(level, msg);
eptp_switching::dump(level, msg);
reserved::dump(level, msg);
}
}
namespace ept_pointer
{
constexpr const auto addr = 0x000000000000201AULL;
constexpr const auto name = "ept_pointer";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_ept::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
namespace memory_type
{
constexpr const auto mask = 0x0000000000000007ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "memory_type";
constexpr const auto uncacheable = 0U;
constexpr const auto write_back = 6U;
inline auto get()
{ return get_bits(get_vmcs_field(addr, name, exists()), mask) >> from; }
inline auto get(value_type field)
{ return get_bits(field, mask) >> from; }
inline auto get_if_exists(bool verbose = false)
{ return get_bits(get_vmcs_field_if_exists(addr, name, verbose, exists()), mask) >> from; }
inline void set(value_type val)
{ set_vmcs_field_bits(val, addr, mask, from, name, exists()); }
inline void set(value_type &field, value_type val)
{ field = set_bits(field, mask, (val << from)); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_bits_if_exists(val, addr, mask, from, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subnhex(level, msg); }
}
namespace page_walk_length_minus_one
{
constexpr const auto mask = 0x0000000000000038ULL;
constexpr const auto from = 3ULL;
constexpr const auto name = "page_walk_length_minus_one";
inline auto get()
{ return get_bits(get_vmcs_field(addr, name, exists()), mask) >> from; }
inline auto get(value_type field)
{ return get_bits(field, mask) >> from; }
inline auto get_if_exists(bool verbose = false)
{ return get_bits(get_vmcs_field_if_exists(addr, name, verbose, exists()), mask) >> from; }
inline void set(value_type val)
{ set_vmcs_field_bits(val, addr, mask, from, name, exists()); }
inline void set(value_type &field, value_type val)
{ field = set_bits(field, mask, (val << from)); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_bits_if_exists(val, addr, mask, from, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subnhex(level, msg); }
}
namespace accessed_and_dirty_flags
{
constexpr const auto mask = 0x0000000000000040ULL;
constexpr const auto from = 6ULL;
constexpr const auto name = "accessed_and_dirty_flags";
inline auto is_enabled()
{ return is_bit_set(get_vmcs_field(addr, name, exists()), from); }
inline auto is_enabled(value_type field)
{ return is_bit_set(field, from); }
inline auto is_enabled_if_exists(bool verbose = false)
{ return is_bit_set(get_vmcs_field_if_exists(addr, name, verbose, exists()), from); }
inline auto is_disabled()
{ return is_bit_cleared(get_vmcs_field(addr, name, exists()), from); }
inline auto is_disabled(value_type field)
{ return is_bit_cleared(field, from); }
inline auto is_disabled_if_exists(bool verbose = false)
{ return is_bit_cleared(get_vmcs_field_if_exists(addr, name, verbose, exists()), from); }
inline void enable()
{ set_vmcs_field_bit(addr, from, name, exists()); }
inline void enable(value_type &field)
{ field = set_bit(field, from); }
inline void enable_if_exists(bool verbose = false)
{ set_vmcs_field_bit_if_exists(addr, from, name, verbose, exists()); }
inline void disable()
{ clear_vmcs_field_bit(addr, from, name, exists()); }
inline void disable(value_type &field)
{ field = clear_bit(field, from); }
inline void disable_if_exists(bool verbose = false)
{ clear_vmcs_field_bit_if_exists(addr, from, name, verbose, exists()); }
inline void set(bool val)
{ val ? enable() : disable(); }
inline void set(value_type &field, bool val)
{ val ? enable(field) : disable(field); }
inline void set_if_exists(bool val, bool verbose = false)
{ val ? enable_if_exists(verbose) : disable_if_exists(verbose); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subbool(level, msg); }
}
namespace phys_addr
{
constexpr const auto mask = 0x0000FFFFFFFFF000ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "phys_addr";
inline auto get()
{ return get_bits(get_vmcs_field(addr, name, exists()), mask) >> from; }
inline auto get(value_type field)
{ return get_bits(field, mask) >> from; }
inline auto get_if_exists(bool verbose = false)
{ return get_bits(get_vmcs_field_if_exists(addr, name, verbose, exists()), mask) >> from; }
inline void set(value_type val)
{ set_vmcs_field_bits(val, addr, mask, from, name, exists()); }
inline void set(value_type &field, value_type val)
{ field = set_bits(field, mask, (val << from)); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_bits_if_exists(val, addr, mask, from, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subnhex(level, msg); }
}
namespace reserved
{
constexpr const auto mask = 0xFFFF000000000F80ULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "reserved";
inline auto get()
{ return get_bits(get_vmcs_field(addr, name, exists()), mask) >> from; }
inline auto get(value_type field)
{ return get_bits(field, mask) >> from; }
inline auto get_if_exists(bool verbose = false)
{ return get_bits(get_vmcs_field_if_exists(addr, name, verbose, exists()), mask) >> from; }
inline void set(value_type val)
{ set_vmcs_field_bits(val, addr, mask, from, name, exists()); }
inline void set(value_type &field, value_type val)
{ field = set_bits(field, mask, (val << from)); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_bits_if_exists(val, addr, mask, from, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_subnhex(level, msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
dump_vmcs_nhex(level, msg);
memory_type::dump(level, msg);
page_walk_length_minus_one::dump(level, msg);
accessed_and_dirty_flags::dump(level, msg);
phys_addr::dump(level, msg);
reserved::dump(level, msg);
}
}
namespace eoi_exit_bitmap_0
{
constexpr const auto addr = 0x000000000000201CULL;
constexpr const auto name = "eoi_exit_bitmap_0";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::virtual_interrupt_delivery::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace eoi_exit_bitmap_1
{
constexpr const auto addr = 0x000000000000201EULL;
constexpr const auto name = "eoi_exit_bitmap_1";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::virtual_interrupt_delivery::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace eoi_exit_bitmap_2
{
constexpr const auto addr = 0x0000000000002020ULL;
constexpr const auto name = "eoi_exit_bitmap_2";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::virtual_interrupt_delivery::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace eoi_exit_bitmap_3
{
constexpr const auto addr = 0x0000000000002022ULL;
constexpr const auto name = "eoi_exit_bitmap_3";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::virtual_interrupt_delivery::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace eptp_list_address
{
constexpr const auto addr = 0x0000000000002024ULL;
constexpr const auto name = "eptp_list_address";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_vm_functions::is_allowed1() &&
msrs::ia32_vmx_vmfunc::eptp_switching::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace vmread_bitmap_address
{
constexpr const auto addr = 0x0000000000002026ULL;
constexpr const auto name = "vmread_bitmap_address";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::vmcs_shadowing::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace vmwrite_bitmap_address
{
constexpr const auto addr = 0x0000000000002028ULL;
constexpr const auto name = "vmwrite_bitmap_address";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::vmcs_shadowing::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace virtualization_exception_information_address
{
constexpr const auto addr = 0x000000000000202AULL;
constexpr const auto name = "virtualization_exception_information_address";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::ept_violation_ve::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace xss_exiting_bitmap
{
constexpr const auto addr = 0x000000000000202CULL;
constexpr const auto name = "xss_exiting_bitmap";
inline bool exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_xsaves_xrstors::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace encls_exiting_bitmap
{
constexpr const auto addr = 0x000000000000202EULL;
constexpr const auto name = "encls_exiting_bitmap";
inline bool exists() noexcept
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_encls_exiting::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace tsc_multiplier
{
constexpr const auto addr = 0x0000000000002032ULL;
constexpr const auto name = "tsc_multiplier";
inline bool exists() noexcept
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::use_tsc_scaling::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
}
}
// *INDENT-ON*
#endif

View file

@ -1,67 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_64BIT_READ_ONLY_DATA_FIELD_H
#define VMCS_INTEL_X64_64BIT_READ_ONLY_DATA_FIELD_H
#include <arch/intel_x64/vmcs/helpers.h>
/// Intel x86_64 VMCS 64-bit Read-Only Data Fields
///
/// The following provides the interface for the 64-bit read-only data VMCS
/// fields as defined in Appendix B.2.2, Vol. 3 of the Intel Software Developer's
/// Manual.
///
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
namespace guest_physical_address
{
constexpr const auto addr = 0x0000000000002400ULL;
constexpr const auto name = "guest_physical_address";
inline auto exists()
{
return msrs::ia32_vmx_true_procbased_ctls::activate_secondary_controls::is_allowed1() &&
msrs::ia32_vmx_procbased_ctls2::enable_ept::is_allowed1();
}
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
}
}
// *INDENT-ON*
#endif

View file

@ -1,285 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_DEBUG_H
#define VMCS_INTEL_X64_DEBUG_H
#include <arch/intel_x64/vmcs/16bit_control_fields.h>
#include <arch/intel_x64/vmcs/16bit_guest_state_fields.h>
#include <arch/intel_x64/vmcs/16bit_host_state_fields.h>
#include <arch/intel_x64/vmcs/32bit_control_fields.h>
#include <arch/intel_x64/vmcs/32bit_guest_state_fields.h>
#include <arch/intel_x64/vmcs/32bit_host_state_fields.h>
#include <arch/intel_x64/vmcs/32bit_read_only_data_fields.h>
#include <arch/intel_x64/vmcs/64bit_control_fields.h>
#include <arch/intel_x64/vmcs/64bit_guest_state_fields.h>
#include <arch/intel_x64/vmcs/64bit_host_state_fields.h>
#include <arch/intel_x64/vmcs/64bit_read_only_data_fields.h>
#include <arch/intel_x64/vmcs/natural_width_control_fields.h>
#include <arch/intel_x64/vmcs/natural_width_guest_state_fields.h>
#include <arch/intel_x64/vmcs/natural_width_host_state_fields.h>
#include <arch/intel_x64/vmcs/natural_width_read_only_data_fields.h>
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
namespace debug
{
inline void dump(int level = 0)
{
bfdebug_transaction(level, [&](std::string * msg) {
bfdebug_lnbr(level, msg);
bfdebug_info(level, "16bit control fields", msg);
bfdebug_brk3(level, msg);
virtual_processor_identifier::dump(level, msg);
posted_interrupt_notification_vector::dump(level, msg);
eptp_index::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "16bit guest state fields", msg);
bfdebug_brk3(level, msg);
guest_es_selector::dump(level, msg);
guest_cs_selector::dump(level, msg);
guest_ss_selector::dump(level, msg);
guest_ds_selector::dump(level, msg);
guest_fs_selector::dump(level, msg);
guest_gs_selector::dump(level, msg);
guest_ldtr_selector::dump(level, msg);
guest_tr_selector::dump(level, msg);
guest_interrupt_status::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "16bit host state fields", msg);
bfdebug_brk3(level, msg);
host_es_selector::dump(level, msg);
host_cs_selector::dump(level, msg);
host_ss_selector::dump(level, msg);
host_ds_selector::dump(level, msg);
host_fs_selector::dump(level, msg);
host_gs_selector::dump(level, msg);
host_tr_selector::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "64bit control fields", msg);
bfdebug_brk3(level, msg);
address_of_io_bitmap_a::dump(level, msg);
address_of_io_bitmap_b::dump(level, msg);
address_of_msr_bitmap::dump(level, msg);
vm_exit_msr_store_address::dump(level, msg);
vm_exit_msr_load_address::dump(level, msg);
vm_entry_msr_load_address::dump(level, msg);
executive_vmcs_pointer::dump(level, msg);
tsc_offset::dump(level, msg);
virtual_apic_address::dump(level, msg);
apic_access_address::dump(level, msg);
posted_interrupt_descriptor_address::dump(level, msg);
vm_function_controls::dump(level, msg);
ept_pointer::dump(level, msg);
eoi_exit_bitmap_0::dump(level, msg);
eoi_exit_bitmap_1::dump(level, msg);
eoi_exit_bitmap_2::dump(level, msg);
eoi_exit_bitmap_3::dump(level, msg);
eptp_list_address::dump(level, msg);
vmread_bitmap_address::dump(level, msg);
vmwrite_bitmap_address::dump(level, msg);
virtualization_exception_information_address::dump(level, msg);
xss_exiting_bitmap::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "64bit read-only data fields", msg);
bfdebug_brk3(level, msg);
guest_physical_address::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "64bit guest state fields", msg);
bfdebug_brk3(level, msg);
vmcs_link_pointer::dump(level, msg);
guest_ia32_debugctl::dump(level, msg);
guest_ia32_pat::dump(level, msg);
guest_ia32_efer::dump(level, msg);
guest_ia32_perf_global_ctrl::dump(level, msg);
guest_pdpte0::dump(level, msg);
guest_pdpte1::dump(level, msg);
guest_pdpte2::dump(level, msg);
guest_pdpte3::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "64bit host state fields", msg);
bfdebug_brk3(level, msg);
host_ia32_pat::dump(level, msg);
host_ia32_efer::dump(level, msg);
host_ia32_perf_global_ctrl::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "32bit control fields", msg);
bfdebug_brk3(level, msg);
pin_based_vm_execution_controls::dump(level, msg);
primary_processor_based_vm_execution_controls::dump(level, msg);
exception_bitmap::dump(level, msg);
page_fault_error_code_mask::dump(level, msg);
page_fault_error_code_match::dump(level, msg);
cr3_target_count::dump(level, msg);
vm_exit_controls::dump(level, msg);
vm_exit_msr_store_count::dump(level, msg);
vm_exit_msr_load_count::dump(level, msg);
vm_entry_controls::dump(level, msg);
vm_entry_msr_load_count::dump(level, msg);
vm_entry_interruption_information::dump(level, msg);
vm_entry_exception_error_code::dump(level, msg);
vm_entry_instruction_length::dump(level, msg);
tpr_threshold::dump(level, msg);
secondary_processor_based_vm_execution_controls::dump(level, msg);
ple_gap::dump(level, msg);
ple_window::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "32bit read-only data fields", msg);
bfdebug_brk3(level, msg);
exit_reason::dump(level, msg);
vm_exit_interruption_information::dump(level, msg);
vm_exit_interruption_error_code::dump(level, msg);
idt_vectoring_information::dump(level, msg);
idt_vectoring_error_code::dump(level, msg);
vm_exit_instruction_length::dump(level, msg);
vm_exit_instruction_information::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "32bit guest state fields", msg);
bfdebug_brk3(level, msg);
guest_es_limit::dump(level, msg);
guest_cs_limit::dump(level, msg);
guest_ss_limit::dump(level, msg);
guest_ds_limit::dump(level, msg);
guest_fs_limit::dump(level, msg);
guest_gs_limit::dump(level, msg);
guest_ldtr_limit::dump(level, msg);
guest_tr_limit::dump(level, msg);
guest_gdtr_limit::dump(level, msg);
guest_idtr_limit::dump(level, msg);
guest_es_access_rights::dump(level, msg);
guest_cs_access_rights::dump(level, msg);
guest_ss_access_rights::dump(level, msg);
guest_ds_access_rights::dump(level, msg);
guest_fs_access_rights::dump(level, msg);
guest_gs_access_rights::dump(level, msg);
guest_ldtr_access_rights::dump(level, msg);
guest_tr_access_rights::dump(level, msg);
guest_interruptibility_state::dump(level, msg);
guest_activity_state::dump(level, msg);
guest_smbase::dump(level, msg);
guest_ia32_sysenter_cs::dump(level, msg);
preemption_timer_value::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "32bit host state fields", msg);
bfdebug_brk3(level, msg);
host_ia32_sysenter_cs::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "natural width control fields", msg);
bfdebug_brk3(level, msg);
cr0_guest_host_mask::dump(level, msg);
cr4_guest_host_mask::dump(level, msg);
cr0_read_shadow::dump(level, msg);
cr4_read_shadow::dump(level, msg);
cr3_target_value_0::dump(level, msg);
cr3_target_value_1::dump(level, msg);
cr3_target_value_2::dump(level, msg);
cr3_target_value_3::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "natural width read-only data fields", msg);
bfdebug_brk3(level, msg);
exit_qualification::dump(level, msg);
io_rcx::dump(level, msg);
io_rsi::dump(level, msg);
io_rdi::dump(level, msg);
io_rip::dump(level, msg);
guest_linear_address::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "natural width guest state fields", msg);
bfdebug_brk3(level, msg);
guest_cr0::dump(level, msg);
guest_cr3::dump(level, msg);
guest_cr4::dump(level, msg);
guest_es_base::dump(level, msg);
guest_cs_base::dump(level, msg);
guest_ss_base::dump(level, msg);
guest_ds_base::dump(level, msg);
guest_fs_base::dump(level, msg);
guest_gs_base::dump(level, msg);
guest_ldtr_base::dump(level, msg);
guest_tr_base::dump(level, msg);
guest_gdtr_base::dump(level, msg);
guest_idtr_base::dump(level, msg);
guest_dr7::dump(level, msg);
guest_rsp::dump(level, msg);
guest_rip::dump(level, msg);
guest_rflags::dump(level, msg);
guest_pending_debug_exceptions::dump(level, msg);
guest_ia32_sysenter_esp::dump(level, msg);
guest_ia32_sysenter_eip::dump(level, msg);
bfdebug_lnbr(level, msg);
bfdebug_info(level, "natural width host state fields", msg);
bfdebug_brk3(level, msg);
host_cr0::dump(level, msg);
host_cr3::dump(level, msg);
host_cr4::dump(level, msg);
host_fs_base::dump(level, msg);
host_gs_base::dump(level, msg);
host_tr_base::dump(level, msg);
host_gdtr_base::dump(level, msg);
host_idtr_base::dump(level, msg);
host_ia32_sysenter_esp::dump(level, msg);
host_ia32_sysenter_eip::dump(level, msg);
host_rsp::dump(level, msg);
host_rip::dump(level, msg);
});
}
}
}
}
// *INDENT-ON*
#endif

View file

@ -1,296 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_HELPERS_H
#define VMCS_INTEL_X64_HELPERS_H
#include <bfdebug.h>
#include <bfbitmanip.h>
#include <arch/x64/misc.h>
#include <arch/x64/cpuid.h>
#include <arch/intel_x64/vmx.h>
#include <arch/intel_x64/msrs.h>
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
using field_type = uint64_t;
using value_type = uint64_t;
inline value_type
get_vmcs_field(
field_type addr, const char *name, bool exists)
{
if (!exists) {
throw std::logic_error("field doesn't exist: " + std::string(name));
}
return intel_x64::vm::read(addr, name);
}
inline value_type
get_vmcs_field_if_exists(
field_type addr, const char *name, bool verbose, bool exists)
{
if (exists) {
return intel_x64::vm::read(addr, name);
}
else {
if (verbose) {
bfalert_text(0, "field doesn't exist: ", name);
}
}
return 0ULL;
}
inline void
set_vmcs_field(
value_type val, field_type addr, const char *name, bool exists)
{
if (!exists) {
throw std::logic_error("field doesn't exist: " + std::string(name));
}
intel_x64::vm::write(addr, val, name);
}
inline void
set_vmcs_field_if_exists(
value_type val, field_type addr, const char *name, bool verbose, bool exists)
{
if (exists) {
intel_x64::vm::write(addr, val, name);
}
else {
if (verbose) {
bfalert_text(0, "field doesn't exist: ", name);
}
}
}
inline void
set_vmcs_field_bits(
value_type val, field_type addr, value_type mask, value_type from, const char *name, bool exists)
{
auto field = get_vmcs_field(addr, name, exists);
set_vmcs_field(set_bits(field, mask, (val << from)), addr, name, exists);
}
inline void
set_vmcs_field_bits_if_exists(
value_type val, field_type addr, value_type mask, value_type from, const char *name, bool verbose, bool exists)
{
auto field = get_vmcs_field_if_exists(addr, name, verbose, exists);
set_vmcs_field_if_exists(set_bits(field, mask, (val << from)), addr, name, verbose, exists);
}
inline void
set_vmcs_field_bit(
field_type addr, value_type from, const char *name, bool exists)
{
auto field = get_vmcs_field(addr, name, exists);
set_vmcs_field(set_bit(field, from), addr, name, exists);
}
inline void
set_vmcs_field_bit_if_exists(
field_type addr, value_type from, const char *name, bool verbose, bool exists)
{
auto field = get_vmcs_field_if_exists(addr, name, verbose, exists);
set_vmcs_field_if_exists(set_bit(field, from), addr, name, verbose, exists);
}
inline void
clear_vmcs_field_bit(
field_type addr, value_type from, const char *name, bool exists)
{
auto field = get_vmcs_field(addr, name, exists);
set_vmcs_field(clear_bit(field, from), addr, name, exists);
}
inline void
clear_vmcs_field_bit_if_exists(
field_type addr, value_type from, const char *name, bool verbose, bool exists)
{
auto field = get_vmcs_field_if_exists(addr, name, verbose, exists);
set_vmcs_field_if_exists(clear_bit(field, from), addr, name, verbose, exists);
}
inline void
enable_vm_control(
field_type addr, value_type from, bool is_allowed1, const char *name, bool exists)
{
if (!exists) {
throw std::logic_error("field doesn't exist: " + std::string(name));
}
if (!is_allowed1) {
throw std::logic_error("field is_allowed1 false: " + std::string(name));
}
intel_x64::vm::write(addr, set_bit(intel_x64::vm::read(addr, name), from), name);
}
inline void
enable_vm_control_if_allowed(
field_type addr, value_type from, bool is_allowed1, const char *name, bool verbose, bool exists)
{
if (!exists) {
if (verbose) {
bfalert_text(0, "field doesn't exist: ", name);
}
return;
}
if (!is_allowed1) {
if (verbose) {
bfalert_text(0, "field is_allowed1 false: ", name);
}
return;
}
intel_x64::vm::write(addr, set_bit(intel_x64::vm::read(addr, name), from), name);
}
inline void
disable_vm_control(
field_type addr, value_type from, bool is_allowed0, const char *name, bool exists)
{
if (!exists) {
throw std::logic_error("field doesn't exist: " + std::string(name));
}
if (!is_allowed0) {
throw std::logic_error("field is_allowed0 false: " + std::string(name));
}
intel_x64::vm::write(addr, clear_bit(intel_x64::vm::read(addr, name), from), name);
}
inline void
disable_vm_control_if_allowed(
field_type addr, value_type from, bool is_allowed0, const char *name, bool verbose, bool exists)
{
if (!exists) {
if (verbose) {
bfalert_text(0, "field doesn't exist: ", name);
}
return;
}
if (!is_allowed0) {
if (verbose) {
bfalert_text(0, "field is_allowed0 false: ", name);
}
return;
}
intel_x64::vm::write(addr, clear_bit(intel_x64::vm::read(addr, name), from), name);
}
inline void
dump_vm_control(int level, bool exists, bool is_allowed1, bool enabled, const char *name, std::string *msg)
{
if (!exists || !is_allowed1) {
bfdebug_subtext(level, name, "unsupported", msg);
return;
}
bfdebug_subbool(level, name, enabled, msg);
}
inline auto
memory_type_reserved(value_type memory_type)
{
switch (memory_type) {
case x64::memory_type::uncacheable:
case x64::memory_type::write_combining:
case x64::memory_type::write_through:
case x64::memory_type::write_protected:
case x64::memory_type::write_back:
case x64::memory_type::uncacheable_minus:
return false;
default:
return true;
}
}
#define dump_vmcs_nhex(a,b) \
if (exists()) { \
bfdebug_nhex(a, name, get(), b); \
} \
else { \
bfdebug_text(a, name, "unsupported", b); \
}
#define dump_vmcs_subnhex(a,b) \
if (exists()) { \
bfdebug_subnhex(a, name, get(), b); \
} \
else { \
bfdebug_subtext(a, name, "unsupported", b); \
}
#define dump_vmcs_bool(a,b) \
if (exists()) { \
bfdebug_bool(a, name, is_enabled(), b); \
} \
else { \
bfdebug_text(a, name, "unsupported", b); \
}
#define dump_vmcs_subbool(a,b) \
if (exists()) { \
bfdebug_subbool(a, name, is_enabled(), b); \
} \
else { \
bfdebug_subtext(a, name, "unsupported", b); \
}
#define dump_vmcs_text(a,b) \
if (exists()) { \
bfdebug_text(a, name, description(), b); \
} \
else { \
bfdebug_text(a, name, "unsupported", b); \
}
#define dump_vmcs_subtext(a,b) \
if (exists()) { \
bfdebug_subtext(a, name, description(), b); \
} \
else { \
bfdebug_subtext(a, name, "unsupported", b); \
}
}
}
// *INDENT-ON*
#endif

View file

@ -1,238 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMCS_INTEL_X64_NATURAL_WIDTH_CONTROL_FIELDS_H
#define VMCS_INTEL_X64_NATURAL_WIDTH_CONTROL_FIELDS_H
#include <arch/intel_x64/vmcs/helpers.h>
/// Intel x86_64 VMCS Natural-Width Control Fields
///
/// The following provides the interface for the natural-width control VMCS
/// fields as defined in Appendix B.4.1, Vol. 3 of the Intel Software Developer's
/// Manual.
///
// *INDENT-OFF*
namespace intel_x64
{
namespace vmcs
{
namespace cr0_guest_host_mask
{
constexpr const auto addr = 0x0000000000006000ULL;
constexpr const auto name = "cr0_guest_host_mask";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr4_guest_host_mask
{
constexpr const auto addr = 0x0000000000006002ULL;
constexpr const auto name = "cr4_guest_host_mask";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr0_read_shadow
{
constexpr const auto addr = 0x0000000000006004ULL;
constexpr const auto name = "cr0_read_shadow";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr4_read_shadow
{
constexpr const auto addr = 0x0000000000006006ULL;
constexpr const auto name = "cr4_read_shadow";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr3_target_value_0
{
constexpr const auto addr = 0x0000000000006008ULL;
constexpr const auto name = "cr3_target_value_0";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr3_target_value_1
{
constexpr const auto addr = 0x000000000000600AULL;
constexpr const auto name = "cr3_target_value_1";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr3_target_value_2
{
constexpr const auto addr = 0x000000000000600CULL;
constexpr const auto name = "cr3_target_value_2";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
namespace cr3_target_value_3
{
constexpr const auto addr = 0x000000000000600EULL;
constexpr const auto name = "cr3_target_value_3";
inline auto exists()
{ return true; }
inline auto get()
{ return get_vmcs_field(addr, name, exists()); }
inline auto get_if_exists(bool verbose = false)
{ return get_vmcs_field_if_exists(addr, name, verbose, exists()); }
inline void set(value_type val)
{ set_vmcs_field(val, addr, name, exists()); }
inline void set_if_exists(value_type val, bool verbose = false)
{ set_vmcs_field_if_exists(val, addr, name, verbose, exists()); }
inline void dump(int level, std::string *msg = nullptr)
{ dump_vmcs_nhex(level, msg); }
}
}
}
// *INDENT-ON*
#endif

View file

@ -1,203 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef VMX_INTEL_X64_H
#define VMX_INTEL_X64_H
#include <bfgsl.h>
#include <bfdebug.h>
#include <bfbitmanip.h>
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" bool _vmxon(void *ptr) noexcept;
extern "C" bool _vmxoff(void) noexcept;
extern "C" bool _vmclear(void *ptr) noexcept;
extern "C" bool _vmptrld(void *ptr) noexcept;
extern "C" bool _vmptrst(void *ptr) noexcept;
extern "C" bool _vmread(uint64_t field, uint64_t *value) noexcept;
extern "C" bool _vmwrite(uint64_t field, uint64_t value) noexcept;
extern "C" bool _vmlaunch_demote(void) noexcept;
extern "C" bool _invept(uint64_t type, void *ptr) noexcept;
extern "C" bool _invvpid(uint64_t type, void *ptr) noexcept;
extern "C" uintptr_t _vmcall(uintptr_t r1, uintptr_t r2, uintptr_t r3, uintptr_t r4) noexcept;
extern "C" uintptr_t _vmcall1(void *r1) noexcept;
extern "C" uintptr_t _vmcall2(void *r1, void *r2) noexcept;
extern "C" uintptr_t _vmcall3(void *r1, void *r2, void *r3) noexcept;
extern "C" uintptr_t _vmcall4(void *r1, void *r2, void *r3, void *r4) noexcept;
// *INDENT-OFF*
namespace intel_x64
{
namespace vmx
{
using vpid_type = uint64_t;
using eptp_type = uint64_t;
using integer_pointer = uintptr_t;
inline void on(gsl::not_null<void *> ptr)
{
if (!_vmxon(ptr)) {
throw std::runtime_error("vmx::on failed");
}
}
inline void off()
{
if (!_vmxoff()) {
throw std::runtime_error("vmx::off failed");
}
}
inline void invept_single_context(eptp_type eptp)
{
uint64_t descriptor[2] = { eptp, 0 };
if (!_invept(1, static_cast<void *>(descriptor))) {
throw std::runtime_error("vm::invept_singal_context failed");
}
}
inline void invept_global()
{
uint64_t descriptor[2] = { 0, 0 };
if (!_invept(2, static_cast<void *>(descriptor))) {
throw std::runtime_error("vm::invept_global failed");
}
}
inline void invvpid_individual_address(vpid_type vpid, integer_pointer addr)
{
uint64_t descriptor[2] = { vpid, addr };
if (!_invvpid(0, static_cast<void *>(descriptor))) {
throw std::runtime_error("vm::invvpid_individual_address failed");
}
}
inline void invvpid_single_context(vpid_type vpid)
{
uint64_t descriptor[2] = { vpid, 0 };
if (!_invvpid(1, static_cast<void *>(descriptor))) {
throw std::runtime_error("vm::invvpid_single_context failed");
}
}
inline void invvpid_all_contexts()
{
uint64_t descriptor[2] = { 0, 0 };
if (!_invvpid(2, static_cast<void *>(descriptor))) {
throw std::runtime_error("vm::invvpid_all_contexts failed");
}
}
inline void invvpid_single_context_global(vpid_type vpid)
{
uint64_t descriptor[2] = { vpid, 0 };
if (!_invvpid(3, static_cast<void *>(descriptor))) {
throw std::runtime_error("vm::invvpid_single_context_global failed");
}
}
}
namespace vm
{
using field_type = uint64_t;
using value_type = uint64_t;
using name_type = const char *;
using integer_pointer = uintptr_t;
inline void clear(gsl::not_null<void *> ptr)
{
if (!_vmclear(ptr)) {
throw std::runtime_error("vm::clear failed");
}
}
inline void load(gsl::not_null<void *> ptr)
{
if (!_vmptrld(ptr)) {
throw std::runtime_error("vm::load failed");
}
}
inline void store(gsl::not_null<void *> ptr)
{
if (!_vmptrst(ptr)) {
throw std::runtime_error("vm::store failed");
}
}
inline auto read(field_type field, name_type name = "")
{
value_type value = {};
if (!_vmread(field, &value))
{
bferror_info(0, "vm::read failed");
bferror_subtext(0, "field", name);
throw std::runtime_error("vm::read failed");
}
return value;
}
inline void write(field_type field, value_type value, name_type name = "")
{
if (!_vmwrite(field, value))
{
bferror_info(0, "vm::write failed");
bferror_subtext(0, "field", name);
bferror_subnhex(0, "value", value);
throw std::runtime_error("vm::write failed");
}
}
inline void launch_demote()
{
if (!_vmlaunch_demote()) {
throw std::runtime_error("vm::launch_demote failed");
}
}
inline uintptr_t call(uintptr_t r1 = 0, uintptr_t r2 = 0, uintptr_t r3 = 0, uintptr_t r4 = 0)
{ return _vmcall(r1, r2, r3, r4); }
inline uintptr_t call(uintptr_t *r1)
{ return _vmcall1(r1); }
inline uintptr_t call(uintptr_t *r1, uintptr_t *r2)
{ return _vmcall2(r1, r2); }
inline uintptr_t call(uintptr_t *r1, uintptr_t *r2, uintptr_t *r3)
{ return _vmcall3(r1, r2, r3); }
inline uintptr_t call(uintptr_t *r1, uintptr_t *r2, uintptr_t *r3, uintptr_t *r4)
{ return _vmcall4(r1, r2, r3, r4); }
}
}
// *INDENT-ON*
#endif

View file

@ -1,62 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef CACHE_X64_H
#define CACHE_X64_H
#include <cstdint>
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" void _invd(void) noexcept;
extern "C" void _wbinvd(void) noexcept;
extern "C" void _clflush(void *addr) noexcept;
// *INDENT-OFF*
namespace x64
{
namespace cache
{
using pointer = void *;
using integer_pointer = uintptr_t;
inline void invd() noexcept
{ _invd(); }
inline void wbinvd() noexcept
{ _wbinvd(); }
inline void clflush(integer_pointer addr) noexcept
{ _clflush(reinterpret_cast<pointer>(addr)); }
inline void clflush(pointer addr) noexcept
{ _clflush(addr); }
}
}
// *INDENT-ON*
#endif

View file

@ -1,359 +0,0 @@
//
// Copyright (C) 2019 Assured Information Security, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef CPUID_X64_H
#define CPUID_X64_H
#include <bfdebug.h>
#include <bfbitmanip.h>
#pragma pack(push, 1)
// -----------------------------------------------------------------------------
// Definitions
// -----------------------------------------------------------------------------
extern "C" uint32_t _cpuid_eax(uint32_t val) noexcept;
extern "C" uint32_t _cpuid_ebx(uint32_t val) noexcept;
extern "C" uint32_t _cpuid_ecx(uint32_t val) noexcept;
extern "C" uint32_t _cpuid_edx(uint32_t val) noexcept;
extern "C" uint32_t _cpuid_subeax(uint32_t val, uint32_t sub) noexcept;
extern "C" uint32_t _cpuid_subebx(uint32_t val, uint32_t sub) noexcept;
extern "C" uint32_t _cpuid_subecx(uint32_t val, uint32_t sub) noexcept;
extern "C" uint32_t _cpuid_subedx(uint32_t val, uint32_t sub) noexcept;
extern "C" void _cpuid(void *eax, void *ebx, void *ecx, void *edx) noexcept;
// *INDENT-OFF*
namespace x64
{
namespace cpuid
{
using field_type = uint32_t;
using value_type = uint32_t;
struct cpuid_regs {
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
};
inline auto get(field_type eax, field_type ebx, field_type ecx, field_type edx) noexcept
{
_cpuid(&eax, &ebx, &ecx, &edx);
return cpuid_regs{eax, ebx, ecx, edx};
}
namespace eax
{
inline auto get(field_type eax) noexcept
{ return _cpuid_eax(eax); }
}
namespace ebx
{
inline auto get(field_type ebx) noexcept
{ return _cpuid_ebx(ebx); }
}
namespace ecx
{
inline auto get(field_type ecx) noexcept
{ return _cpuid_ecx(ecx); }
}
namespace edx
{
inline auto get(field_type edx) noexcept
{ return _cpuid_edx(edx); }
}
namespace addr_size
{
constexpr const auto addr = 0x80000008ULL;
constexpr const auto name = "addr_size";
inline auto get() noexcept
{ return _cpuid_eax(addr); }
namespace phys
{
constexpr const auto mask = 0x000000FFULL;
constexpr const auto from = 0ULL;
constexpr const auto name = "phys";
inline auto get() noexcept
{ return get_bits(_cpuid_eax(addr), mask) >> from; }
inline auto get(value_type msr) noexcept
{ return get_bits(msr, mask) >> from; }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_subnhex(level, name, get(), msg); }
}
namespace linear
{
constexpr const auto mask = 0x0000FF00ULL;
constexpr const auto from = 8ULL;
constexpr const auto name = "linear";
inline auto get() noexcept
{ return get_bits(_cpuid_eax(addr), mask) >> from; }
inline auto get(value_type msr) noexcept
{ return get_bits(msr, mask) >> from; }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_subnhex(level, name, get(), msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
bfdebug_nhex(level, name, get(), msg);
phys::dump(level, msg);
linear::dump(level, msg);
}
}
namespace basic_cpuid_info
{
constexpr const auto addr = 0x00000000ULL;
namespace eax
{
constexpr const auto name = "basic_cpuid_info_eax";
inline auto get() noexcept
{ return _cpuid_eax(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
eax::dump(level, msg);
}
}
namespace extend_cpuid_info
{
constexpr const auto addr = 0x80000000ULL;
namespace eax
{
constexpr const auto name = "extend_cpuid_info_eax";
inline auto get() noexcept
{ return _cpuid_eax(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
eax::dump(level, msg);
}
}
namespace processor_string_1
{
constexpr const auto addr = 0x80000002ULL;
namespace eax
{
constexpr const auto name = "processor_string_1_eax";
inline auto get() noexcept
{ return _cpuid_eax(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace ebx
{
constexpr const auto name = "processor_string_1_ebx";
inline auto get() noexcept
{ return _cpuid_ebx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace ecx
{
constexpr const auto name = "processor_string_1_ecx";
inline auto get() noexcept
{ return _cpuid_ecx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace edx
{
constexpr const auto name = "processor_string_1_edx";
inline auto get() noexcept
{ return _cpuid_edx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
eax::dump(level, msg);
ebx::dump(level, msg);
ecx::dump(level, msg);
edx::dump(level, msg);
}
}
namespace processor_string_2
{
constexpr const auto addr = 0x80000003ULL;
namespace eax
{
constexpr const auto name = "processor_string_2_eax";
inline auto get() noexcept
{ return _cpuid_eax(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace ebx
{
constexpr const auto name = "processor_string_2_ebx";
inline auto get() noexcept
{ return _cpuid_ebx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace ecx
{
constexpr const auto name = "processor_string_2_ecx";
inline auto get() noexcept
{ return _cpuid_ecx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace edx
{
constexpr const auto name = "processor_string_2_edx";
inline auto get() noexcept
{ return _cpuid_edx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
eax::dump(level, msg);
ebx::dump(level, msg);
ecx::dump(level, msg);
edx::dump(level, msg);
}
}
namespace processor_string_3
{
constexpr const auto addr = 0x80000004ULL;
namespace eax
{
constexpr const auto name = "processor_string_3_eax";
inline auto get() noexcept
{ return _cpuid_eax(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace ebx
{
constexpr const auto name = "processor_string_3_ebx";
inline auto get() noexcept
{ return _cpuid_ebx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace ecx
{
constexpr const auto name = "processor_string_3_ecx";
inline auto get() noexcept
{ return _cpuid_ecx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
namespace edx
{
constexpr const auto name = "processor_string_3_edx";
inline auto get() noexcept
{ return _cpuid_edx(addr); }
inline void dump(int level, std::string *msg = nullptr)
{ bfdebug_nhex(level, name, get(), msg); }
}
inline void dump(int level, std::string *msg = nullptr)
{
eax::dump(level, msg);
ebx::dump(level, msg);
ecx::dump(level, msg);
edx::dump(level, msg);
}
}
}
}
// *INDENT-ON*
#pragma pack(pop)
#endif

Some files were not shown because too many files have changed in this diff Show more