Blame hurd/catch-exc.c

Packit Service 82fcde
/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <mach/exc_server.h>
Packit Service 82fcde
#include <hurd/signal.h>
Packit Service 82fcde
#include <assert.h>
Packit Service 82fcde
Packit Service 82fcde
/* Called by the microkernel when a thread gets an exception.  */
Packit Service 82fcde
Packit Service 82fcde
kern_return_t
Packit Service 82fcde
_S_catch_exception_raise (mach_port_t port,
Packit Service 82fcde
			  thread_t thread,
Packit Service 82fcde
			  task_t task,
Packit Service 82fcde
#ifdef EXC_MASK_ALL		/* New interface flavor.  */
Packit Service 82fcde
			  exception_type_t exception,
Packit Service 82fcde
			  exception_data_t code,
Packit Service 82fcde
			  mach_msg_type_number_t codeCnt
Packit Service 82fcde
#else				/* Vanilla Mach 3.0 interface.  */
Packit Service 82fcde
			  integer_t exception,
Packit Service 82fcde
			  integer_t code, integer_t subcode
Packit Service 82fcde
#endif
Packit Service 82fcde
			  )
Packit Service 82fcde
{
Packit Service 82fcde
  struct hurd_sigstate *ss;
Packit Service 82fcde
  int signo;
Packit Service 82fcde
  struct hurd_signal_detail d;
Packit Service 82fcde
Packit Service 82fcde
  if (task != __mach_task_self ())
Packit Service 82fcde
    /* The sender wasn't the kernel.  */
Packit Service 82fcde
    return EPERM;
Packit Service 82fcde
Packit Service 82fcde
  d.exc = exception;
Packit Service 82fcde
#ifdef EXC_MASK_ALL
Packit Service 82fcde
  assert (codeCnt >= 2);
Packit Service 82fcde
  d.exc_code = code[0];
Packit Service 82fcde
  d.exc_subcode = code[1];
Packit Service 82fcde
#else
Packit Service 82fcde
  d.exc_code = code;
Packit Service 82fcde
  d.exc_subcode = subcode;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  /* Call the machine-dependent function to translate the Mach exception
Packit Service 82fcde
     codes into a signal number and subcode.  */
Packit Service 82fcde
  _hurd_exception2signal (&d, &signo);
Packit Service 82fcde
Packit Service 82fcde
  /* Find the sigstate structure for the faulting thread.  */
Packit Service 82fcde
  __mutex_lock (&_hurd_siglock);
Packit Service 82fcde
  for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
Packit Service 82fcde
    if (ss->thread == thread)
Packit Service 82fcde
      break;
Packit Service 82fcde
  __mutex_unlock (&_hurd_siglock);
Packit Service 82fcde
  if (ss == NULL)
Packit Service 82fcde
    ss = _hurd_thread_sigstate (thread); /* Allocate a fresh one.  */
Packit Service 82fcde
Packit Service 82fcde
  if (__spin_lock_locked (&ss->lock))
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Loser.  The thread faulted with its sigstate lock held.  Its
Packit Service 82fcde
	 sigstate data is now suspect.  So we reset the parts of it which
Packit Service 82fcde
	 could cause trouble for the signal thread.  Anything else
Packit Service 82fcde
	 clobbered therein will just hose this user thread, but it's
Packit Service 82fcde
	 faulting already.
Packit Service 82fcde
Packit Service 82fcde
	 This is almost certainly a library bug: unless random memory
Packit Service 82fcde
	 clobberation caused the sigstate lock to gratuitously appear held,
Packit Service 82fcde
	 no code should do anything that can fault while holding the
Packit Service 82fcde
	 sigstate lock.  */
Packit Service 82fcde
Packit Service 82fcde
      __spin_unlock (&ss->critical_section_lock);
Packit Service 82fcde
      ss->context = NULL;
Packit Service 82fcde
      __spin_unlock (&ss->lock);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Post the signal.  */
Packit Service 82fcde
  _hurd_internal_post_signal (ss, signo, &d,
Packit Service 82fcde
			      MACH_PORT_NULL, MACH_MSG_TYPE_PORT_SEND,
Packit Service 82fcde
			      0);
Packit Service 82fcde
Packit Service 82fcde
  return KERN_SUCCESS;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifdef EXC_MASK_ALL
Packit Service 82fcde
/* XXX New interface flavor has additional RPCs that we could be using
Packit Service 82fcde
   instead.  These RPCs roll a thread_get_state/thread_set_state into
Packit Service 82fcde
   the message, so the signal thread ought to use these to save some calls.
Packit Service 82fcde
 */
Packit Service 82fcde
kern_return_t
Packit Service 82fcde
_S_catch_exception_raise_state (mach_port_t port,
Packit Service 82fcde
				exception_type_t exception,
Packit Service 82fcde
				exception_data_t code,
Packit Service 82fcde
				mach_msg_type_number_t codeCnt,
Packit Service 82fcde
				int *flavor,
Packit Service 82fcde
				thread_state_t old_state,
Packit Service 82fcde
				mach_msg_type_number_t old_stateCnt,
Packit Service 82fcde
				thread_state_t new_state,
Packit Service 82fcde
				mach_msg_type_number_t *new_stateCnt)
Packit Service 82fcde
{
Packit Service 82fcde
  abort ();
Packit Service 82fcde
  return KERN_FAILURE;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
kern_return_t
Packit Service 82fcde
_S_catch_exception_raise_state_identity (mach_port_t exception_port,
Packit Service 82fcde
					 thread_t thread,
Packit Service 82fcde
					 task_t task,
Packit Service 82fcde
					 exception_type_t exception,
Packit Service 82fcde
					 exception_data_t code,
Packit Service 82fcde
					 mach_msg_type_number_t codeCnt,
Packit Service 82fcde
					 int *flavor,
Packit Service 82fcde
					 thread_state_t old_state,
Packit Service 82fcde
					 mach_msg_type_number_t old_stateCnt,
Packit Service 82fcde
					 thread_state_t new_state,
Packit Service 82fcde
					 mach_msg_type_number_t *new_stateCnt)
Packit Service 82fcde
{
Packit Service 82fcde
  abort ();
Packit Service 82fcde
  return KERN_FAILURE;
Packit Service 82fcde
}
Packit Service 82fcde
#endif