Ejemplo n.º 1
0
static void luasandbox_timer_handle_signal(int signo, siginfo_t * info, void * context)
{
	luasandbox_timer_callback_data * data;
	
	if (signo != LUASANDBOX_SIGNAL
			|| info->si_code != SI_TIMER
			|| !info->si_value.sival_ptr)
	{
		return;
	}

	data = (luasandbox_timer_callback_data*)info->si_value.sival_ptr;

	lua_State * L = data->sandbox->state;

	if (data->type == LUASANDBOX_TIMER_EMERGENCY) {
		sigset_t set;
		sigemptyset(&set);
		sigprocmask(SIG_SETMASK, &set, NULL);
		data->sandbox->timed_out = 1;
		data->sandbox->emergency_timed_out = 1;
		if (data->sandbox->in_php) {
			// The whole PHP request context is dirty now. We need to kill it,
			// like what happens if there is a max_execution_time timeout.
			zend_error(E_ERROR, "The maximum execution time for a Lua sandbox script "
					"was exceeded and a PHP callback failed to return");
		} else {
			// The Lua state is dirty now and can't be used again.
			lua_pushstring(L, "emergency timeout");
			luasandbox_wrap_fatal(L);
			lua_error(L);
		}
	} else {
		luasandbox_timer_set * lts = &data->sandbox->timer;
		if (luasandbox_timer_is_paused(lts)) {
			// The timer is paused. luasandbox_timer_unpause will reschedule when unpaused.
			clock_gettime(LUASANDBOX_CLOCK_ID, &lts->normal_expired_at);
		} else if (!luasandbox_timer_is_zero(&lts->pause_delta)) {
			// The timer is not paused, but we have a pause delta. Reschedule.
			luasandbox_timer_subtract(&lts->usage, &lts->pause_delta);
			lts->normal_remaining = lts->pause_delta;
			luasandbox_timer_zero(&lts->pause_delta);
			luasandbox_timer_set_one_time(&lts->normal_timer, &lts->normal_remaining);
		} else {
			// Set a hook which will terminate the script execution in a graceful way
			data->sandbox->timed_out = 1;
			lua_sethook(L, luasandbox_timer_timeout_hook,
				LUA_MASKCOUNT | LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 1);
		}
	}
}
Ejemplo n.º 2
0
void luasandbox_timer_set_limit(luasandbox_timer_set * lts,
		struct timespec * timeout)
{
	int was_running = 0;
	int was_paused = luasandbox_timer_is_paused(lts);
	if (lts->is_running) {
		was_running = 1;
		luasandbox_timer_stop(lts);
	}
	lts->limiter_remaining = lts->limiter_limit = *timeout;
	luasandbox_timer_zero(&lts->limiter_expired_at);

	if (was_running) {
		luasandbox_timer_start(lts);
	}
	if (was_paused) {
		luasandbox_timer_pause(lts);
	}
}
Ejemplo n.º 3
0
void luasandbox_timer_set_limits(luasandbox_timer_set * lts,
		struct timespec * normal_timeout, 
		struct timespec * emergency_timeout)
{
	int was_running = 0;
	int was_paused = luasandbox_timer_is_paused(lts);
	if (lts->is_running) {
		was_running = 1;
		luasandbox_timer_stop(lts);
	}
	lts->normal_remaining = lts->normal_limit = *normal_timeout;
	lts->emergency_remaining = lts->emergency_limit = *emergency_timeout;
	luasandbox_timer_zero(&lts->normal_expired_at);

	if (was_running) {
		luasandbox_timer_start(lts);
	}
	if (was_paused) {
		luasandbox_timer_pause(lts);
	}
}
Ejemplo n.º 4
0
static void luasandbox_timer_handle_limiter(luasandbox_timer * lt)
{
	lua_State * L = lt->sandbox->state;

	luasandbox_timer_set * lts = &lt->sandbox->timer;
	if (luasandbox_timer_is_paused(lts)) {
		// The timer is paused. luasandbox_timer_unpause will reschedule when unpaused.
		// Note that we need to use lt->clock_id here since CLOCK_THREAD_CPUTIME_ID
		// would get the time usage of the timer thread rather than the Lua thread.
		clock_gettime(lt->clock_id, &lts->limiter_expired_at);
	} else if (!luasandbox_timer_is_zero(&lts->pause_delta)) {
		// The timer is not paused, but we have a pause delta. Reschedule.
		luasandbox_timer_subtract(&lts->usage, &lts->pause_delta);
		lts->limiter_remaining = lts->pause_delta;
		luasandbox_timer_zero(&lts->pause_delta);
		luasandbox_timer_set_one_time(lts->limiter_timer, &lts->limiter_remaining);
	} else {
		// Set a hook which will terminate the script execution in a graceful way
		lt->sandbox->timed_out = 1;
		lua_sethook(L, luasandbox_timer_timeout_hook,
			LUA_MASKCOUNT | LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE, 1);
	}
}