コード例 #1
0
ファイル: proxy.c プロジェクト: 3sOx/asuswrt-merlin
int debugger_syscall(debugger_state *debugger, pid_t child)
{
	long arg1, arg2, arg3, arg4, arg5, result;
	int syscall, ret = 0;

	syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, 
			      &arg5);

	switch(syscall){
	case __NR_execve:
		/* execve never returns */
		debugger->handle_trace = debugger_syscall; 
		break;

	case __NR_ptrace:
		if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;
		if(!debugger->debugee->in_context) 
			child = debugger->debugee->pid;
		result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,
				      &ret);
		syscall_cancel(debugger->pid, result);
		debugger->handle_trace = debugger_syscall;
		return(ret);

#ifdef __NR_waitpid
	case __NR_waitpid:
#endif
	case __NR_wait4:
		if(!debugger_wait(debugger, (int *) arg2, arg3, 
				  debugger_syscall, debugger_normal_return, 
				  proxy_wait_return))
			return(0);
		break;

	case __NR_kill:
		if(!debugger->debugee->in_context) 
			child = debugger->debugee->pid;
		if(arg1 == debugger->debugee->pid){
			result = kill(child, arg2);
			syscall_cancel(debugger->pid, result);
			debugger->handle_trace = debugger_syscall;
			return(0);
		}
		else debugger->handle_trace = debugger_normal_return;
		break;

	default:
		debugger->handle_trace = debugger_normal_return;
	}

	syscall_continue(debugger->pid);
	return(0);
}
コード例 #2
0
ファイル: parent.c プロジェクト: SPETsgnom/strace
static void	trace_process(int pid, char **strtab)
{
  int		status;

  while (1)
    {
      wait4(pid, &status, WUNTRACED, NULL);
      if (get_stopsig(pid, strtab))
      	break;
      if (status == 0)
	break;
      if (get_syscall(pid, strtab))
	break ;
      ptrace(PTRACE_SINGLESTEP, pid, NULL, 0);
    }
}
コード例 #3
0
ファイル: powerpc64-fbsd.c プロジェクト: Alkzndr/freebsd
void
powerpc64_syscall_entry(struct trussinfo *trussinfo, int nargs)
{
	struct ptrace_io_desc iorequest;
	struct reg regs;
	struct freebsd_syscall *fsc;
	struct syscall *sc;
	void *args;
	lwpid_t tid;
	int i, regargs, syscall_num;

	tid = trussinfo->curthread->tid;

	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
		return;
	}

	/*
	 * FreeBSD has two special kinds of system call redirctions --
	 * SYS_syscall, and SYS___syscall.  The former is the old syscall()
	 * routine, basically; the latter is for quad-aligned arguments.
	 */
	regargs = NARGREG;
	syscall_num = regs.fixreg[0];
	args = &regs.fixreg[3];
	if (syscall_num == SYS_syscall || syscall_num == SYS___syscall) {
		args = &regs.fixreg[4];
		regargs -= 1;
		syscall_num = regs.fixreg[3];
	}

	fsc = alloc_fsc();
	if (fsc == NULL)
		return;
	fsc->number = syscall_num;
	fsc->name = (syscall_num < 0 || syscall_num >= nsyscalls) ?
	    NULL : syscallnames[syscall_num];
	if (!fsc->name) {
		fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n",
		    syscall_num);
	}

	if (fsc->name && (trussinfo->flags & FOLLOWFORKS) &&
	    (strcmp(fsc->name, "fork") == 0 ||
	    strcmp(fsc->name, "rfork") == 0 ||
	    strcmp(fsc->name, "vfork") == 0))
		trussinfo->curthread->in_fork = 1;

	if (nargs == 0)
		return;

	fsc->args = malloc((1 + nargs) * sizeof(unsigned long));

	if (nargs > regargs) {
		memmove(&fsc->args[0], args, regargs * sizeof(fsc->args[0]));

		iorequest.piod_op = PIOD_READ_D;
		iorequest.piod_offs = (void *)(regs.fixreg[1] + 48);
		iorequest.piod_addr = &fsc->args[regargs];
		iorequest.piod_len = (nargs - regargs) * sizeof(fsc->args[0]);
		ptrace(PT_IO, tid, (caddr_t)&iorequest, 0);
		if (iorequest.piod_len == 0)
			return;
	} else
		memmove(&fsc->args[0], args, nargs * sizeof(fsc->args[0]));

	sc = get_syscall(fsc->name);
	if (sc)
		fsc->nargs = sc->nargs;
	else {
#if DEBUG
		fprintf(trussinfo->outfile, "unknown syscall %s -- setting "
		    "args to %d\n", fsc->name, nargs);
#endif
		fsc->nargs = nargs;
	}

	fsc->s_args = calloc(1, (1 + fsc->nargs) * sizeof(char *));
	fsc->sc = sc;

	/*
	 * At this point, we set up the system call arguments.
	 * We ignore any OUT ones, however -- those are arguments that
	 * are set by the system call, and so are probably meaningless
	 * now.	This doesn't currently support arguments that are
	 * passed in *and* out, however.
	 */

	if (fsc->name) {
#if DEBUG
		fprintf(stderr, "syscall %s(", fsc->name);
#endif
		for (i = 0; i < fsc->nargs; i++) {
#if DEBUG
			fprintf(stderr, "0x%x%s", sc ?
			    fsc->args[sc->args[i].offset] : fsc->args[i],
			    i < (fsc->nargs - 1) ? "," : "");
#endif
			if (sc && !(sc->args[i].type & OUT)) {
				fsc->s_args[i] = print_arg(&sc->args[i],
				    fsc->args, 0, trussinfo);
			}
		}
#if DEBUG
		fprintf(stderr, ")\n");
#endif
	}

#if DEBUG
	fprintf(trussinfo->outfile, "\n");
#endif

	if (fsc->name && (strcmp(fsc->name, "execve") == 0 ||
	    strcmp(fsc->name, "exit") == 0)) {
		/*
		 * XXX
		 * This could be done in a more general
		 * manner but it still wouldn't be very pretty.
		 */
		if (strcmp(fsc->name, "execve") == 0) {
			if ((trussinfo->flags & EXECVEARGS) == 0) {
				if (fsc->s_args[1]) {
					free(fsc->s_args[1]);
					fsc->s_args[1] = NULL;
				}
			}
			if ((trussinfo->flags & EXECVEENVS) == 0) {
				if (fsc->s_args[2]) {
					free(fsc->s_args[2]);
					fsc->s_args[2] = NULL;
				}
			}
		}
	}
	trussinfo->curthread->fsc = fsc;
}
コード例 #4
0
/*
 * Function: main
 * Purpose:  
 * Comments: 
 */
int main(int argc, char *argv[])
{
  int                i;
  struct sigaction   si_sa;
  int                euid, ruid;
  struct host_entry *cursor;

  /*
   * first things first
   * if anything goes wrong anywhere, we want to be super careful to release
   * any file descriptor we have on /dev/lkm, and it probably makes sense to
   * shutdown the raw socket we have too.
   */
  atexit(cleanup);

  /*
   * get the effective and the real user id's so we know if we are running
   * with elevated permissions or not
   */
  euid = geteuid();
  ruid = getuid();

  /* check for the command line arguments */
  if(check_options(argc,argv) == 0)
    {
      return -1;
    }

  /*
   * open the raw socket now.  i used to have this further down closer to
   * where it was needed, but because you can't change the euid/uid to and
   * from root (unless you're the superuser) i can only do this once
   */
  if(options & OPT_IPV4)
    {
      if(open_ipmp_sockets4() == 0) return -1; 
    }
  else if(options & OPT_IPV6)
    {
      if(open_ipmp_sockets6() == 0) return -1; 
    }
  else
    {
      if(open_ipmp_sockets4() == 0) return -1;
      if(open_ipmp_sockets6() == 0) return -1;
    }

  /*
   * revoke the permissions we requested as we only need them to open a raw
   * socket.  this is to reduce the impact of any buffer overflow exploits
   * that may be present
   */
  if(ruid != euid)
    {
      setreuid(ruid, ruid);
    }

  /*
   * we get the pid so we can identify incoming ipmp packets destined for
   * this instance of ipmp_ping
   */
  pid = getpid();

  /*
   * need to know about the addresses this host has
   */
  learn_localaddresses();

  /*
   * in FreeBSD, the actual ping is done by a kernel module that has a syscall
   * in it.  the kernel module allows the protocol to get a timestamp as close
   * to when the mbuf is actually sent to ip_output as possible
   */
#if defined(__FreeBSD__)
  if((options & OPT_RAW) == 0)
    {
      i = get_syscall("ipmp_ping", &syscall_num);
      if(i != 0)
        {
          printerror(i, strerror, "could not get the syscall for ipmp_ping");
          return -1;
        }
    }
#endif

  /*
   * the -n option means that the user has supplied a list of hosts to
   * ping, so we read those entries and put them in an list of hosts with
   * details regarding each host.  the task of putting hosts into the list
   * is handled by read_hosts_file
   *
   * if the -n option isnt specified, we create a list containing just the 
   * one host to ping.  this way, all the program logic can be used in a
   * multitude of situations.
   */
  if(options & OPT_NLANR)
    {
      /*
       * if something went wrong parsing the file, we quit.
       */
      if(read_hosts_file() == 0)
	{
	  return -1;
	}
    }
  else
    {
      /*
       * if the user didnt specify a host to ping, we bail, telling them
       * why first...
       */
      if(argc - optind != 1)
	{
	  usage(0);
          return -1;
	}

      /*
       * if we can't add a host entry for the host supplied on the command line
       * tell the user that it couldnt be parse and cleanup
       */
      if(add_host_entry(argv[optind], NULL) == 0)
	{
	  return -1;
	}
    }

  /*
   * we now put some handlers into action so if the user ctrl-c's us we have
   * the opportunity to tell them what we found out first
   * also, if the user specified a timeout, put an alarm in for that so we
   * can bail when they tell us to...
   */
  sigemptyset(&si_sa.sa_mask);
  si_sa.sa_flags = 0;
  si_sa.sa_handler = alarm_bells;
  if(sigaction(SIGINT, &si_sa, 0) == -1)
    {
      printerror(errno, strerror, "could not set sigaction for SIGINT");
      return -1;
    }
  if(options & OPT_TIMEOUT)
    {
      if(sigaction(SIGALRM, &si_sa, 0) == -1)
	{
	  printerror(errno, strerror, "could not set sigaction for SIGALRM");
	  return -1;
	}
    }

  /*
   * we loop for as long as we have not been told to finish up.
   * the finish_up loop will exit when
   *  - there has been an alarm set that goes off
   *  - a SIGINT is received (from e.g. Ctrl-C)
   *  - we have got_all_response()'s
   *
   * this is not an expensive loop in terms of cpu cycles, as the
   * recv_echo_response will sleep if there is nothing to recv until we have
   * told it to stop blocking - typically one second or whatever the between
   * timeout is.
   *
   * the loop does two things:
   *  - sends echo requests
   *  - receives echo responses
   *
   * the loop sends packets, pausing for however long the timeout is set for
   * between packets.  this pause is implemented in the recv_echo_response
   * function in a call to select(2).  if we cannot send a request to one of
   * them, we bail, as this probably means the syscall could not be called.
   *
   * the loop recv's the response and associates the packet with a host_entry
   * we then parse that response for the host entry, and then check if we have
   * now got all the responses we are looking for.  if we have, we exit the
   * loop by setting the finish_up flag
   */

  sent_all_requests = 0;
  i = 0;

  cursor = head;

  while(finish_up == 0)
    {
      while(sent_all_requests == 0)
	{
	  if(send_echo_request(cursor) != 0)
	    {
	      return -1;
	    }
	  cursor->tx++;

	  if(cursor->tx == count)
	    {
	      cursor = cursor->next;
	      if(cursor == NULL)
		{
		  sent_all_requests = 1;
		  alarm(timeout);
		  break;
		}
	    }

	  if(wait_between > 0)
	    {
	      gettimeofday(&wait_between_tv, &tz);
	      timeval_add(&wait_between_tv, wait_between);
	      break;
	    }
	}

      while(time_to_send_request() == 0 && finish_up == 0)
	{
	  if(recv_echo_responses() > 0)
	    {
	      if(got_all_responses() == 1)
		{
		  finish_up = 1;
		}
	    }
	}
    }

  /*
   * if we have been given a list of hosts to ping, we have to print out which
   * hosts did not give us a reply
   */
  if(options & OPT_NLANR)
    {
      show_loss();
    }

  return 0;
}
コード例 #5
0
ファイル: mips-fbsd.c プロジェクト: niuzhenlin/freebsd
void
mips_syscall_entry(struct trussinfo *trussinfo, int nargs)
{
	struct ptrace_io_desc iorequest;
	struct reg regs;
	struct freebsd_syscall *fsc;
	struct syscall *sc;
	lwpid_t tid;
	int i, syscall_num;
	int indir;	/* indirect system call */

	tid = trussinfo->curthread->tid;

	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
		return;
	}

	indir = 0;
	syscall_num = regs.r_regs[V0];
	if (syscall_num == SYS_syscall) {
		indir = 1;
		syscall_num = regs.r_regs[A0];
	}

	fsc = alloc_fsc();
	if (fsc == NULL)
		return;
	fsc->number = syscall_num;
	fsc->name = (syscall_num < 0 || syscall_num >= nsyscalls) ?
	    NULL : syscallnames[syscall_num];
	if (!fsc->name) {
		fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n",
		    syscall_num);
	}

	if (fsc->name && (trussinfo->flags & FOLLOWFORKS) &&
	    (strcmp(fsc->name, "fork") == 0 ||
	    strcmp(fsc->name, "pdfork") == 0 ||
	    strcmp(fsc->name, "rfork") == 0 ||
	    strcmp(fsc->name, "vfork") == 0))
		trussinfo->curthread->in_fork = 1;

	if (nargs == 0)
		return;

	fsc->args = malloc((1 + nargs) * sizeof(unsigned long));
#if 0 // XXX
	iorequest.piod_op = PIOD_READ_D;
	iorequest.piod_offs = (void *)parm_offset;
	iorequest.piod_addr = fsc->args;
	iorequest.piod_len = (1 + nargs) * sizeof(unsigned long);
	ptrace(PT_IO, tid, (caddr_t)&iorequest, 0);
	if (iorequest.piod_len == 0)
		return;
#else
	iorequest.piod_op = PIOD_READ_D;
#endif

	switch (nargs) {
	default:
		/*
		 * The OS doesn't seem to allow more than 10 words of
		 * parameters (yay!).	So we shouldn't be here.
		 */
		warn("More than 10 words (%d) of arguments!\n", nargs);
		break;
	case 10:
	case 9:
	case 8:
	case 7:
	case 6:
	case 5:
		/*
		 * If there are 7-10 words of arguments, they are placed
		 * on the stack, as is normal for other processors.
		 * The fall-through for all of these is deliberate!!!
		 */
		// XXX BAD constant used here
		iorequest.piod_op = PIOD_READ_D;
		iorequest.piod_offs = (void *)(regs.r_regs[SP] +
		    4 * sizeof(uint32_t));
		iorequest.piod_addr = &fsc->args[4];
		iorequest.piod_len = (nargs - 4) * sizeof(fsc->args[0]);
		ptrace(PT_IO, tid, (caddr_t)&iorequest, 0);
		if (iorequest.piod_len == 0)
			return;
	case 4:	fsc->args[3] = regs.r_regs[A3];
	case 3:	fsc->args[2] = regs.r_regs[A2];
	case 2:	fsc->args[1] = regs.r_regs[A1];
	case 1:	fsc->args[0] = regs.r_regs[A0];
	case 0: break;
	}
	if (indir) {
		memmove(&fsc->args[0], &fsc->args[1],
		    (nargs - 1) * sizeof(fsc->args[0]));
	}

	sc = get_syscall(fsc->name);
	if (sc)
		fsc->nargs = sc->nargs;
	else {
#if DEBUG
		fprintf(trussinfo->outfile, "unknown syscall %s -- setting "
		    "args to %d\n", fsc->name, nargs);
#endif
		fsc->nargs = nargs;
	}

	fsc->s_args = calloc(1, (1 + fsc->nargs) * sizeof(char *));
	fsc->sc = sc;

	/*
	 * At this point, we set up the system call arguments.
	 * We ignore any OUT ones, however -- those are arguments that
	 * are set by the system call, and so are probably meaningless
	 * now.	This doesn't currently support arguments that are
	 * passed in *and* out, however.
	 */

	if (fsc->name) {
#if DEBUG
		fprintf(stderr, "syscall %s(", fsc->name);
#endif
		for (i = 0; i < fsc->nargs; i++) {
#if DEBUG
			fprintf(stderr, "0x%x%s", sc ?
			    fsc->args[sc->args[i].offset] : fsc->args[i],
			    i < (fsc->nargs - 1) ? "," : "");
#endif
			if (sc && !(sc->args[i].type & OUT)) {
				fsc->s_args[i] = print_arg(&sc->args[i],
				    fsc->args, 0, trussinfo);
			}
		}
#if DEBUG
		fprintf(stderr, ")\n");
#endif
	}

#if DEBUG
	fprintf(trussinfo->outfile, "\n");
#endif

	trussinfo->curthread->fsc = fsc;
}
コード例 #6
0
ファイル: arm-fbsd.c プロジェクト: JabirTech/Source
void
arm_syscall_entry(struct trussinfo *trussinfo, int nargs)
{
	struct ptrace_io_desc iorequest;
	struct reg regs;
	struct freebsd_syscall *fsc;
	struct syscall *sc;
	lwpid_t tid;
	int i, syscall_num;
	register_t *ap;

	tid = trussinfo->curthread->tid;

	if (ptrace(PT_GETREGS, tid, (caddr_t)&regs, 0) < 0) {
		fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
		return;
	}
	ap = &regs.r[0];

	/*
	 * FreeBSD has two special kinds of system call redirctions --
	 * SYS_syscall, and SYS___syscall.  The former is the old syscall()
	 * routine, basically; the latter is for quad-aligned arguments.
	 */
#ifdef __ARM_EABI__
	syscall_num = regs.r[7];
#else
	if ((syscall_num = ptrace(PT_READ_I, tid, 
	    (caddr_t)(regs.r[_REG_PC] - INSN_SIZE), 0)) == -1) {
		fprintf(trussinfo->outfile, "-- CANNOT READ PC --\n");
		return;
	}
	syscall_num = syscall_num & 0x000fffff;
#endif
	switch (syscall_num) {
	case SYS_syscall:
		syscall_num = *ap++;
		nargs--;
		break;
	case SYS___syscall:
		syscall_num = ap[_QUAD_LOWWORD];
		ap += 2;
		nargs -= 2;
		break;
	}

	fsc = alloc_fsc();
	if (fsc == NULL)
		return;
	fsc->number = syscall_num;
	fsc->name = (syscall_num < 0 || syscall_num >= nsyscalls) ?
	    NULL : syscallnames[syscall_num];
	if (!fsc->name) {
		fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n",
		    syscall_num);
	}

	if (fsc->name && (trussinfo->flags & FOLLOWFORKS) &&
	    (strcmp(fsc->name, "fork") == 0 ||
	    strcmp(fsc->name, "rfork") == 0 ||
	    strcmp(fsc->name, "vfork") == 0))
		trussinfo->curthread->in_fork = 1;

	if (nargs == 0)
		return;

	fsc->args = malloc((1 + nargs) * sizeof(unsigned long));
	switch (nargs) {
	default:
		/*
		 * The OS doesn't seem to allow more than 10 words of
		 * parameters (yay!).	So we shouldn't be here.
		 */
		warn("More than 10 words (%d) of arguments!\n", nargs);
		break;
	case 10:
	case 9:
	case 8:
	case 7:
	case 6:
	case 5:
		/*
		 * If there are 7-10 words of arguments, they are placed
		 * on the stack, as is normal for other processors.
		 * The fall-through for all of these is deliberate!!!
		 */
		// XXX BAD constant used here
		iorequest.piod_op = PIOD_READ_D;
		iorequest.piod_offs = (void *)(regs.r[_REG_SP] +
		    4 * sizeof(uint32_t));
		iorequest.piod_addr = &fsc->args[4];
		iorequest.piod_len = (nargs - 4) * sizeof(fsc->args[0]);
		ptrace(PT_IO, tid, (caddr_t)&iorequest, 0);
		if (iorequest.piod_len == 0)
			return;
	case 4:	fsc->args[3] = ap[3];
	case 3:	fsc->args[2] = ap[2];
	case 2:	fsc->args[1] = ap[1];
	case 1:	fsc->args[0] = ap[0];
	case 0: break;
	}

	sc = NULL;
	if (fsc->name)
		sc = get_syscall(fsc->name);
	if (sc)
		fsc->nargs = sc->nargs;
	else {
#if DEBUG
		fprintf(trussinfo->outfile, "unknown syscall %s -- setting "
		    "args to %d\n", fsc->name, nargs);
#endif
		fsc->nargs = nargs;
	}

	fsc->s_args = calloc(1, (1 + fsc->nargs) * sizeof(char *));
	fsc->sc = sc;

	/*
	 * At this point, we set up the system call arguments.
	 * We ignore any OUT ones, however -- those are arguments that
	 * are set by the system call, and so are probably meaningless
	 * now.	This doesn't currently support arguments that are
	 * passed in *and* out, however.
	 */

	if (fsc->name) {
#if DEBUG
		fprintf(stderr, "syscall %s(", fsc->name);
#endif
		for (i = 0; i < fsc->nargs; i++) {
#if DEBUG
			fprintf(stderr, "0x%x%s", sc ?
			    fsc->args[sc->args[i].offset] : fsc->args[i],
			    i < (fsc->nargs - 1) ? "," : "");
#endif
			if (sc && !(sc->args[i].type & OUT)) {
				fsc->s_args[i] = print_arg(&sc->args[i],
				    fsc->args, 0, trussinfo);
			}
		}
#if DEBUG
		fprintf(stderr, ")\n");
#endif
	}

#if DEBUG
	fprintf(trussinfo->outfile, "\n");
#endif

	if (fsc->name != NULL && (strcmp(fsc->name, "execve") == 0 ||
	    strcmp(fsc->name, "exit") == 0)) {
		/*
		 * XXX
		 * This could be done in a more general
		 * manner but it still wouldn't be very pretty.
		 */
		if (strcmp(fsc->name, "execve") == 0) {
			if ((trussinfo->flags & EXECVEARGS) == 0) {
				if (fsc->s_args[1]) {
					free(fsc->s_args[1]);
					fsc->s_args[1] = NULL;
				}
			}
			if ((trussinfo->flags & EXECVEENVS) == 0) {
				if (fsc->s_args[2]) {
					free(fsc->s_args[2]);
					fsc->s_args[2] = NULL;
				}
			}
		}
	}
	trussinfo->curthread->fsc = fsc;
}
コード例 #7
0
ファイル: amd64-linux32.c プロジェクト: AhmadTux/freebsd
void
amd64_linux32_syscall_entry(struct trussinfo *trussinfo, int nargs) {
  struct reg regs;
  int syscall_num;
  int i;
  struct syscall *sc;

  cpid = trussinfo->curthread->tid;

  clear_fsc();
  
  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
  {
    fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
    return;
  } 
  syscall_num = regs.r_rax;

  fsc.number = syscall_num;
  fsc.name =
    (syscall_num < 0 || syscall_num >= nsyscalls) ? NULL : linux32_syscallnames[syscall_num];
  if (!fsc.name) {
    fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall_num);
  }

  if (fsc.name && (trussinfo->flags & FOLLOWFORKS)
   && ((!strcmp(fsc.name, "linux_fork")
    || !strcmp(fsc.name, "linux_vfork"))))
  {
    trussinfo->curthread->in_fork = 1;
  }

  if (nargs == 0)
    return;

  /*
   * Linux passes syscall arguments in registers, not
   * on the stack.  Fortunately, we've got access to the
   * register set.  Note that we don't bother checking the
   * number of arguments.  And what does linux do for syscalls
   * that have more than five arguments?
   */

  fsc.args[0] = regs.r_rbx;
  fsc.args[1] = regs.r_rcx;
  fsc.args[2] = regs.r_rdx;
  fsc.args[3] = regs.r_rsi;
  fsc.args[4] = regs.r_rdi;

  sc = get_syscall(fsc.name);
  if (sc) {
    fsc.nargs = sc->nargs;
  } else {
#if DEBUG
    fprintf(trussinfo->outfile, "unknown syscall %s -- setting args to %d\n",
	   fsc.name, nargs);
#endif
    fsc.nargs = nargs;
  }

  fsc.s_args = calloc(1, (1+fsc.nargs) * sizeof(char*));
  fsc.sc = sc;

  /*
   * At this point, we set up the system call arguments.
   * We ignore any OUT ones, however -- those are arguments that
   * are set by the system call, and so are probably meaningless
   * now.  This doesn't currently support arguments that are
   * passed in *and* out, however.
   */

  if (fsc.name) {

#if DEBUG
    fprintf(stderr, "syscall %s(", fsc.name);
#endif
    for (i = 0; i < fsc.nargs; i++) {
#if DEBUG
      fprintf(stderr, "0x%x%s",
	      sc
	      ? fsc.args[sc->args[i].offset]
	      : fsc.args[i],
	      i < (fsc.nargs - 1) ? "," : "");
#endif
      if (sc && !(sc->args[i].type & OUT)) {
	fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo);
      }
    }
#if DEBUG
    fprintf(stderr, ")\n");
#endif
  }

#if DEBUG
  fprintf(trussinfo->outfile, "\n");
#endif

  if (fsc.name != NULL &&
      (!strcmp(fsc.name, "linux_execve") || !strcmp(fsc.name, "exit"))) {

    /* XXX
     * This could be done in a more general
     * manner but it still wouldn't be very pretty.
     */
    if (!strcmp(fsc.name, "linux_execve")) {
        if ((trussinfo->flags & EXECVEARGS) == 0)
          if (fsc.s_args[1]) {
            free(fsc.s_args[1]);
            fsc.s_args[1] = NULL;
          }
        if ((trussinfo->flags & EXECVEENVS) == 0)
          if (fsc.s_args[2]) {
            free(fsc.s_args[2]);
            fsc.s_args[2] = NULL;
          }
    }
  }

  return;
}
コード例 #8
0
ファイル: aslr_perfs.c プロジェクト: SabunMacTavish/pmcma
/*
* Run a command passed as an argument,
* stop when execle + dynamic loading is done
* record mapping to further study ASLR
*/
int run_aslr_tests(int argc, char *argv, char **envp)
{
	int status,s;
	pid_t child;
	siginfo_t si;
	int nmaps = 0;

	memset(&si, 0, sizeof(siginfo_t));

	/*
	 * We run the given command, wait for the
	 * mapping to be done, and read the map
	 */
	if ((child = fork()) < 0) {
		perror("fork:");
		exit(-1);
	} else if (!child) {	// child 

		FILE *f=fopen("/dev/zero","r");	// just in case it starts with a read...
		stdin=f;

		ptrace(PTRACE_TRACEME, 0, 0, 0);

		// drop privileges (if any)
//		setgid(gid);
//		setuid(uid);

		execle((char*)argv, (char*)argv, NULL,envp);
		perror("execle:");
		exit(-1);
	}

	while (1) {
		// Wait for an event
		while (waitpid(child,&status,0) < 0) {
			if (errno == ECHILD) {
				printf(" [!!] Child exited\n");
				exit(0);
			} else if (errno == EINTR) {
				continue;
			} else {
				perror("wait:");
				exit(-1);
			}
		}

		s=get_syscall(child);
//printf("syscall: %d\n",s);
		if(still_loading(s) || s == -1){
			ptrace(PTRACE_SYSCALL, child, 0, 0);
//		} else if (s == -1){
//			usleep(200);
		//	ptrace(PTRACE_SYSCALL, child, 0, 0);
//			goto done_tracing;

		}else{
			break;
		}
	}

	// read mapping
	nmaps = read_maps(child);
	if (debug_flag)
		printf("Number of maps read for aslr test: %d\n", nmaps);

	//kill child
	kill_pid(child);
	waitpid(child,&status,0);
	return 0;
}
コード例 #9
0
ファイル: i386-fbsd.c プロジェクト: AhmadTux/freebsd
void
i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
  struct reg regs;
  int syscall_num;
  int i;
  unsigned int parm_offset;
  struct syscall *sc = NULL;
  struct ptrace_io_desc iorequest;
  cpid = trussinfo->curthread->tid;

  clear_fsc();
  
  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
  {
    fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
    return;
  }
  parm_offset = regs.r_esp + sizeof(int);

  /*
   * FreeBSD has two special kinds of system call redirctions --
   * SYS_syscall, and SYS___syscall.  The former is the old syscall()
   * routine, basically; the latter is for quad-aligned arguments.
   */
  syscall_num = regs.r_eax;
  switch (syscall_num) {
  case SYS_syscall:
    syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
    parm_offset += sizeof(int);
    break;
  case SYS___syscall:
    syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
    parm_offset += sizeof(quad_t);
    break;
  }

  fsc.number = syscall_num;
  fsc.name =
    (syscall_num < 0 || syscall_num >= nsyscalls) ? NULL : syscallnames[syscall_num];
  if (!fsc.name) {
    fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall_num);
  }

  if (fsc.name && (trussinfo->flags & FOLLOWFORKS)
   && ((!strcmp(fsc.name, "fork")
    || !strcmp(fsc.name, "rfork")
    || !strcmp(fsc.name, "vfork"))))
  {
    trussinfo->curthread->in_fork = 1;
  }

  if (nargs == 0)
    return;

  fsc.args = malloc((1+nargs) * sizeof(unsigned long));
  iorequest.piod_op = PIOD_READ_D;
  iorequest.piod_offs = (void *)parm_offset;
  iorequest.piod_addr = fsc.args;
  iorequest.piod_len = (1+nargs) * sizeof(unsigned long);
  ptrace(PT_IO, cpid, (caddr_t)&iorequest, 0);
  if (iorequest.piod_len == 0)
    return;

  if (fsc.name)
  	sc = get_syscall(fsc.name);
  if (sc) {
    fsc.nargs = sc->nargs;
  } else {
#if DEBUG
    fprintf(trussinfo->outfile, "unknown syscall %s -- setting args to %d\n",
	   fsc.name, nargs);
#endif
    fsc.nargs = nargs;
  }

  fsc.s_args = calloc(1, (1+fsc.nargs) * sizeof(char*));
  fsc.sc = sc;

  /*
   * At this point, we set up the system call arguments.
   * We ignore any OUT ones, however -- those are arguments that
   * are set by the system call, and so are probably meaningless
   * now.  This doesn't currently support arguments that are
   * passed in *and* out, however.
   */

  if (fsc.name) {

#if DEBUG
    fprintf(stderr, "syscall %s(", fsc.name);
#endif
    for (i = 0; i < fsc.nargs; i++) {
#if DEBUG
      fprintf(stderr, "0x%x%s",
	      sc
	      ? fsc.args[sc->args[i].offset]
	      : fsc.args[i],
	      i < (fsc.nargs - 1) ? "," : "");
#endif
      if (sc && !(sc->args[i].type & OUT)) {
	fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo);
      }
    }
#if DEBUG
    fprintf(stderr, ")\n");
#endif
  }

#if DEBUG
  fprintf(trussinfo->outfile, "\n");
#endif

  if (fsc.name != NULL &&
      (!strcmp(fsc.name, "execve") || !strcmp(fsc.name, "exit"))) {

    /* XXX
     * This could be done in a more general
     * manner but it still wouldn't be very pretty.
     */
    if (!strcmp(fsc.name, "execve")) {
        if ((trussinfo->flags & EXECVEARGS) == 0)
          if (fsc.s_args[1]) {
            free(fsc.s_args[1]);
            fsc.s_args[1] = NULL;
          }
        if ((trussinfo->flags & EXECVEENVS) == 0)
          if (fsc.s_args[2]) {
            free(fsc.s_args[2]);
            fsc.s_args[2] = NULL;
          }
    }

  }

  return;
}
コード例 #10
0
ファイル: judge_main.cpp プロジェクト: nobystander/WhutOJ
void watch(pid_t pid,enum judge_status &judge_status,long &max_used_memory,long &used_time,long error_size)
{
    long init_used_time = used_time;
    long used_memory;

    init_syscall_limit();

    int status;
    struct rusage ru;

    while(1)
    {
        pid_t pid_ret = wait4(pid,&status,0,&ru);
        if(pid_ret != pid)
            error_report("wait4");

        //TLE
        used_time = init_used_time + ru.ru_utime.tv_sec * 100 + ru.ru_utime.tv_usec / 1000;
        if(used_time >= time_limit * 1000)
        {
            judge_status = JUDGE_TLE;
            goto send_kill;
        }

        //MLE
        if (language == LANG_JAVA)
        {
            // JVM GC ask VM before need, so used kernel page fault times and page size.
            used_memory = get_page_fault_memory(ru, pid);
        } else
        {
            // other use VmPeak
            used_memory = get_proc_status(pid, "VmPeak:") << 10;
        }

        if(used_memory > max_used_memory)
            max_used_memory = used_memory;
        if(max_used_memory > memory_limit)
        {
            judge_status = JUDGE_MLE;
            goto send_kill;
        }


        //RE 判断stderr
        if(get_file_size(code_error_path) > error_size)
        {
            judge_status = JUDGE_RE;
            goto send_kill;
        }

        //进程退出
        if(WIFEXITED(status))
        {
            int exitcode = WEXITSTATUS(status);
            if(exitcode != 0)
            {
                judge_status = JUDGE_RE;
            }
            break;
        }

        //未捕捉到信号而中止
        if(WIFSIGNALED(status))
        {
            int sigcode = WTERMSIG(status);
            break;
        }

        // 未捕捉信号而暂停
        // 子进程被追踪(ptrace)或调用WUN-TRACED时才可能发生
        if (WIFSTOPPED(status))
        {

            int sigcode = WSTOPSIG(status);

            switch (sigcode) {
                case SIGSTOP:
                    // JAVA 使用 SIGSTOP 等待下次 CPU 运行
                    if (language != LANG_JAVA) {
                        judge_status = JUDGE_RE;
                        goto send_kill;
                    }
                case SIGTRAP:
                    // c++ case 语句中不能出现带初始化的变量声明
                    unsigned long syscall;
                    syscall = get_syscall(pid);
                    //printf("System call: %lu\n", syscall);
                    switch (check_syscall(syscall)) {
                        case 0:

                            judge_status = JUDGE_RE;
                            goto send_kill;
                        case 1:
                            ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
                            break;
                        case 2:
                            //ptrace(PTRACE_SETREGS, pid, NULL, NULL);
                            break;
                    }

                    break;
                case SIGSEGV:
                    judge_status = JUDGE_MLE;
                    goto send_kill;
                case SIGCHLD:
                case SIGALRM:
                    alarm(0);
                case SIGXCPU:
                case SIGKILL:
                    judge_status = JUDGE_TLE;
                    goto send_kill;
                case SIGXFSZ:
                    judge_status = JUDGE_OLE;
                    goto send_kill;
                default:
                    judge_status = JUDGE_SE;
                    goto send_kill;
            }

        }
    }

    return;
    send_kill:
        ptrace(PTRACE_KILL,pid,NULL,NULL);
}
コード例 #11
0
ファイル: compile_ioshark.c プロジェクト: MIPS/system-extras
/*
 * For each tracefile, we first create in-memory structures, then once
 * we've processed each tracefile completely, we write out the in-memory
 * structures and free them.
 */
int main(int argc, char **argv)
{
	FILE *fp;
	char path[512];
	char syscall[512];
	char lseek_action_str[512];
	char *s;
	char open_flags_str[64];
	void *db_node;
	int num_io_operations = 0;
	struct ioshark_header header;
	struct ioshark_file_operation *disk_file_op;
	struct in_mem_file_op *in_mem_fop;
	struct stat st;
	char *infile, *outfile;
	struct timeval prev_time;
	char trace_type[64];

	progname = argv[0];
	if (argc != 3) {
		usage();
		exit(EXIT_FAILURE);
	}
	infile = argv[1];
	outfile = argv[2];
	if (stat(infile, &st) < 0) {
		fprintf(stderr, "%s Can't stat %s\n",
			progname, infile);
		exit(EXIT_FAILURE);
	}
	if (st.st_size == 0) {
		fprintf(stderr, "%s Empty file %s\n",
			progname, infile);
		exit(EXIT_FAILURE);
	}
	init_prev_time(&prev_time);
	init_filename_cache();
	fp = fopen(infile, "r");
	if (fp == NULL) {
		fprintf(stderr, "%s Can't open %s\n",
			progname, infile);
		exit(EXIT_FAILURE);
	}
	while (fgets(in_buf, 2048, fp)) {
		s = in_buf;
		while (isspace(*s))
			s++;
		in_mem_fop = malloc(sizeof(struct in_mem_file_op));
		disk_file_op = &in_mem_fop->disk_file_op;
		disk_file_op->delta_us = get_delta_ts(s, &prev_time);
		get_tracetype(s, trace_type);
		if (strcmp(trace_type, "strace") == 0) {
			get_syscall(s, syscall);
			disk_file_op->file_op = map_syscall(syscall);
		} else
			disk_file_op->file_op = map_syscall("ftrace");
		get_pathname(s, path, disk_file_op->file_op);
		db_node = files_db_add(path);
		disk_file_op->fileno = files_db_get_fileno(db_node);
		switch (disk_file_op->file_op) {
		case IOSHARK_LLSEEK:
		case IOSHARK_LSEEK:
			get_lseek_offset_action(s,
					disk_file_op->file_op,
					&disk_file_op->lseek_offset,
					lseek_action_str);
			disk_file_op->lseek_action =
				map_lseek_action(lseek_action_str);
			if (disk_file_op->lseek_action == SEEK_SET)
				files_db_update_size(db_node,
						     disk_file_op->lseek_offset);
			break;
		case IOSHARK_PREAD64:
		case IOSHARK_PWRITE64:
			get_prw64_offset_len(s,
					     &disk_file_op->prw_offset,
					     (u_int64_t *)&disk_file_op->prw_len);
			files_db_update_size(db_node,
					     disk_file_op->prw_offset +
					     disk_file_op->prw_len);
			break;
		case IOSHARK_READ:
		case IOSHARK_WRITE:
			get_rw_len(s, (u_int64_t *)&disk_file_op->rw_len);
			files_db_add_to_size(db_node,
					     disk_file_op->rw_len);
			break;
		case IOSHARK_MMAP:
		case IOSHARK_MMAP2:
			get_mmap_offset_len_prot(s,
				    &disk_file_op->mmap_prot,
				    &disk_file_op->mmap_offset,
				    (u_int64_t *)&disk_file_op->mmap_len);
			files_db_update_size(db_node,
				     disk_file_op->mmap_offset +
				     disk_file_op->mmap_len);
			break;
		case IOSHARK_OPEN:
			disk_file_op->open_mode = 0;
			get_openat_flags_mode(s, open_flags_str,
				      &disk_file_op->open_mode);
			disk_file_op->open_flags =
				map_open_flags(open_flags_str);
			break;
		case IOSHARK_FSYNC:
		case IOSHARK_FDATASYNC:
			break;
		case IOSHARK_CLOSE:
			break;
		case IOSHARK_MAPPED_PREAD:
			/* Convert a mmap'ed read into a PREAD64 */
			disk_file_op->file_op = IOSHARK_PREAD64;
			get_ftrace_offset_len(s,
					      &disk_file_op->prw_offset,
					      (u_int64_t *)&disk_file_op->prw_len);
			files_db_update_size(db_node,
					     disk_file_op->prw_offset +
					     disk_file_op->prw_len);
			break;
		default:
			break;
		}
		/* Chain at the end */
		num_io_operations++;
		in_mem_fop->next = NULL;
		if (in_mem_file_op_head == NULL) {
			in_mem_file_op_tail = in_mem_fop;
			in_mem_file_op_head = in_mem_fop;
		} else {
			in_mem_file_op_tail->next = in_mem_fop;
			in_mem_file_op_tail = in_mem_fop;
		}
	}
	fclose(fp);
	/*
	 * Now we can write everything out to the output tracefile.
	 */
	fp = fopen(outfile, "w+");
	if (fp == NULL) {
		fprintf(stderr, "%s Can't open trace.outfile\n",
			progname);
		exit(EXIT_FAILURE);
	}
	header.num_io_operations = num_io_operations;
	header.num_files = files_db_get_total_obj();
	if (fwrite(&header, sizeof(struct ioshark_header), 1, fp) != 1) {
		fprintf(stderr, "%s Write error trace.outfile\n",
			progname);
		exit(EXIT_FAILURE);
	}
	files_db_write_objects(fp);
	while (in_mem_file_op_head != NULL) {
		struct in_mem_file_op *temp;

		disk_file_op = &in_mem_file_op_head->disk_file_op;
		if (fwrite(disk_file_op,
			   sizeof(struct ioshark_file_operation), 1, fp) != 1) {
			fprintf(stderr, "%s Write error trace.outfile\n",
				progname);
			exit(EXIT_FAILURE);
		}
		temp = in_mem_file_op_head;
		in_mem_file_op_head = in_mem_file_op_head->next;
		free(temp);
	}
	store_filename_cache();
}