예제 #1
0
/**
 * Abort current process, producing an abnormal program termination.
 * The function raises the SIGABRT signal.
 */
void __attr_noreturn___ __attr_used___
abort (void)
{
  syscall_1 (SYSCALL_NO (close), (long int) stdin);
  syscall_1 (SYSCALL_NO (close), (long int) stdout);
  syscall_1 (SYSCALL_NO (close), (long int) stderr);

  raise (SIGABRT);

  while (true)
  {
    /* unreachable */
  }
} /* abort */
예제 #2
0
/**
 * Exit - cause normal process termination with specified status code
 */
void __attr_noreturn___ __attr_used___
exit (int status) /**< status code */
{
  syscall_1 (SYSCALL_NO (close), (long int) stdin);
  syscall_1 (SYSCALL_NO (close), (long int) stdout);
  syscall_1 (SYSCALL_NO (close), (long int) stderr);

  syscall_1 (SYSCALL_NO (exit_group), status);

  while (true)
  {
    /* unreachable */
  }
} /* exit */
예제 #3
0
/**
 * fwrite
 *
 * @return number of elements written
 */
size_t
fwrite (const void *ptr, /**< data to write */
        size_t size, /**< size of elements to write */
        size_t nmemb, /**< number of elements */
        FILE *stream) /**< stream pointer */
{
  size_t bytes_written = 0;

  if (size == 0)
  {
    return 0;
  }

  do
  {
    long int ret = syscall_3 (SYSCALL_NO (write),
                              (long int) stream,
                              (long int) ((uint8_t *) ptr + bytes_written),
                              (long int) (size * nmemb - bytes_written));

    bytes_written += (size_t) ret;
  }
  while (bytes_written != size * nmemb);

  return bytes_written / size;
} /* fwrite */
예제 #4
0
/**
 * fread
 *
 * @return number of elements read
 */
size_t
fread (void *ptr, /**< address of buffer to read to */
       size_t size, /**< size of elements to read */
       size_t nmemb, /**< number of elements to read */
       FILE *stream) /**< stream pointer */
{
  long int ret;
  size_t bytes_read = 0;

  if (size == 0)
  {
    return 0;
  }

  do
  {
    ret = syscall_3 (SYSCALL_NO (read),
                     (long int) stream,
                     (long int) ((uint8_t *) ptr + bytes_read),
                     (long int) (size * nmemb - bytes_read));

    bytes_read += (size_t) ret;
  }
  while (bytes_read != size * nmemb && ret != 0);

  return bytes_read / size;
} /* fread */
예제 #5
0
/**
 * fclose
 *
 * @return 0 - upon successful completion,
 *         non-zero value - otherwise.
 */
int
fclose (FILE *fp) /**< stream pointer */
{
  syscall_2 (SYSCALL_NO (close), (long int) fp, 0);

  return 0;
} /* fclose */
예제 #6
0
/**
 * Exit - cause normal process termination with specified status code
 */
void __attr_noreturn___ __attr_used___
exit (int status) /**< status code */
{
#ifdef ENABLE_INIT_FINI
  libc_fini_array ();
#endif /* ENABLE_INIT_FINI */

  syscall_1 (SYSCALL_NO (close), (long int) stdin);
  syscall_1 (SYSCALL_NO (close), (long int) stdout);
  syscall_1 (SYSCALL_NO (close), (long int) stderr);

  syscall_1 (SYSCALL_NO (exit_group), status);

  while (true)
  {
    /* unreachable */
  }
} /* exit */
예제 #7
0
/**
 * Setup new memory limits
 */
void
jrt_set_mem_limits (size_t data_size, /**< limit for data + bss + brk heap */
                    size_t stack_size) /**< limit for stack */
{
  struct
  {
    unsigned long long rlim_cur;
    unsigned long long rlim_max;
  } data_limit = { data_size, data_size };

  struct
  {
    unsigned long long rlim_cur;
    unsigned long long rlim_max;
  } stack_limit = { stack_size, stack_size };

  long int ret;

#if defined (__TARGET_HOST_x64)
  ret = syscall_2 (SYSCALL_NO (setrlimit), RLIMIT_DATA, (intptr_t) &data_limit);
  assert (ret == 0);

  ret = syscall_2 (SYSCALL_NO (setrlimit), RLIMIT_STACK, (intptr_t) &stack_limit);
  assert (ret == 0);
#elif defined (__TARGET_HOST_ARMv7)
  ret = syscall_3 (SYSCALL_NO (prlimit64), 0, RLIMIT_DATA, (intptr_t) &data_limit);
  assert (ret == 0);

  ret = syscall_3 (SYSCALL_NO (prlimit64), 0, RLIMIT_STACK, (intptr_t) &stack_limit);
  assert (ret == 0);
#elif defined (__TARGET_HOST_x86)
# error "__TARGET_HOST_x86 case is not implemented"
#else /* !__TARGET_HOST_x64 && !__TARGET_HOST_ARMv7 && !__TARGET_HOST_x86 */
# error "!__TARGET_HOST_x64 && !__TARGET_HOST_ARMv7 && !__TARGET_HOST_x86"
#endif /* __TARGET_HOST_x64 */
} /* jrt_set_mem_limits */
예제 #8
0
/**
 * Send a signal to the current process.
 */
int __attr_used___
raise (int sig)
{
  return (int) syscall_2 (SYSCALL_NO (kill), syscall_0 (SYSCALL_NO (getpid)), sig);
} /* raise */
예제 #9
0
/**
 * This function can get the time as well as a timezone.
 *
 * @return 0 if success, -1 otherwise
 */
int
gettimeofday (void *tp,  /**< struct timeval */
              void *tzp) /**< struct timezone */
{
  return (int) syscall_2 (SYSCALL_NO (gettimeofday), (long int) tp, (long int) tzp);
} /* gettimeofday */
예제 #10
0
/**
 * fopen
 *
 * @return FILE pointer - upon successful completion,
 *         NULL - otherwise
 */
FILE *
fopen (const char *path, /**< file path */
       const char *mode) /**< file open mode */
{
  bool may_read = false;
  bool may_write = false;
  bool truncate = false;
  bool create_if_not_exist = false;
  bool position_at_end = false;

  assert (path != NULL && mode != NULL);
  assert (mode[1] == '+' || mode[1] == '\0');

  switch (mode[0])
  {
    case 'r':
    {
      may_read = true;
      may_write = (mode[1] == '+');
      break;
    }
    case 'w':
    {
      may_write = true;
      truncate = true;
      create_if_not_exist = true;
      may_read = (mode[1] == '+');
      break;
    }
    case 'a':
    {
      may_write = true;
      position_at_end = true;
      create_if_not_exist = true;
      if (mode[1] == '+')
      {
        assert (false && "unsupported mode a+");
      }
      break;
    }
    default:
    {
      assert (false && "unsupported mode");
    }
  }

  int flags = 0;
  int access = S_IRUSR | S_IWUSR;
  if (may_read && !may_write)
  {
    flags = O_RDONLY;
  }
  else if (!may_read && may_write)
  {
    flags = O_WRONLY;
  }
  else
  {
    assert (may_read && may_write);

    flags = O_RDWR;
  }

  if (truncate)
  {
    flags |= O_TRUNC;
  }

  if (create_if_not_exist)
  {
    flags |= O_CREAT;
  }

  if (position_at_end)
  {
    flags |= O_APPEND;
  }

  long int ret = syscall_3 (SYSCALL_NO (open), (long int) path, flags, access);

  return ((ret < 0) ? NULL : (void *) (uintptr_t) (ret));
} /* fopen */
예제 #11
0
파일: sandbox.c 프로젝트: sw072/myoj
int sandbox_excute(sandbox_t *psbox)
{
	pid_t child;
	child = fork();
	if(child < 0)
	{
		psbox->result = INTERNAL_ERROR;
		__TRACE_LN(__TRACE_KEY, "Error : fork target process failed");
		return -1;
	}
	else if(child == 0)
	{
		_exit(_sandbox_excute(&psbox->task));
	}
	else
	{
	    __TRACE_LN(__TRACE_DBG, "child pid : %d", child);
		pid_t wait_result = 0;
		int wait_status = 0;
		proc_t proc_data = { 0 };
		int in_syscall = 1;
		event_t e = { 0 };
		action_t action = { 0 };

        /* Have signals kill the prisoner but not self (if possible).  */
        /* In fact, I have deleted the '-' before "child" so this may not be necessary */
        sig_t terminate_signal;
        sig_t interrupt_signal;
        sig_t quit_signal;

        terminate_signal = signal(SIGTERM, SIG_IGN);
        interrupt_signal = signal(SIGINT, SIG_IGN);
        quit_signal = signal(SIGQUIT, SIG_IGN);

        /* Get wallclock start time */
        gettimeofday(&psbox->stat.start_timestamp, NULL);


        /* get initial resource usage */
		wait_result = wait4(child, &wait_status, 0, &psbox->stat.ru);
		memcpy(&psbox->stat.init_ru, &psbox->stat.ru, sizeof(struct rusage));
		/* trace loop */
		__TRACE_LN(__TRACE_DBG, "Enter trace loop");
		bool internal_error = false;
		do{
			if(!wait_result)	/* wait_result == 0 : noting happent */
			{
				goto cont;
			}
			memset(&e, 0, sizeof(event_t));
			memset(&action, 0, sizeof(action_t));
			if(WIFSTOPPED(wait_status))
			{
				switch(WSTOPSIG(wait_status))
				{
				case SIGALRM:
					POST_EVENT(e, EVENT_QUOTA, QUOTA_WALLCLOCK);
					break;
				case SIGXCPU:
				case SIGPROF:
				case SIGVTALRM:
					POST_EVENT(e, EVENT_QUOTA, QUOTA_CPUTIME);
					break;
				case SIGML:
					POST_EVENT(e, EVENT_QUOTA, QUOTA_MEMORY);
					break;
				case SIGXFSZ:
					POST_EVENT(e, EVENT_QUOTA, QUOTA_OUTPUT);
					break;
				case SIGTRAP:
					if(!proc_probe(child, &proc_data))
					{
						/* error */
						internal_error = true;
                        psbox->result = INTERNAL_ERROR;
						kill(child, SIGKILL);
						__TRACE_LN(__TRACE_KEY, "Internal Error : porc_probe() failed");
						break;
					}
					if(psbox->stat.vsize_peak < proc_data.vsize)
					{
						psbox->stat.vsize_peak = proc_data.vsize;
						if(psbox->stat.vsize_peak > psbox->task.quota[QUOTA_MEMORY])
						{
							kill(child, SIGML);
						}
					}
					/* system call or system call return */
					if(in_syscall)
					{
						in_syscall = 0;
						POST_EVENT(e, EVENT_SYSTEM_CALL_RETURN, SYSCALL_NO(&proc_data), SYSCALL_RETVAL(&proc_data));
					}
					else
					{
						in_syscall = 1;
						POST_EVENT(e, EVENT_SYSTEM_CALL, SYSCALL_NO(&proc_data),
									SYSCALL_ARG1(&proc_data), SYSCALL_ARG2(&proc_data),
									SYSCALL_ARG3(&proc_data), SYSCALL_ARG4(&proc_data),
																			SYSCALL_ARG5(&proc_data));
					}
					break;
				default: POST_EVENT(e, EVENT_SIGNAL, WSTOPSIG(wait_status));
				}
			}
			else if(WIFSIGNALED(wait_status))
			{
				POST_EVENT(e, EVENT_SIGNAL, WTERMSIG(wait_status));
			}
			else if(WIFEXITED(wait_status))
			{
				psbox->stat.data.exitcode = WEXITSTATUS(wait_status);
				POST_EVENT(e, EVENT_EXIT, WEXITSTATUS(wait_status));
			}

			/* sink event */
			psbox->policy(&e, &action);
            __TRACE(__TRACE_DBG, "Event type : %s", event_name(e.type));
            __TRACE_LN(__TRACE_DBG, "\tEvent data : %ld %ld %ld %ld %ld %ld",
                                    e.data._bitmap_.a, e.data._bitmap_.b, e.data._bitmap_.c,
                                    e.data._bitmap_.d, e.data._bitmap_.e, e.data._bitmap_.f);
            __TRACE(__TRACE_DBG, "Action type : %s", action_name(action.type));
            __TRACE_LN(__TRACE_DBG, "\tAction data : %ld %ld", action.data._bitmap_.a,
                                                                                                                         action.data._bitmap_.b);
			/* action */
			switch(action.type)
			{
			case ACTION_CONTINUE:
				if(!trace_next(&proc_data))
				{
					internal_error = true;
					psbox->result = INTERNAL_ERROR;
					kill(child, SIGKILL);
					__TRACE_LN(__TRACE_KEY, "Internal Error : trace_next() failed");
					break;
				}
				goto cont;
			case ACTION_KILL:
				trace_kill(&proc_data, 0);
				psbox->result = action.data._kill.result;
				if(psbox->result == RUNTIME_ERROR)
				{
					psbox->stat.data.signo = action.data._kill.data;
				}
				else if(psbox->result == RESTRICTED_FUNCTION)
				{
					psbox->stat.data.rf = action.data._kill.data;
				}
				kill(child, SIGKILL);
				break;
			case ACTION_EXIT:
				psbox->stat.data.exitcode = action.data._exit.code;
				if(psbox->stat.data.exitcode)
				{
				    __TRACE_LN(__TRACE_DBG, "exit code : %ld", psbox->stat.data.exitcode);
					psbox->result = ABNORMAL_TERMINATION;
				}
				/*
				else
				{
				    psbox->result = PENDED;
				}
				*/
				break;
			}
			break;
cont:
            /* trace infomation */
            __TRACE_LN(__TRACE_DBG, "----------------------wait4()----------------------");
		}while(!internal_error && (wait_result = wait4(child, &wait_status, 0, &psbox->stat.ru)) >= 0);
		/* if the sandbox's result is PENDED, the prisoned process is exited nomally */
        /* Get wallclock stop time (call a second time to compensate overhead) */
        gettimeofday(&psbox->stat.end_timestamp, NULL);
        /* Restore signal handlers */
        signal(SIGTERM, interrupt_signal);
        signal(SIGINT, interrupt_signal);
        signal(SIGQUIT, quit_signal);
	}
	return 0;
}