BoxFort-master/ 0002755 0001750 0001750 00000000000 13603450524 012376 5 ustar sasa sasa BoxFort-master/.cirrus.yml 0000644 0001750 0001750 00000002502 13603450524 014503 0 ustar sasa sasa _pipeline: &pipeline
info_script: |
meson --version
ninja --version
configure_script: meson build
compile_script: ninja -C build
test_script: ninja -C build test
Debian (gcc)_task:
container:
image: snaipe/ci-meson:debian-10
<<: *pipeline
Alpine (gcc,x86_64)_task:
container:
image: snaipe/ci-meson:alpine
<<: *pipeline
Alpine (gcc,i386)_task:
container:
image: snaipe/ci-meson:alpine-x86
<<: *pipeline
Alpine (gcc,arm)_task:
container:
image: snaipe/ci-meson:alpine-armhf
env:
CIRRUS_SHELL: /sbin/qemu-sh
<<: *pipeline
Alpine (gcc,aarch64)_task:
container:
image: snaipe/ci-meson:alpine-aarch64
env:
CIRRUS_SHELL: /sbin/qemu-sh
<<: *pipeline
MacOS_task:
osx_instance:
image: mojave-xcode-10.2
setup_script: brew install meson
<<: *pipeline
FreeBSD_task:
freebsd_instance:
image_family: freebsd-12-0
setup_script: pkg install -y meson
<<: *pipeline
Windows_task:
windows_container:
image: cirrusci/windowsservercore:cmake
os_version: 2019
env:
PATH: C:\\Python;C:\\Python\\Scripts;C:\\ProgramData\\chocolatey\\lib\\ninja\\tools;%PATH%
meson-setup_script: |-
choco install -y --no-progress python3 --params "/InstallDir:C:\Python"
pip install meson
ninja-setup_script: choco install -y --no-progress ninja
<<: *pipeline
BoxFort-master/.githooks/ 0002755 0001750 0001750 00000000000 13603450524 014303 5 ustar sasa sasa BoxFort-master/.githooks/canonicalize_filename.sh 0000644 0001750 0001750 00000003201 13603450524 021130 0 ustar sasa sasa #!/bin/sh
# Provide the canonicalize filename (physical filename with out any symlinks)
# like the GNU version readlink with the -f option regardless of the version of
# readlink (GNU or BSD).
# This file is part of a set of unofficial pre-commit hooks available
# at github.
# Link: https://github.com/githubbrowser/Pre-commit-hooks
# Contact: David Martin, david.martin.mailbox@googlemail.com
###########################################################
# There should be no need to change anything below this line.
# Canonicalize by recursively following every symlink in every component of the
# specified filename. This should reproduce the results of the GNU version of
# readlink with the -f option.
#
# Reference: http://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac
canonicalize_filename () {
local target_file="$1"
local physical_directory=""
local result=""
# Need to restore the working directory after work.
local working_dir="`pwd`"
cd -- "$(dirname -- "$target_file")"
target_file="$(basename -- "$target_file")"
# Iterate down a (possible) chain of symlinks
while [ -L "$target_file" ]
do
target_file="$(readlink -- "$target_file")"
cd -- "$(dirname -- "$target_file")"
target_file="$(basename -- "$target_file")"
done
# Compute the canonicalized name by finding the physical path
# for the directory we're in and appending the target file.
physical_directory="`pwd -P`"
result="$physical_directory/$target_file"
# restore the working directory after work.
cd -- "$working_dir"
echo "$result"
}
BoxFort-master/.githooks/install.sh 0000755 0001750 0001750 00000000073 13603450524 016306 0 ustar sasa sasa #!/bin/sh
rm -Rf .git/hooks
ln -s ../.githooks .git/hooks
BoxFort-master/.githooks/pre-commit 0000755 0001750 0001750 00000014246 13603450524 016312 0 ustar sasa sasa #!/bin/sh
# git pre-commit hook that runs an Uncrustify stylecheck.
# Features:
# - abort commit when commit does not comply with the style guidelines
# - create a patch of the proposed style changes
#
# More info on Uncrustify: http://uncrustify.sourceforge.net/
# This file is part of a set of unofficial pre-commit hooks available
# at github.
# Link: https://github.com/githubbrowser/Pre-commit-hooks
# Contact: David Martin, david.martin.mailbox@googlemail.com
##################################################################
# CONFIGURATION
# set uncrustify path or executable
# UNCRUSTIFY="/usr/bin/uncrustify"
UNCRUSTIFY="uncrustify"
# set uncrustify config location
# CONFIG="/home/user/.config/uncrustify.cfg"
CONFIG=".uncrustify.cfg"
# the source language: C, CPP, D, CS, JAVA, PAWN, VALA, OC, OC+
# use AUTO to let Uncrustify decide which language a given file uses.
# the detected language is printed to the console when Uncrustify is called.
# override if the automatic detection seems off.
# SOURCE_LANGUAGE="AUTO"
SOURCE_LANGUAGE="AUTO"
# remove any older patches from previous commits. Set to true or false.
# DELETE_OLD_PATCHES=false
DELETE_OLD_PATCHES=false
# only parse files with the extensions in FILE_EXTS. Set to true or false.
# if false every changed file in the commit will be parsed with Uncrustify.
# if true only files matching one of the extensions are parsed with Uncrustify.
# PARSE_EXTS=true
PARSE_EXTS=true
# file types to parse. Only effective when PARSE_EXTS is true.
# FILE_EXTS=".c .h .cpp .hpp"
FILE_EXTS=".c .h .cc .hh .cpp .hpp .hxx"
##################################################################
# There should be no need to change anything below this line.
. "$(dirname -- "$0")/canonicalize_filename.sh"
# exit on error
set -e
# check whether the given file matches any of the set extensions
matches_extension() {
local filename="$(basename -- "$1")"
local extension=".${filename##*.}"
local ext
for ext in $FILE_EXTS; do [ "$ext" = "$extension" ] && return 0; done
return 1
}
# necessary check for initial commit
if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# make sure the config file and executable are correctly set
if [ ! -f "$CONFIG" ] ; then
printf "Error: uncrustify config file not found.\n"
printf "Set the correct path in $(canonicalize_filename "$0").\n"
exit 1
fi
if ! command -v "$UNCRUSTIFY" > /dev/null ; then
printf "Error: uncrustify executable not found.\n"
printf "Set the correct path in $(canonicalize_filename "$0").\n"
exit 1
fi
# create a filename to store our generated patch
prefix="pre-commit-uncrustify"
suffix="$(date +%C%y-%m-%d_%Hh%Mm%Ss)"
patch="/tmp/$prefix-$suffix.patch"
# clean up any older uncrustify patches
$DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
# create one patch containing all changes to the files
# sed to remove quotes around the filename, if inserted by the system
# (done sometimes, if the filename contains special characters, like the quote itself)
git diff-index --cached --diff-filter=ACMR --name-only $against -- | \
sed -e 's/^"\(.*\)"$/\1/' | \
while read file
do
# ignore file if we do check for file extensions and the file
# does not match any of the extensions specified in $FILE_EXTS
if $PARSE_EXTS && ! matches_extension "$file"; then
continue;
fi
# escape special characters in the source filename:
# - '\': backslash needs to be escaped
# - '*': used as matching string => '*' would mean expansion
# (curiously, '?' must not be escaped)
# - '[': used as matching string => '[' would mean start of set
# - '|': used as sed split char instead of '/', so it needs to be escaped
# in the filename
# printf %s particularly important if the filename contains the % character
file_escaped_source=$(printf "%s" "$file" | sed -e 's/[\*[|]/\\&/g')
# escape special characters in the target filename:
# phase 1 (characters escaped in the output diff):
# - '\': backslash needs to be escaped in the output diff
# - '"': quote needs to be escaped in the output diff if present inside
# of the filename, as it used to bracket the entire filename part
# phase 2 (characters escaped in the match replacement):
# - '\': backslash needs to be escaped again for sed itself
# (i.e. double escaping after phase 1)
# - '&': would expand to matched string
# - '|': used as sed split char instead of '/'
# printf %s particularly important if the filename contains the % character
file_escaped_target=$(printf "%s" "$file" | sed -e 's/[\"]/\\&/g' -e 's/[\&|]/\\&/g')
# Uncrustify detects the language automatically if it is not specified
language_option=""
if [ "$SOURCE_LANGUAGE" != "AUTO" ] ; then
language_option="-l $SOURCE_LANGUAGE"
fi
# uncrustify our sourcefile, create a patch with diff and append it to our $patch
# The sed call is necessary to transform the patch from
# --- $file timestamp
# +++ - timestamp
# to both lines working on the same file and having a a/ and b/ prefix.
# Else it can not be applied with 'git apply'.
"$UNCRUSTIFY" -c "$CONFIG" -f "$file" $language_option | \
git --no-pager diff --color=always --no-index -- "$file" - | \
sed -e "1s|--- $file_escaped_source|--- \"a/$file_escaped_target\"|" -e "2s|+++ -|+++ \"b/$file_escaped_target\"|" >> "$patch"
done
# if no patch has been generated all is ok, clean up the file stub and exit
if [ ! -s "$patch" ] ; then
printf "Files in this commit comply with the uncrustify rules.\n"
rm -f "$patch"
exit 0
fi
# a patch has been created, notify the user and exit
printf "\nThe following differences were found between the code to commit "
printf "and the uncrustify rules:\n\n"
cat "$patch"
printf "\nYou can apply these changes with:\n git apply $patch\n"
printf "(may need to be called from the root directory of your repository)\n"
printf "Aborting commit. Apply changes and commit again or skip checking with"
printf " --no-verify (not recommended).\n"
exit 1
BoxFort-master/.gitignore 0000644 0001750 0001750 00000000027 13603450524 014363 0 ustar sasa sasa build/
*.swp
*.swo
*~
BoxFort-master/.uncrustify.cfg 0000644 0001750 0001750 00000015717 13603450524 015361 0 ustar sasa sasa # General
tok_split_gte=false
utf8_byte=false
utf8_force=true
code_width=80
newlines=lf
utf8_bom=remove
input_tab_size=4
output_tab_size=4
# Comments
cmt_indent_multi=true
cmt_c_group=false
cmt_c_nl_start=false
cmt_c_nl_end=false
cmt_cpp_group=true
cmt_cpp_nl_start=false
cmt_cpp_nl_end=false
cmt_cpp_to_c=true
cmt_star_cont=false
cmt_multi_check_last=true
cmt_insert_before_preproc=false
# Indentation
indent_columns=4
indent_continue=8
indent_xml_string=2
indent_ctor_init=4
indent_switch_case=4
indent_label=1
indent_access_spec=0
indent_with_tabs=0
indent_cmt_with_tabs=false
indent_align_string=true
indent_braces=false
indent_braces_no_func=false
indent_braces_no_class=false
indent_braces_no_struct=false
indent_brace_parent=false
indent_namespace=false
indent_extern=false
indent_class=false
indent_class_colon=true
indent_else_if=true
indent_var_def_cont=false
indent_func_call_param=true
indent_func_def_param=true
indent_func_proto_param=true
indent_func_class_param=true
indent_func_ctor_var_param=true
indent_template_param=true
indent_func_param_double=true
indent_relative_single_line_comments=false
indent_col1_comment=false
indent_access_spec_body=true
indent_paren_nl=false
indent_comma_paren=false
indent_bool_paren=false
indent_first_bool_expr=false
indent_square_nl=false
indent_preserve_sql=false
indent_align_assign=true
# Alignment
align_var_def_span=0
align_assign_span=1
align_assign_thresh=3
align_enum_equ_span=1
align_enum_equ_thresh=3
align_var_struct_span=0
align_struct_init_span=1
align_right_cmt_span=1
align_keep_tabs=false
align_with_tabs=false
align_on_tabstop=false
align_number_left=false
align_func_params=false
align_same_func_call_params=false
align_var_def_colon=true
align_var_def_attribute=false
align_var_def_inline=true
align_right_cmt_mix=false
align_on_operator=false
align_mix_var_proto=false
align_single_line_func=true
align_single_line_brace=true
align_nl_cont=true
align_left_shift=true
align_oc_decl_colon=false
# Spacing
sp_arith=force
sp_assign=force
sp_assign_default=force
sp_enum_assign=force
sp_pp_concat=force
sp_pp_stringify=remove
sp_bool=force
sp_compare=force
sp_inside_paren=remove
sp_paren_paren=remove
sp_paren_brace=force
sp_before_ptr_star=force
sp_between_ptr_star=remove
sp_after_ptr_star=remove
sp_after_ptr_star_func=remove
sp_before_ptr_star_func=force
sp_before_byref=force
sp_before_unnamed_byref=force
sp_after_byref=remove
sp_after_byref_func=remove
sp_before_byref_func=force
sp_after_type=force
sp_template_angle=add
sp_before_angle=remove
sp_inside_angle=remove
sp_after_angle=force
sp_angle_paren=remove
sp_angle_word=force
sp_angle_shift=ignore
sp_before_sparen=force
sp_inside_sparen=remove
sp_after_sparen=force
sp_sparen_brace=force
sp_special_semi=remove
sp_before_semi=remove
sp_before_semi_for=remove
sp_before_semi_for_empty=remove
sp_after_semi=force
sp_after_semi_for=force
sp_after_semi_for_empty=remove
sp_before_square=remove
sp_before_squares=remove
sp_inside_square=remove
sp_after_comma=force
sp_before_comma=remove
sp_paren_comma=ignore
sp_before_ellipsis=remove
sp_after_class_colon=force
sp_before_class_colon=force
sp_before_case_colon=remove
sp_after_operator=remove
sp_after_operator_sym=remove
sp_after_cast=force
sp_inside_paren_cast=remove
sp_cpp_cast_paren=force
sp_sizeof_paren=force
sp_inside_braces_enum=force
sp_inside_braces_struct=force
sp_inside_braces=force
sp_inside_braces_empty=remove
sp_func_proto_paren=remove
sp_func_def_paren=remove
sp_inside_fparens=remove
sp_inside_fparen=remove
sp_square_fparen=remove
sp_fparen_brace=force
sp_func_call_paren=remove
sp_func_call_user_paren=remove
sp_func_class_paren=remove
sp_return_paren=force
sp_attribute_paren=remove
sp_defined_paren=force
sp_throw_paren=force
sp_catch_paren=force
sp_macro=force
sp_macro_func=force
sp_else_brace=force
sp_brace_else=force
sp_brace_typedef=force
sp_catch_brace=force
sp_brace_catch=force
sp_finally_brace=force
sp_brace_finally=force
sp_try_brace=force
sp_getset_brace=force
sp_before_dc=remove
sp_after_dc=remove
sp_not=remove
sp_inv=remove
sp_addr=remove
sp_member=remove
sp_deref=remove
sp_sign=remove
sp_incdec=remove
sp_before_nl_cont=force
sp_cond_colon=force
sp_cond_question=force
sp_case_label=force
sp_cmt_cpp_start=force
sp_endif_cmt=force
sp_after_new=force
sp_before_tr_emb_cmt=force
sp_num_before_tr_emb_cmt=1
sp_balance_nested_parens=false
cmt_sp_before_star_cont=0
cmt_sp_after_star_cont=1
# Newlines
nl_max=2
nl_end_of_file_min=1
nl_func_var_def_blk=1
nl_start_of_file=remove
nl_end_of_file=force
nl_assign_brace=remove
nl_fcall_brace=remove
nl_enum_brace=remove
nl_struct_brace=remove
nl_union_brace=remove
nl_if_brace=remove
nl_brace_else=remove
nl_elseif_brace=remove
nl_else_brace=remove
nl_else_if=remove
nl_brace_finally=remove
nl_finally_brace=remove
nl_try_brace=remove
nl_getset_brace=remove
nl_for_brace=remove
nl_catch_brace=remove
nl_brace_catch=remove
nl_while_brace=remove
nl_using_brace=remove
nl_brace_brace=ignore
nl_do_brace=remove
nl_brace_while=remove
nl_switch_brace=remove
nl_namespace_brace=remove
nl_template_class=force
nl_class_brace=remove
nl_func_type_name=remove
nl_func_type_name_class=remove
nl_func_scope_name=remove
nl_func_proto_type_name=remove
nl_func_paren=remove
nl_func_def_paren=remove
nl_func_decl_end=remove
nl_func_def_end=remove
nl_func_decl_empty=remove
nl_func_def_empty=remove
nl_fdef_brace=force
nl_return_expr=remove
nl_collapse_empty_body=false
nl_assign_leave_one_liners=true
nl_class_leave_one_liners=true
nl_enum_leave_one_liners=true
nl_getset_leave_one_liners=true
nl_func_leave_one_liners=false
nl_if_leave_one_liners=false
nl_multi_line_cond=true
nl_multi_line_define=true
nl_before_case=false
nl_after_case=false
nl_after_return=false
nl_after_semicolon=true
nl_after_brace_open=false
nl_after_brace_open_cmt=false
nl_after_vbrace_open=true
nl_after_vbrace_open_empty=false
nl_after_brace_close=false
nl_after_vbrace_close=true
nl_define_macro=true
nl_squeeze_ifdef=false
nl_ds_struct_enum_cmt=false
nl_ds_struct_enum_close_brace=false
nl_create_if_one_liner=false
nl_create_for_one_liner=false
nl_create_while_one_liner=false
nl_after_multiline_comment=false
ls_for_split_full=true
ls_func_split_full=true
eat_blanks_after_open_brace=false
eat_blanks_before_close_brace=false
# Positioning
pos_arith=lead
pos_assign=trail
pos_bool=lead
pos_compare=lead
pos_conditional=lead
pos_comma=trail
pos_class_comma=trail
pos_class_colon=lead
# Modifications
mod_full_brace_do=force
mod_full_brace_for=remove
mod_full_brace_if=remove
mod_full_brace_while=remove
mod_full_brace_using=remove
mod_paren_on_return=remove
mod_full_brace_nl=2
mod_full_brace_if_chain=true
mod_pawn_semicolon=false
mod_full_paren_if_bool=false
mod_remove_extra_semicolon=true
mod_sort_import=false
mod_sort_using=false
mod_sort_include=false
mod_move_case_break=false
mod_remove_empty_return=true
# Preprocessor
pp_indent=remove
pp_space=force
pp_space_count=1
pp_indent_at_level=false
pp_region_indent_code=false
pp_if_indent_code=false
pp_define_at_level=false
# nonstd cast attributes
set cpp_cast nonstd
# gettext macros
set func_call_user _ N_
BoxFort-master/LICENSE 0000644 0001750 0001750 00000002125 13603450524 013401 0 ustar sasa sasa The MIT License (MIT)
Copyright © 2016 Franklin "Snaipe" Mathieu
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.
BoxFort-master/README.md 0000644 0001750 0001750 00000002137 13603450524 013656 0 ustar sasa sasa # BoxFort
[](https://cirrus-ci.com/github/Snaipe/BoxFort)
[](https://github.com/diacritic/BoxFort/blob/master/LICENSE)
[](https://github.com/diacritic/BoxFort/releases)
A simple, cross-platform sandboxing C library powering [Criterion][criterion].
**Warning**: This library is experimental. APIs may change without notice until Beta is hit. Use at your own risk.
BoxFort provides a simple API to run user code in isolated processes.
Although BoxFort provides some kind of security of the parent process
from spawned sandboxes, a sandbox has by default the same system
permissions and access than its parent, and is hence, without care,
ill-fitted for security purposes.
The main goal of this project **is not** security, but portable code
isolation -- if you want complete system isolation, consider using
properly configured containers.
[criterion]: https://github.com/Snaipe/Criterion
BoxFort-master/ci/ 0002755 0001750 0001750 00000000000 13603450524 012771 5 ustar sasa sasa BoxFort-master/ci/cram-env.patch 0000644 0001750 0001750 00000001336 13603450524 015523 0 ustar sasa sasa --- _test.py.orig 2016-09-03 00:50:27.505527300 +0200
+++ "/c/Program Files/Python35/lib/site-packages/cram/_test.py" 2016-09-03 00:48:48.708932100 +0200
@@ -143,11 +143,15 @@
after.setdefault(pos, []).append(line)
stdin.append(b('echo %s %s $?\n' % (usalt, i + 1)))
+ env = {k: v.decode('utf-8') if isinstance(v, bytes) else v for k, v in env.items()}
+
output, retcode = execute(shell + ['-'], stdin=b('').join(stdin),
stdout=PIPE, stderr=STDOUT, env=env)
if retcode == 80:
return (refout, None, [])
+ output = output.replace(b'\r\n', b'\n').replace(b'\r', b'\n')
+
pos = -1
ret = 0
for i, line in enumerate(output[:-1].splitlines(True)):
BoxFort-master/ci/isdir.py 0000755 0001750 0001750 00000000201 13603450524 014447 0 ustar sasa sasa #!/usr/bin/env python3
import os, sys
os.chdir(os.environ['MESON_SOURCE_ROOT'])
sys.exit(0 if os.path.isdir(sys.argv[1]) else 1)
BoxFort-master/include/ 0002755 0001750 0001750 00000000000 13603450524 014021 5 ustar sasa sasa BoxFort-master/include/boxfort.h 0000644 0001750 0001750 00000020356 13603450524 015661 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 BOXFORT_H_
#define BOXFORT_H_
#include
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
#if !defined BXF_STATIC_LIB && !defined BXF_API
# if defined _WIN32 || defined __CYGWIN__
# ifdef BXF_BUILDING_LIB
# ifdef __GNUC__
# define BXF_API __attribute__((dllexport))
# else
# define BXF_API __declspec(dllexport)
# endif
# else
# ifdef __GNUC__
# define BXF_API __attribute__((dllimport))
# else
# define BXF_API __declspec(dllimport)
# endif
# endif
# else
# if __GNUC__ >= 4
# define BXF_API __attribute__((visibility("default")))
# else
# define BXF_API
# endif
# endif
#elif !defined BXF_API
# define BXF_API
#endif
/* Arena API */
/**
* The opaque handle type representing a BoxFort memory arena.
*/
typedef struct bxf_arena_s *bxf_arena;
enum {
/**
* Allow the arena to be resized during allocations.
*/
BXF_ARENA_RESIZE = (1 << 0),
/**
* Memory may be reclaimed with bxf_arena_free.
*/
BXF_ARENA_DYNAMIC = (1 << 1),
/**
* If BXF_ARENA_RESIZE is specified, allow the arena to be moved in
* memory.
*
* All allocation operations invalidate virtual addresses inside the arena.
*/
BXF_ARENA_MAYMOVE = (1 << 2),
/**
* Map 1:1 the arena in the sandbox instance, exactly where the arena
* exists in the parent's address space.
*
* All virtual pointers used by the parent are kept valid in the sandbox
* instance.
*/
BXF_ARENA_IDENTITY = (1 << 3),
/**
* The arena in the sandbox instance is mapped read-only. All write
* accesses to memory allocated inside the arena result in a segmentation
* fault.
*/
BXF_ARENA_IMMUTABLE = (1 << 4),
/**
* The arena in the parent is not unmapped upon termination. All related
* shared memory resources are still cleaned up.
*
* This is necessary for special languages semantics like C++ destructors
* of static objects that assume that the heap is still mapped before
* a call free().
*/
BXF_ARENA_KEEPMAPPED = (1 << 5),
};
typedef intptr_t bxf_ptr;
typedef int (bxf_arena_fn)(void *, size_t, void *);
BXF_API int bxf_arena_init(size_t initial, int flags, bxf_arena *arena);
BXF_API int bxf_arena_copy(bxf_arena orig, int flags, bxf_arena *arena);
BXF_API int bxf_arena_term(bxf_arena *arena);
BXF_API bxf_ptr bxf_arena_alloc(bxf_arena *arena, size_t size);
BXF_API bxf_ptr bxf_arena_realloc(bxf_arena *arena, bxf_ptr ptr,
size_t newsize);
BXF_API int bxf_arena_grow(bxf_arena *arena, bxf_ptr ptr, size_t newsize);
BXF_API int bxf_arena_free(bxf_arena *arena, bxf_ptr ptr);
BXF_API int bxf_arena_iter(bxf_arena arena, bxf_arena_fn *fn, void *user);
BXF_API void *bxf_arena_ptr(bxf_arena arena, bxf_ptr ptr);
/* Resource context API */
#ifdef _WIN32
typedef void *bxf_fhandle;
#else
typedef int bxf_fhandle;
#endif
typedef struct bxf_context_s *bxf_context;
BXF_API int bxf_context_init(bxf_context *ctx);
BXF_API int bxf_context_term(bxf_context ctx);
BXF_API int bxf_context_addstatic(bxf_context ctx, const void *ptr,
size_t size);
BXF_API int bxf_context_addarena(bxf_context ctx, bxf_arena arena);
BXF_API int bxf_context_addobject(bxf_context ctx, const char *name,
const void *ptr, size_t size);
BXF_API int bxf_context_getobject(bxf_context ctx, const char *name,
void **ptr);
BXF_API int bxf_context_addaddr(bxf_context ctx, const char *name,
const void *addr);
BXF_API int bxf_context_getaddr(bxf_context ctx, const char *name,
void **addr);
BXF_API int bxf_context_addfnaddr(bxf_context ctx, const char *name,
void (*fn)(void));
BXF_API int bxf_context_getfnaddr(bxf_context ctx, const char *name,
void(**fn)(void));
BXF_API int bxf_context_addfhandle(bxf_context ctx, bxf_fhandle hndl);
BXF_API int bxf_context_addfile(bxf_context ctx, const char *name, FILE *file);
BXF_API int bxf_context_getfile(bxf_context ctx, const char *name, FILE **file);
BXF_API bxf_context bxf_context_current(void);
/* Sandbox API */
typedef unsigned long long bxf_pid;
typedef int (bxf_fn)(void);
struct bxf_quotas {
size_t memory;
size_t subprocesses;
size_t files;
double runtime;
};
struct bxf_inheritance {
unsigned files : 1;
unsigned data : 1;
bxf_context context;
};
enum bxf_debugger {
BXF_DBG_NONE, /* Do not debug the sandbox */
BXF_DBG_GDB, /* Spawn with gdbserver */
BXF_DBG_LLDB, /* Spawn with lldb-server */
BXF_DBG_WINDBG, /* Spawn with windbg (Windows only) */
};
#if defined (__clang__)
# define BXF_DBG_NATIVE BXF_DBG_LLDB
#elif defined (__GNUC__)
# define BXF_DBG_NATIVE BXF_DBG_GDB
#elif defined (_WIN32)
# define BXF_DBG_NATIVE BXF_DBG_WINDBG
#endif
struct bxf_debug {
enum bxf_debugger debugger;
int tcp;
};
#define BXFI_SANDBOX_FIELDS \
int suspended; \
struct bxf_quotas quotas; \
struct bxf_quotas iquotas; \
struct bxf_inheritance inherit; \
struct bxf_debug debug;
struct bxf_sandbox_s {
BXFI_SANDBOX_FIELDS
};
typedef const struct bxf_sandbox_s bxf_sandbox;
struct bxf_instance_s {
bxf_sandbox *sandbox;
bxf_pid pid;
volatile struct {
int signal;
int exit;
int alive;
int stopped;
int timed_out;
} status;
volatile struct {
uint64_t start;
uint64_t end;
uint64_t elapsed;
} time;
void *user;
};
typedef const struct bxf_instance_s bxf_instance;
typedef void (bxf_callback)(bxf_instance *);
typedef int (bxf_preexec)(bxf_instance *);
typedef void (bxf_dtor)(bxf_instance *, void *);
struct bxf_spawn_params_s {
int bxfi_sentinel_; /* Reserved */
bxf_fn *fn;
bxf_preexec *preexec;
void *user;
bxf_dtor *user_dtor;
bxf_callback *callback;
BXFI_SANDBOX_FIELDS
};
typedef const struct bxf_spawn_params_s *bxf_spawn_params;
struct bxf_start_params_s {
int bxfi_sentinel_; /* Reserved */
bxf_fn *fn;
bxf_preexec *preexec;
void *user;
bxf_dtor *user_dtor;
bxf_callback *callback;
};
#define BXF_FOREVER INFINITY
typedef const struct bxf_start_params_s *bxf_start_params;
#define bxf_start(Instance, Sandbox, ...) \
(bxf_start_struct((Instance), \
(Sandbox), \
&(struct bxf_start_params_s) { .bxfi_sentinel_ = 0, __VA_ARGS__ }))
BXF_API int bxf_start_struct(bxf_instance **instance,
bxf_sandbox *sandbox, bxf_start_params params);
BXF_API int bxf_term(bxf_instance *instance);
BXF_API int bxf_wait(bxf_instance *instance, double timeout);
#define bxf_spawn(Instance, ...) \
(bxf_spawn_struct((Instance), \
&(struct bxf_spawn_params_s) { .bxfi_sentinel_ = 0, __VA_ARGS__ }))
BXF_API int bxf_spawn_struct(bxf_instance **instance, bxf_spawn_params params);
#define bxf_run(...) \
(bxf_run_struct( \
&(struct bxf_spawn_params_s) { .bxfi_sentinel_ = 0, __VA_ARGS__ }))
BXF_API int bxf_run_struct(bxf_spawn_params params);
BXF_API void bxf_suspend(bxf_instance *instance);
BXF_API void bxf_resume(bxf_instance *instance);
#ifdef __cplusplus
}
#endif
#endif /* !BOXFORT_H_ */
BoxFort-master/meson.build 0000644 0001750 0001750 00000011721 13603450524 014540 0 ustar sasa sasa project('boxfort', 'c',
meson_version : '>= 0.48.0',
license : 'MIT',
version : '0.0.1',
default_options : ['c_std=c99', 'warning_level=3', 'b_lundef=false'])
# standard install directories
prefix = get_option('prefix')
# Helper scripts
auxdir = join_paths(meson.current_source_dir(), 'ci')
isdir = join_paths(auxdir, 'isdir.py')
python3 = find_program('python3')
git = find_program('git', required: false)
# Get the right version
is_git_repo = run_command([isdir, '.git']).returncode() == 0
version = 'v' + meson.project_version()
if git.found() and is_git_repo
version = run_command([git.path(), 'describe', '--dirty', '--tags']).stdout().strip()
branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip()
if branch != 'master'
version = '@0@ (@1@)'.format(version, branch)
endif
endif
cc = meson.get_compiler('c')
add_project_arguments(
cc.get_supported_arguments([
'-Wno-unused-parameter',
'-Wno-unused-value',
'-fvisibility=hidden',
# MSVC-specific stuff
'/SAFESEH:NO',
'/source-charset:utf-8',
]),
'-DBXF_BUILDING_LIB',
'-D_GNU_SOURCE',
language: ['c', 'cpp'])
if host_machine.system() == 'windows'
add_project_arguments(
'-DVC_EXTRALEAN',
'-DWIN32_LEAN_AND_MEAN',
'-D_CRT_SECURE_NO_WARNINGS',
'-D_WIN32_WINNT=0x600',
language: ['c', 'cpp'])
endif
boxfort_includedir = include_directories(
'include',
'src',
)
threads = dependency('threads')
# optional platform-dependent standard libs
librt = cc.find_library('rt', required: false)
libm = cc.find_library('m', required: false)
config = configuration_data()
config.set('package', meson.project_name())
config.set('version', version)
os = host_machine.system()
arch = host_machine.cpu_family()
mangling = 'none'
if cc.symbols_have_underscore_prefix()
mangling = 'leading-underscore'
endif
if arch == 'x86'
bitness = 32
elif arch == 'x86_64'
bitness = 64
elif arch == 'arm'
bitness = 32
elif arch == 'aarch64'
bitness = 64
else
error('Architecture "@0@" is not supported.'.format(arch))
endif
if get_option('arena_reopen_shm')
config.set('BXF_ARENA_REOPEN_SHM', 1)
endif
if get_option('arena_file_backed')
config.set('BXF_ARENA_FILE_BACKED', 1)
endif
binfmt = 'elf'
os_family = 'posix'
if os == 'windows'
binfmt = 'pe'
os_family = 'windows'
elif os == 'darwin'
binfmt = 'mach-o'
# This is mandatory because OS X fails silently when mmap'ing an inherited
# shm file descriptor
config.set('BXF_ARENA_REOPEN_SHM', 1)
config.set('BXF_ARENA_FILE_BACKED', 1)
endif
config.set('BXF_EXE_FORMAT', binfmt)
config.set('BXF_EXE_FMT_@0@'.format(binfmt.to_upper().underscorify()), 1)
config.set('BXF_OS_FAMILY', os_family)
config.set('BXF_ARCH', '"' + arch + '"')
config.set('BXF_ARCH_@0@'.format(arch), 1)
config.set('BXF_MANGLING', mangling)
config.set('BXF_BITS', bitness)
checks = [
{'fn': 'clock_gettime'},
{'fn': 'gettimeofday'},
{'fn': 'mincore'},
{'fn': 'prctl'},
{'fn': 'shm_open'},
# some platforms define mincore with an unsigned vector
{
'fn': 'mincore',
'proto': 'int _(void *, size_t, unsigned char *)',
'headers': ['unistd.h', 'sys/mman.h'],
'var': 'HAVE_UNSIGNED_MINCORE_VEC',
},
{'sym': 'PR_SET_PDEATHSIG', 'header': 'sys/prctl.h'},
{'sym': 'CLOCK_MONOTONIC_RAW', 'header': 'time.h'},
{'sym': 'environ', 'header': 'unistd.h'},
]
if binfmt == 'elf'
checks += [
{'sym': '_r_debug', 'header': 'link.h'},
{'sym': '_DYNAMIC', 'header': 'link.h'},
]
endif
check_prelude = '''
#define _GNU_SOURCE
'''
prototype_check = check_prelude + '''
@0@
typedef @1@;
static _ *check = @2@;
'''
foreach check : checks
chk_prefix = check.get('prefix', '')
if chk_prefix != ''
chk_prefix = chk_prefix + '_'
endif
result = false
if check.has_key('proto')
includes = ''
foreach hdr : check.get('headers')
includes += '#include <@0@>\n'.format(hdr)
endforeach
result = cc.compiles(prototype_check.format(includes, check.get('proto'), check.get('fn')))
elif check.has_key('fn')
name = check.get('fn')
libs = ['c']
if librt.found()
libs += 'rt'
endif
if libm.found()
libs += 'm'
endif
if check.has_key('libs')
libs += check.get('libs')
endif
args = []
foreach lib : libs
args += '-l' + lib
endforeach
result = cc.has_function(name, prefix: check_prelude, args: args)
elif check.has_key('sym')
name = check.get('sym')
result = cc.has_header_symbol(check.get('header'), name, prefix: check_prelude)
elif check.has_key('hdr')
name = check.get('hdr')
result = cc.has_header(name)
endif
if check.has_key('var')
name = check.get('var')
else
name = 'HAVE_@1@@0@'.format(name.to_upper(), chk_prefix.to_upper())
endif
config.set(name, result)
endforeach
api = files('include/boxfort.h')
if not meson.is_subproject()
install_headers(api)
endif
includedir = include_directories(
'include',
'src',
)
if target_machine.system() == 'windows'
config.set10('HAVE_WIN32_THREADS', true)
else
config.set10('HAVE_PTHREADS', true)
endif
subdir('src')
subdir('sample')
subdir('test')
BoxFort-master/meson_options.txt 0000644 0001750 0001750 00000000465 13603450524 016036 0 ustar sasa sasa option('arena_reopen_shm', type: 'boolean', value: false, description: 'Reopen shared memory file in worker process rather than just inherit a file descriptor')
option('arena_file_backed', type: 'boolean', value: false, description: 'Use a file in tempfs to store the arena rather than using shm facilities')
BoxFort-master/sample/ 0002755 0001750 0001750 00000000000 13603450524 013657 5 ustar sasa sasa BoxFort-master/sample/callback.c 0000644 0001750 0001750 00000001062 13603450524 015554 0 ustar sasa sasa #include
#include
#include
#include
#include "boxfort.h"
#define _assert(Cond) do { if (!(Cond)) abort(); } while (0)
#ifdef _WIN32
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
static volatile int called;
static int child(void)
{
return 5;
}
static void callback(bxf_instance *instance)
{
printf("Child exited with code %d\n", instance->status.exit);
called = 1;
}
EXPORT int main(void)
{
_assert(!bxf_run(child, .callback = callback));
while (!called);
return 0;
}
BoxFort-master/sample/context.c 0000644 0001750 0001750 00000002650 13603450524 015510 0 ustar sasa sasa #include
#include
#include
#include
#include "boxfort.h"
#define _assert(Cond) do { if (!(Cond)) abort(); } while (0)
#ifdef _WIN32
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
static int *my_int;
static int child(void)
{
bxf_context ctx = bxf_context_current();
long *my_long = NULL;
bxf_context_getobject(ctx, "long_id", (void **)&my_long);
printf("my_int = %d\n", *my_int);
printf("my_long = %ld\n", *my_long);
return 0;
}
EXPORT int main(void)
{
bxf_context ctx;
_assert(!bxf_context_init(&ctx));
/* The value of the `my_int` global variable shall be inherited */
_assert(!bxf_context_addstatic(ctx, &my_int, sizeof (my_int)));
/* We create an arena that shall be mapped 1:1 */
bxf_arena arena;
_assert(!bxf_arena_init(0, BXF_ARENA_IDENTITY, &arena));
/* The newly created arena shall also be inherited. */
_assert(!bxf_context_addarena(ctx, arena));
bxf_ptr intp = bxf_arena_alloc(&arena, sizeof (int));
_assert(intp > 0);
my_int = bxf_arena_ptr(arena, intp);
*my_int = 42;
long my_long = 24;
_assert(!bxf_context_addobject(ctx, "long_id", &my_long, sizeof (my_long)));
/* We run the child function with the created context */
_assert(!bxf_run(child, .inherit.context = ctx));
_assert(!bxf_arena_term(&arena));
_assert(!bxf_context_term(ctx));
return 0;
}
BoxFort-master/sample/meson.build 0000644 0001750 0001750 00000000524 13603450524 016020 0 ustar sasa sasa samples = [
'nested.c',
'callback.c',
'timeout.c',
'context.c',
]
foreach sample : samples
e = executable(sample + '.bin', sample,
include_directories: includedir,
dependencies: [libm],
link_with: libboxfort,
c_args: [
cc.get_supported_arguments([
'-fvisibility=default',
])
])
test(sample, e)
endforeach
BoxFort-master/sample/nested.c 0000644 0001750 0001750 00000001022 13603450524 015276 0 ustar sasa sasa #include
#include
#include
#include
#include "boxfort.h"
#define _assert(Cond) do { if (!(Cond)) abort(); } while (0)
#ifdef _WIN32
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
int second(void)
{
printf("I am a nested worker!\n");
fflush(stdout);
return 0;
}
int first(void)
{
printf("I am a worker!\n");
fflush(stdout);
_assert(!bxf_run(second));
return 0;
}
EXPORT int main(void)
{
_assert(!bxf_run(first));
return 0;
}
BoxFort-master/sample/timeout.c 0000644 0001750 0001750 00000001171 13603450524 015507 0 ustar sasa sasa #include
#include
#include
#include
#include "boxfort.h"
#define _assert(Cond) do { if (!(Cond)) abort(); } while (0)
#ifdef _WIN32
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
static int child(void)
{
for (;;);
return 0;
}
EXPORT int main(void)
{
bxf_instance *box;
_assert(!bxf_spawn(&box, child, .quotas.runtime = 2.0));
bxf_wait(box, 1.0);
printf("Wait timed out after 1 second\n");
bxf_wait(box, BXF_FOREVER);
printf("Process killed after %.1f seconds\n", box->time.elapsed / 1000000000.);
bxf_term(box);
return 0;
}
BoxFort-master/src/ 0002755 0001750 0001750 00000000000 13603450524 013165 5 ustar sasa sasa BoxFort-master/src/addr.c 0000644 0001750 0001750 00000003565 13603450524 014252 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include "addr.h"
#include "exe.h"
int bxfi_normalize_addr(const void *addr, struct bxfi_addr *to)
{
size_t seg;
const char *name;
uintptr_t slide = bxfi_slide_from_addr(addr, &name, &seg);
if (slide == (uintptr_t) -1)
return -errno;
to->addr = (char *) addr - slide;
to->soname = name;
to->seg = seg;
return 0;
}
void *bxfi_denormalize_addr(struct bxfi_addr *addr)
{
uintptr_t slide = bxfi_slide_from_name(addr->soname, addr->seg);
if (slide == (uintptr_t) -1)
return NULL;
return (char *) addr->addr + slide;
}
void bxfi_addr_term(struct bxfi_addr *addr)
{
bxfi_lib_name_term(addr->soname);
}
BoxFort-master/src/addr.h 0000644 0001750 0001750 00000003401 13603450524 014244 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 ADDR_H_
#define ADDR_H_
#include "boxfort.h"
#include "common.h"
struct bxfi_addr {
const char *soname;
const void *addr;
size_t seg;
};
int bxfi_normalize_addr(const void *addr, struct bxfi_addr *to);
void *bxfi_denormalize_addr(struct bxfi_addr *addr);
void bxfi_addr_term(struct bxfi_addr *addr);
static inline int bxfi_normalize_fnaddr(bxf_fn *addr, struct bxfi_addr *to)
{
return bxfi_normalize_addr(nonstd (void *) addr, to);
}
static inline bxf_fn *bxfi_denormalize_fnaddr(struct bxfi_addr *addr)
{
return nonstd (bxf_fn *) bxfi_denormalize_addr(addr);
}
#endif /* !ADDR_H_ */
BoxFort-master/src/arena.c 0000644 0001750 0001750 00000045764 13603450524 014435 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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.
*/
#ifdef _WIN32
# define _CRT_RAND_S
#endif
#include
#include
#include
#include
#include
#include "arena.h"
#include "boxfort.h"
#include "common.h"
#include "timestamp.h"
#ifndef _WIN32
# include
# define __BSD_VISIBLE 1
# include
# undef __BSD_VISIBLE
# include
# include
#endif
#define GROWTH_RATIO (1.61)
#define MAP_RETRIES 10
#if BXF_BITS == 32
static void *mmap_base = (void *) 0x40000000;
static void *mmap_max = (void *) 0x80000000;
static intptr_t mmap_off = (intptr_t) 1 << 16;
static intptr_t mmap_off_mask = 0x3fff;
#elif BXF_BITS == 64
/* On Linux it seems that you cannot map > 48-bit addresses */
static void *mmap_base = (void *) 0x200000000000;
static void *mmap_max = (void *) 0x7f0000000000;
static intptr_t mmap_off = (intptr_t) 1 << 24;
static intptr_t mmap_off_mask = 0x3fffff;
#else
# error Platform not supported
#endif
static unsigned int mmap_seed;
static inline void *ptr_add(void *ptr, size_t off)
{
return (char *) ptr + off;
}
#define chunk_next(Chunk) \
((struct bxfi_arena_chunk *) ((Chunk)->next ? ptr_add(*arena, \
(Chunk)->next) : NULL))
#define get_free_chunks(arena) (ptr_add(*arena, (*arena)->free_chunks))
static int page_mapped(void *addr) {
#ifdef _WIN32
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof (mbi));
if (VirtualQuery(addr, &mbi, sizeof (mbi)))
if (mbi.State != MEM_FREE)
return 1;
return 0;
#elif defined (HAVE_MINCORE) && !defined (__APPLE__)
/* mincore is somewhat broken on OS X, for some reason. */
# if defined(HAVE_UNSIGNED_MINCORE_VEC)
unsigned
# endif
char p;
errno = EAGAIN;
while (errno == EAGAIN) {
if (!mincore(addr, pagesize(), &p))
return 1;
if (errno == ENOMEM)
return 0;
}
bug("mincore(2) returned an unexpected error");
#else
if (!msync(addr, pagesize(), MS_ASYNC))
return 1;
if (errno == ENOMEM)
return 0;
bug("msync(2) returned an unexpected error");
#endif
}
int bxf_arena_init(size_t initial, int flags, bxf_arena *arena)
{
initial = align2_up(initial, PAGE_SIZE);
if (!initial)
initial = 32 * PAGE_SIZE;
#ifdef _WIN32
SECURITY_ATTRIBUTES inherit = {
.nLength = sizeof (SECURITY_ATTRIBUTES),
.bInheritHandle = TRUE,
};
/* Consider available commit limit for possible max heap size */
MEMORYSTATUSEX mem = { .dwLength = sizeof (mem) };
if (!GlobalMemoryStatusEx(&mem))
return -ENOMEM;
LARGE_INTEGER sz = { .QuadPart = mem.ullAvailPageFile };
HANDLE hndl = CreateFileMapping(INVALID_HANDLE_VALUE, &inherit,
PAGE_READWRITE | SEC_RESERVE, sz.HighPart, sz.LowPart, NULL);
if (!hndl)
return -EINVAL;
if (!mmap_seed)
mmap_seed = bxfi_timestamp_monotonic();
intptr_t r;
struct bxf_arena_s *a;
int tries = 0;
for (tries = 0; tries < MAP_RETRIES;) {
rand_s(&mmap_seed);
r = mmap_seed;
r &= mmap_off_mask;
void *base = ptr_add(mmap_base, r * mmap_off);
if (base > mmap_max || base < mmap_base)
continue;
for (void *addr = base; addr < ptr_add(base, initial);
addr = ptr_add(addr, PAGE_SIZE))
{
if (page_mapped(addr))
goto retry;
}
a = MapViewOfFileEx(hndl, FILE_MAP_WRITE, 0, 0, initial, base);
if (!a)
goto error;
if (!VirtualAlloc(a, initial, MEM_COMMIT, PAGE_READWRITE))
goto error;
if ((void *) a < mmap_max && (void *) a > mmap_base)
break;
UnmapViewOfFile(a);
retry: ;
++tries;
}
if (tries == MAP_RETRIES)
goto error;
#else
char name[BXFI_ARENA_NAME_SIZE];
/* Some platforms (like OS X) have the *great* idea of silently failing
all mapping operations on inherited shm file descriptors. We have
to provide a fallback for these dipshits by reopening the shm file
in the child instance. */
# ifdef BXF_ARENA_REOPEN_SHM
static size_t count;
size_t id = __sync_fetch_and_add(&count, 1);
# ifdef BXF_ARENA_FILE_BACKED
snprintf(name, sizeof (name), "/tmp/bxf_arena_%d_%zu", getpid(), id);
# else
snprintf(name, sizeof (name), "/bxf_arena_%d_%zu", getpid(), id);
# endif
# else
# ifdef BXF_ARENA_FILE_BACKED
snprintf(name, sizeof (name), "/tmp/bxf_arena_%d", getpid());
# else
snprintf(name, sizeof (name), "/bxf_arena_%d", getpid());
# endif
# endif
# ifdef BXF_ARENA_FILE_BACKED
int fd = open(name, O_CREAT | O_RDWR | O_EXCL, 0600);
# else
int fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600);
# endif
if (fd == -1)
goto error;
# ifndef BXF_ARENA_REOPEN_SHM
# ifdef BXF_ARENA_FILE_BACKED
unlink(name);
# else
shm_unlink(name);
# endif
# endif
if (ftruncate(fd, initial) == -1)
goto error;
if (!mmap_seed)
mmap_seed = bxfi_timestamp_monotonic();
intptr_t r;
struct bxf_arena_s *a;
int tries = 0;
for (tries = 0; tries < MAP_RETRIES;) {
r = rand_r(&mmap_seed) & mmap_off_mask;
void *base = ptr_add(mmap_base, r * mmap_off);
if (base > mmap_max || base < mmap_base)
continue;
for (void *addr = base; addr < ptr_add(base, initial);
addr = ptr_add(addr, PAGE_SIZE))
{
if (page_mapped(addr))
goto retry;
}
a = mmap(base, initial, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED, fd, 0);
if (a == MAP_FAILED)
goto error;
if ((void *) a < mmap_max && (void *) a > mmap_base)
break;
munmap(a, initial);
retry: ;
++tries;
}
if (tries == MAP_RETRIES)
goto error;
#endif
a->flags = flags;
a->size = initial;
a->addr = a;
a->free_chunks = sizeof (*a);
#ifdef BXF_ARENA_REOPEN_SHM
strcpy(a->name, name);
#endif
#ifdef _WIN32
a->handle = hndl;
#else
a->handle = fd;
#endif
struct bxfi_arena_chunk *first = ptr_add(a, a->free_chunks);
*first = (struct bxfi_arena_chunk) {
.size = initial - sizeof (*a),
};
*arena = a;
return 0;
error:;
#ifdef _WIN32
CloseHandle(hndl);
return -ENOMEM;
#else
int errnum = errno;
if (fd != -1) {
# ifdef BXF_ARENA_REOPEN_SHM
# ifdef BXF_ARENA_FILE_BACKED
unlink(name);
# else
shm_unlink(name);
# endif
# endif
close(fd);
}
return -errnum;
#endif
}
int bxfi_arena_inherit(bxf_fhandle hndl, int flags, bxf_arena *arena)
{
void *base = NULL;
if (flags & BXF_ARENA_IDENTITY)
base = *arena;
#ifdef _WIN32
DWORD prot;
if (flags & BXF_ARENA_IMMUTABLE)
prot = FILE_MAP_READ;
else
prot = FILE_MAP_COPY;
struct bxf_arena_s *a = MapViewOfFile(hndl, prot, 0, 0, sizeof (*a));
if (!a)
return -ENOMEM;
size_t size = a->size;
UnmapViewOfFile(a);
a = MapViewOfFileEx(hndl, prot, 0, 0, size, base);
if (!a)
return -ENOMEM;
#else
int mmapfl = MAP_PRIVATE;
if (flags & BXF_ARENA_IDENTITY)
mmapfl |= MAP_FIXED;
int prot = PROT_READ;
if (!(flags & BXF_ARENA_IMMUTABLE))
prot |= PROT_WRITE;
struct bxf_arena_s *a = mmap(NULL, sizeof (*a), prot, MAP_PRIVATE, hndl, 0);
if (a == MAP_FAILED)
return -errno;
size_t size = a->size;
munmap(a, sizeof (*a));
a = mmap(base, size, prot, mmapfl, hndl, 0);
if (a == MAP_FAILED)
return -errno;
#endif
*arena = a;
return 0;
}
int bxf_arena_copy(bxf_arena orig, int flags, bxf_arena *arena)
{
int rc = bxf_arena_init(orig->size, flags, arena);
if (rc > 0) {
memcpy(*arena + 1, orig + 1, orig->size - sizeof (orig));
(*arena)->free_chunks = orig->free_chunks;
}
return rc;
}
int bxf_arena_term(bxf_arena *arena)
{
#ifdef _WIN32
CloseHandle((*arena)->handle);
if (!((*arena)->flags & BXF_ARENA_KEEPMAPPED))
UnmapViewOfFile(*arena);
#else
# ifdef BXF_ARENA_REOPEN_SHM
# ifdef BXF_ARENA_FILE_BACKED
unlink((*arena)->name);
# else
shm_unlink((*arena)->name);
# endif
# endif
close((*arena)->handle);
if (!((*arena)->flags & BXF_ARENA_KEEPMAPPED))
munmap(*arena, (*arena)->size);
#endif
*arena = NULL;
return 0;
}
static inline int arena_valid(bxf_arena arena)
{
return arena && arena->addr == arena;
}
static int arena_resize(bxf_arena *arena, size_t newsize)
{
size_t size = (*arena)->size;
#ifdef _WIN32
void *base = ptr_add(*arena, (*arena)->size);
LARGE_INTEGER off = { .QuadPart = (*arena)->size };
void *addr = MapViewOfFileEx((*arena)->handle, FILE_MAP_WRITE,
off.HighPart, off.LowPart, newsize - size, base);
if (addr != base) {
if (!((*arena)->flags & BXF_ARENA_MAYMOVE))
return -ENOMEM;
FlushViewOfFile(*arena, size);
struct bxf_arena_s *a = MapViewOfFile((*arena)->handle, FILE_MAP_WRITE,
0, 0, newsize);
if (!a)
return -ENOMEM;
addr = ptr_add(a, size);
a->addr = a;
UnmapViewOfFile(*arena);
*arena = a;
}
if (!VirtualAlloc(addr, newsize - size, MEM_COMMIT, PAGE_READWRITE))
return -ENOMEM;
return 0;
#else
if (ftruncate((*arena)->handle, newsize) < 0)
return -ENOMEM;
# if defined (HAVE_MREMAP)
int flags = (*arena)->flags & BXF_ARENA_MAYMOVE ? MREMAP_MAYMOVE : 0;
struct bxf_arena_s *a = mremap(*arena, (*arena)->size, newsize, flags);
if (a == MAP_FAILED)
return -errno;
a->addr = a;
*arena = a;
# else
size_t remsz = newsize - (*arena)->size;
char *addr_hi = ptr_add(*arena, (*arena)->size);
int move = 0;
for (char *addr = addr_hi; remsz; remsz -= PAGE_SIZE, addr += PAGE_SIZE) {
if (page_mapped(addr)) {
move = 1;
break;
}
}
if (move) {
if (!((*arena)->flags & BXF_ARENA_MAYMOVE))
return -ENOMEM;
msync(*arena, (*arena)->size, MS_SYNC);
struct bxf_arena_s *a = mmap(*arena, newsize, PROT_READ | PROT_WRITE,
MAP_SHARED, (*arena)->handle, 0);
if (a == MAP_FAILED)
return -ENOMEM;
a->addr = a;
munmap(*arena, (*arena)->size);
*arena = a;
} else {
size_t remsz = newsize - (*arena)->size;
void *raddr = mmap(addr_hi, remsz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED, (*arena)->handle, (*arena)->size);
if (raddr == MAP_FAILED)
return -errno;
}
# endif
/* Extend the free chunk at the end of the arena. If it's not free,
then initialize a new free chunk. */
struct bxfi_arena_chunk *last;
for (last = get_free_chunks(arena); last; last = chunk_next(last)) {
if (ptr_add(last, last->size) == ptr_add(*arena, size)) {
break;
}
}
if (last) {
last->size += newsize - size;
} else {
last->next = (intptr_t) size;
last = ptr_add(*arena, size);
*last = (struct bxfi_arena_chunk) {
.size = newsize - size,
};
}
(*arena)->size = newsize;
return 0;
#endif
return -ENOMEM;
}
bxf_ptr bxf_arena_alloc(bxf_arena *arena, size_t size)
{
if (!arena_valid(*arena))
return -EINVAL;
size = align2_up(size + sizeof (struct bxfi_arena_chunk), sizeof (void *));
struct bxfi_arena_chunk *best = NULL;
intptr_t *nptr_best = NULL;
intptr_t *nptr;
find_chunk:
nptr = &(*arena)->free_chunks;
for (struct bxfi_arena_chunk *c = get_free_chunks(arena);
c; c = chunk_next(c))
{
if ((c->size >= size && (!best || best->size > c->size))
|| (!c->next && !best))
{
best = c;
nptr_best = nptr;
}
if (c->size == size)
break;
nptr = &c->next;
}
size_t next_off_end = (size_t) ((intptr_t) best + size
- (intptr_t) *arena + sizeof (*best));
if (next_off_end > (*arena)->size || best->size < size) {
if (!((*arena)->flags & BXF_ARENA_RESIZE))
return -ENOMEM;
/* size - best->size is the extra space we need, but we need to take
the size of the next chunk header into account when calculating the
required space. */
size_t oksize = (*arena)->size + size - best->size + sizeof (*best);
size_t newsize = (*arena)->size;
while (newsize < oksize)
newsize *= GROWTH_RATIO;
newsize = align2_up(newsize, PAGE_SIZE);
int rc = arena_resize(arena, newsize);
if (rc < 0)
return rc;
/* Everything was invalidated, because the arena might have moved.
Just give up and retry. */
goto find_chunk;
}
size_t remsz = best->size - size;
best->size = size;
struct bxfi_arena_chunk *next = ptr_add(best, best->size);
*next = (struct bxfi_arena_chunk) {
.size = remsz,
.next = best->next,
};
*nptr_best = (intptr_t) next - (intptr_t) *arena;
best->addr = (intptr_t) (best + 1) - (intptr_t) *arena;
return best->addr;
}
bxf_ptr bxf_arena_realloc(bxf_arena *arena, bxf_ptr ptr, size_t size)
{
if (!arena_valid(*arena))
return -EINVAL;
if (!ptr)
return bxf_arena_alloc(arena, size);
void *p = ptr_add(*arena, ptr);
if (p <= ptr_add(*arena, sizeof (struct bxfi_arena_chunk))
|| p >= ptr_add(*arena, (*arena)->size))
return -EFAULT;
struct bxfi_arena_chunk *chunk = p;
--chunk;
if (ptr_add(*arena, chunk->addr) != p)
return -EFAULT;
int rc = bxf_arena_grow(arena, ptr, size);
if (rc == -ENOMEM) {
/* If we can't call free, give up and let the user call alloc */
if (!((*arena)->flags & BXF_ARENA_DYNAMIC))
return rc;
rc = bxf_arena_alloc(arena, size);
if (rc > 0) {
void *np = ptr_add(*arena, rc);
memcpy(np, p, chunk->size);
bxf_arena_free(arena, ptr);
}
}
return rc;
}
int bxf_arena_grow(bxf_arena *arena, bxf_ptr p, size_t size)
{
if (!arena_valid(*arena))
return -EINVAL;
void *ptr = ptr_add(*arena, p);
size = align2_up(size + sizeof (struct bxfi_arena_chunk), sizeof (void *));
if (!ptr || ptr <= ptr_add(*arena, sizeof (struct bxfi_arena_chunk))
|| ptr >= ptr_add(*arena, (*arena)->size))
return -EFAULT;
struct bxfi_arena_chunk *chunk = ptr;
--chunk;
if (ptr_add(*arena, chunk->addr) != ptr)
return -EFAULT;
struct bxfi_arena_chunk *next = ptr_add(chunk, chunk->size);
if (next->addr)
return -ENOMEM;
if (ptr_add(next, size) > ptr_add(*arena, (*arena)->size)) {
if (!((*arena)->flags & BXF_ARENA_RESIZE))
return -ENOMEM;
size_t oksize = (*arena)->size + size - next->size + sizeof (*next);
size_t newsize = (*arena)->size;
while (newsize < oksize)
newsize *= GROWTH_RATIO;
size_t oldsize = (*arena)->size;
intptr_t off = (intptr_t) *arena;
newsize = align2_up(newsize, PAGE_SIZE);
int rc = arena_resize(arena, newsize);
if (rc < 0)
return rc;
off = (intptr_t) *arena - off;
ptr = ptr_add(ptr, off);
chunk = ptr_add(chunk, off);
next = ptr_add(next, off);
next->size += newsize - oldsize;
}
if (next->size < size - chunk->size)
return -ENOMEM;
/* Remove the next chunk from the free list */
intptr_t *nptr = &(*arena)->free_chunks;
for (struct bxfi_arena_chunk *c = get_free_chunks(arena);
c; c = chunk_next(c))
{
if (c == next)
break;
nptr = &c->next;
}
*nptr = next->next;
chunk->size += next->size;
/* If there is enough space to fit another chunk at the end of the newly
* merged block, do so */
size_t asize = align2_down(chunk->size, sizeof (void *));
if (chunk->size - asize >= align2_up(sizeof (*chunk) + 1, sizeof (void *))
&& asize >= size)
{
struct bxfi_arena_chunk *next = ptr_add(chunk, size);
*next = (struct bxfi_arena_chunk) {
.next = *nptr,
};
*nptr = (intptr_t) next - (intptr_t) *arena;
}
return 0;
}
int bxf_arena_free(bxf_arena *arena, bxf_ptr p)
{
if (!arena_valid(*arena))
return -EINVAL;
if (!((*arena)->flags & BXF_ARENA_DYNAMIC))
return -ENOTSUP;
if (!p)
return 0;
void *ptr = ptr_add(*arena, p);
if (ptr <= ptr_add(*arena, sizeof (struct bxfi_arena_chunk))
|| ptr >= ptr_add(*arena, (*arena)->size))
return -EFAULT;
struct bxfi_arena_chunk *chunk = ptr;
--chunk;
if (ptr_add(*arena, chunk->addr) != ptr)
return -EFAULT;
intptr_t *nptr = &(*arena)->free_chunks;
struct bxfi_arena_chunk *prev = NULL;
for (struct bxfi_arena_chunk *c = get_free_chunks(arena);
c; c = chunk_next(c))
{
if (c > chunk)
break;
nptr = &c->next;
prev = c;
}
chunk->next = *nptr;
*nptr = (intptr_t) chunk - (intptr_t) *arena;
if (prev) {
prev->size += chunk->size;
prev->next = chunk->next;
chunk = prev;
}
if (chunk->next) {
chunk->size += chunk_next(chunk)->size;
chunk->next = chunk->next;
}
chunk->addr = 0;
return 0;
}
int bxf_arena_iter(bxf_arena arena, bxf_arena_fn *fn, void *user)
{
struct bxfi_arena_chunk *c = (void *) (arena + 1);
for (; (void *) c < ptr_add(arena, arena->size);
c = ptr_add(c, c->size))
{
if (c->addr) {
int rc = fn(ptr_add(arena, c->addr), c->size - sizeof (*c), user);
if (rc)
return rc;
}
}
return 0;
}
void *bxf_arena_ptr(bxf_arena arena, bxf_ptr ptr)
{
return ptr_add(arena, ptr);
}
BoxFort-master/src/arena.h 0000644 0001750 0001750 00000004036 13603450524 014425 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 ARENA_H_
#define ARENA_H_
#ifdef _WIN32
# include
#endif
#include
#include "boxfort.h"
#include "config.h"
struct bxfi_arena_chunk {
intptr_t addr;
size_t size;
intptr_t next;
};
#ifdef BXF_ARENA_REOPEN_SHM
# ifdef BXF_ARENA_FILE_BACKED
# define BXFI_ARENA_NAME_SIZE (sizeof ("/tmp/bxf_arena__") + 31)
# else
# define BXFI_ARENA_NAME_SIZE (sizeof ("/bxf_arena__") + 31)
# endif
#else
# ifdef BXF_ARENA_FILE_BACKED
# define BXFI_ARENA_NAME_SIZE (sizeof ("/tmp/bxf_arena_") + 11)
# else
# define BXFI_ARENA_NAME_SIZE (sizeof ("/bxf_arena_") + 11)
# endif
#endif
struct bxf_arena_s {
void *addr;
size_t size;
intptr_t free_chunks;
int flags;
bxf_fhandle handle;
#ifdef BXF_ARENA_REOPEN_SHM
char name[BXFI_ARENA_NAME_SIZE];
#endif
};
int bxfi_arena_inherit(bxf_fhandle hndl, int flags, bxf_arena *arena);
#endif /* !ARENA_H_ */
BoxFort-master/src/asm/ 0002755 0001750 0001750 00000000000 13603450524 013745 5 ustar sasa sasa BoxFort-master/src/asm/mangling.h 0000644 0001750 0001750 00000003015 13603450524 015707 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 ASM_MANGLING_H_
#define ASM_MANGLING_H_
#include "config.h"
#define MANGLING_STR_(x) #x
#define MANGLING_STR(x) MANGLING_STR_(x)
/* *INDENT-OFF* - formatters try to add spaces here */
#define MANGLING_HEADER_ mangling/BXF_MANGLING.h
#define MANGLING_HEADER MANGLING_STR(MANGLING_HEADER_)
/* *INDENT-ON* */
#include MANGLING_HEADER
#endif /* !ASM_MANGLING_H_ */
BoxFort-master/src/asm/mangling/ 0002755 0001750 0001750 00000000000 13603450524 015541 5 ustar sasa sasa BoxFort-master/src/asm/mangling/leading-underscore.h 0000644 0001750 0001750 00000000031 13603450524 021454 0 ustar sasa sasa #define MANGLE(x) _ ## x
BoxFort-master/src/asm/mangling/none.h 0000644 0001750 0001750 00000000024 13603450524 016643 0 ustar sasa sasa #define MANGLE(x) x
BoxFort-master/src/asm/setjmp-x86.asm 0000644 0001750 0001750 00000004014 13603450524 016371 0 ustar sasa sasa ;
; The MIT License (MIT)
;
; Copyright © 2016 Franklin "Snaipe" Mathieu
;
; 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.
;
.386
.MODEL FLAT, C
.CODE
; The windows CRT defines the jmp_buf on x86 as:
; uint32_t Ebp;
; uint32_t Ebx;
; uint32_t Edi;
; uint32_t Esi;
; uint32_t Esp;
; uint32_t Eip;
; uint32_t Registration;
; uint32_t TryLevel;
; uint32_t Cookie;
; uint32_t UnwindFunc;
; uint32_t UnwindData[6];
; We're only setting the first 6 fields.
bxfi_setjmp label far
mov eax, [esp+4]
mov [eax], ebp
mov [eax + 4], ebx
mov [eax + 8], edi
mov [eax + 12], esi
mov [eax + 16], esp
mov esi, [esp]
mov [eax + 20], esi
xor eax, eax
ret
bxfi_longjmp label far
mov esi, [esp+4]
mov eax, [esi + 20] ; EIP
mov ebx, [esi + 16] ; ESP
mov [ebx], eax
mov eax, [esp + 8] ; return value
mov ebp, [esi]
mov ebx, [esi + 4]
mov edi, [esi + 8]
mov esp, [esi + 16]
mov esi, [esi + 12]
ret
public bxfi_setjmp
public bxfi_longjmp
end
BoxFort-master/src/asm/setjmp-x86_64.asm 0000644 0001750 0001750 00000004430 13603450524 016704 0 ustar sasa sasa ;
; The MIT License (MIT)
;
; Copyright © 2016 Franklin "Snaipe" Mathieu
;
; 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
; The windows CRT defines the jmp_buf on x86_64 as:
; uint64_t Frame;
; uint64_t Rbx;
; uint64_t Rsp;
; uint64_t Rbp;
; uint64_t Rsi;
; uint64_t Rdi;
; uint64_t R12;
; uint64_t R13;
; uint64_t R14;
; uint64_t R15;
; uint64_t Rip;
; uint64_t Spare;
; uint128_t Xmm6;
; uint128_t Xmm7;
; uint128_t Xmm8;
; uint128_t Xmm9;
; uint128_t Xmm10;
; uint128_t Xmm11;
; uint128_t Xmm12;
; uint128_t Xmm13;
; uint128_t Xmm14;
; uint128_t Xmm15;
bxfi_setjmp label far
mov [rcx + 8], rbx
mov [rcx + 16], rsp
mov [rcx + 24], rbp
mov [rcx + 32], rsi
mov [rcx + 40], rdi
mov [rcx + 48], r12
mov [rcx + 56], r13
mov [rcx + 64], r14
mov [rcx + 72], r15
pop [rcx + 80] ; rip
push [rcx + 80]
xor rax, rax
ret
bxfi_longjmp label far
mov rbx, [rcx + 8]
mov rsp, [rcx + 16]
mov rbp, [rcx + 24]
mov rsi, [rcx + 32]
mov rdi, [rcx + 40]
mov r12, [rcx + 48]
mov r13, [rcx + 56]
mov r14, [rcx + 64]
mov r15, [rcx + 72]
pop rax
push [rcx + 80]
mov rax, rdx ; return value
ret
public bxfi_setjmp
public bxfi_longjmp
end
BoxFort-master/src/asm/stackfix.h 0000644 0001750 0001750 00000002702 13603450524 015731 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 patch is necessary to harden the stack on ELF targets; otherwise,
programs compiled with BoxFort will ask for an executable stack, which
is not ideal, and even not supported on some platforms. */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
BoxFort-master/src/asm/trampoline-aarch64.S 0000644 0001750 0001750 00000003304 13603450524 017467 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2018 Franklin "Snaipe" Mathieu
*
* 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 "config.h"
#include "mangling.h"
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline)
#endif
.globl MANGLE(bxfi_trampoline)
MANGLE(bxfi_trampoline):
ldr x16, addr_data
br x16
.align 3
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_addr)
#endif
.globl MANGLE(bxfi_trampoline_addr)
MANGLE(bxfi_trampoline_addr):
addr_data:
.fill 8, 1, 0
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_end)
#endif
.globl MANGLE(bxfi_trampoline_end)
MANGLE(bxfi_trampoline_end):
#include "stackfix.h"
BoxFort-master/src/asm/trampoline-arm.S 0000644 0001750 0001750 00000003263 13603450524 017022 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 "config.h"
#include "mangling.h"
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline)
#endif
.globl MANGLE(bxfi_trampoline)
MANGLE(bxfi_trampoline):
ldr pc, addr_data
.align 2
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_addr)
#endif
.globl MANGLE(bxfi_trampoline_addr)
MANGLE(bxfi_trampoline_addr):
addr_data:
.fill 4, 1, 0
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_end)
#endif
.globl MANGLE(bxfi_trampoline_end)
MANGLE(bxfi_trampoline_end):
#include "stackfix.h"
BoxFort-master/src/asm/trampoline-x86.S 0000644 0001750 0001750 00000003414 13603450524 016666 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 "config.h"
#include "mangling.h"
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline)
#endif
.globl MANGLE(bxfi_trampoline)
MANGLE(bxfi_trampoline):
call next
next:
pop %eax
jmp *(addr_data - next)(%eax)
#ifdef BXF_EXE_FMT_MACH_O
.align 2
#else
.align 4
#endif
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_addr)
#endif
.globl MANGLE(bxfi_trampoline_addr)
MANGLE(bxfi_trampoline_addr):
addr_data:
.fill 4, 1, 0
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_end)
#endif
.globl MANGLE(bxfi_trampoline_end)
MANGLE(bxfi_trampoline_end):
#include "stackfix.h"
BoxFort-master/src/asm/trampoline-x86.asm 0000644 0001750 0001750 00000002753 13603450524 017251 0 ustar sasa sasa ;
; The MIT License (MIT)
;
; Copyright © 2016 Franklin "Snaipe" Mathieu
;
; 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.
;
.386
.MODEL FLAT, C
.CODE
bxfi_trampoline label far
call next ; Retrieve IP
next:
pop eax
jmp dword ptr (addr_data - next) [eax]
ALIGN 4
bxfi_trampoline_addr label far
addr_data byte 4 dup (0)
bxfi_trampoline_end label far
public bxfi_trampoline
public bxfi_trampoline_addr
public bxfi_trampoline_end
end
BoxFort-master/src/asm/trampoline-x86_64.S 0000644 0001750 0001750 00000003342 13603450524 017177 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 "config.h"
#include "mangling.h"
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline)
#endif
.globl MANGLE(bxfi_trampoline)
MANGLE(bxfi_trampoline):
jmp *addr_data(%rip)
#ifdef BXF_EXE_FMT_MACH_O
.align 3
#else
.align 8
#endif
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_addr)
#endif
.globl MANGLE(bxfi_trampoline_addr)
MANGLE(bxfi_trampoline_addr):
addr_data:
.fill 8, 1, 0
#ifdef ASSEMBLER_SUPPORTS_HIDDEN
.hidden MANGLE(bxfi_trampoline_end)
#endif
.globl MANGLE(bxfi_trampoline_end)
MANGLE(bxfi_trampoline_end):
#include "stackfix.h"
BoxFort-master/src/asm/trampoline-x86_64.asm 0000644 0001750 0001750 00000002563 13603450524 017561 0 ustar sasa sasa ;
; The MIT License (MIT)
;
; Copyright © 2016 Franklin "Snaipe" Mathieu
;
; 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
bxfi_trampoline label far
jmp qword ptr addr_data
ALIGN 8
bxfi_trampoline_addr label far
addr_data byte 8 dup (0)
bxfi_trampoline_end label far
public bxfi_trampoline
public bxfi_trampoline_addr
public bxfi_trampoline_end
end
BoxFort-master/src/common.h 0000644 0001750 0001750 00000004520 13603450524 014625 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#ifdef __GNUC__
# define nonstd __extension__
#else
# define nonstd
#endif
#ifdef _WIN32
# include
#else
# include
#endif
#define align2_down(v, d) ((v) & ~((d) - 1))
#define align2_up(v, d) ((((v) - 1) & ~((d) - 1)) + (d))
#define bxfi_cont(Var, Type, Member) \
(Var ? ((Type *) (((char *) Var) - offsetof(Type, Member))) : NULL)
static inline size_t pagesize(void) {
static size_t cached;
if (!cached) {
#ifdef _WIN32
SYSTEM_INFO si;
GetSystemInfo(&si);
cached = (size_t) si.dwPageSize;
#else
cached = (size_t) sysconf(_SC_PAGESIZE);
#endif
}
return cached;
}
#define PAGE_SIZE (pagesize())
#define bug(...) do { \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, ": %s\n" \
"This is a bug; please report it " \
"on the repository's issue tracker.\n", \
strerror(errno)); \
abort(); \
} while (0)
#endif /* !COMMON_H_ */
BoxFort-master/src/config.h.in 0000644 0001750 0001750 00000004153 13603450524 015211 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 CONFIG_H_IN_
# define CONFIG_H_IN_
#mesondefine BXF_ARCH
#mesondefine BXF_BITS
#mesondefine BXF_MANGLING
#mesondefine BXF_OS_FAMILY
# ifdef BXF_OS_FAMILY
# define BXF_OS_FAMILY_STR #BXF_OS_FAMILY
# endif
#mesondefine BXF_ARCH_x86
#mesondefine BXF_ARCH_x86_64
#mesondefine BXF_ARCH_ARM
#mesondefine BXF_ARCH_ARM64
#mesondefine BXF_EXE_FMT_ELF
#mesondefine BXF_EXE_FMT_PE
#mesondefine BXF_EXE_FMT_MACH_O
#mesondefine BXF_ARENA_REOPEN_SHM
#mesondefine BXF_ARENA_FILE_BACKED
#mesondefine BXF_FORK_RESILIENCE
#mesondefine HAVE__R_DEBUG
#mesondefine HAVE__DYNAMIC
#mesondefine HAVE_PR_SET_PDEATHSIG
#mesondefine HAVE_CLOCK_GETTIME
#mesondefine HAVE_CLOCK_MONOTONIC_RAW
#mesondefine HAVE_GETTIMEOFDAY
#mesondefine HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
#mesondefine HAVE_ENVIRON
#mesondefine HAVE_MINCORE
#mesondefine HAVE_UNSIGNED_MINCORE_VEC
#mesondefine ASSEMBLER_SUPPORTS_HIDDEN
# define BXFI_STR_(x) #x
# define BXFI_STR(x) BXFI_STR_(x)
#endif /* !CONFIG_H_IN_ */
BoxFort-master/src/context.c 0000644 0001750 0001750 00000024152 13603450524 015017 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include "arena.h"
#include "boxfort.h"
#include "context.h"
#ifdef _WIN32
# include
#endif
#ifdef BXF_ARENA_REOPEN_SHM
# include
# include
#endif
int bxf_context_init(bxf_context *ctx)
{
struct bxf_context_s *nctx = malloc(sizeof (*nctx));
if (!nctx)
return -ENOMEM;
int rc = bxf_arena_init(0,
BXF_ARENA_RESIZE | BXF_ARENA_MAYMOVE,
&nctx->arena);
if (!rc)
*ctx = nctx;
return rc;
}
int bxf_context_addstatic(bxf_context ctx, const void *ptr, size_t size)
{
struct bxfi_ctx_static *elt;
struct bxfi_addr addr;
int rc = bxfi_normalize_addr(ptr, &addr);
if (rc < 0)
return rc;
bxf_ptr p = bxf_arena_alloc(&ctx->arena,
sizeof (*elt) + size + strlen(addr.soname) + 1);
if (p < 0)
return p;
elt = bxf_arena_ptr(ctx->arena, p);
elt->tag = BXFI_TAG_STATIC;
elt->addr = addr.addr;
elt->seg = addr.seg;
elt->size = size;
strcpy(&elt->data[size], addr.soname);
return 0;
}
int bxf_context_addarena(bxf_context ctx, bxf_arena arena)
{
struct bxfi_ctx_arena *elt;
bxf_ptr p = bxf_arena_alloc(&ctx->arena, sizeof (*elt));
if (p < 0)
return p;
elt = bxf_arena_ptr(ctx->arena, p);
elt->tag = BXFI_TAG_ARENA;
elt->flags = arena->flags;
elt->base = arena->flags & BXF_ARENA_IDENTITY ? arena : NULL;
#ifdef BXF_ARENA_REOPEN_SHM
strcpy(elt->name, arena->name);
#else
elt->handle = arena->handle;
#endif
return 0;
}
int bxf_context_addobject(bxf_context ctx, const char *name,
const void *ptr, size_t size)
{
struct bxfi_ctx_object *elt;
size_t len = strlen(name) + 1;
bxf_ptr p = bxf_arena_alloc(&ctx->arena, sizeof (*elt) + len + size);
if (p < 0)
return p;
elt = bxf_arena_ptr(ctx->arena, p);
elt->tag = BXFI_TAG_OBJECT;
elt->namesz = len;
memcpy(&elt->data, name, len);
memcpy(&elt->data[elt->namesz], ptr, size);
return 0;
}
struct bxfi_find_ctx {
const char *name;
void *result;
};
static int find_obj(void *ptr, size_t size, void *user)
{
(void) size;
struct bxfi_find_ctx *ctx = user;
enum bxfi_ctx_tag *tag = ptr;
if (*tag != BXFI_TAG_OBJECT)
return 0;
struct bxfi_ctx_object *obj = ptr;
if (!strcmp(obj->data, ctx->name)) {
ctx->result = &obj->data[obj->namesz];
return 1;
}
return 0;
}
int bxf_context_getobject(bxf_context ctx, const char *name, void **ptr)
{
struct bxfi_find_ctx fctx = { .name = name };
int found = bxf_arena_iter(ctx->arena, find_obj, &fctx);
if (found)
*ptr = fctx.result;
return found;
}
int bxf_context_addaddr(bxf_context ctx, const char *name, const void *addr)
{
struct bxfi_addr norm;
int rc = bxfi_normalize_addr(addr, &norm);
if (rc < 0)
return rc;
struct bxfi_ctx_object *elt;
size_t sonamelen = strlen(norm.soname) + 1;
size_t size = sizeof (void *) + sizeof (norm.seg) + sonamelen;
size_t len = strlen(name) + 1;
bxf_ptr p = bxf_arena_alloc(&ctx->arena, sizeof (*elt) + len + size);
if (p < 0)
return p;
elt = bxf_arena_ptr(ctx->arena, p);
elt->tag = BXFI_TAG_OBJECT;
elt->namesz = len;
size_t i = 0;
memcpy(&elt->data[i], name, len);
i += elt->namesz;
memcpy(&elt->data[i], &norm.addr, sizeof (void *));
i += sizeof (void *);
memcpy(&elt->data[i], &norm.seg, sizeof (norm.seg));
i += sizeof (norm.seg);
memcpy(&elt->data[i], norm.soname, sonamelen);
return 0;
}
int bxf_context_getaddr(bxf_context ctx, const char *name, void **addr)
{
struct {
void *addr;
size_t seg;
const char soname[];
} *serialized;
int rc = bxf_context_getobject(ctx, name, (void **) &serialized);
if (rc > 0) {
struct bxfi_addr norm = {
.addr = serialized->addr,
.soname = serialized->soname,
.seg = serialized->seg,
};
*addr = bxfi_denormalize_addr(&norm);
}
return rc;
}
int bxf_context_addfnaddr(bxf_context ctx, const char *name, void (*fn)(void))
{
return bxf_context_addaddr(ctx, name, nonstd (void *) fn);
}
int bxf_context_getfnaddr(bxf_context ctx, const char *name, void(**fn)(void))
{
return bxf_context_getaddr(ctx, name, nonstd (void **) fn);
}
int bxf_context_addfhandle(bxf_context ctx, bxf_fhandle hndl)
{
struct bxfi_ctx_fhandle *elt;
bxf_ptr p = bxf_arena_alloc(&ctx->arena, sizeof (*elt));
if (p < 0)
return p;
elt = bxf_arena_ptr(ctx->arena, p);
elt->tag = BXFI_TAG_FHANDLE;
elt->handle = hndl;
return 0;
}
int bxf_context_addfile(bxf_context ctx, const char *name, FILE *file)
{
#ifdef _WIN32
HANDLE hndl = (HANDLE) _get_osfhandle(_fileno(file));
int rc = bxf_context_addfhandle(ctx, hndl);
if (!rc)
rc = bxf_context_addobject(ctx, name, &hndl, sizeof (hndl));
#else
int fd = fileno(file);
int rc = bxf_context_addfhandle(ctx, fd);
if (!rc)
rc = bxf_context_addobject(ctx, name, &fd, sizeof (int));
#endif
return rc;
}
int bxf_context_getfile(bxf_context ctx, const char *name, FILE **file)
{
#ifdef _WIN32
HANDLE *hndl;
int rc = bxf_context_getobject(ctx, name, (void **) &hndl);
if (rc > 0)
*file = _fdopen(_open_osfhandle((intptr_t) *hndl, 0), "r+");
#else
int *fd;
int rc = bxf_context_getobject(ctx, name, (void **) &fd);
if (rc > 0)
*file = fdopen(*fd, "r+");
#endif
return rc;
}
int bxf_context_term(bxf_context ctx)
{
int rc = bxf_arena_term(&ctx->arena);
free(ctx);
return rc;
}
bxf_fhandle bxfi_context_gethandle(bxf_context ctx)
{
return ctx->arena->handle;
}
struct bxfi_prepare_ctx {
bxf_fhandle_fn *fn;
void *user;
};
static int prepare_elt(void *ptr, size_t size, void *user)
{
(void) size;
struct bxfi_prepare_ctx *ctx = user;
enum bxfi_ctx_tag *tag = ptr;
switch (*tag) {
case BXFI_TAG_STATIC: {
struct bxfi_ctx_static *elt = ptr;
struct bxfi_addr a = {
.addr = elt->addr,
.soname = &elt->data[elt->size],
.seg = elt->seg,
};
void *addr = bxfi_denormalize_addr(&a);
if (!addr)
return -EINVAL;
memcpy(elt->data, addr, elt->size);
} break;
#ifndef BXF_ARENA_REOPEN_SHM
case BXFI_TAG_ARENA: {
struct bxfi_ctx_arena *elt = ptr;
if (ctx->fn)
return ctx->fn(elt->handle, ctx->user);
} break;
#endif
case BXFI_TAG_FHANDLE: {
struct bxfi_ctx_fhandle *elt = ptr;
if (ctx->fn)
return ctx->fn(elt->handle, ctx->user);
} break;
default: break;
}
return 0;
}
int bxfi_context_prepare(bxf_context ctx, bxf_fhandle_fn *fn, void *user)
{
struct bxfi_prepare_ctx uctx = {
.fn = fn,
.user = user,
};
if (fn) {
int rc = fn(ctx->arena->handle, user);
if (rc < 0)
return rc;
}
return bxf_arena_iter(ctx->arena, prepare_elt, &uctx);
}
static int inherit_elt(void *ptr, size_t size, void *user)
{
(void) size, (void) user;
enum bxfi_ctx_tag *tag = ptr;
switch (*tag) {
case BXFI_TAG_STATIC: {
struct bxfi_ctx_static *elt = ptr;
struct bxfi_addr a = {
.addr = elt->addr,
.soname = &elt->data[elt->size],
.seg = elt->seg,
};
void *addr = bxfi_denormalize_addr(&a);
if (!addr)
return -EINVAL;
memcpy(addr, elt->data, elt->size);
} break;
case BXFI_TAG_ARENA: {
struct bxfi_ctx_arena *elt = ptr;
bxf_arena arena = elt->base;
#ifdef BXF_ARENA_REOPEN_SHM
# ifdef BXF_ARENA_FILE_BACKED
int hndl = open(elt->name, O_RDONLY, 0600);
# else
int hndl = shm_open(elt->name, O_RDONLY, 0600);
# endif
if (hndl < 0)
return -errno;
#else
bxf_fhandle hndl = elt->handle;
#endif
bxfi_arena_inherit(hndl, elt->flags, &arena);
} break;
default: break;
}
return 0;
}
static struct bxf_context_s current_ctx;
int bxfi_context_inherit(struct bxfi_ctx_arena *ctx)
{
#ifdef BXF_ARENA_REOPEN_SHM
if (!ctx->name[0])
return 0;
# ifdef BXF_ARENA_FILE_BACKED
int hndl = open(ctx->name, O_RDONLY, 0600);
# else
int hndl = shm_open(ctx->name, O_RDONLY, 0600);
# endif
if (hndl < 0)
return -errno;
#else
bxf_fhandle hndl = ctx->handle;
if (!hndl)
return 0;
#endif
bxf_arena arena = NULL;
int rc = bxfi_arena_inherit(hndl, 0, &arena);
if (rc < 0)
return rc;
current_ctx.arena = arena;
return bxf_arena_iter(arena, inherit_elt, NULL);
}
bxf_context bxf_context_current(void)
{
if (!current_ctx.arena)
return NULL;
return ¤t_ctx;
}
BoxFort-master/src/context.h 0000644 0001750 0001750 00000004157 13603450524 015027 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 CONTEXT_H_
#define CONTEXT_H_
#include "addr.h"
#include "arena.h"
struct bxf_context_s {
bxf_arena arena;
};
enum bxfi_ctx_tag {
BXFI_TAG_STATIC,
BXFI_TAG_ARENA,
BXFI_TAG_OBJECT,
BXFI_TAG_FHANDLE,
};
struct bxfi_ctx_static {
enum bxfi_ctx_tag tag;
const void *addr;
size_t seg;
size_t size;
char data[];
};
struct bxfi_ctx_arena {
enum bxfi_ctx_tag tag;
int flags;
void *base;
#ifdef BXF_ARENA_REOPEN_SHM
char name[BXFI_ARENA_NAME_SIZE];
#else
bxf_fhandle handle;
#endif
};
struct bxfi_ctx_object {
enum bxfi_ctx_tag tag;
size_t namesz;
char data[];
};
struct bxfi_ctx_fhandle {
enum bxfi_ctx_tag tag;
bxf_fhandle handle;
};
typedef int (bxf_fhandle_fn)(bxf_fhandle, void *);
bxf_fhandle bxfi_context_gethandle(bxf_context ctx);
int bxfi_context_prepare(bxf_context ctx, bxf_fhandle_fn *fn, void *user);
int bxfi_context_inherit(struct bxfi_ctx_arena *ctx);
#endif /* !CONTEXT_H_ */
BoxFort-master/src/exe-elf.c 0000644 0001750 0001750 00000022714 13603450524 014662 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include
#include "config.h"
#include "exe.h"
#include "addr.h"
#include "common.h"
#if BXF_BITS == 32
typedef Elf32_Word ElfWord;
typedef Elf32_Sword ElfSWord;
# ifndef ELF_R_SYM
# define ELF_R_SYM(i) ELF32_R_SYM(i)
# endif
#elif BXF_BITS == 64
typedef Elf64_Xword ElfWord;
typedef Elf64_Sxword ElfSWord;
# ifndef ELF_R_SYM
# define ELF_R_SYM(i) ELF64_R_SYM(i)
# endif
#else
# error Unsupported architecture
#endif
typedef ElfW (Addr) ElfAddr;
typedef ElfW (Dyn) ElfDyn;
typedef ElfW (Sym) ElfSym;
typedef ElfW (Word) ElfWWord;
typedef ElfW (Off) ElfOff;
extern char **environ;
static void *lib_dt_lookup(bxfi_exe_lib lib, ElfSWord tag)
{
ElfAddr base = (ElfAddr) lib->l_addr;
for (const ElfDyn *dyn = lib->l_ld; dyn->d_tag != DT_NULL; ++dyn) {
if (dyn->d_tag == tag) {
if (dyn->d_un.d_ptr >= base
&& (dyn->d_un.d_ptr >> (BXF_BITS - 8)) ^ 0xff)
return (void *) dyn->d_un.d_ptr;
else
return (char *) base + dyn->d_un.d_ptr;
}
}
return NULL;
}
static ElfWord lib_dt_lookup_val(bxfi_exe_lib lib, ElfSWord tag)
{
for (const ElfDyn *dyn = lib->l_ld; dyn->d_tag != DT_NULL; ++dyn) {
if (dyn->d_tag == tag)
return dyn->d_un.d_val;
}
return (ElfWord) - 1;
}
#if !defined HAVE__R_DEBUG
static int find_dynamic(struct dl_phdr_info *info, size_t size, void *data)
{
ElfAddr *ctx = data;
(void)size;
for (ElfOff i = 0; i < info->dlpi_phnum; ++i) {
if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
*ctx = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr;
return 1;
}
}
return -1;
}
static struct r_debug *r_debug_from_dynamic(void *dynamic)
{
for (const ElfDyn *dyn = dynamic; dyn->d_tag != DT_NULL; ++dyn) {
if (dyn->d_tag == DT_DEBUG)
return (struct r_debug *) dyn->d_un.d_ptr;
}
return NULL;
}
#endif
static struct r_debug *get_r_debug(void)
{
/* Find our own r_debug */
struct r_debug *dbg = NULL;
/* First use some known shortcuts */
#if defined HAVE__R_DEBUG
dbg = &_r_debug;
#elif defined HAVE__DYNAMIC
dbg = r_debug_from_dynamic(_DYNAMIC);
#endif
#if !defined HAVE__R_DEBUG
/* If there are no available shortcuts, we manually query our own phdrs */
/* *INDENT-OFF* (formatters cannot handle this part of the code) */
# if defined HAVE__DYNAMIC
if (!dbg) {
# endif
ElfAddr dynamic;
if (dl_iterate_phdr(find_dynamic, &dynamic) > 0)
dbg = r_debug_from_dynamic((void *) dynamic);
# if defined HAVE__DYNAMIC
}
# endif
/* *INDENT-ON* */
#endif
return dbg;
}
static bxfi_exe_ctx init_exe_ctx(void)
{
static struct r_debug *dbg = (void *) -1;
if (dbg == (void *) -1)
dbg = get_r_debug();
return dbg;
}
static unsigned long elf_hash(const char *s)
{
unsigned long h = 0, high;
while (*s) {
h = (h << 4) + (unsigned char) *s++;
if ((high = h & 0xf0000000))
h ^= high >> 24;
h &= ~high;
}
return h;
}
static ElfSym *elf_hash_find(ElfWWord *hash, ElfSym *symtab,
const char *strtab, const char *name)
{
struct {
ElfWWord nb_buckets;
ElfWWord nb_chains;
} *h_info = (void *) hash;
ElfWWord *buckets = (ElfWWord *) (h_info + 1);
ElfWWord *chains = (ElfWWord *) (h_info + 1) + h_info->nb_buckets;
unsigned long idx = elf_hash(name) % h_info->nb_buckets;
for (ElfWWord si = buckets[idx]; si != STN_UNDEF; si = chains[si]) {
if (!strcmp(&strtab[symtab[si].st_name], name))
return &symtab[si];
}
return NULL;
}
static ElfSym *dynsym_lookup(bxfi_exe_lib lib, const char *name)
{
ElfWWord *hash = lib_dt_lookup(lib, DT_HASH);
ElfSym *symtab = lib_dt_lookup(lib, DT_SYMTAB);
const char *strtab = lib_dt_lookup(lib, DT_STRTAB);
if (!hash || !symtab || !strtab)
return NULL;
return elf_hash_find(hash, symtab, strtab, name);
}
extern int main(void);
extern void *bxfi_trampoline;
extern void *bxfi_trampoline_addr;
extern void *bxfi_trampoline_end;
#define BXFI_TRAMPOLINE_SIZE \
((uintptr_t) &bxfi_trampoline_end \
- (uintptr_t) &bxfi_trampoline)
int bxfi_exe_patch_main(bxfi_exe_fn *new_main)
{
void *addr = nonstd (void *) &main;
if (!addr)
return -1;
/* Reserve enough space for the trampoline and copy the default opcodes */
char opcodes[BXFI_TRAMPOLINE_SIZE];
memcpy(opcodes, &bxfi_trampoline, sizeof (opcodes));
uintptr_t jmp_offset = (uintptr_t) &bxfi_trampoline_addr
- (uintptr_t) &bxfi_trampoline;
/* The trampoline code is a jump followed by an aligned pointer value --
after copying the jmp opcode, we write this pointer value. */
*(uintptr_t *) (&opcodes[jmp_offset]) = (uintptr_t) new_main;
void *base = (void *) align2_down((uintptr_t) addr, PAGE_SIZE);
uintptr_t offset = (uintptr_t) addr - (uintptr_t) base;
size_t len = align2_up(offset + sizeof (opcodes), PAGE_SIZE);
mprotect(base, len, PROT_READ | PROT_WRITE | PROT_EXEC);
memcpy(nonstd (void *) addr, opcodes, sizeof (opcodes));
mprotect(base, len, PROT_READ | PROT_EXEC);
return 0;
}
struct find_lib_from_addr_ctx {
const void *addr;
const char *name;
size_t segidx;
void *base;
int first;
};
static int find_lib_from_addr(struct dl_phdr_info *info,
size_t size, void *data)
{
(void) size;
struct find_lib_from_addr_ctx *ctx = data;
size_t segidx = 0;
for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
const ElfW(Phdr) *phdr = &info->dlpi_phdr[i];
if (phdr->p_type != PT_LOAD)
continue;
void *base = (void *) (info->dlpi_addr + phdr->p_vaddr);
void *end = (char *) base + phdr->p_memsz;
if (ctx->addr >= base && ctx->addr < end) {
if (!ctx->first) {
ctx->name = info->dlpi_name;
} else {
ctx->name = "";
}
ctx->segidx = segidx;
ctx->base = base;
return 1;
}
++segidx;
}
ctx->first = 0;
return 0;
}
uintptr_t bxfi_slide_from_addr(const void *addr, const char **name, size_t *seg)
{
struct find_lib_from_addr_ctx ctx = {
.addr = addr,
.first = 1,
};
if (!dl_iterate_phdr(find_lib_from_addr, &ctx)) {
errno = EINVAL;
return (uintptr_t) -1;
}
*name = ctx.name;
*seg = ctx.segidx;
return (uintptr_t) ctx.base;
}
struct find_lib_from_name_ctx {
const char *name;
size_t segidx;
void *base;
int first;
};
static int find_lib_from_name(struct dl_phdr_info *info,
size_t size, void *data)
{
(void) size;
struct find_lib_from_name_ctx *ctx = data;
size_t segidx = 0;
if (!(ctx->first && !ctx->name[0]) && strcmp(info->dlpi_name, ctx->name))
return 0;
ctx->first = 0;
for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) {
const ElfW(Phdr) *phdr = &info->dlpi_phdr[i];
if (phdr->p_type != PT_LOAD)
continue;
if (segidx == ctx->segidx) {
ctx->base = (void *) (info->dlpi_addr + phdr->p_vaddr);
return 1;
}
++segidx;
}
return 0;
}
uintptr_t bxfi_slide_from_name(const char *name, size_t seg)
{
struct find_lib_from_name_ctx ctx = {
.name = name,
.segidx = seg,
.first = 1,
};
if (!dl_iterate_phdr(find_lib_from_name, &ctx)) {
errno = EINVAL;
return (uintptr_t) -1;
}
return (uintptr_t) ctx.base;
}
const char *bxfi_lib_name(bxfi_exe_lib lib)
{
bxfi_exe_ctx ctx = init_exe_ctx();
/* The name of the main shared object is the empty string,
we return something to be consistent with the eglibc weirdity */
if (lib == ctx->r_map)
return "self";
/* Somewhy, eglibc always set l_name to the empty string. */
if (lib->l_name[0])
return lib->l_name;
const char *strtab = lib_dt_lookup(lib, DT_STRTAB);
ElfWord soname_off = lib_dt_lookup_val(lib, DT_SONAME);
if (!strtab || soname_off == (ElfWord) - 1)
return NULL;
return &strtab[soname_off];
}
void bxfi_lib_name_term(const char *str)
{
(void) str;
}
size_t bxfi_exe_get_vmslide(bxfi_exe_lib lib)
{
return (size_t)lib->l_addr;
}
BoxFort-master/src/exe-elf.h 0000644 0001750 0001750 00000003051 13603450524 014660 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 PLT_ELF_H_
#define PLT_ELF_H_
#include
#ifdef __FreeBSD__
# include
# define ElfW(type) ElfW_(Elf, type)
# define ElfW_(e, t) ElfW__(e, _ ## t)
# define ElfW__(e, t) e ## t
#endif
typedef struct link_map *bxfi_exe_lib;
typedef struct r_debug *bxfi_exe_ctx;
typedef void (bxfi_exe_fn)(void);
#define BXFI_INVALID_LIB ((bxfi_exe_lib) 0)
#endif /* !PLT_ELF_H_ */
BoxFort-master/src/exe-mach-o.c 0000644 0001750 0001750 00000013423 13603450524 015255 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include
#include
#include
#include
#include
#include "config.h"
#include "exe.h"
#include "addr.h"
#include "common.h"
#if BXF_BITS == 32
typedef struct mach_header mach_hdr;
typedef struct nlist sym;
typedef struct section section;
typedef struct segment_command segment_cmd;
# define BXF_LC_SEGMENT LC_SEGMENT
#elif BXF_BITS == 64
typedef struct mach_header_64 mach_hdr;
typedef struct nlist_64 sym;
typedef struct section_64 section;
typedef struct segment_command_64 segment_cmd;
# define BXF_LC_SEGMENT LC_SEGMENT_64
#else
# error Unsupported architecture
#endif
static inline void *ptr_add(const void *ptr, size_t off)
{
return (char *) ptr + off;
}
void *get_main_addr(void)
{
return dlsym(RTLD_DEFAULT, "main");
}
extern void *bxfi_trampoline;
extern void *bxfi_trampoline_addr;
extern void *bxfi_trampoline_end;
#define BXFI_TRAMPOLINE_SIZE \
((uintptr_t) &bxfi_trampoline_end \
- (uintptr_t) &bxfi_trampoline)
int bxfi_exe_patch_main(bxfi_exe_fn *new_main)
{
void *addr = get_main_addr();
if (!addr)
return -1;
/* Reserve enough space for the trampoline and copy the default opcodes */
char opcodes[BXFI_TRAMPOLINE_SIZE];
memcpy(opcodes, &bxfi_trampoline, sizeof (opcodes));
uintptr_t jmp_offset = (uintptr_t) &bxfi_trampoline_addr
- (uintptr_t) &bxfi_trampoline;
/* The trampoline code is a jump followed by an aligned pointer value --
after copying the jmp opcode, we write this pointer value. */
*(uintptr_t *) (&opcodes[jmp_offset]) = (uintptr_t) new_main;
void *base = (void *) align2_down((uintptr_t) addr, PAGE_SIZE);
uintptr_t offset = (uintptr_t) addr - (uintptr_t) base;
size_t len = align2_up(offset + sizeof (opcodes), PAGE_SIZE);
mprotect(base, len, PROT_READ | PROT_WRITE | PROT_EXEC);
memcpy(nonstd (void *) addr, opcodes, sizeof (opcodes));
mprotect(base, len, PROT_READ | PROT_EXEC);
return 0;
}
uintptr_t bxfi_slide_from_addr(const void *addr, const char **name, size_t *seg)
{
/* TODO: this is not thread safe, as another thread can load or unload
* images on the fly -- find a way to fix this. */
bxfi_exe_lib nb_images = _dyld_image_count();
for (bxfi_exe_lib i = 0; i < nb_images; ++i) {
const mach_hdr *hdr = (const mach_hdr *) _dyld_get_image_header(i);
intptr_t slide = bxfi_exe_get_vmslide(i);
size_t segidx = 0;
const struct load_command *lc = ptr_add(hdr, sizeof (mach_hdr));
for (size_t c = 0; c < hdr->ncmds; ++c, lc = ptr_add(lc, lc->cmdsize)) {
if (lc->cmd == BXF_LC_SEGMENT) {
const segment_cmd *sc = (void *) lc;
uintptr_t start = sc->vmaddr + slide;
uintptr_t end = start + sc->vmsize - 1;
if ((uintptr_t) addr >= start && (uintptr_t) addr <= end) {
*name = bxfi_lib_name(i);
*seg = segidx;
return start;
}
++segidx;
}
}
}
errno = EINVAL;
return (uintptr_t) -1;
}
uintptr_t bxfi_slide_from_name(const char *name, size_t seg)
{
bxfi_exe_lib lib = 0;
if (strcmp("self", name)) {
/* TODO: this is not thread safe, as another thread can load or unload
* images on the fly -- find a way to fix this. */
bxfi_exe_lib nb_images = _dyld_image_count();
for (bxfi_exe_lib i = 1; i < nb_images; ++i) {
const char *img_name = _dyld_get_image_name(i);
if (img_name && !strcmp(img_name, name)) {
lib = i;
break;
}
}
if (!lib) {
errno = EINVAL;
return (uintptr_t) -1;
}
}
const mach_hdr *hdr = (const mach_hdr *) _dyld_get_image_header(lib);
uintptr_t slide = bxfi_exe_get_vmslide(lib);
size_t segidx = 0;
const struct load_command *lc = ptr_add(hdr, sizeof (mach_hdr));
for (size_t c = 0; c < hdr->ncmds; ++c, lc = ptr_add(lc, lc->cmdsize)) {
if (lc->cmd != BXF_LC_SEGMENT)
continue;
const segment_cmd *sc = (void *) lc;
if (segidx == seg)
return sc->vmaddr + slide;
++segidx;
}
errno = EINVAL;
return (uintptr_t) -1;
}
const char *bxfi_lib_name(bxfi_exe_lib lib)
{
if (!lib)
return "self";
return _dyld_get_image_name(lib);
}
void bxfi_lib_name_term(const char *str)
{
(void) str;
}
size_t bxfi_exe_get_vmslide(bxfi_exe_lib lib)
{
return _dyld_get_image_vmaddr_slide(lib);
}
BoxFort-master/src/exe-mach-o.h 0000644 0001750 0001750 00000002550 13603450524 015261 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 EXE_MACH_O_H_
#define EXE_MACH_O_H_
typedef int bxfi_exe_lib;
typedef void *bxfi_exe_ctx;
typedef void (bxfi_exe_fn)(void);
#define BXFI_INVALID_LIB ((bxfi_exe_lib) - 1)
#endif /* !EXE_MACH_O_H_ */
BoxFort-master/src/exe-pe.c 0000644 0001750 0001750 00000010263 13603450524 014514 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 "exe.h"
#include "common.h"
#include
#include
#ifdef _MSC_VER
# include
#endif
static void *get_main_addr(void)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
GetCurrentProcessId());
if (snap == INVALID_HANDLE_VALUE)
return NULL;
MODULEENTRY32 mod = { .dwSize = sizeof (MODULEENTRY32) };
for (BOOL more = Module32First(snap, &mod); more;
more = Module32Next(snap, &mod))
{
FARPROC fn = GetProcAddress(mod.hModule, "main");
if (fn != NULL)
return nonstd (void *) fn;
}
return NULL;
}
extern void *bxfi_trampoline;
extern void *bxfi_trampoline_addr;
extern void *bxfi_trampoline_end;
int bxfi_exe_patch_main(bxfi_exe_fn *new_main)
{
void *addr = get_main_addr();
if (!addr)
return -1;
#if defined (BXF_ARCH_x86) || defined (BXF_ARCH_x86_64)
/* If we got stuck on a jmp table entry we need to follow the trail */
if (*(char *) addr == (char) 0xE9)
addr = (char *) addr + *(DWORD *) ((char *) addr + 1) + 5;
#endif
/* Reserve enough space for the trampoline and copy the default opcodes */
uintptr_t size = (uintptr_t) &bxfi_trampoline_end
- (uintptr_t) &bxfi_trampoline;
#ifndef _MSC_VER
char opcodes[size]; /* VLA */
#else
char *opcodes = alloca(size);
#endif
memcpy(opcodes, &bxfi_trampoline, size);
uintptr_t jmp_offset = (uintptr_t) &bxfi_trampoline_addr
- (uintptr_t) &bxfi_trampoline;
/* The trampoline code is a jump followed by an aligned pointer value --
after copying the jmp opcode, we write this pointer value. */
*(uintptr_t *) (&opcodes[jmp_offset]) = (uintptr_t) new_main;
void *base = (void *) align2_down((uintptr_t) addr, PAGE_SIZE);
uintptr_t offset = (uintptr_t) addr - (uintptr_t) base;
size_t len = align2_up(offset + size, PAGE_SIZE);
DWORD old;
VirtualProtect(base, len, PAGE_EXECUTE_READWRITE, &old);
memcpy(nonstd (void *) addr, opcodes, size);
VirtualProtect(base, len, old, NULL);
return 0;
}
uintptr_t bxfi_slide_from_addr(const void *addr, const char **name, size_t *seg)
{
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(addr, &mbi, sizeof (mbi))) {
HMODULE hmod = mbi.AllocationBase;
*name = bxfi_lib_name(hmod);
*seg = 0;
return (uintptr_t) hmod;
}
errno = EINVAL;
return (uintptr_t) -1;
}
uintptr_t bxfi_slide_from_name(const char *name, size_t seg)
{
(void) seg;
if (!strcmp(name, "self"))
name = NULL;
HMODULE hmod = GetModuleHandle(name);
if (!hmod) {
errno = EINVAL;
return (uintptr_t) -1;
}
return (uintptr_t) hmod;
}
const char *bxfi_lib_name(bxfi_exe_lib lib)
{
char *out = LocalAlloc(LMEM_FIXED, MAX_PATH);
if (GetModuleFileNameA(lib, out, MAX_PATH))
return out;
LocalFree(out);
return NULL;
}
void bxfi_lib_name_term(const char *str)
{
LocalFree((char *) str);
}
size_t bxfi_exe_get_vmslide(bxfi_exe_lib lib)
{
return (size_t) lib;
}
BoxFort-master/src/exe-pe.h 0000644 0001750 0001750 00000002567 13603450524 014531 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 EXE_PE_H_
#define EXE_PE_H_
#include
typedef HMODULE bxfi_exe_lib;
typedef void *bxfi_exe_ctx;
typedef void (bxfi_exe_fn)(void);
#define BXFI_INVALID_LIB ((bxfi_exe_lib) NULL)
#endif /* !EXE_PE_H_ */
BoxFort-master/src/exe.h 0000644 0001750 0001750 00000003342 13603450524 014117 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 PLT_H_
#define PLT_H_
#include
#include "config.h"
#if defined BXF_EXE_FMT_ELF
# include "exe-elf.h"
#elif defined BXF_EXE_FMT_PE
# include "exe-pe.h"
#elif defined BXF_EXE_FMT_MACH_O
# include "exe-mach-o.h"
#endif
int bxfi_exe_patch_main(bxfi_exe_fn *new_main);
uintptr_t bxfi_slide_from_addr(const void *addr, const char **name, size_t *seg);
uintptr_t bxfi_slide_from_name(const char *name, size_t seg);
const char *bxfi_lib_name(bxfi_exe_lib lib);
void bxfi_lib_name_term(const char *str);
size_t bxfi_exe_get_vmslide(bxfi_exe_lib lib);
#endif /* !PLT_H_ */
BoxFort-master/src/meson.build 0000644 0001750 0001750 00000003567 13603450524 015340 0 ustar sasa sasa sources = files(
'addr.c',
'addr.h',
'arena.c',
'arena.h',
'context.c',
'context.h',
'exe.h',
'exe-@0@.c'.format(binfmt),
'exe-@0@.h'.format(binfmt),
'sandbox-@0@.c'.format(os_family),
'sandbox-@0@.h'.format(os_family),
'sandbox.c',
'sandbox.h',
'timeout-@0@.c'.format(os_family),
'timeout.h',
'timestamp.c',
'timestamp.h',
)
asm_extension = '.S'
if cc.get_id() == 'msvc'
asm_extension = '.asm'
endif
asm = files('asm/trampoline-@0@@1@'.format(arch, asm_extension))
if cc.get_id() == 'msvc'
if bitness == 32
masm = find_program('ml')
else
masm = find_program('ml64')
endif
masm_gen = generator(masm,
output: '@BASENAME@.obj',
depfile: '@BASENAME@.obj.ndep',
arguments: [
'/I', '@CURRENT_SOURCE_DIR@/asm/',
'/I', '@0@/'.format(meson.current_build_dir()),
'/safeseh',
'@EXTRA_ARGS@',
'/Fo', '@OUTPUT@',
'/c',
'@INPUT@',
])
asm += 'asm/setjmp-@0@@1@'.format(arch, asm_extension)
sources += masm_gen.process(asm)
else
sources += asm
endif
configure_file(input : 'config.h.in',
output : 'config.h',
configuration : config)
deps = [
threads,
librt,
libm,
]
extra_cflags = cc.get_supported_arguments([
'-DBXF_STATIC_LIB=1',
])
libboxfort = static_library('boxfort', sources,
include_directories: [boxfort_includedir],
dependencies: deps,
install: not meson.is_subproject(),
link_args: cc.get_supported_link_arguments([
'-Wl,--exclude-libs,ALL',
]),
)
boxfort = declare_dependency(
compile_args: extra_cflags,
include_directories: [boxfort_includedir],
dependencies: [threads, librt, libm],
link_with: [libboxfort])
if not meson.is_subproject()
pkgconfig = import('pkgconfig')
pkgconfig.generate(
name: meson.project_name(),
description: 'A portable process sandboxing library',
url: 'https://snai.pe/git/boxfort',
extra_cflags: extra_cflags,
libraries: [libboxfort],
)
endif
BoxFort-master/src/sandbox-posix.c 0000644 0001750 0001750 00000060354 13603450524 016135 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __FreeBSD__
# include
#endif
#if defined (HAVE_CLOCK_GETTIME)
# include
#elif defined (HAVE_GETTIMEOFDAY)
# include
#endif
#include "addr.h"
#include "boxfort.h"
#include "context.h"
#include "sandbox.h"
#include "timestamp.h"
#include "timeout.h"
#if defined (HAVE_PR_SET_PDEATHSIG)
# include
#endif
#if defined (__APPLE__)
# include
#endif
#ifndef HAVE_ENVIRON
# ifdef __APPLE__
# include
# define environ (*_NSGetEnviron())
# else
extern char **environ;
# endif
#endif
static struct {
struct bxfi_sandbox *alive;
struct bxfi_sandbox *dead;
pthread_mutex_t sync;
pthread_cond_t cond;
pthread_t child_pump;
int child_pump_active;
} self = {
.sync = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
};
static struct bxfi_sandbox *reap_child(pid_t pid,
uint64_t ts_end, uint64_t mts_end)
{
struct bxfi_sandbox *s;
pthread_mutex_lock(&self.sync);
for (s = self.alive; s; s = s->next) {
if (s->wait_pid == pid)
break;
}
if (!s) {
pthread_mutex_unlock(&self.sync);
return NULL;
}
pthread_mutex_unlock(&self.sync);
bxfi_cancel_timeout(s);
int status;
pid_t rc = waitpid(pid, &status, WNOHANG);
if (rc != pid)
return NULL;
pthread_mutex_lock(&s->sync);
s->props.time.end = ts_end;
s->props.time.elapsed = mts_end - s->start_monotonic;
if (WIFEXITED(status))
s->props.status.exit = WEXITSTATUS(status);
if (WIFSIGNALED(status))
s->props.status.signal = WTERMSIG(status);
s->props.status.stopped = WIFSTOPPED(status);
s->props.status.alive = WIFSTOPPED(status);
if (!s->props.status.alive && s->callback)
s->callback(&s->props);
pthread_mutex_unlock(&s->sync);
return s;
}
static void remove_alive_by_pid(bxf_pid pid)
{
struct bxfi_sandbox **prev = &self.alive;
for (struct bxfi_sandbox *s = self.alive; s; s = s->next) {
if (s->wait_pid == (pid_t) pid) {
*prev = s->next;
s->next = self.dead;
self.dead = s;
break;
}
prev = &s->next;
}
}
static void *child_pump_fn(void *nil)
{
int wflags = WEXITED | WNOWAIT;
for (;;) {
pthread_mutex_lock(&self.sync);
while (!self.alive)
pthread_cond_wait(&self.cond, &self.sync);
pthread_mutex_unlock(&self.sync);
siginfo_t infop;
memset(&infop, 0, sizeof (infop));
int rc;
for (;;) {
rc = waitid(P_ALL, 0, &infop, wflags);
if (rc != -1 || errno == EINTR)
break;
}
if (rc)
continue;
uint64_t mts_end = bxfi_timestamp_monotonic();
uint64_t ts_end = bxfi_timestamp();
for (;;) {
memset(&infop, 0, sizeof (infop));
if (waitid(P_ALL, 0, &infop, wflags | WNOHANG) == -1)
break;
if (!infop.si_pid)
break;
struct bxfi_sandbox *instance = reap_child(infop.si_pid,
ts_end, mts_end);
if (!instance)
continue;
int alive;
pthread_mutex_lock(&self.sync);
remove_alive_by_pid((bxf_pid) infop.si_pid);
alive = !!self.alive;
pthread_mutex_unlock(&self.sync);
pthread_mutex_lock(&instance->sync);
instance->waited = 1;
pthread_cond_broadcast(&instance->cond);
pthread_mutex_unlock(&instance->sync);
if (!alive)
goto end;
}
}
end:
return nil;
}
static int bxfi_create_local_ctx(struct bxfi_map *map,
const char *name, size_t sz)
{
shm_unlink(name);
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd == -1)
goto error;
if (ftruncate(fd, sizeof (struct bxfi_context) + sz) == -1)
goto error;
struct bxfi_context *ctx = mmap(NULL,
sizeof (struct bxfi_context) + sz,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (ctx == MAP_FAILED)
goto error;
ctx->total_sz = sizeof (struct bxfi_context) + sz;
*map = (struct bxfi_map) { .ctx = ctx, .fd = fd };
return 0;
error:;
int err = errno;
shm_unlink(name);
if (fd != -1)
close(fd);
return -err;
}
static void bxfi_unmap_local_ctx(struct bxfi_map *map)
{
size_t sz = map->ctx->total_sz;
munmap(map->ctx, sz);
close(map->fd);
}
int bxfi_check_sandbox_ctx(void)
{
return !!getenv("BXFI_MAP");
}
int bxfi_init_sandbox_ctx(struct bxfi_map *map)
{
const char *ctx_path = getenv("BXFI_MAP");
int fd = shm_open(ctx_path, O_RDWR, 0600);
if (fd == -1)
goto error;
size_t total_sz;
size_t *sz = mmap(NULL,
sizeof (total_sz), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (sz == MAP_FAILED)
goto error;
total_sz = *sz;
munmap(sz, sizeof (total_sz));
struct bxfi_context *ctx = mmap(NULL,
total_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ctx == MAP_FAILED)
goto error;
*map = (struct bxfi_map) { .ctx = ctx, .fd = fd };
return 0;
error:;
int err = errno;
if (fd != -1)
close(fd);
return -err;
}
int bxfi_term_sandbox_ctx(struct bxfi_map *map)
{
/* This is either our PID or the debugging server's PID */
pid_t control_pid = map->ctx->pid;
int suspend = map->ctx->suspend;
map->ctx->ok = 1;
map->ctx->pid = getpid();
bxfi_unmap_local_ctx(map);
const char *ctx_path = getenv("BXFI_MAP");
if (shm_unlink(ctx_path) == -1)
return -errno;
/* Notify the parent to finalize initialization */
kill(control_pid, SIGSTOP);
if (suspend)
raise(SIGSTOP);
return 0;
}
static int get_exe_path(char *buf, size_t sz)
{
#if defined (__linux__)
const char *self = "/proc/self/exe";
#elif defined __NetBSD__
const char *self = "/proc/curproc/exe";
#elif defined __FreeBSD__
const char *self = "/proc/curproc/file";
int fd = open(self, O_RDONLY);
/* Fallback */
char path[PATH_MAX];
if (fd == -1 && errno == ENOENT) {
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
size_t cb = sizeof (path);
sysctl(mib, sizeof (mib) / sizeof (int), path, &cb, NULL, 0);
self = path;
}
if (fd != -1)
close(fd);
#elif defined __OpenBSD__ || defined __DragonFly__
const char *self = "/proc/curproc/file";
#elif defined (__APPLE__)
uint32_t size = sz;
if (_NSGetExecutablePath(buf, &size) == -1)
return -ENAMETOOLONG;
/* _NSGetExecutablePath already returns the correct path */
char *self;
(void) self;
return 0;
#else
# error Platform not supported
#endif
/* We can't just use /proc/self/exe or equivalent to re-exec the
executable, because tools like valgrind use this path to open
and map the ELF file -- which would point to the valgrind binary. */
ssize_t rc = readlink(self, buf, sz);
if (rc == -1) {
if (errno == EINVAL) {
strncpy(buf, self, sz);
return 0;
}
return -errno;
}
if ((size_t) rc == sz)
return -ENAMETOOLONG;
memset(buf + rc, 0, sz - rc);
return 0;
}
static pid_t wait_stop(pid_t pid)
{
int status;
pid_t rc;
for (;;) {
rc = waitpid(pid, &status, WUNTRACED);
if (rc != -1 || errno != EINTR)
break;
}
if (rc == -1)
return -pid;
if (!WIFSTOPPED(status)) {
errno = EPROTO;
return 0;
}
return pid;
}
static int setup_limit(int limit, size_t iquota, size_t quota)
{
if (!quota && !iquota)
return 0;
struct rlimit rl;
if (getrlimit(limit, &rl) < 0)
return -errno;
if (quota)
rl.rlim_max = quota;
if (iquota)
rl.rlim_cur = iquota;
else if (quota)
rl.rlim_cur = quota;
if (setrlimit(limit, &rl) < 0)
return -errno;
return 0;
}
#define setup_limit(Limit, Quota) \
(setup_limit((Limit), \
sandbox->iquotas.Quota, \
sandbox->quotas.Quota))
static int setup_limits(bxf_sandbox *sandbox)
{
int errnum;
errnum = setup_limit(RLIMIT_AS, memory);
if (errnum < 0)
return errnum;
errnum = setup_limit(RLIMIT_NOFILE, files);
if (errnum < 0)
return errnum;
errnum = setup_limit(RLIMIT_NPROC, subprocesses);
if (errnum < 0)
return errnum;
return 0;
}
static int nocloexec_fd(bxf_fhandle fd, void *ctx)
{
(void) ctx;
int flags = fcntl(fd, F_GETFD);
if (flags < 0)
return -errno;
flags &= ~FD_CLOEXEC;
int rc = fcntl(fd, F_SETFD, flags);
if (rc < 0)
return -errno;
return 0;
}
static int inherit_fd(bxf_fhandle fd, void *ctx)
{
int rc = nocloexec_fd(fd, NULL);
if (rc < 0)
return rc;
uint8_t *do_close = ctx;
do_close[fd] = 0;
return 0;
}
static int setup_inheritance(bxf_sandbox *sandbox)
{
bxf_context ctx = sandbox->inherit.context;
if (sandbox->inherit.files) {
int rc = 0;
if (ctx)
rc = bxfi_context_prepare(ctx, nocloexec_fd, NULL);
return rc;
} else {
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return -errno;
uint8_t *do_close = malloc(rl.rlim_cur);
if (!do_close)
return -errno;
memset(do_close, 1, rl.rlim_cur);
do_close[STDIN_FILENO] = 0;
do_close[STDOUT_FILENO] = 0;
do_close[STDERR_FILENO] = 0;
if (ctx) {
int rc = bxfi_context_prepare(ctx, inherit_fd, do_close);
if (rc < 0) {
free(do_close);
return rc;
}
}
/* /dev/fd is somewhat more common than /proc/self/fd; we'll handle
special cases later. */
int fds = open("/dev/fd", O_RDONLY | O_DIRECTORY);
if (fds >= 0) {
/* this is somewhat problematic, as fdopendir/readdir are not
signal-safe, and thus not fork-safe. We can thread the needle
here by assuming deadlocks are going to be extremely unlikely,
but not using these APIs and rolling with a custom-made readdir
might be a better choice for the unforseeable future. */
DIR *dirfd = fdopendir(fds);
/* we have a shortcut; iterate through the directory entries */
struct dirent *dir;
while ((dir = readdir(dirfd)) != NULL) {
errno = 0;
long fd = strtol(dir->d_name, NULL, 10);
if (errno != 0 || fd < 0 || fd > (long) rl.rlim_cur || !do_close[fd])
continue;
close(fd);
}
return 0;
} else {
for (int fd = 0; fd < (int) rl.rlim_cur; ++fd) {
if (!do_close[fd])
continue;
int flags = fcntl(fd, F_GETFD);
if (flags > 0 && !(flags & FD_CLOEXEC))
close(fd);
}
}
free(do_close);
}
return 0;
}
#ifdef BXF_FORK_RESILIENCE
static void prefork(void)
{
pthread_mutex_lock(&self.sync);
for (struct bxfi_sandbox *s = self.alive; s; s = s->next)
pthread_mutex_lock(&s->sync);
for (struct bxfi_sandbox *s = self.dead; s; s = s->next)
pthread_mutex_lock(&s->sync);
}
static void postfork_parent(void)
{
for (struct bxfi_sandbox *s = self.dead; s; s = s->next)
pthread_mutex_unlock(&s->sync);
for (struct bxfi_sandbox *s = self.alive; s; s = s->next)
pthread_mutex_unlock(&s->sync);
pthread_mutex_unlock(&self.sync);
}
static void postfork_child(void)
{
postfork_parent();
pthread_cond_t nil = PTHREAD_COND_INITIALIZER;
memcpy(&self.cond, &nil, sizeof (nil));
if (self.alive)
pthread_join(self.child_pump, NULL);
for (struct bxfi_sandbox *s = self.alive; s; s = self.alive) {
memset((void *) &s->props.status, 0, sizeof (s->props.status));
self.alive = s->next;
s->next = self.dead;
self.dead = s;
}
bxfi_reset_timeout_killer();
}
static void init_atfork(void)
{
pthread_atfork(prefork, postfork_parent, postfork_child);
}
#endif
static void init_child_pump(pid_t pid)
{
if (pthread_create(&self.child_pump, NULL, child_pump_fn, NULL))
goto thread_err;
self.child_pump_active = 1;
return;
thread_err:
perror("boxfort: could not initialize child pump");
kill(pid, SIGKILL);
waitpid(pid, NULL, 0);
abort();
}
static void term_child_pump(void)
{
if (self.child_pump_active) {
pthread_join(self.child_pump, NULL);
self.child_pump_active = 0;
}
}
static int find_exe(const char *progname, char *out, size_t size)
{
char *sptr = NULL;
char *path = strdup(getenv("PATH"));
char *p = strtok_r(path, ":", &sptr);
while (p) {
snprintf(out, size, "%s/%s", *p ? p : ".", progname);
struct stat sb;
int rc = stat(out, &sb);
if (!rc && (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)))
break;
p = strtok_r(NULL, ":", &sptr);
}
free(path);
if (!p)
return -ENOENT;
return 0;
}
static char **dupenv(char **concat)
{
size_t len = 0, clen = 0;
for (char **e = environ; *e; ++e, ++len) ;
for (char **e = concat; *e; ++e, ++clen) ;
char **dupe = malloc(sizeof (void *) * (len + clen + 1));
memcpy(dupe, environ, (len + 1) * sizeof (void *));
char **d = dupe + len;
for (char **e = concat; *e; ++e) {
char **de = dupe;
for (; *de; ++de) {
char *eq1 = strchr(*e, '='), *eq2 = strchr(*de, '=');
if (!eq1 || !eq2)
continue;
size_t l1 = (size_t)(eq1 - *e), l2 = (size_t)(eq2 - *de);
if (l1 != l2)
continue;
if (!strncmp(*e, *de, l1)) {
*de = *e;
break;
}
}
if (!*de) {
*d++ = *e;
*d = NULL;
}
}
return dupe;
}
int bxfi_exec(bxf_instance **out, bxf_sandbox *sandbox,
int mantled, bxf_fn *fn, bxf_preexec *preexec, bxf_callback *callback,
void *user, bxf_dtor user_dtor)
{
static char exe[PATH_MAX + 1];
#ifdef BXF_FORK_RESILIENCE
static pthread_once_t atfork = PTHREAD_ONCE_INIT;
pthread_once(&atfork, init_atfork);
#endif
char map_name[sizeof ("/bxfi_") + 21];
struct bxfi_sandbox *instance = NULL;
struct bxfi_map local_ctx;
pid_t pid = 0;
memset(&local_ctx, 0, sizeof (local_ctx));
intptr_t errnum;
int map_rc = -1;
if (!exe[0] && (errnum = get_exe_path(exe, sizeof (exe))) < 0)
return errnum;
struct bxfi_addr addr;
if (bxfi_normalize_fnaddr(fn, &addr) < 0)
return -EINVAL;
char dbg_full[PATH_MAX];
if (sandbox->debug.debugger) {
const char *dbg = NULL;
switch (sandbox->debug.debugger) {
case BXF_DBG_GDB: dbg = "gdbserver"; break;
case BXF_DBG_LLDB: dbg = "lldb-server"; break;
default:
return -EINVAL;
}
if (find_exe(dbg, dbg_full, sizeof (dbg_full)) < 0)
return -ENOENT;
}
errnum = -ENOMEM;
instance = malloc(sizeof (*instance));
if (!instance)
goto err;
*instance = (struct bxfi_sandbox) {
.mantled = mantled,
.callback = callback,
.user = user,
.user_dtor = user_dtor,
};
if ((errnum = -pthread_mutex_init(&instance->sync, NULL)))
goto err;
if ((errnum = -pthread_cond_init(&instance->cond, NULL)))
goto err;
pid = fork();
if (pid == -1) {
errnum = -errno;
goto err;
} else if (pid) {
instance->start_monotonic = bxfi_timestamp_monotonic();
instance->wait_pid = pid;
instance->props = (struct bxf_instance_s) {
.sandbox = sandbox,
.pid = pid,
.status.alive = 1,
.time.start = bxfi_timestamp(),
.user = instance->user,
};
if ((pid = wait_stop(pid)) <= 0) {
errnum = -errno;
goto err;
}
snprintf(map_name, sizeof (map_name), "/bxfi_%d", pid);
size_t len = strlen(addr.soname);
map_rc = bxfi_create_local_ctx(&local_ctx, map_name, len + 1);
errnum = map_rc;
if (map_rc < 0)
goto err;
local_ctx.ctx->ok = 0;
local_ctx.ctx->fn = addr.addr;
local_ctx.ctx->seg = addr.seg;
local_ctx.ctx->pid = pid;
local_ctx.ctx->suspend = sandbox->suspended;
bxf_context ictx = sandbox->inherit.context;
if (ictx) {
#ifdef BXF_ARENA_REOPEN_SHM
strcpy(local_ctx.ctx->context.name, ictx->arena->name);
#else
local_ctx.ctx->context.handle = ictx->arena->handle;
#endif
}
memcpy(local_ctx.ctx + 1, addr.soname, len + 1);
local_ctx.ctx->fn_soname_sz = len + 1;
kill(pid, SIGCONT);
if ((pid = wait_stop(pid)) <= 0) {
errnum = -errno;
goto err;
}
if (!local_ctx.ctx->ok)
goto err;
instance->props.pid = local_ctx.ctx->pid;
if (sandbox->quotas.runtime > 0)
if (bxfi_push_timeout(instance, sandbox->quotas.runtime) < 0)
goto err;
if (sandbox->iquotas.runtime > 0)
if (bxfi_push_timeout(instance, sandbox->iquotas.runtime) < 0)
goto err;
pthread_mutex_lock(&self.sync);
/* spawn a wait thread if no sandboxes are alive right now */
if (!self.alive) {
term_child_pump();
init_child_pump(pid);
}
instance->next = self.alive;
self.alive = instance;
pthread_cond_broadcast(&self.cond);
pthread_mutex_unlock(&self.sync);
bxfi_unmap_local_ctx(&local_ctx);
kill(pid, SIGCONT);
if (sandbox->suspended)
instance->props.status.stopped = 1;
*out = &instance->props;
return 0;
}
#if defined (HAVE_PR_SET_PDEATHSIG)
int pdeathsig = sandbox->debug.debugger ? SIGTERM : SIGKILL;
prctl(PR_SET_PDEATHSIG, pdeathsig);
#endif
pid = getpid();
instance->props = (struct bxf_instance_s) {
.sandbox = sandbox,
.pid = pid,
};
if (preexec && preexec(&instance->props) < 0)
abort();
if (setup_limits(sandbox) < 0)
abort();
if (setup_inheritance(sandbox) < 0)
abort();
setsid();
raise(SIGSTOP);
snprintf(map_name, sizeof (map_name), "/bxfi_%d", pid);
char env_map[sizeof ("BXFI_MAP=") + sizeof (map_name)];
snprintf(env_map, sizeof (env_map), "BXFI_MAP=%s", map_name);
char **env = dupenv((char *[]) { env_map, "GMON_OUT_PREFIX=sandbox-gmon", NULL });
char *fullpath = exe;
char *argv[16] = { "boxfort-worker" };
size_t argc = 1;
if (sandbox->debug.debugger) {
char port[11];
switch (sandbox->debug.debugger) {
case BXF_DBG_GDB:
snprintf(port, sizeof (port), ":%d", sandbox->debug.tcp);
break;
case BXF_DBG_LLDB:
argv[argc++] = "gdbserver";
snprintf(port, sizeof (port), "*:%d", sandbox->debug.tcp);
break;
default:
abort();
}
argv[argc++] = port;
argv[argc++] = exe;
fullpath = dbg_full;
}
argv[argc++] = NULL;
execve(fullpath, argv, env);
_exit(errno);
err:
if (pid) {
kill(pid, SIGKILL);
waitpid(pid, NULL, 0);
}
if (!map_rc) {
bxfi_unmap_local_ctx(&local_ctx);
shm_unlink(map_name);
}
free(instance);
return errnum;
}
int bxf_term(bxf_instance *instance)
{
if (instance->status.alive)
return -EINVAL;
struct bxfi_sandbox *sb = bxfi_cont(instance, struct bxfi_sandbox, props);
if (!sb->waited)
return -EINVAL;
pthread_mutex_lock(&self.sync);
struct bxfi_sandbox **prev = &self.dead;
int ok = 0;
for (struct bxfi_sandbox *s = self.dead; s; s = s->next) {
if (s == sb) {
*prev = s->next;
ok = 1;
break;
}
prev = &s->next;
}
pthread_mutex_unlock(&self.sync);
if (!ok)
return -EINVAL;
if (sb->user && sb->user_dtor)
sb->user_dtor(instance, sb->user);
if (sb->mantled)
free((void *) instance->sandbox);
pthread_mutex_destroy(&sb->sync);
pthread_cond_destroy(&sb->cond);
free(sb);
return 0;
}
int bxf_wait(bxf_instance *instance, double timeout)
{
if (timeout < 0)
timeout = 0;
static const size_t nanosecs = 1000000000;
size_t to_ns = (timeout - (size_t) timeout) * nanosecs;
size_t to_s = timeout;
struct timespec timeo;
#if defined (HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP)
timeo = (struct timespec) { .tv_sec = to_ns, .tv_nsec = to_s };
typedef int (*const f_timedwait)(pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime);
static f_timedwait pthread_cond_timedwait =
pthread_cond_timedwait_relative_np;
#elif defined (HAVE_CLOCK_GETTIME)
clock_gettime(CLOCK_REALTIME, &timeo);
size_t new_nsec = (timeo.tv_nsec + to_ns) % nanosecs;
timeo.tv_sec += to_s + (timeo.tv_nsec + to_ns) / nanosecs;
timeo.tv_nsec = new_nsec;
#elif defined (HAVE_GETTIMEOFDAY)
struct timeval tv;
gettimeofday(&tv, NULL);
timeo = (struct timespec) {
.tv_sec = tv.tv_sec + to_s + (tv.tv_usec * 1000 + to_ns) / nanosecs,
.tv_nsec = (tv.tv_usec * 1000 + to_ns) % nanosecs,
};
#else
# error bxf_wait needs a way to get the current time.
#endif
struct bxfi_sandbox *sb = bxfi_cont(instance, struct bxfi_sandbox, props);
pthread_mutex_lock(&sb->sync);
int rc = 0;
while (!sb->waited) {
if (timeout == BXF_FOREVER || !isfinite(timeout))
rc = pthread_cond_wait(&sb->cond, &sb->sync);
else
rc = pthread_cond_timedwait(&sb->cond, &sb->sync, &timeo);
if (!rc || rc == ETIMEDOUT)
break;
}
if (!rc)
sb->waited = 1;
pthread_mutex_unlock(&sb->sync);
if (rc)
return -rc;
pthread_mutex_lock(&self.sync);
if (!self.alive)
term_child_pump();
pthread_mutex_unlock(&self.sync);
/* Enforce the deletion of the shm file */
if (!instance->status.alive) {
char map_name[sizeof ("/bxfi_") + 21];
snprintf(map_name, sizeof (map_name), "/bxfi_%d", (int) instance->pid);
shm_unlink(map_name);
}
return 0;
}
void bxf_suspend(bxf_instance *instance)
{
kill((pid_t) instance->pid, SIGSTOP);
}
void bxf_resume(bxf_instance *instance)
{
kill((pid_t) instance->pid, SIGCONT);
}
BoxFort-master/src/sandbox-posix.h 0000644 0001750 0001750 00000004406 13603450524 016136 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 SANDBOX_POSIX_H_
#define SANDBOX_POSIX_H_
#include
#include
#include
#include "context.h"
struct bxfi_context {
size_t total_sz;
const void *fn;
size_t seg;
pid_t pid;
struct bxfi_ctx_arena context;
size_t fn_soname_sz;
int ok;
int suspend;
};
struct bxfi_map {
struct bxfi_context *ctx;
int fd;
};
struct bxfi_sandbox {
struct bxf_instance_s props;
/* A sandbox is said to be mantled if there is an unique instance
managing its memory. */
int mantled;
/* Set to 1 if the instance has been waited for in the child pump */
int waited;
/* The monotonic timestamp representing the start of the sandbox instance.
* Only used to calculate more accurate run times */
uint64_t start_monotonic;
/* The child PID. Might be different from the sandbox PID, e.g. if run
* with a debugging server. */
pid_t wait_pid;
pthread_mutex_t sync;
pthread_cond_t cond;
bxf_callback *callback;
void *user;
bxf_dtor *user_dtor;
struct bxfi_sandbox *next;
};
#endif /* !SANDBOX_POSIX_H_ */
BoxFort-master/src/sandbox-windows.c 0000644 0001750 0001750 00000043240 13603450524 016460 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include
#include
#include "addr.h"
#include "context.h"
#include "sandbox.h"
#include "timestamp.h"
#include "timeout.h"
int bxfi_check_sandbox_ctx(void)
{
int is_sandbox = !!_tcsstr(GetCommandLine(), TEXT("BXFI_MAP="));
/* If we are a sandbox, first thing we do is disable the crash dialog */
if (is_sandbox)
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
return is_sandbox;
}
static int bxfi_create_local_ctx(struct bxfi_map *map, LPTCH name, size_t sz)
{
HANDLE shm = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sz, name);
if (!shm || GetLastError() == ERROR_ALREADY_EXISTS)
return -EEXIST;
struct bxfi_context *ctx = MapViewOfFile(shm, FILE_MAP_ALL_ACCESS,
0, 0, sizeof (struct bxfi_context) + sz);
if (!ctx)
return -ENOMEM;
*map = (struct bxfi_map) { .ctx = ctx, .handle = shm };
memcpy(map->map_name, name, (_tcslen(name) + 1) * sizeof (TCHAR));
return 0;
}
int bxfi_init_sandbox_ctx(struct bxfi_map *map)
{
TCHAR *env = _tcsstr(GetCommandLine(), TEXT("BXFI_MAP="));
TCHAR *name = env + sizeof ("BXFI_MAP=") - 1;
HANDLE shm = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
if (!shm)
return -ENOENT;
struct bxfi_context *ctx = MapViewOfFile(shm, FILE_MAP_ALL_ACCESS,
0, 0, sizeof (struct bxfi_context));
errno = -ENOMEM;
if (!ctx)
goto error;
DWORD size = ctx->total_sz;
errno = -EINVAL;
if (!UnmapViewOfFile(ctx))
goto error;
ctx = MapViewOfFile(shm, FILE_MAP_ALL_ACCESS, 0, 0, size);
errno = -ENOMEM;
if (!ctx)
goto error;
*map = (struct bxfi_map) { .ctx = ctx, .handle = shm };
memcpy(map->map_name, name, (_tcslen(name) + 1) * sizeof (TCHAR));
return 0;
error:
if (shm)
CloseHandle(shm);
return -errno;
}
int bxfi_unmap_local_ctx(struct bxfi_map *map)
{
UnmapViewOfFile(map->ctx);
CloseHandle(map->handle);
return 0;
}
int bxfi_term_sandbox_ctx(struct bxfi_map *map)
{
HANDLE sync = map->ctx->sync;
int waitfordebugger = map->ctx->suspend;
int rc = bxfi_unmap_local_ctx(map);
SetEvent(sync);
if (waitfordebugger) {
while (!IsDebuggerPresent())
Sleep(100);
}
return rc;
}
struct callback_ctx {
HANDLE whandle;
bxf_callback *callback;
struct bxfi_sandbox *instance;
};
#ifndef STATUS_BAD_STACK
# define STATUS_BAD_STACK 0xC0000028L
#endif
/*
* NTSTATUS specification, from ntstatus.h:
*
* > Values are 32 bit values laid out as follows:
* >
* > 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
* > 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* > +---+-+-+-----------------------+-------------------------------+
* > |Sev|C|R| Facility | Code |
* > +---+-+-+-----------------------+-------------------------------+
* >
* > where
* >
* > Sev - is the severity code
* >
* > 00 - Success
* > 01 - Informational
* > 10 - Warning
* > 11 - Error
* >
* > C - is the Customer code flag
* >
* > R - is a reserved bit
* >
* > Facility - is the facility code
* >
* > Code - is the facility's status code
*
* We consider that all exit codes with error severity bits that cannot
* be directly translated to translate to SIGSYS.
*
*/
static void get_status(HANDLE handle, struct bxf_instance_s *instance)
{
DWORD exit_code;
GetExitCodeProcess(handle, &exit_code);
unsigned int sig = 0;
switch (exit_code) {
case STATUS_FLOAT_DENORMAL_OPERAND:
case STATUS_FLOAT_DIVIDE_BY_ZERO:
case STATUS_FLOAT_INEXACT_RESULT:
case STATUS_FLOAT_INVALID_OPERATION:
case STATUS_FLOAT_OVERFLOW:
case STATUS_FLOAT_STACK_CHECK:
case STATUS_FLOAT_UNDERFLOW:
case STATUS_INTEGER_DIVIDE_BY_ZERO:
case STATUS_INTEGER_OVERFLOW: sig = SIGFPE;
break;
case STATUS_ILLEGAL_INSTRUCTION:
case STATUS_PRIVILEGED_INSTRUCTION:
case STATUS_NONCONTINUABLE_EXCEPTION: sig = SIGILL;
break;
case STATUS_ACCESS_VIOLATION:
case STATUS_DATATYPE_MISALIGNMENT:
case STATUS_ARRAY_BOUNDS_EXCEEDED:
case STATUS_GUARD_PAGE_VIOLATION:
case STATUS_IN_PAGE_ERROR:
case STATUS_NO_MEMORY:
case STATUS_INVALID_DISPOSITION:
case STATUS_BAD_STACK:
case STATUS_STACK_OVERFLOW: sig = SIGSEGV;
break;
case STATUS_CONTROL_C_EXIT: sig = SIGINT;
break;
default: break;
}
if (!sig && exit_code & 0xC0000000)
sig = SIGABRT;
instance->status.signal = sig;
instance->status.exit = exit_code;
instance->status.alive = 0;
}
static void CALLBACK handle_child_terminated(PVOID lpParameter,
BOOLEAN TimerOrWaitFired)
{
(void) TimerOrWaitFired;
uint64_t mts_end = bxfi_timestamp_monotonic();
uint64_t ts_end = bxfi_timestamp();
struct callback_ctx *ctx = lpParameter;
struct bxfi_sandbox *instance = ctx->instance;
bxf_callback *callback = ctx->callback;
bxfi_cancel_timeout(instance);
get_status(instance->proc, &instance->props);
instance->props.time.end = ts_end;
instance->props.time.elapsed = mts_end - instance->start_monotonic;
HANDLE whandle = ctx->whandle;
free(lpParameter);
UnregisterWaitEx(whandle, NULL);
if (callback)
callback(&instance->props);
SetEvent(instance->waited);
}
struct bxfi_prepare_ctx {
HANDLE *handles;
uint8_t *inherited;
size_t size;
size_t capacity;
LPPROC_THREAD_ATTRIBUTE_LIST attr;
};
static void prepare_ctx_term(struct bxfi_prepare_ctx *ctx)
{
for (size_t i = 0; i < ctx->size; ++i) {
if (!ctx->inherited[i]) {
if (!SetHandleInformation(ctx->handles[i], HANDLE_FLAG_INHERIT, 0))
continue;
}
}
free(ctx->handles);
free(ctx->inherited);
if (ctx->attr)
free(ctx->attr);
ctx->capacity = 0;
}
static int do_inherit_handle(bxf_fhandle handle, void *user)
{
struct bxfi_prepare_ctx *ctx = user;
if (!ctx->handles) {
ctx->handles = malloc(32 * sizeof (HANDLE));
ctx->inherited = malloc(32);
ctx->capacity = 32;
}
/* Reserve a slot for the sync event handle */
if (ctx->size + 2 >= ctx->capacity) {
ctx->capacity *= 1.61;
ctx->handles = realloc(ctx->handles, ctx->capacity);
ctx->inherited = realloc(ctx->inherited, ctx->capacity);
}
ctx->handles[ctx->size++] = handle;
ctx->inherited[ctx->size - 1] = 1;
DWORD info;
if (!GetHandleInformation(handle, &info))
return -EINVAL;
if (info & HANDLE_FLAG_INHERIT)
return 0;
if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
return -EINVAL;
ctx->inherited[ctx->size - 1] = 0;
return 0;
}
static int prepare_context(bxf_context ictx, bxf_sandbox *sandbox,
HANDLE sync, STARTUPINFOEX *si,
struct bxfi_prepare_ctx *prep)
{
if (ictx) {
if (bxfi_context_prepare(ictx, do_inherit_handle, prep) < 0)
return 0;
}
if (!prep->handles) {
prep->handles = malloc(sizeof (HANDLE));
*prep->handles = sync;
prep->size = 1;
} else {
prep->handles[prep->size++] = sync;
}
if (!sandbox->inherit.files) {
SIZE_T attrsz = 0;
InitializeProcThreadAttributeList(NULL, 1, 0, &attrsz);
LPPROC_THREAD_ATTRIBUTE_LIST attr = malloc(attrsz);
if (!attr)
return 0;
BOOL ok = InitializeProcThreadAttributeList(attr, 1, 0, &attrsz);
if (!ok)
return 0;
si->lpAttributeList = attr;
ok = UpdateProcThreadAttribute(attr, 0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, prep->handles,
prep->size * sizeof (HANDLE), NULL, NULL);
prep->attr = attr;
if (!ok)
return 0;
}
return 1;
}
int bxfi_exec(bxf_instance **out, bxf_sandbox *sandbox,
int mantled, bxf_fn *fn, bxf_preexec *preexec, bxf_callback *callback,
void *user, bxf_dtor user_dtor)
{
int errnum = 0;
struct bxfi_sandbox *instance = NULL;
BOOL success = FALSE;
struct bxfi_prepare_ctx prep = {
.handles = NULL,
};
/* Process params and allocate relevant ressources */
struct bxfi_addr addr;
if (bxfi_normalize_fnaddr(fn, &addr) < 0)
return -EINVAL;
errnum = -ENOMEM;
instance = malloc(sizeof (*instance));
if (!instance)
goto error;
instance->mantled = mantled;
instance->user = user;
instance->user_dtor = user_dtor;
instance->waited = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!instance->waited)
goto error;
PROCESS_INFORMATION info;
STARTUPINFOEX si = { .StartupInfo.cb = sizeof (si) };
ZeroMemory(&info, sizeof (info));
SECURITY_ATTRIBUTES inherit_handle = {
.nLength = sizeof (SECURITY_ATTRIBUTES),
.bInheritHandle = TRUE
};
HANDLE sync = CreateEvent(&inherit_handle, FALSE, FALSE, NULL);
errnum = -EPROTO;
if (!sync)
goto error;
/* Process initialization */
bxf_context ictx = sandbox->inherit.context;
if (!prepare_context(ictx, sandbox, sync, &si, &prep))
goto error;
TCHAR filename[MAX_PATH];
GetModuleFileName(NULL, filename, MAX_PATH);
uint64_t ts_start = bxfi_timestamp();
uint64_t mts_start = bxfi_timestamp_monotonic();
TCHAR map_name[sizeof ("Local\\bxfi_") + 21];
_sntprintf(map_name, sizeof (map_name), TEXT("Local\\bxfi_%lu"), (unsigned long)GetCurrentProcessId());
TCHAR env_map[sizeof ("BXFI_MAP=") + sizeof (map_name) + 2];
memset(env_map, 0, sizeof (env_map));
_sntprintf(env_map, sizeof (env_map), "BXFI_MAP=%s", map_name);
if (sandbox->debug.debugger) {
TCHAR *dbg = NULL;
TCHAR *cmdline = NULL;
SIZE_T size;
switch (sandbox->debug.debugger) {
case BXF_DBG_WINDBG: {
dbg = TEXT("windbg");
TCHAR *fmt = TEXT("boxfort-worker -server tcp:port=%d %s %s");
size = _sctprintf(fmt, sandbox->debug.tcp, filename,
env_map);
cmdline = malloc(sizeof (TCHAR) * (size + 1));
_sntprintf(cmdline, size, fmt, sandbox->debug.tcp, filename,
env_map);
} break;
case BXF_DBG_GDB: {
dbg = TEXT("gdbserver");
TCHAR *fmt = TEXT("boxfort-worker :%d %s %s");
size = _sctprintf(fmt, sandbox->debug.tcp, filename,
env_map);
cmdline = malloc(sizeof (TCHAR) * size);
_sntprintf(cmdline, size, fmt, sandbox->debug.tcp, filename,
env_map);
} break;
case BXF_DBG_LLDB: {
dbg = TEXT("lldb-server");
TCHAR *fmt = TEXT("boxfort-worker gdbserver *:%d %s %s");
size = _sctprintf(fmt, sandbox->debug.tcp, filename,
env_map);
cmdline = malloc(sizeof (TCHAR) * size);
_sntprintf(cmdline, size, fmt, sandbox->debug.tcp, filename,
env_map);
} break;
default:
errnum = -EINVAL;
goto error;
}
/* _sntprinf does not null-terminate its output */
cmdline[size] = '\0';
DWORD pathsz = GetEnvironmentVariable(TEXT("PATH"), NULL, 0);
TCHAR *path = malloc(pathsz * sizeof (TCHAR));
TCHAR *dbg_full = NULL;
GetEnvironmentVariable(TEXT("PATH"), path, pathsz);
pathsz = SearchPath(path, dbg, TEXT(".exe"), 0, NULL, NULL);
if (!pathsz)
goto file_not_found;
dbg_full = malloc(pathsz * sizeof (TCHAR));
pathsz = SearchPath(path, dbg, TEXT(".exe"), pathsz, dbg_full, NULL);
if (!pathsz) {
file_not_found:
free(dbg_full);
free(path);
free(cmdline);
errnum = -ENOENT;
goto error;
}
success = CreateProcess(dbg_full, cmdline, NULL,
NULL, TRUE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT,
NULL, NULL, &si.StartupInfo, &info);
free(dbg_full);
free(path);
free(cmdline);
} else {
TCHAR *fmt = TEXT("boxfort-worker %s");
SIZE_T size = _sctprintf(fmt, filename, env_map);
TCHAR *cmdline = malloc(sizeof (TCHAR) * size);
_sntprintf(cmdline, size, fmt, env_map);
success = CreateProcess(filename, cmdline, NULL,
NULL, TRUE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT,
NULL, NULL, &si.StartupInfo, &info);
free(cmdline);
}
errnum = -EPROTO;
if (!success)
goto error;
if (si.lpAttributeList)
DeleteProcThreadAttributeList(si.lpAttributeList);
instance->props = (struct bxf_instance_s) {
.sandbox = sandbox,
.pid = info.dwProcessId,
.status.alive = 1,
.time.start = ts_start,
.user = instance->user,
};
instance->start_monotonic = mts_start;
if (sandbox->quotas.runtime > 0)
if (bxfi_push_timeout(instance, sandbox->quotas.runtime) < 0)
goto error;
if (sandbox->iquotas.runtime > 0)
if (bxfi_push_timeout(instance, sandbox->iquotas.runtime) < 0)
goto error;
if (preexec && preexec(&instance->props) < 0)
goto error;
if (prep.capacity)
prepare_ctx_term(&prep);
instance->proc = info.hProcess;
size_t len = strlen(addr.soname);
struct bxfi_map map;
if ((errnum = bxfi_create_local_ctx(&map, map_name, len + 1)) < 0)
goto error;
map.ctx->sync = sync;
map.ctx->suspend = sandbox->suspended;
map.ctx->fn = addr.addr;
map.ctx->seg = addr.seg;
if (ictx)
map.ctx->context.handle = bxfi_context_gethandle(ictx);
memcpy(map.ctx + 1, addr.soname, len + 1);
map.ctx->fn_soname_sz = len + 1;
errnum = -ECHILD;
if (ResumeThread(info.hThread) == (DWORD) -1)
goto error;
/* wait until the child has initialized itself */
HANDLE handles[] = { info.hProcess, sync };
DWORD wres = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (wres == WAIT_OBJECT_0)
goto error;
instance->mainthread = info.hThread;
CloseHandle(sync);
struct callback_ctx *wctx = malloc(sizeof (*wctx));
*wctx = (struct callback_ctx) {
.instance = instance,
.callback = callback,
};
RegisterWaitForSingleObject(
&wctx->whandle,
info.hProcess,
handle_child_terminated,
wctx,
INFINITE,
WT_EXECUTELONGFUNCTION | WT_EXECUTEONLYONCE);
bxfi_unmap_local_ctx(&map);
bxfi_addr_term(&addr);
if (sandbox->suspended)
instance->props.status.stopped = 1;
*out = &instance->props;
return 0;
error:
if (prep.capacity)
prepare_ctx_term(&prep);
if (si.lpAttributeList)
DeleteProcThreadAttributeList(si.lpAttributeList);
if (sync)
CloseHandle(sync);
if (success) {
CloseHandle(info.hThread);
TerminateProcess(info.hProcess, 3);
CloseHandle(info.hProcess);
}
bxfi_addr_term(&addr);
return errnum;
}
int bxf_term(bxf_instance *instance)
{
struct bxfi_sandbox *sb = bxfi_cont(instance, struct bxfi_sandbox, props);
if (sb->user && sb->user_dtor)
sb->user_dtor(instance, sb->user);
if (sb->mantled)
free((void *) instance->sandbox);
CloseHandle(sb->proc);
CloseHandle(sb->mainthread);
CloseHandle(sb->waited);
free(sb);
return 0;
}
int bxf_wait(bxf_instance *instance, double timeout)
{
DWORD dwtimeout;
if (timeout == BXF_FOREVER || !isfinite(timeout))
dwtimeout = INFINITE;
else
dwtimeout = timeout * 1000;
struct bxfi_sandbox *sb = bxfi_cont(instance, struct bxfi_sandbox, props);
if (WaitForSingleObject(sb->waited, dwtimeout) != WAIT_OBJECT_0)
return -ECHILD;
return 0;
}
void bxf_suspend(bxf_instance *instance)
{
struct bxfi_sandbox *sb = bxfi_cont(instance, struct bxfi_sandbox, props);
SuspendThread(sb->mainthread);
}
void bxf_resume(bxf_instance *instance)
{
struct bxfi_sandbox *sb = bxfi_cont(instance, struct bxfi_sandbox, props);
ResumeThread(sb->mainthread);
}
BoxFort-master/src/sandbox-windows.h 0000644 0001750 0001750 00000003774 13603450524 016475 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 SANDBOX_WINDOWS_H_
#define SANDBOX_WINDOWS_H_
#include
#include "context.h"
struct bxfi_context {
size_t total_sz;
const void *fn;
size_t seg;
struct bxfi_ctx_arena context;
size_t fn_soname_sz;
HANDLE sync;
int suspend;
};
struct bxfi_map {
struct bxfi_context *ctx;
HANDLE handle;
TCHAR map_name[sizeof ("bxfi_") + 21];
};
struct bxfi_sandbox {
struct bxf_instance_s props;
HANDLE proc;
HANDLE mainthread;
/* A sandbox is said to be mantled if there is an unique instance
managing its memory. */
int mantled;
/* The monotonic timestamp representing the start of the sandbox instance.
* Only used to calculate more accurate run times */
uint64_t start_monotonic;
void *user;
bxf_dtor *user_dtor;
HANDLE waited;
};
#endif /* !SANDBOX_WINDOWS_H_ */
BoxFort-master/src/sandbox.c 0000644 0001750 0001750 00000006065 13603450524 014774 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include "addr.h"
#include "context.h"
#include "exe.h"
#include "sandbox.h"
static int bxfi_main(void)
{
struct bxfi_map local_ctx;
if (bxfi_init_sandbox_ctx(&local_ctx) < 0)
abort();
struct bxfi_addr addr = {
.soname = (char *) (local_ctx.ctx + 1),
.addr = local_ctx.ctx->fn,
.seg = local_ctx.ctx->seg,
};
bxf_fn *fn = bxfi_denormalize_fnaddr(&addr);
if (!fn)
abort();
if (bxfi_context_inherit(&local_ctx.ctx->context) < 0)
abort();
if (bxfi_term_sandbox_ctx(&local_ctx) < 0)
abort();
return fn();
}
BXFI_INITIALIZER(patch_main)
static void patch_main(void)
{
if (!bxfi_check_sandbox_ctx())
return;
if (bxfi_exe_patch_main((bxfi_exe_fn *) bxfi_main) < 0)
abort();
}
int bxf_spawn_struct(bxf_instance **out, bxf_spawn_params params)
{
if (!params->fn)
return -EINVAL;
struct bxf_sandbox_s *sandbox = calloc(1, sizeof (*sandbox));
if (!sandbox)
return -ENOMEM;
/* 2nd parameter must be the start of the BXFI_SANDBOX_FIELDS in the
parameter structure */
memcpy(sandbox, ¶ms->callback + 1, sizeof (*sandbox));
int rc;
if ((rc = bxfi_exec(out, sandbox, 1, params->fn,
params->preexec, params->callback,
params->user, params->user_dtor)))
free(sandbox);
return rc;
}
int bxf_run_struct(bxf_spawn_params params)
{
bxf_instance *box;
int rc;
if ((rc = bxf_spawn_struct(&box, params)))
return rc;
rc = bxf_wait(box, BXF_FOREVER);
bxf_term(box);
return rc;
}
int bxf_start_struct(bxf_instance **out, bxf_sandbox *sandbox,
bxf_start_params params)
{
return bxfi_exec(out, sandbox, 0, params->fn,
params->preexec, params->callback,
params->user, params->user_dtor);
}
BoxFort-master/src/sandbox.h 0000644 0001750 0001750 00000004453 13603450524 015000 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 SANDBOX_H_
#define SANDBOX_H_
#include "boxfort.h"
#include "config.h"
/* *INDENT-OFF* - formatters try to add spaces here */
#include BXFI_STR(sandbox-BXF_OS_FAMILY.h)
/* *INDENT-ON* */
int bxfi_exec(bxf_instance **out, bxf_sandbox *sandbox,
int mantled, bxf_fn *fn, bxf_preexec *preexec, bxf_callback *callback,
void *user, bxf_dtor user_dtor);
int bxfi_check_sandbox_ctx(void);
int bxfi_init_sandbox_ctx(struct bxfi_map *map);
int bxfi_term_sandbox_ctx(struct bxfi_map *map);
#if defined (_MSC_VER)
# define BXFI_INITIALIZER_(Fn, Prefix) \
static void Fn(void); \
__pragma(section(".CRT$XCU", read)) \
__declspec(allocate(".CRT$XCU")) void(*Fn ## _init)(void) = Fn; \
__pragma(comment(linker, "/include:" Prefix #Fn "_init"))
# ifdef _WIN64
# define BXFI_INITIALIZER(Fn) BXFI_INITIALIZER_(Fn, "")
# else
# define BXFI_INITIALIZER(Fn) BXFI_INITIALIZER_(Fn, "_")
# endif
#elif defined (__GNUC__)
# define BXFI_INITIALIZER(...) __attribute__((constructor))
#else
# error Compiler not supported
#endif
#endif /* !SANDBOX_H_ */
BoxFort-master/src/timeout-posix.c 0000644 0001750 0001750 00000014231 13603450524 016156 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include
#include
#include
#include
#include
#include
#include "config.h"
#include "sandbox.h"
struct bxfi_timeout_request {
struct timespec timeout;
pid_t pid;
struct bxfi_sandbox *sb;
int cancelled;
struct bxfi_timeout_request *next;
};
static struct {
struct bxfi_timeout_request *volatile requests;
struct bxfi_timeout_request *volatile cancelled;
pthread_t thread;
int thread_active;
pthread_mutex_t sync;
pthread_cond_t cond;
pthread_cond_t termcond;
} self = {
.sync = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.termcond = PTHREAD_COND_INITIALIZER,
};
static int timespec_cmp(struct timespec *a, struct timespec *b)
{
if (a->tv_sec < b->tv_sec)
return -1;
if (a->tv_sec > b->tv_sec)
return 1;
if (a->tv_nsec < b->tv_nsec)
return -1;
if (a->tv_nsec > b->tv_nsec)
return 1;
return 0;
}
static void to_timespec(double timeout, struct timespec *timeo)
{
static const uint64_t nanosecs = 1000000000;
uint64_t to_ns = (timeout - (uint64_t) timeout) * nanosecs;
uint64_t to_s = timeout;
#if defined (HAVE_CLOCK_GETTIME)
clock_gettime(CLOCK_REALTIME, timeo);
uint64_t new_nsec = (timeo->tv_nsec + to_ns) % nanosecs;
timeo->tv_sec += to_s + (timeo->tv_nsec + to_ns) / nanosecs;
timeo->tv_nsec = new_nsec;
#elif defined (HAVE_GETTIMEOFDAY)
struct timeval tv;
gettimeofday(&tv, NULL);
*timeo = (struct timespec) {
.tv_sec = tv.tv_sec + to_s + (tv.tv_usec * 1000 + to_ns) / nanosecs,
.tv_nsec = (tv.tv_usec * 1000 + to_ns) % nanosecs,
};
#else
# error No way to get a viable timespec.
#endif
}
static void *timeout_killer_fn(void *nil)
{
pthread_mutex_lock(&self.sync);
while (!self.requests)
pthread_cond_wait(&self.cond, &self.sync);
struct bxfi_timeout_request *req;
for (;;) {
while (self.cancelled) {
req = self.cancelled;
self.cancelled = req->next;
free(req);
}
req = self.requests;
if (!req)
goto end;
int rc = pthread_cond_timedwait(&self.cond, &self.sync, &req->timeout);
if (!rc || req->cancelled)
continue;
assert(rc == ETIMEDOUT);
kill(req->pid, SIGPROF);
pthread_mutex_lock(&req->sb->sync);
req->sb->props.status.timed_out = 1;
pthread_mutex_unlock(&req->sb->sync);
self.requests = req->next;
free(req);
}
end:
pthread_cond_broadcast(&self.termcond);
pthread_mutex_unlock(&self.sync);
return nil;
}
void bxfi_reset_timeout_killer(void)
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
memcpy(&self.sync, &mutex, sizeof (mutex));
memcpy(&self.cond, &cond, sizeof (cond));
memcpy(&self.termcond, &cond, sizeof (cond));
if (self.requests)
pthread_join(self.thread, NULL);
}
int bxfi_push_timeout(struct bxfi_sandbox *instance, double timeout)
{
int rc;
struct bxfi_timeout_request *req = calloc(1, sizeof (*req));
if (!req)
return -ENOMEM;
to_timespec(timeout, &req->timeout);
req->sb = instance;
req->pid = instance->props.pid;
pthread_mutex_lock(&self.sync);
if (!self.requests) {
if (self.thread_active)
pthread_join(self.thread, NULL);
self.thread_active = 1;
rc = -pthread_create(&self.thread, NULL, timeout_killer_fn, NULL);
if (rc)
goto error;
}
struct bxfi_timeout_request *volatile *nptr = &self.requests;
for (struct bxfi_timeout_request *r = self.requests; r; r = r->next) {
if (timespec_cmp(&r->timeout, &req->timeout) > 0)
break;
nptr = &r->next;
}
*nptr = req;
pthread_cond_broadcast(&self.cond);
pthread_cond_broadcast(&self.termcond);
pthread_mutex_unlock(&self.sync);
return 0;
error:
pthread_mutex_unlock(&self.sync);
free(req);
return rc;
}
void bxfi_cancel_timeout(struct bxfi_sandbox *instance)
{
pthread_mutex_lock(&self.sync);
int cancelled = 0;
struct bxfi_timeout_request *volatile *nptr = &self.requests;
for (struct bxfi_timeout_request *r = self.requests; r; r = r->next) {
if (r->pid == (pid_t) instance->props.pid) {
*nptr = r->next;
r->next = self.cancelled;
self.cancelled = r;
r->cancelled = cancelled = 1;
}
nptr = &r->next;
}
if (cancelled) {
pthread_cond_broadcast(&self.cond);
if (!self.requests) {
while (self.cancelled && !self.requests)
pthread_cond_wait(&self.termcond, &self.sync);
if (self.requests)
goto end;
if (self.thread_active) {
pthread_join(self.thread, NULL);
self.thread_active = 0;
}
}
}
end:
pthread_mutex_unlock(&self.sync);
}
BoxFort-master/src/timeout-windows.c 0000644 0001750 0001750 00000003737 13603450524 016517 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include
#include "config.h"
#include "sandbox.h"
#define BXFI_TIMEOUT_STATUS 0xEFFFFFFF
void CALLBACK timeout_killer_fn(void *lpParameter, BOOLEAN TimerOrWaitFired)
{
(void) TimerOrWaitFired;
struct bxfi_sandbox *sb = lpParameter;
if (WaitForSingleObject(sb->proc, 0) == WAIT_OBJECT_0)
return;
TerminateProcess(sb->proc, BXFI_TIMEOUT_STATUS);
sb->props.status.timed_out = 1;
}
int bxfi_push_timeout(struct bxfi_sandbox_s *instance, double timeout)
{
HANDLE timer;
BOOL ok = CreateTimerQueueTimer(&timer, NULL, timeout_killer_fn, instance,
timeout * 1000, 0, WT_EXECUTEDEFAULT);
if (!ok)
return -1;
return 0;
}
void bxfi_cancel_timeout(struct bxfi_sandbox_s *instance)
{
(void) instance;
}
void bxfi_reset_timeout_killer(void)
{
}
BoxFort-master/src/timeout.h 0000644 0001750 0001750 00000002575 13603450524 015033 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 TIMEOUT_H_
#define TIMEOUT_H_
int bxfi_push_timeout(struct bxfi_sandbox *instance, double timeout);
void bxfi_cancel_timeout(struct bxfi_sandbox *instance);
void bxfi_reset_timeout_killer(void);
#endif /* !TIMEOUT_H_ */
BoxFort-master/src/timestamp.c 0000644 0001750 0001750 00000006567 13603450524 015350 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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
#include "config.h"
#include "timestamp.h"
#define KILO 1000ull
#define MEGA (KILO * 1000ull)
#define GIGA (MEGA * 1000ull)
#if defined (HAVE_GETTIMEOFDAY)
# include
#endif
#if defined (HAVE_CLOCK_GETTIME)
# include
#endif
#if defined (__APPLE__)
# include
# include
# include
#endif
#if defined (_WIN32) || defined (__CYGWIN__)
# include
#endif
#if defined (HAVE_CLOCK_GETTIME)
# if defined (HAVE_CLOCK_MONOTONIC_RAW)
# define CLOCK CLOCK_MONOTONIC_RAW
# else
# define CLOCK CLOCK_MONOTONIC
# endif
#endif
uint64_t bxfi_timestamp(void)
{
#if defined (HAVE_CLOCK_GETTIME)
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * GIGA + now.tv_nsec;
#elif defined (HAVE_GETTIMEOFDAY)
struct timeval now;
gettimeofday(&now, NULL);
return now.tv_sec * GIGA + now.tv_usec * KILO;
#elif defined (_WIN32) || defined (__CYGWIN__)
FILETIME ftime;
SYSTEMTIME systime;
GetSystemTime(&systime);
SystemTimeToFileTime(&systime, &ftime);
ULARGE_INTEGER ts = {
.LowPart = ftime.dwLowDateTime,
.HighPart = ftime.dwHighDateTime,
};
static const uint64_t epoch = 116444736000000000ull;
return (ts.QuadPart - epoch) / (10 * MEGA) + systime.wMilliseconds * KILO;
#else
errno = ENOTSUP;
return (uint64_t) -1;
#endif
}
uint64_t bxfi_timestamp_monotonic(void)
{
#if defined (HAVE_CLOCK_GETTIME)
struct timespec now;
clock_gettime(CLOCK, &now);
return now.tv_sec * GIGA + now.tv_nsec;
#elif defined (__APPLE__)
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
int res = clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
return mts.tv_sec * GIGA + mts.tv_nsec;
#elif defined (_WIN32) || defined (__CYGWIN__)
LARGE_INTEGER freq, count;
if (!QueryPerformanceFrequency(&freq)
|| !QueryPerformanceCounter(&count))
return -1;
uint64_t sec = count.QuadPart / freq.QuadPart;
uint64_t nano = ((count.QuadPart * GIGA) / freq.QuadPart) % GIGA;
return sec * GIGA + nano;
#else
errno = ENOTSUP;
return (uint64_t) -1;
#endif
}
BoxFort-master/src/timestamp.h 0000644 0001750 0001750 00000002473 13603450524 015345 0 ustar sasa sasa /*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu
*
* 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 TIMESTAMP_H_
#define TIMESTAMP_H_
#include
uint64_t bxfi_timestamp(void);
uint64_t bxfi_timestamp_monotonic(void);
#endif /* !TIMESTAMP_H_ */
BoxFort-master/test/ 0002755 0001750 0001750 00000000000 13603450524 013355 5 ustar sasa sasa BoxFort-master/test/cram/ 0002755 0001750 0001750 00000000000 13603450524 014277 5 ustar sasa sasa BoxFort-master/test/cram/core.t 0000644 0001750 0001750 00000000415 13603450524 015412 0 ustar sasa sasa Testing basic samples
$ nested.c.bin
I am a worker!
I am a nested worker!
Testing whether the callbacks are working
$ callback.c.bin
Child exited with code 5
Testing if the context sample behave as expected
$ context.c.bin
my_int = 42
my_long = 24
BoxFort-master/test/meson.build 0000644 0001750 0001750 00000000745 13603450524 015523 0 ustar sasa sasa sh = find_program('sh', required: false)
cram = find_program('cram', required: false)
if sh.found() and cram.found()
env = environment()
env.prepend('PATH',
join_paths(meson.current_build_dir(), '..', 'sample'),
join_paths(meson.current_build_dir(), '..', 'sample'))
env.set('LC_ALL', 'en_US.utf8')
env.set('MSYS2_ARG_CONV_EXCL', '--filter=')
env.set('TERM', 'dumb')
test('cram tests', cram,
args: [join_paths(meson.current_source_dir(), 'cram')],
env: env)
endif