Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ See [migration.md](docs/migration.md) for a list of the API changes in the lates

## VMF Compatibility

As of now, VMF can be run in Docker and on the following distributions of Linux:
As of now, VMF can be run in Docker and on the following distributions of Linux and BSD:

- CentOS 8 and 9
- FreeBSD 15.0 and 15.1
- Kali
- Oracle Linux 8 and 9
- RedHat 8 and 9
Expand Down Expand Up @@ -116,6 +117,26 @@ You may alternatively open the VMF.sln file that has been generated in the build

More information on the build system is available in our [Build System Documentation](docs/build_system.md).

### Building VMF (FreeBSD)

Install dependencies for the build with `pkg install curl cmake gmake`.

When building and installing AFL++, support for FreeBSD has been merged into the official repository. The most recent tested commit is e33e7cd4f4b1da9cc76c19b7766deea790a2c5ee.

Execute the following commands to build and install VMF. Note the use of the `gmake` command instead of `make`, the BSD make is incompatible and the GNU make must be used.

*Note: The -DCMAKE_INSTALL_PREFIX may be used to optionally specify an install location other than the default (build/vmf_install).*

```bash
# from /path/to/vmf/ directory:
mkdir build
cd build
cmake ..
#Or optionally use this version instead to specify an install path
#cmake -DCMAKE_INSTALL_PREFIX=<your install path here> ..
gmake install -j8
```

### Running VMF
VMF can be run in a standalone mode, with a single fuzzing instance, as well as in a distributed mode where multiple VMF instances work together to fuzz something.

Expand Down
5 changes: 4 additions & 1 deletion vmf/src/framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ set(Framework_LINKLIST
restclient-cpp
)

if(NOT WIN32)
if (BSD)
#explicitly linking stdc++fs not needed on FreeBSD
list(APPEND Framework_LINKLIST)
elseif(NOT WIN32)
list(APPEND Framework_LINKLIST stdc++fs)
else()
list(APPEND Framework_LINKLIST wldap32 ws2_32 Crypt32.lib Wldap32 Normaliz)
Expand Down
2 changes: 1 addition & 1 deletion vmf/src/framework/util/OSAPI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class OSAPI
* @param handler this is the pointer to a function that will be run when an interrupt signal is received by
* VMF.
*/
virtual void setSignalHandlers(sighandler_t handler) = 0;
virtual void setSignalHandlers(__sighandler_t handler) = 0;
#endif

virtual ~OSAPI() {};
Expand Down
19 changes: 18 additions & 1 deletion vmf/src/framework/util/linux/OSAPIImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@
#include <filesystem>
#include <libgen.h> // dirname
#include <unistd.h> // readlink
#ifdef __FreeBSD__
#include <sys/syslimits.h>
#include <sys/sysctl.h>
#else
#include <linux/limits.h> // PATH_MAX
#endif

using namespace vmf;

Expand Down Expand Up @@ -100,7 +105,19 @@ std::string OSAPIImp::getExecutablePath()
char result[PATH_MAX];
const char *path = nullptr;

#ifdef __FreeBSD__
//no /proc/self/exe on FreeBSD
size_t count = sizeof(result);
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
sysctl(mib, 4, result, &count, NULL, 0);
#else
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);

#endif
if (count > 0) {
result[count] = 0;
path = dirname(result);
Expand Down Expand Up @@ -164,7 +181,7 @@ bool OSAPIImp::commandLineZip(std::string zipFilePath, std::string inputDir)
return success;
}

void OSAPIImp::setSignalHandlers(sighandler_t handler)
void OSAPIImp::setSignalHandlers(__sighandler_t handler)
{
signal(SIGINT, handler);
signal(SIGTERM, handler);
Expand Down
4 changes: 2 additions & 2 deletions vmf/src/framework/util/linux/OSAPIImp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ class OSAPIImp: public OSAPI
* @param handler this is the pointer to a function that will be run when an interrupt signal is received by
* VMF.
*/
virtual void setSignalHandlers(sighandler_t handler);
virtual void setSignalHandlers(__sighandler_t handler);

virtual ~OSAPIImp();
};
}
}
19 changes: 18 additions & 1 deletion vmf/src/modules/linux/executor/AFLForkserverExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,12 @@ void AFLForkserverExecutor::init(ConfigInterface& config) {
parseSUTDebugInfo();
validateVersionCompatibility();

#ifndef __FreeBSD__
bool useCoreDumpCheck = config.getBoolParam(getModuleName(),"enableCoreDumpCheck", true);
#else //FreeBSD
/* /proc/sys/kernel/core_pattern does not exist on FreeBSD, cannot verify core pattern. */
bool useCoreDumpCheck = config.getBoolParam(getModuleName(),"enableCoreDumpCheck", false);
#endif
if(useCoreDumpCheck)
{
verifyCorePattern();
Expand Down Expand Up @@ -138,6 +143,10 @@ bool AFLForkserverExecutor::verifyCorePattern(void) {
/* Check that the core dump pattern does not begin with a pipe.
This causes crashes to be sent to an external utility, which is very slow
and causes VMF to misinterpret them as timeouts. As such, this is a fatal error. */
///proc/sys/kernel/core_pattern does not exist on FreeBSD.
#ifdef __FreeBSD__
throw RuntimeException("/proc/sys/kernel/core_pattern does not exist on FreeBSD, cannot verify core pattern.", RuntimeException::CONFIGURATION_ERROR);
#endif
int corepattern_fd = open("/proc/sys/kernel/core_pattern", O_RDONLY);

if (corepattern_fd < 0)
Expand All @@ -150,7 +159,7 @@ bool AFLForkserverExecutor::verifyCorePattern(void) {
"to be misinterpreted as timeouts.\nTo fix, please log in as root "
"and run the following command: \n"
" echo core >/proc/sys/kernel/core_pattern",
RuntimeException::UNEXPECTED_ERROR);
RuntimeException::CONFIGURATION_ERROR);
return true;
}

Expand Down Expand Up @@ -1294,10 +1303,18 @@ void AFLForkserverExecutor::setResourceLimits(void) {
* values as high as our default constants for pipes */
long unsigned max_fd = std::max({CTRL_PIPE_RD, CTRL_PIPE_WR, STAT_PIPE_RD, STAT_PIPE_WR});
getrlimit(RLIMIT_NOFILE, &r);
#ifdef __FreeBSD__
/* freebsd r.rlim_cur is signed long, and clang cares about unsigned vs signed comparison */
if (static_cast<unsigned long>(r.rlim_cur) < max_fd + 1) {
r.rlim_cur = max_fd + 2;
setrlimit(RLIMIT_NOFILE, &r);
}
#else
if (r.rlim_cur < max_fd + 1) {
r.rlim_cur = max_fd + 2;
setrlimit(RLIMIT_NOFILE, &r);
}
#endif

/* Memory Limit */
if (sut_mem_limit > 0) {
Expand Down