Created
March 4, 2023 21:43
-
-
Save vinipsmaker/3ddd430b74e05fa9381de13e7553bcb3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright (c) 2021, 2022, 2023 Vinícius dos Santos Oliveira | |
Distributed under the Boost Software License, Version 1.0. (See accompanying | |
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ | |
#include <csignal> | |
#include <boost/preprocessor/control/iif.hpp> | |
#include <boost/vmd/is_number.hpp> | |
#include <boost/vmd/empty.hpp> | |
#define LUA_REGISTRYINDEX (-10000) | |
struct lua_State; | |
typedef long lua_Integer; | |
typedef int (*lua_CFunction) (lua_State *L); | |
struct vm_context | |
{ | |
bool is_master(); | |
}; | |
void lua_newtable (lua_State *L); | |
void lua_pushliteral (lua_State *L, const char *s); | |
void lua_pushlightuserdata (lua_State *L, void *p); | |
void lua_pushinteger (lua_State *L, lua_Integer n); | |
void lua_pushcfunction (lua_State *L, lua_CFunction f); | |
void lua_rawset (lua_State *L, int index); | |
lua_Integer luaL_checkinteger(lua_State*, int); | |
int luaL_error (lua_State *L, const char *fmt, ...); | |
vm_context& get_vm_context(lua_State*); | |
namespace emilua { | |
static char system_signal_key; | |
static int system_signal_raise(lua_State* L) | |
{ | |
int signal_number = luaL_checkinteger(L, 1); | |
#define EMILUA_DETAIL_IS_SIG_X_OR(SIG) signal_number == SIG || | |
#define EMILUA_IS_SIG_X_OR(SIG) BOOST_PP_IIF( \ | |
BOOST_VMD_IS_NUMBER(SIG), EMILUA_DETAIL_IS_SIG_X_OR, BOOST_VMD_EMPTY \ | |
)(SIG) | |
#define EMILUA_DETAIL_IS_NOT_SIG_X_AND(SIG) signal_number != SIG && | |
#define EMILUA_IS_NOT_SIG_X_AND(SIG) BOOST_PP_IIF( \ | |
BOOST_VMD_IS_NUMBER(SIG), \ | |
EMILUA_DETAIL_IS_NOT_SIG_X_AND, BOOST_VMD_EMPTY \ | |
)(SIG) | |
vm_context& vm_ctx = get_vm_context(L); | |
if (!vm_ctx.is_master()) { | |
// SIGKILL and SIGSTOP are the only signals that cannot be caught, | |
// blocked, or ignored. If we allowed any child VM to raise these | |
// signals, then the protection to only allow the main VM to force-exit | |
// the process would be moot. | |
if ( | |
EMILUA_IS_SIG_X_OR(SIGKILL) | |
EMILUA_IS_SIG_X_OR(SIGSTOP) | |
false | |
) { | |
return luaL_error(L, "EPERM"); | |
} | |
// Unless the main VM has a handler installed (the check doesn't need to | |
// be race-free... that's not a problem) for the process-terminating | |
// signal, forbid slave VMs from raising it. | |
if ( | |
// Default action is to continue the process (whatever lol) | |
EMILUA_IS_NOT_SIG_X_AND(SIGCONT) | |
// Default action is to ignore the signal | |
EMILUA_IS_NOT_SIG_X_AND(SIGCHLD) | |
EMILUA_IS_NOT_SIG_X_AND(SIGURG) | |
EMILUA_IS_NOT_SIG_X_AND(SIGWINCH) | |
true | |
) { | |
// TODO: a Windows implementation that checks for SIG_DFL | |
return luaL_error(L, "EPERM"); | |
} | |
} | |
#undef EMILUA_IS_NOT_SIG_X_AND | |
#undef EMILUA_DETAIL_IS_NOT_SIG_X_AND | |
#undef EMILUA_IS_SIG_X_OR | |
#undef EMILUA_DETAIL_IS_SIG_X_OR | |
int ret = std::raise(signal_number); | |
if (ret != 0) { | |
return luaL_error(L, "raise error"); | |
} | |
return 0; | |
} | |
void init_system(lua_State* L) | |
{ | |
lua_pushlightuserdata(L, &system_signal_key); | |
{ | |
lua_newtable(L); | |
lua_pushliteral(L, "raise"); | |
lua_pushcfunction(L, system_signal_raise); | |
lua_rawset(L, -3); | |
#define EMILUA_DEF_SIGNAL(KEY, VALUE) do { \ | |
lua_pushliteral(L, KEY); \ | |
lua_pushinteger(L, VALUE); \ | |
lua_rawset(L, -3); \ | |
} while(0) | |
#define EMILUA_DEF_SIGNAL2(SIG) EMILUA_DEF_SIGNAL(#SIG, SIG) | |
// <signal.h> | |
EMILUA_DEF_SIGNAL2(SIGABRT); | |
EMILUA_DEF_SIGNAL2(SIGFPE); | |
EMILUA_DEF_SIGNAL2(SIGILL); | |
EMILUA_DEF_SIGNAL2(SIGINT); | |
EMILUA_DEF_SIGNAL2(SIGSEGV); | |
EMILUA_DEF_SIGNAL2(SIGTERM); | |
#define EMILUA_DEF_SIGNAL3(SIG) BOOST_PP_IIF( \ | |
BOOST_VMD_IS_NUMBER(SIG), EMILUA_DEF_SIGNAL, BOOST_VMD_EMPTY \ | |
)(#SIG, SIG) | |
// Unix | |
EMILUA_DEF_SIGNAL3(SIGALRM); | |
EMILUA_DEF_SIGNAL3(SIGBUS); | |
EMILUA_DEF_SIGNAL3(SIGCHLD); | |
EMILUA_DEF_SIGNAL3(SIGCONT); | |
EMILUA_DEF_SIGNAL3(SIGHUP); | |
EMILUA_DEF_SIGNAL3(SIGIO); | |
EMILUA_DEF_SIGNAL3(SIGKILL); | |
EMILUA_DEF_SIGNAL3(SIGPIPE); | |
EMILUA_DEF_SIGNAL3(SIGPROF); | |
EMILUA_DEF_SIGNAL3(SIGQUIT); | |
EMILUA_DEF_SIGNAL3(SIGSTOP); | |
EMILUA_DEF_SIGNAL3(SIGSYS); | |
EMILUA_DEF_SIGNAL3(SIGTRAP); | |
EMILUA_DEF_SIGNAL3(SIGTSTP); | |
EMILUA_DEF_SIGNAL3(SIGTTIN); | |
EMILUA_DEF_SIGNAL3(SIGTTOU); | |
EMILUA_DEF_SIGNAL3(SIGURG); | |
EMILUA_DEF_SIGNAL3(SIGUSR1); | |
EMILUA_DEF_SIGNAL3(SIGUSR2); | |
EMILUA_DEF_SIGNAL3(SIGVTALRM); | |
EMILUA_DEF_SIGNAL3(SIGWINCH); | |
EMILUA_DEF_SIGNAL3(SIGXCPU); | |
EMILUA_DEF_SIGNAL3(SIGXFSZ); | |
// Windows | |
EMILUA_DEF_SIGNAL3(SIGBREAK); | |
#undef EMILUA_DEF_SIGNAL3 | |
#undef EMILUA_DEF_SIGNAL2 | |
#undef EMILUA_DEF_SIGNAL | |
} | |
lua_rawset(L, LUA_REGISTRYINDEX); | |
} | |
} // namespace emilua |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment