Skip to content

Commit

Permalink
Solve issues with MSVC, improve macros for sandbox_plugin.
Browse files Browse the repository at this point in the history
  • Loading branch information
viferga committed Oct 5, 2023
1 parent e002bc1 commit 88a83e3
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 137 deletions.
6 changes: 3 additions & 3 deletions source/cli/plugins/cli_core_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,18 @@ target_link_libraries(${target}
#

# Copy metacall.json
add_custom_target(${target}-create-plugin-dir ALL
add_custom_target(${target}_config ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json
)

set_target_properties(${target}-create-plugin-dir
set_target_properties(${target}_config
PROPERTIES
FOLDER "${IDE_FOLDER}"
)

add_dependencies(${target}
${target}-create-plugin-dir
${target}_config
plugin_extension
)
59 changes: 0 additions & 59 deletions source/plugin/include/plugin/plugin_interface.h

This file was deleted.

104 changes: 104 additions & 0 deletions source/plugin/include/plugin/plugin_interface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Plugin Library by Parra Studios
* A library for plugins at run-time into a process.
*
* Copyright (C) 2016 - 2022 Vicente Eduardo Ferrer Garcia <vic798@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#ifndef PLUGIN_INTERFACE_HPP
#define PLUGIN_INTERFACE_HPP 1

/* Private interface for using it inside any loader, extension or plugin for registering functions */
/* TODO: Move this to source/metacall/include/metacall/private? */

#include <preprocessor/preprocessor.h>

#include <log/log.h>

#include <reflect/reflect.h>

#include <metacall/metacall.h>

#include <sstream>
#include <string>

#define EXTENSION_FUNCTION_IMPL_VOID(ret, name) \
do \
{ \
if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, 0, NULL) != 0) \
{ \
log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \
return 1; \
} \
} while (0)

#define EXTENSION_FUNCTION_IMPL(ret, name, ...) \
do \
{ \
enum metacall_value_id arg_types[] = { __VA_ARGS__ }; \
if (metacall_register_loaderv(loader, context, PREPROCESSOR_STRINGIFY(name), name, ret, PREPROCESSOR_ARGS_COUNT(__VA_ARGS__), arg_types) != 0) \
{ \
log_write("metacall", LOG_LEVEL_ERROR, "Failed to register function: " PREPROCESSOR_STRINGIFY(name)); \
return 1; \
} \
} while (0)

#define EXTENSION_FUNCTION(ret, name, ...) \
PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \
EXTENSION_FUNCTION_IMPL_VOID(ret, name), \
EXTENSION_FUNCTION_IMPL(ret, name, __VA_ARGS__))

#define EXTENSION_FUNCTION_THROW(error) \
do \
{ \
log_write("metacall", LOG_LEVEL_ERROR, error); \
exception ex = exception_create_const(error, "PluginException", 0, ""); \
throwable th = throwable_create(value_create_exception(ex)); \
return value_create_throwable(th); \
} while (0)

#define EXTENSION_FUNCTION_CHECK_ITERATOR(value, iterator, error) \
if (metacall_value_id(args[iterator]) != value) \
{ \
std::stringstream ss; \
ss << error ". The parameter number " PREPROCESSOR_STRINGIFY(PREPROCESSOR_ARGS_COUNT(iterator)) " requires a value of type " metacall_value_id_name(value) ", received: " << metacall_value_type_name(args[iterator]); \
std::string error_msg = ss.str(); \
EXTENSION_FUNCTION_THROW(error_msg.c_str()); \
}

/* TODO: */
#define PREPROCESSOR_FOR(macro, context, ...)

#define EXTENSION_FUNCTION_CHECK(error, ...) \
do \
{ \
(void)data; /* TODO: Do something with data */ \
/* Disable warning on args when no args */ \
PREPROCESSOR_IF(PREPROCESSOR_ARGS_EMPTY(__VA_ARGS__), \
(void)args; \
, \
PREPROCESSOR_EMPTY_SYMBOL()) \
if (argc != PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) \
{ \
std::stringstream ss; \
ss << error ". The required number of argumens is " PREPROCESSOR_STRINGIFY(PREPROCESSOR_ARGS_COUNT(__VA_ARGS__)) ", received: " << argc; \
std::string error_msg = ss.str(); \
EXTENSION_FUNCTION_THROW(error_msg.c_str()); \
} \
PREPROCESSOR_FOR(EXTENSION_FUNCTION_CHECK_ITERATOR, error, __VA_ARGS__) \
} while (0)

#endif /* PLUGIN_INTERFACE_HPP */
6 changes: 3 additions & 3 deletions source/plugins/backtrace_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,18 @@ target_link_libraries(${target}
#

# Copy metacall.json
add_custom_target(${target}-create-plugin-dir ALL
add_custom_target(${target}_config ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json
)

set_target_properties(${target}-create-plugin-dir
set_target_properties(${target}_config
PROPERTIES
FOLDER "${IDE_FOLDER}"
)

add_dependencies(${target}
${target}-create-plugin-dir
${target}_config
plugin_extension
)
6 changes: 3 additions & 3 deletions source/plugins/sandbox_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,18 @@ target_link_libraries(${target}
#

# Copy metacall.json
add_custom_target(${target}-create-plugin-dir ALL
add_custom_target(${target}_config ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json
)

set_target_properties(${target}-create-plugin-dir
set_target_properties(${target}_config
PROPERTIES
FOLDER "${IDE_FOLDER}"
)

add_dependencies(${target}
${target}-create-plugin-dir
${target}_config
plugin_extension
)
86 changes: 22 additions & 64 deletions source/plugins/sandbox_plugin/source/sandbox_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,113 +20,71 @@

#include <sandbox_plugin/sandbox_plugin.h>

#include <plugin/plugin_interface.h>
#include <plugin/plugin_interface.hpp>

#include <seccomp.h>

/* TODO: Use SCMP_ACT_KILL_PROCESS for catching the signal and showing the stack trace? */
#define SANDBOX_DEFAULT_ACTION SCMP_ACT_ALLOW // SCMP_ACT_KILL
/* TODO: Use SCMP_ACT_KILL_PROCESS instead of SCMP_ACT_KILL for catching the signal and showing the stack trace? */
/* TODO: We can disable bool (true/false) for string ("allow"/"disable") */
#define SANDBOX_ACTION(value) \
metacall_value_to_bool(value) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW

/* Error messages */
#define SANDBOX_INITIALIZE_ERROR "Sandbox plugin failed to initialize a context"
#define SANDBOX_UNAME_ERROR "Sandbox plugin failed to set uname syscall permissions"
#define SANDBOX_DESTROY_ERROR "Sandbox plugin failed to destroy a context"

void *sandbox_initialize(size_t argc, void *args[], void *data)
{
scmp_filter_ctx ctx;

(void)argc;
(void)args;
(void)data;
/* Validate function parameters */
EXTENSION_FUNCTION_CHECK(SANDBOX_INITIALIZE_ERROR, METACALL_BOOL);

/* Initialize the scmp context */
ctx = seccomp_init(SANDBOX_DEFAULT_ACTION);
/* Initialize the seccomp context */
ctx = seccomp_init(SANDBOX_ACTION(args[0]));

if (ctx == NULL)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to initialize a context.");
/* Throw exception if seccomp initialization failed */
EXTENSION_FUNCTION_THROW(SANDBOX_INITIALIZE_ERROR);
}

return metacall_value_create_ptr(ctx);
}

/*int sandbox_uname(void *ctx, int allow)
{
seccomp_rule_add(ctx, allow == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW, SCMP_SYS(uname), 0);
seccomp_load(ctx);
return 0;
}*/

void *sandbox_uname(size_t argc, void *args[], void *data)
{
scmp_filter_ctx ctx;

(void)data;

if (argc != 2)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. The required number of argumens is one, received: %" PRIuS, argc);
goto error_args;
}

if (metacall_value_id(args[0]) != METACALL_PTR)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. "
"The first parameter requires a pointer to the context, received: %s",
metacall_value_type_name(args[0]));
goto error_args;
}

if (metacall_value_id(args[1]) != METACALL_BOOL)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to set uname syscall permissions. "
"The second parameter requires a boolean indicating if it is allowed or not, received: %s",
metacall_value_type_name(args[1]));
goto error_args;
}
/* Validate function parameters */
EXTENSION_FUNCTION_CHECK(SANDBOX_UNAME_ERROR, METACALL_PTR, METACALL_BOOL);

ctx = metacall_value_to_ptr(args[0]);

seccomp_rule_add(ctx, metacall_value_to_bool(args[1]) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW, SCMP_SYS(uname), 0);
seccomp_rule_add(ctx, SANDBOX_ACTION(args[1]), SCMP_SYS(uname), 0);
seccomp_load(ctx);

return metacall_value_create_int(0);

error_args:
return metacall_value_create_int(1);
}

void *sandbox_destroy(size_t argc, void *args[], void *data)
{
scmp_filter_ctx ctx;

(void)data;

if (argc != 1)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. The required number of argumens is one, received: %" PRIuS, argc);
goto error_args;
}

if (metacall_value_id(args[0]) != METACALL_PTR)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. "
"The first parameter requires a pointer to the context, received: %s",
metacall_value_type_name(args[0]));
goto error_args;
}
/* Validate function parameters */
EXTENSION_FUNCTION_CHECK(SANDBOX_DESTROY_ERROR, METACALL_PTR);

ctx = metacall_value_to_ptr(args[0]);

if (ctx == NULL)
{
log_write("metacall", LOG_LEVEL_ERROR, "Sandbox plugin failed to destroy a context. "
"The first parameter requires a non null pointer");
goto error_args;
EXTENSION_FUNCTION_THROW(SANDBOX_DESTROY_ERROR ", the first parameter requires a non null pointer");
}

seccomp_release(ctx);

return metacall_value_create_int(0);

error_args:
return metacall_value_create_int(1);
}

#if 0 /* TODO: Fork safety */
Expand Down
2 changes: 1 addition & 1 deletion source/preprocessor/include/preprocessor/preprocessor_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extern "C" {

/* -- Macros -- */

#if defined(__GNUC__) || defined(__clang__)
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
#define PREPROCESSOR_IIF_IMPL_EXPAND_ARGS(...) __VA_ARGS__
#define PREPROCESSOR_IIF_IMPL_EXPAND(expr) expr
#define PREPROCESSOR_IIF_IMPL_EXPAND_REMOVE_PARENTHESIS(expr) PREPROCESSOR_IIF_IMPL_EXPAND(PREPROCESSOR_IIF_IMPL_EXPAND_ARGS expr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ extern "C" {
/* Stringify a symbol or return empty string if the expression expands to nothing */
#if defined(_MSC_VER) && !defined(__clang__)
#define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(...) #__VA_ARGS__
#define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) \
PREPROCESSOR_IF(PREPROCESSOR_ARGS_NOT_EMPTY(__VA_ARGS__), \
PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(__VA_ARGS__), \
#define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) \
PREPROCESSOR_IF(PREPROCESSOR_ARGS_NOT_EMPTY(__VA_ARGS__), \
PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL_II(__VA_ARGS__), \
"")
#else
#define PREPROCESSOR_STRINGIFY_OR_EMPTY_IMPL(...) #__VA_ARGS__
Expand Down
2 changes: 1 addition & 1 deletion source/tests/metacall_sandbox_plugin_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if(NOT PROJECT_OS_FAMILY STREQUAL unix)
return()
endif()

# Thread Sanitizer deadlocks with ASSERT_EXIT
# Thread Sanitizer deadlocks with ASSERT_EXIT (TODO: Review this when fork safety is implemented in sandbox_plugin)
if(OPTION_BUILD_THREAD_SANITIZER)
return()
endif()
Expand Down

0 comments on commit 88a83e3

Please sign in to comment.