示例#1
0
void luasandbox_timer_stop(luasandbox_timer_set * lts)
{
	struct timespec usage, delta;

	if (lts->is_running) {
		lts->is_running = 0;
	} else {
		return;
	}

	// Make sure timers aren't paused, and extract the delta
	luasandbox_timer_unpause(lts);
	delta = lts->pause_delta;
	luasandbox_timer_zero(&lts->pause_delta);

	// Stop the interval timers and save the time remaining
	if (lts->emergency_running) {
		luasandbox_timer_stop_one(&lts->emergency_timer, &lts->emergency_remaining);
		lts->emergency_running = 0;
	}
	if (lts->normal_running) {
		luasandbox_timer_stop_one(&lts->normal_timer, &lts->normal_remaining);
		lts->normal_running = 0;
		luasandbox_timer_add(&lts->normal_remaining, &delta);
	}

	// Update the usage
	luasandbox_update_usage(lts);
	clock_gettime(LUASANDBOX_CLOCK_ID, &usage);
	luasandbox_timer_subtract(&usage, &lts->usage_start);
	luasandbox_timer_add(&lts->usage, &usage);
	luasandbox_timer_subtract(&lts->usage, &delta);
}
示例#2
0
void luasandbox_timer_get_usage(luasandbox_timer_set * lts, struct timespec * ts)
{
	struct timespec delta;

	if (lts->is_running) {
		luasandbox_update_usage(lts);
	}
	*ts = lts->usage;
	// Subtract the pause delta from the usage
	luasandbox_timer_subtract(ts, &lts->pause_delta);
	// If currently paused, subtract the time-since-pause too
	if (!luasandbox_timer_is_zero(&lts->pause_start)) {
		clock_gettime(LUASANDBOX_CLOCK_ID, &delta);
		luasandbox_timer_subtract(&delta, &lts->pause_start);
		luasandbox_timer_subtract(ts, &delta);
	}
}
示例#3
0
static void luasandbox_update_usage(luasandbox_timer_set * lts)
{
	struct timespec current, usage;
	clock_gettime(LUASANDBOX_CLOCK_ID, &current);
	usage = current;
	luasandbox_timer_subtract(&usage, &lts->usage_start);
	luasandbox_timer_add(&lts->usage, &usage);
	lts->usage_start = current;
}
示例#4
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);
		}
	}
}
示例#5
0
void luasandbox_timer_unpause(luasandbox_timer_set * lts) {
	struct timespec delta;

	if (!luasandbox_timer_is_zero(&lts->pause_start)) {
		clock_gettime(LUASANDBOX_CLOCK_ID, &delta);
		luasandbox_timer_subtract(&delta, &lts->pause_start);

		if (luasandbox_timer_is_zero(&lts->normal_expired_at)) {
			// Easy case, timer didn't expire while paused. Throw the whole delta
			// into pause_delta for later timer and usage adjustment.
			luasandbox_timer_add(&lts->pause_delta, &delta);
			luasandbox_timer_zero(&lts->pause_start);
		} else {
			// If the normal limit expired, we need to fold the whole
			// accumulated delta into usage immediately, and then restart the
			// timer with the portion before the expiry.

			// adjust usage
			luasandbox_timer_subtract(&lts->usage, &delta);
			luasandbox_timer_subtract(&lts->usage, &lts->pause_delta);

			// calculate timer delta
			delta = lts->normal_expired_at;
			luasandbox_timer_subtract(&delta, &lts->pause_start);
			luasandbox_timer_add(&delta, &lts->pause_delta);

			// Zero out pause vars and expired timestamp (since we handled it)
			luasandbox_timer_zero(&lts->pause_start);
			luasandbox_timer_zero(&lts->pause_delta);
			luasandbox_timer_zero(&lts->normal_expired_at);

			// Restart timer
			lts->normal_remaining = delta;
			luasandbox_timer_set_one_time(&lts->normal_timer, &lts->normal_remaining);
		}
	}
}
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);
	}
}