/* 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); }
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; }
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); }
/* 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); }