Example #1
0
/* For asynchronous cancellation we use a signal.  This is the handler.  */
static void
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
{
  /* Safety check.  It would be possible to call this function for
     other signals and send a signal from another process.  This is not
     correct and might even be a security problem.  Try to catch as
     many incorrect invocations as possible.  */
  if (sig != SIGSETXID
#ifdef __ASSUME_CORRECT_SI_PID
      /* Kernels before 2.5.75 stored the thread ID and not the process
	 ID in si_pid so we skip this test.  */
      || si->si_pid != THREAD_GETMEM (THREAD_SELF, pid)
#endif
      || si->si_code != SI_TKILL)
    return;

  INTERNAL_SYSCALL_DECL (err);
  INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
			__xidcmd->id[1], __xidcmd->id[2]);

  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
    lll_futex_wake (&__xidcmd->cntr, 1);

  /* Reset the SETXID flag.  */
  struct pthread *self = THREAD_SELF;
  int flags = THREAD_GETMEM (self, cancelhandling);
  THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);

  /* And release the futex.  */
  self->setxid_futex = 1;
  lll_futex_wake (&self->setxid_futex, 1);
}
Example #2
0
long int
syscall (long int syscall_number, long int arg1, long int arg2, long int arg3,
	 long int arg4, long int arg5, long int arg6, long int arg7)
{
  long int ret;
  INTERNAL_SYSCALL_DECL (err);

  ret = INTERNAL_SYSCALL_NCS (syscall_number, err, 7, arg1, arg2, arg3, arg4,
			      arg5, arg6, arg7);

  if (INTERNAL_SYSCALL_ERROR_P (ret, err))
    return __syscall_error (ret);

  return ret;
}
Example #3
0
long syscall (long syscall_number, long arg1, long arg2, long arg3,
	      long arg4, long arg5, long arg6, long arg7)
{
  long ret, err; 

  ret = INTERNAL_SYSCALL_NCS(syscall_number, err, 7, arg1, arg2, arg3, arg4,
			     arg5, arg6, arg7);

  if (INTERNAL_SYSCALL_ERROR_P (ret, err))
    {
      extern long __syscall_error() attribute_hidden;
      return __syscall_error();
    }

  return ret;
}
/* For asynchronous cancellation we use a signal.  This is the handler.  */
static void
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
{
#ifdef __ASSUME_CORRECT_SI_PID
  /* Determine the process ID.  It might be negative if the thread is
     in the middle of a fork() call.  */
  pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
  if (__builtin_expect (pid < 0, 0))
    pid = -pid;
#endif

  /* Safety check.  It would be possible to call this function for
     other signals and send a signal from another process.  This is not
     correct and might even be a security problem.  Try to catch as
     many incorrect invocations as possible.  */
  if (sig != SIGSETXID
#ifdef __ASSUME_CORRECT_SI_PID
      /* Kernels before 2.5.75 stored the thread ID and not the process
	 ID in si_pid so we skip this test.  */
      || si->si_pid != pid
#endif
      || si->si_code != SI_TKILL)
    return;

  INTERNAL_SYSCALL_DECL (err);
  INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
			__xidcmd->id[1], __xidcmd->id[2]);

  /* Reset the SETXID flag.  */
  struct pthread *self = THREAD_SELF;
  int flags, newval;
  do
    {
      flags = THREAD_GETMEM (self, cancelhandling);
      newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
					  flags & ~SETXID_BITMASK, flags);
    }
  while (flags != newval);

  /* And release the futex.  */
  self->setxid_futex = 1;
  lll_futex_wake (&self->setxid_futex, 1, LLL_PRIVATE);

  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
    lll_futex_wake (&__xidcmd->cntr, 1, LLL_PRIVATE);
}
Example #5
0
/* We use the SIGSETXID signal in the setuid, setgid, etc. implementations to
   tell each thread to call the respective setxid syscall on itself.  This is
   the handler.  */
static void
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
{
  /* Determine the process ID.  It might be negative if the thread is
     in the middle of a fork() call.  */
  pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
  int result;
  if (__glibc_unlikely (pid < 0))
    pid = -pid;

  /* Safety check.  It would be possible to call this function for
     other signals and send a signal from another process.  This is not
     correct and might even be a security problem.  Try to catch as
     many incorrect invocations as possible.  */
  if (sig != SIGSETXID
      || si->si_pid != pid
      || si->si_code != SI_TKILL)
    return;

  INTERNAL_SYSCALL_DECL (err);
  result = INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
				 __xidcmd->id[1], __xidcmd->id[2]);
  int error = 0;
  if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (result, err)))
    error = INTERNAL_SYSCALL_ERRNO (result, err);
  __nptl_setxid_error (__xidcmd, error);

  /* Reset the SETXID flag.  */
  struct pthread *self = THREAD_SELF;
  int flags, newval;
  do
    {
      flags = THREAD_GETMEM (self, cancelhandling);
      newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
					  flags & ~SETXID_BITMASK, flags);
    }
  while (flags != newval);

  /* And release the futex.  */
  self->setxid_futex = 1;
  futex_wake (&self->setxid_futex, 1, FUTEX_PRIVATE);

  if (atomic_decrement_val (&__xidcmd->cntr) == 0)
    futex_wake ((unsigned int *) &__xidcmd->cntr, 1, FUTEX_PRIVATE);
}