Example #1
0
void efab_signal_process_fini(struct mm_signal_data *tramp_data)
{
  int sig;

  OO_DEBUG_SIGNAL(ci_log("%s(%p) pid %d: current->flags=%x, "
                         "tramp_data->user_data=%p", __func__,
                         tramp_data, current->pid, (int)current->flags,
                         CI_USER_PTR_GET(tramp_data->user_data)));
  /* Check if we should really do anything */
  if( current->flags & PF_EXITING )
    return; /* the process is exiting */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
  if( current->in_execve )
    return; /* in execve() */
#endif
  if( CI_USER_PTR_GET(tramp_data->user_data) == NULL )
    return; /* nothing was inited */

  OO_DEBUG_SIGNAL(ci_log("%s(%p) pid %d: uninstall interception",
                         __func__, tramp_data, current->pid));
  for( sig = 1; sig <= _NSIG; sig++ ) {
    if( sig_kernel_only(sig) )
      continue;
    if( efab_signal_report_sigaction(sig, NULL, tramp_data) != 0 ) {
      ci_log("%s: ERROR: pid %d failed to back off signal %d handler",
             __func__, current->pid, sig);
      continue;
    }
  }
}
Example #2
0
void efab_signal_process_init(struct mm_signal_data *tramp_data)
{
  int sig;
  int rc;

  OO_DEBUG_SIGNAL(ci_log("%s(%p) pid %d",
                         __func__, tramp_data, current->pid));

  /* At start-of-day, we intercept all already-installed handlers
   * and deadly SIG_DFL */
  for( sig = 1; sig <= _NSIG; sig++ ) {
    struct k_sigaction *k;

    tramp_data->signal_data[sig - 1].type = OO_SIGHANGLER_USER |
                                            OO_SIGHANGLER_IGN_BIT;
    CI_USER_PTR_SET(tramp_data->signal_data[sig - 1].handler, NULL);

    /* Never, never intercept SIGKILL. You'll get deadlock since exit_group
     * sends SIGKILL to all other threads. */
    if( sig_kernel_only(sig) )
      continue;

    /* If this is our handler, do nothing.  This is second init from the
     * same process.  It happens in fork hooks, when second netif is
     * created, etc. */
    spin_lock_irq(&current->sighand->siglock);
    k = &current->sighand->action[sig - 1];
    if( k->sa.sa_handler == tramp_data->handler_postpone ) {
      spin_unlock_irq(&current->sighand->siglock);
      OO_DEBUG_SIGNAL(ci_log("%s: double init pid=%d",
                             __func__, current->pid));
      rc = copy_from_user(tramp_data->signal_data,
                          CI_USER_PTR_GET(tramp_data->user_data),
                          sizeof(tramp_data->signal_data));
      if( rc != 0 )
        ci_log("%s: ERROR: failed to copy signal data (%d)", __func__, rc);

      break;
    }
    spin_unlock_irq(&current->sighand->siglock);

    /* Ignore any errors */
    (void) efab_signal_substitute(sig, NULL, tramp_data);
  }

  tramp_data->kernel_sighand = current->sighand;
}
Example #3
0
static struct pid *good_sigevent(sigevent_t * event)
{
	struct task_struct *rtn = current->group_leader;
	int sig = event->sigev_signo;

	if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
		(!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) ||
		 !same_thread_group(rtn, current) ||
		 (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
		return NULL;

	if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) &&
	    (sig <= 0 || sig > SIGRTMAX || sig_kernel_only(sig) ||
	     sig_kernel_coredump(sig)))
		return NULL;

	return task_pid(rtn);
}
Example #4
0
static int
efab_signal_do_sigaction(int sig, struct sigaction *act,
                         struct sigaction *oact,
                         struct mm_signal_data *tramp_data,
                         int *out_pass_to_kernel)
{
  int rc = 0;

  if( !valid_signal(sig) || sig < 1 || (act != NULL && sig_kernel_only(sig)) )
    return -EINVAL;


  if( oact != NULL ) {
    rc = efab_signal_report_sigaction(sig, oact, tramp_data);
    if( rc != 0 )
      return rc;
  }

  if( act != NULL ) {
    sigdelsetmask(&act->sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));

  /* If the signal is ignored now, we should ignore all already-pending
   * signals.  Instead of doing it, pass this to OS. */
    if( act->sa_handler == SIG_IGN ||
        (act->sa_handler == SIG_DFL && sig_kernel_ignore(sig)) )
      *out_pass_to_kernel = 1;
    else if( act->sa_flags & SA_ONSTACK && !tramp_data->sa_onstack_intercept )
      *out_pass_to_kernel = 1;
    else
      rc = efab_signal_substitute(sig, act, tramp_data);
  }
  else
    efab_signal_recheck(sig, tramp_data);

  return rc;
}