diff options
62 files changed, 1252 insertions, 233 deletions
@@ -1,5 +1,38 @@ 2004-09-19 Ulrich Drepper <drepper@redhat.com> + * sysdeps/unix/sysv/linux/setegid.c [HAVE_PTR__NPTL_SETXID]: Call + callback to set IDs in all other threads as well. + * sysdeps/unix/sysv/linux/seteuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setegid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/seteuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setgid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setreuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise. + * sysdeps/unix/sysv/linux/i386/setresuid.c: Likewise. + * sysdeps/unix/sysv/linux/setuid.c: New file. + * sysdeps/unix/sysv/linux/setgid.c: New file. + * sysdeps/unix/sysv/linux/setreuid.c: New file. + * sysdeps/unix/sysv/linux/setregid.c: New file. + * sysdeps/unix/sysv/linux/setresuid.c: New file. + * sysdeps/unix/sysv/linux/setresgid.c: New file. + * sysdeps/unix/sysv/linux/i386/sysdep.h: Define INTERNAL_SYSCALL_NCS. + * sysdeps/unix/sysv/linux/ia64/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c: Use x86 version. + * sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list: Remove setresgid + and setresuid. + * nscd/aicache.c: Use pthread_seteuid_np instead of seteuid. + * nscd/grpcache.c: Likewise. + * nscd/hstcache.c: Likewise. + * nscd/pwdcache.c: Likewise. + * resolv/res_mkquery.c (res_nmkquery): Fix typo. 2004-09-18 Ulrich Drepper <drepper@redhat.com> diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index e31fd40..4a107da 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,25 @@ +2004-09-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Declare pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * pthread_setgid_np.c: New file. + * pthread_setuid_np.c: New file. + * pthread_setegid_np.c: New file. + * pthread_seteuid_np.c: New file. + * pthread_setregid_np.c: New file. + * pthread_setreuid_np.c: New file. + * pthread_setresgid_np.c: New file. + * pthread_setresuid_np.c: New file. + * Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid, + pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid, + pthread_setregid, and pthread_setresgid. + 2004-09-12 Ulrich Drepper <drepper@redhat.com> * sysdeps/pthread/pthread.h: Make rwlock prototypes available also diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile index 926de32..79d412d 100644 --- a/linuxthreads/Makefile +++ b/linuxthreads/Makefile @@ -51,7 +51,11 @@ libpthread-routines := attr cancel condvar join manager mutex ptfork \ ptw-open ptw-open64 ptw-pause ptw-pread ptw-pread64 \ ptw-pwrite ptw-pwrite64 ptw-tcdrain ptw-wait \ ptw-waitpid pt-system old_pthread_atfork pthread_atfork \ - ptcleanup + ptcleanup \ + pthread_setuid pthread_seteuid pthread_setreuid \ + pthread_setresuid \ + pthread_setgid pthread_setegid pthread_setregid \ + pthread_setresgid # Don't generate deps for calls with no sources. See sysdeps/unix/Makefile. omit-deps = $(unix-syscalls:%=ptw-%) diff --git a/linuxthreads/Versions b/linuxthreads/Versions index b9de161..5189697 100644 --- a/linuxthreads/Versions +++ b/linuxthreads/Versions @@ -172,6 +172,12 @@ libpthread { pthread_cond_wait; pthread_cond_timedwait; pthread_cond_signal; pthread_cond_broadcast; } + GLIBC_2.3.4 { + pthread_setuid_np; pthread_seteuid_np; pthread_setreuid_np; + pthread_setresuid_np; + pthread_setgid_np; pthread_setegid_np; pthread_setregid_np; + pthread_setresgid_np; + } GLIBC_PRIVATE { # Internal libc interface to libpthread __pthread_initialize; diff --git a/linuxthreads/pthread_setegid.c b/linuxthreads/pthread_setegid.c new file mode 100644 index 0000000..9e16828 --- /dev/null +++ b/linuxthreads/pthread_setegid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setegid_np (gid_t gid) +{ + return setegid (gid); +} diff --git a/linuxthreads/pthread_seteuid.c b/linuxthreads/pthread_seteuid.c new file mode 100644 index 0000000..9d29d81 --- /dev/null +++ b/linuxthreads/pthread_seteuid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_seteuid_np (uid_t uid) +{ + return seteuid (uid); +} diff --git a/linuxthreads/pthread_setgid.c b/linuxthreads/pthread_setgid.c new file mode 100644 index 0000000..db37dd1 --- /dev/null +++ b/linuxthreads/pthread_setgid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setgid_np (gid_t gid) +{ + return setgid (gid); +} diff --git a/linuxthreads/pthread_setregid.c b/linuxthreads/pthread_setregid.c new file mode 100644 index 0000000..bd75154 --- /dev/null +++ b/linuxthreads/pthread_setregid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setregid_np (gid_t rgid, gid_t egid) +{ + return setregid (rgid, egid); +} diff --git a/linuxthreads/pthread_setresgid.c b/linuxthreads/pthread_setresgid.c new file mode 100644 index 0000000..b570280 --- /dev/null +++ b/linuxthreads/pthread_setresgid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid) +{ + return setresgid (rgid, egid, sgid); +} diff --git a/linuxthreads/pthread_setresuid.c b/linuxthreads/pthread_setresuid.c new file mode 100644 index 0000000..ceb724de --- /dev/null +++ b/linuxthreads/pthread_setresuid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid) +{ + return setresuid (ruid, euid, suid); +} diff --git a/linuxthreads/pthread_setreuid.c b/linuxthreads/pthread_setreuid.c new file mode 100644 index 0000000..ae8933e --- /dev/null +++ b/linuxthreads/pthread_setreuid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setreuid_np (uid_t ruid, uid_t euid) +{ + return setreuid (ruid, euid); +} diff --git a/linuxthreads/pthread_setuid.c b/linuxthreads/pthread_setuid.c new file mode 100644 index 0000000..f82ccc1 --- /dev/null +++ b/linuxthreads/pthread_setuid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <unistd.h> + + +int +pthread_setuid_np (uid_t uid) +{ + return setuid (uid); +} diff --git a/linuxthreads/sysdeps/pthread/pthread.h b/linuxthreads/sysdeps/pthread/pthread.h index 86c7ff7..9589e96 100644 --- a/linuxthreads/sysdeps/pthread/pthread.h +++ b/linuxthreads/sysdeps/pthread/pthread.h @@ -681,6 +681,36 @@ extern int pthread_atfork (void (*__prepare) (void), extern void pthread_kill_other_threads_np (void) __THROW; + +#ifdef __USE_GNU +/* Change UID of calling thread. */ +extern int pthread_setuid_np (__uid_t __uid) __THROW; + +/* Change effective UID of calling thread. */ +extern int pthread_seteuid_np (__uid_t __uid) __THROW; + +/* Change real and effective UID of calling thread. */ +extern int pthread_setreuid_np (__uid_t __ruid, __uid_t __euid) __THROW; + +/* Change real, effective, and saved UID of calling thread. */ +extern int pthread_setresuid_np (__uid_t __ruid, __uid_t __euid, + __uid_t __suid) __THROW; + + +/* Change GID of calling thread. */ +extern int pthread_setgid_np (__gid_t __gid) __THROW; + +/* Change effective GID of calling thread. */ +extern int pthread_setegid_np (__gid_t __gid) __THROW; + +/* Change real and effective GID of calling thread. */ +extern int pthread_setregid_np (__gid_t __rgid, __gid_t __egid) __THROW; + +/* Change real, effective, and saved GID of calling thread. */ +extern int pthread_setresgid_np (__gid_t __rgid, __gid_t __egid, + __gid_t __sgid) __THROW; +#endif + __END_DECLS #endif /* pthread.h */ diff --git a/nptl/ChangeLog b/nptl/ChangeLog index db3aeba..e4bcfed 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,37 @@ +2004-09-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/allocrtsig.c: Allocate second signal for + internal use. + * allocatestack.c (__nptl_setxid): New function. + * descr.h (struct xid_command): Define type. + * init.c (pthread_functions): Add ptr__nptl_setxid initialization. + (sighandler_setxid): New function. + (__pthread_initialize_minimal): Register sighandler_setxid for + SIGCANCEL. + * pt-allocrtsig.c: Update comment. + * pthreadP.h: Define SIGSETXID. Declare __xidcmd variable. + Declare __nptl_setxid. + * sysdeps/pthread/pthread-functions.h: Add ptr__nptl_setxid. + * sysdeps/pthread/pthread.h: Declare pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * pthread_setgid_np.c: New file. + * pthread_setuid_np.c: New file. + * pthread_setegid_np.c: New file. + * pthread_seteuid_np.c: New file. + * pthread_setregid_np.c: New file. + * pthread_setreuid_np.c: New file. + * pthread_setresgid_np.c: New file. + * pthread_setresuid_np.c: New file. + * Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid, + pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid, + pthread_setregid, and pthread_setresgid. + 2004-09-18 Ulrich Drepper <drepper@redhat.com> * allocatestack.c (allocate_stack): Return EAGAIN instead of diff --git a/nptl/Makefile b/nptl/Makefile index e75752f..beaf6d7 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -115,7 +115,11 @@ libpthread-routines = init events version \ pthread_kill_other_threads \ pthread_getaffinity pthread_setaffinity \ pthread_attr_getaffinity pthread_attr_setaffinity \ - cleanup_routine unwind-forcedunwind + cleanup_routine unwind-forcedunwind \ + pthread_setuid pthread_seteuid pthread_setreuid \ + pthread_setresuid \ + pthread_setgid pthread_setegid pthread_setregid \ + pthread_setresgid libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind libpthread-static-only-routines = pthread_atfork diff --git a/nptl/Versions b/nptl/Versions index 7e8ac9e..ee4a6e0 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -228,6 +228,11 @@ libpthread { # New affinity interfaces. pthread_getaffinity_np; pthread_setaffinity_np; pthread_attr_getaffinity_np; pthread_attr_setaffinity_np; + + pthread_setuid_np; pthread_seteuid_np; pthread_setreuid_np; + pthread_setresuid_np; + pthread_setgid_np; pthread_setegid_np; pthread_setregid_np; + pthread_setresgid_np; } GLIBC_PRIVATE { diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index cbdd781..242da0a 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -19,6 +19,7 @@ #include <assert.h> #include <errno.h> +#include <signal.h> #include <stdint.h> #include <string.h> #include <unistd.h> @@ -26,7 +27,7 @@ #include <sys/param.h> #include <dl-sysdep.h> #include <tls.h> - +#include <lowlevellock.h> #ifndef NEED_SEPARATE_REGISTER_STACK @@ -815,6 +816,84 @@ __find_thread_by_id (pid_t tid) } #endif +void +attribute_hidden +__nptl_setxid (struct xid_command *cmdp) +{ + lll_lock (stack_cache_lock); + + __xidcmd = cmdp; + cmdp->cntr = 0; + + INTERNAL_SYSCALL_DECL (err); + + struct pthread *self = THREAD_SELF; + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t != self) + { + int val; +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID); +#endif + + if (!INTERNAL_SYSCALL_ERROR_P (val, err)) + atomic_increment (&cmdp->cntr); + } + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t != self) + { + int val; +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID); +#endif + + if (!INTERNAL_SYSCALL_ERROR_P (val, err)) + atomic_increment (&cmdp->cntr); + } + } + + int cur = cmdp->cntr; + while (cur != 0) + { + lll_futex_wait (&cmdp->cntr, cur); + cur = cmdp->cntr; + } + + lll_unlock (stack_cache_lock); +} + static inline void __attribute__((always_inline)) init_one_static_tls (struct pthread *curp, struct link_map *map) { diff --git a/nptl/descr.h b/nptl/descr.h index 3611698..0f8d347 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -92,6 +92,16 @@ struct pthread_unwind_buf }; +/* Opcodes and data types for communication with the signal handler to + change user/group IDs. */ +struct xid_command +{ + int syscall_no; + id_t id[3]; + volatile int cntr; +}; + + /* Thread descriptor data structure. */ struct pthread { diff --git a/nptl/init.c b/nptl/init.c index e58dae0..aad2c90 100644 --- a/nptl/init.c +++ b/nptl/init.c @@ -32,6 +32,7 @@ #include <version.h> #include <shlib-compat.h> #include <smp.h> +#include <lowlevellock.h> #ifndef __NR_set_tid_address @@ -131,7 +132,8 @@ static const struct pthread_functions pthread_functions = .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore, .ptr_nthreads = &__nptl_nthreads, .ptr___pthread_unwind = &__pthread_unwind, - .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd + .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd, + .ptr__nptl_setxid = __nptl_setxid }; # define ptr_pthread_functions &pthread_functions #else @@ -144,7 +146,7 @@ static void sigcancel_handler (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 thread. This is not + 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 != SIGCANCEL @@ -190,6 +192,34 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx) } +struct xid_command *__xidcmd attribute_hidden; + +/* 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); +} + + /* When using __thread for this, we do it in libc so as not to give libpthread its own TLS segment just for this. */ extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); @@ -242,6 +272,12 @@ __pthread_initialize_minimal_internal (void) (void) __libc_sigaction (SIGCANCEL, &sa, NULL); + /* Install the handle to change the threads' uid/gid. */ + sa.sa_sigaction = sighandler_setxid; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + + (void) __libc_sigaction (SIGSETXID, &sa, NULL); + /* The parent process might have left the signal blocked. Just in case, unblock it. We reuse the signal mask in the sigaction structure. It is already cleared. */ diff --git a/nptl/pt-allocrtsig.c b/nptl/pt-allocrtsig.c index 3598dbb..9481e15 100644 --- a/nptl/pt-allocrtsig.c +++ b/nptl/pt-allocrtsig.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -27,8 +27,9 @@ extern int __libc_current_sigrtmax_private (void); extern int __libc_allocate_rtsig_private (int high); -/* We reserve __SIGRTMIN for use as the cancelation signal. This - signal is used internally. */ +/* We reserve __SIGRTMIN for use as the cancellation signal and + __SIGRTMIN+1 to andle setuid et.al. These signals are used + internally. */ int __libc_current_sigrtmin (void) { diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index c0941f0..1fedce5 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -206,6 +206,13 @@ __do_cancel (void) #define SIGTIMER SIGCANCEL +/* Signal used to implement the setuid et.al. functions. */ +#define SIGSETXID (__SIGRTMIN + 1) + +/* Used to communicate with signal handler. */ +extern struct xid_command *__xidcmd attribute_hidden; + + /* Internal prototypes. */ /* Thread list handling. */ @@ -441,4 +448,6 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer extern void __nptl_deallocate_tsd (void) attribute_hidden; +extern void __nptl_setxid (struct xid_command *cmdp) attribute_hidden; + #endif /* pthreadP.h */ diff --git a/nptl/pthread_setegid.c b/nptl/pthread_setegid.c new file mode 100644 index 0000000..9252dfa --- /dev/null +++ b/nptl/pthread_setegid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define setegid pthread_setegid_np +#include <setegid.c> diff --git a/nptl/pthread_seteuid.c b/nptl/pthread_seteuid.c new file mode 100644 index 0000000..47bb698 --- /dev/null +++ b/nptl/pthread_seteuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define seteuid pthread_seteuid_np +#include <seteuid.c> diff --git a/nptl/pthread_setgid.c b/nptl/pthread_setgid.c new file mode 100644 index 0000000..b06bffb --- /dev/null +++ b/nptl/pthread_setgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setgid pthread_setgid_np +#include <setgid.c> diff --git a/nptl/pthread_setregid.c b/nptl/pthread_setregid.c new file mode 100644 index 0000000..7461d2b --- /dev/null +++ b/nptl/pthread_setregid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setregid pthread_setregid_np +#include <setregid.c> diff --git a/nptl/pthread_setresgid.c b/nptl/pthread_setresgid.c new file mode 100644 index 0000000..369fae2 --- /dev/null +++ b/nptl/pthread_setresgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresgid pthread_setresgid_np +#include <setresgid.c> diff --git a/nptl/pthread_setresuid.c b/nptl/pthread_setresuid.c new file mode 100644 index 0000000..ac57c0f --- /dev/null +++ b/nptl/pthread_setresuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresuid pthread_setresuid_np +#include <setresuid.c> diff --git a/nptl/pthread_setreuid.c b/nptl/pthread_setreuid.c new file mode 100644 index 0000000..aa804ab --- /dev/null +++ b/nptl/pthread_setreuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setreuid pthread_setreuid_np +#include <setreuid.c> diff --git a/nptl/pthread_setuid.c b/nptl/pthread_setuid.c new file mode 100644 index 0000000..ff949c8 --- /dev/null +++ b/nptl/pthread_setuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setuid pthread_setuid_np +#include <setuid.c> diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h index 23af214..b1e0fcb 100644 --- a/nptl/sysdeps/pthread/pthread-functions.h +++ b/nptl/sysdeps/pthread/pthread-functions.h @@ -93,6 +93,8 @@ struct pthread_functions void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) __attribute ((noreturn)) __cleanup_fct_attribute; void (*ptr__nptl_deallocate_tsd) (void); +#define HAVE_PTR__NPTL_SETXID + void (*ptr__nptl_setxid) (struct xid_command *); }; /* Variable in libc.so. */ diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h index 2766648..16f02d1 100644 --- a/nptl/sysdeps/pthread/pthread.h +++ b/nptl/sysdeps/pthread/pthread.h @@ -953,6 +953,36 @@ extern int pthread_atfork (void (*__prepare) (void), void (*__parent) (void), void (*__child) (void)) __THROW; + +#ifdef __USE_GNU +/* Change UID of calling thread. */ +extern int pthread_setuid_np (__uid_t __uid) __THROW; + +/* Change effective UID of calling thread. */ +extern int pthread_seteuid_np (__uid_t __uid) __THROW; + +/* Change real and effective UID of calling thread. */ +extern int pthread_setreuid_np (__uid_t __ruid, __uid_t __euid) __THROW; + +/* Change real, effective, and saved UID of calling thread. */ +extern int pthread_setresuid_np (__uid_t __ruid, __uid_t __euid, + __uid_t __suid) __THROW; + + +/* Change GID of calling thread. */ +extern int pthread_setgid_np (__gid_t __gid) __THROW; + +/* Change effective GID of calling thread. */ +extern int pthread_setegid_np (__gid_t __gid) __THROW; + +/* Change real and effective GID of calling thread. */ +extern int pthread_setregid_np (__gid_t __rgid, __gid_t __egid) __THROW; + +/* Change real, effective, and saved GID of calling thread. */ +extern int pthread_setresgid_np (__gid_t __rgid, __gid_t __egid, + __gid_t __sgid) __THROW; +#endif + __END_DECLS #endif /* pthread.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c index 51aeb22..b37d54d 100644 --- a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c +++ b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -20,7 +20,7 @@ #include <signal.h> -static int current_rtmin = __SIGRTMIN + 1; +static int current_rtmin = __SIGRTMIN + 2; static int current_rtmax = __SIGRTMAX; diff --git a/nscd/aicache.c b/nscd/aicache.c index 7fddd7d..8c2f3f1 100644 --- a/nscd/aicache.c +++ b/nscd/aicache.c @@ -80,7 +80,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, if (db->secure) { oldeuid = geteuid (); - seteuid (uid); + pthread_seteuid_np (uid); } static service_user *hosts_database; @@ -426,7 +426,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, _res.options = old_res_options; if (db->secure) - seteuid (oldeuid); + pthread_seteuid_np (oldeuid); if (dataset != NULL && !alloca_used) { diff --git a/nscd/grpcache.c b/nscd/grpcache.c index bf4a225..d9d9139 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -419,7 +419,7 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, if (db->secure) { oldeuid = geteuid (); - seteuid (uid); + pthread_seteuid_np (uid); } while (lookup (req->type, key, &resultbuf, buffer, buflen, &grp) != 0 @@ -456,7 +456,7 @@ addgrbyX (struct database_dyn *db, int fd, request_header *req, } if (db->secure) - seteuid (oldeuid); + pthread_seteuid_np (oldeuid); cache_addgr (db, fd, req, keystr, grp, uid, he, dh, errval); diff --git a/nscd/hstcache.c b/nscd/hstcache.c index 4066aee..d001e65 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -442,7 +442,7 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, if (db->secure) { oldeuid = geteuid (); - seteuid (uid); + pthread_seteuid_np (uid); } while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst) != 0 @@ -480,7 +480,7 @@ addhstbyX (struct database_dyn *db, int fd, request_header *req, } if (db->secure) - seteuid (oldeuid); + pthread_seteuid_np (oldeuid); cache_addhst (db, fd, req, key, hst, uid, he, dh, h_errno == TRY_AGAIN ? errval : 0); diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c index 93049ba..bfc9ec0 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -415,7 +415,7 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, if (db->secure) { oldeuid = geteuid (); - seteuid (c_uid); + pthread_seteuid_np (c_uid); } while (lookup (req->type, key, &resultbuf, buffer, buflen, &pwd) != 0 @@ -452,7 +452,7 @@ addpwbyX (struct database_dyn *db, int fd, request_header *req, } if (db->secure) - seteuid (oldeuid); + pthread_seteuid_np (oldeuid); /* Add the entry to the cache. */ cache_addpw (db, fd, req, keystr, pwd, c_uid, he, dh, errval); diff --git a/sysdeps/unix/sysv/linux/i386/setegid.c b/sysdeps/unix/sysv/linux/i386/setegid.c index fcd6cf1..b8682e3 100644 --- a/sysdeps/unix/sysv/linux/i386/setegid.c +++ b/sysdeps/unix/sysv/linux/i386/setegid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-1998, 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1995-1998,2000,2002,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,6 +22,7 @@ #include <sysdep.h> #include "kernel-features.h" +#include <pthread-functions.h> #ifdef __NR_setresgid @@ -32,10 +33,17 @@ int setegid (gid) gid_t gid; { + int result; + + if (gid == (gid_t) ~0) + { + __set_errno (EINVAL); + return -1; + } + #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setresgid32, 3, -1, gid, -1); + result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1); #else - int result; /* First try the syscall. */ # ifdef __NR_setresgid result = __setresgid (-1, gid, -1); @@ -49,8 +57,20 @@ setegid (gid) equal to the real user ID, making it impossible to switch back. */ # endif result = __setregid (-1, gid); +#endif - return result; +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setresgid32; + cmd.id[0] = -1; + cmd.id[1] = gid; + cmd.id[2] = -1; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } #endif + + return result; } libc_hidden_def (setegid) diff --git a/sysdeps/unix/sysv/linux/i386/seteuid.c b/sysdeps/unix/sysv/linux/i386/seteuid.c index 87e348a..0abdac8 100644 --- a/sysdeps/unix/sysv/linux/i386/seteuid.c +++ b/sysdeps/unix/sysv/linux/i386/seteuid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -22,6 +22,7 @@ #include <sysdep.h> #include "kernel-features.h" +#include <pthread-functions.h> #ifdef __NR_setresuid @@ -31,10 +32,17 @@ extern int __setresuid (uid_t ruid, uid_t euid, uid_t suid); int seteuid (uid_t uid) { + int result; + + if (uid == (uid_t) ~0) + { + __set_errno (EINVAL); + return -1; + } + #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setresuid32, 3, -1, uid, -1); + result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1); #else - int result; /* First try the syscall. */ # ifdef __NR_setresuid result = __setresuid (-1, uid, -1); @@ -48,8 +56,20 @@ seteuid (uid_t uid) equal to the real user ID, making it impossible to switch back. */ # endif result = __setreuid (-1, uid); +#endif - return result; +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setresuid32; + cmd.id[0] = -1; + cmd.id[1] = uid; + cmd.id[2] = -1; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } #endif + + return result; } libc_hidden_def (seteuid) diff --git a/sysdeps/unix/sysv/linux/i386/setgid.c b/sysdeps/unix/sysv/linux/i386/setgid.c index 1fdca94..17bfc3e 100644 --- a/sysdeps/unix/sysv/linux/i386/setgid.c +++ b/sysdeps/unix/sysv/linux/i386/setgid.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2003, 2004 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -26,6 +27,8 @@ #include <linux/posix_types.h> #include "kernel-features.h" +#include <pthread-functions.h> + #ifdef __NR_setgid32 # if __ASSUME_32BITUIDS == 0 @@ -38,18 +41,21 @@ extern int __libc_missing_32bit_uids; int __setgid (gid_t gid) { + int result; + #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setgid32, 1, gid); + result = INLINE_SYSCALL (setgid32, 1, gid); #else # ifdef __NR_setgid32 if (__libc_missing_32bit_uids <= 0) { - int result; int saved_errno = errno; result = INLINE_SYSCALL (setgid32, 1, gid); - if (result == 0 || errno != ENOSYS) + if (result == 0) + goto out; + if (errno != ENOSYS) return result; __set_errno (saved_errno); @@ -64,7 +70,24 @@ __setgid (gid_t gid) return -1; } - return INLINE_SYSCALL (setgid, 1, gid); + result = INLINE_SYSCALL (setgid, 1, gid); +# ifdef __NR_setgid32 + out: +# endif +#endif + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setgid32; + cmd.id[0] = gid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } #endif + + return result; } +#ifndef __setgid weak_alias (__setgid, setgid) +#endif diff --git a/sysdeps/unix/sysv/linux/i386/setregid.c b/sysdeps/unix/sysv/linux/i386/setregid.c index be1d73c..f883497 100644 --- a/sysdeps/unix/sysv/linux/i386/setregid.c +++ b/sysdeps/unix/sysv/linux/i386/setregid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,7 @@ #include <linux/posix_types.h> #include "kernel-features.h" +#include <pthread-functions.h> #ifdef __NR_setregid32 @@ -38,18 +39,21 @@ extern int __libc_missing_32bit_uids; int __setregid (gid_t rgid, gid_t egid) { + int result; + #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setregid32, 2, rgid, egid); + result = INLINE_SYSCALL (setregid32, 2, rgid, egid); #else # ifdef __NR_setregid32 if (__libc_missing_32bit_uids <= 0) { - int result; int saved_errno = errno; result = INLINE_SYSCALL (setregid32, 2, rgid, egid); - if (result == 0 || errno != ENOSYS) + if (result == 0) + goto out; + if (errno != ENOSYS) return result; __set_errno (saved_errno); @@ -63,7 +67,25 @@ __setregid (gid_t rgid, gid_t egid) return -1; } - return INLINE_SYSCALL (setregid, 2, rgid, egid); + result = INLINE_SYSCALL (setregid, 2, rgid, egid); +# ifdef __NR_setregid32 + out: +# endif #endif + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setregid32; + cmd.id[0] = rgid; + cmd.id[1] = egid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; } +#ifndef __setregid weak_alias (__setregid, setregid) +#endif diff --git a/sysdeps/unix/sysv/linux/i386/setresgid.c b/sysdeps/unix/sysv/linux/i386/setresgid.c index 414a58b..ee782e4 100644 --- a/sysdeps/unix/sysv/linux/i386/setresgid.c +++ b/sysdeps/unix/sysv/linux/i386/setresgid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,8 @@ #include <sysdep.h> #include <sys/syscall.h> #include "kernel-features.h" +#include <pthread-functions.h> + #ifdef __NR_setresgid @@ -39,17 +41,20 @@ extern int __libc_missing_32bit_uids; int __setresgid (gid_t rgid, gid_t egid, gid_t sgid) { + int result; + # if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid); + result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid); # else # ifdef __NR_setresgid32 if (__libc_missing_32bit_uids <= 0) { - int result; int saved_errno = errno; result = INLINE_SYSCALL (setresgid32, 3, rgid, egid, sgid); - if (result == 0 || errno != ENOSYS) + if (result == 0) + goto out; + if (errno != ENOSYS) return result; __set_errno (saved_errno); @@ -65,11 +70,30 @@ __setresgid (gid_t rgid, gid_t egid, gid_t sgid) return -1; } - return INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid); + result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid); +# ifdef __NR_setresgid32 + out: +# endif # endif + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setresgid32; + cmd.id[0] = rgid; + cmd.id[1] = egid; + cmd.id[2] = sgid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; } libc_hidden_def (__setresgid) +#ifndef __setresgid weak_alias (__setresgid, setresgid) +#endif #else diff --git a/sysdeps/unix/sysv/linux/i386/setresuid.c b/sysdeps/unix/sysv/linux/i386/setresuid.c index 537fb79..66e5a1c 100644 --- a/sysdeps/unix/sysv/linux/i386/setresuid.c +++ b/sysdeps/unix/sysv/linux/i386/setresuid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,8 @@ #include <sysdep.h> #include <sys/syscall.h> #include "kernel-features.h" +#include <pthread-functions.h> + #ifdef __NR_setresuid @@ -39,17 +41,20 @@ extern int __libc_missing_32bit_uids; int __setresuid (uid_t ruid, uid_t euid, uid_t suid) { + int result; + # if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid); + result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid); # else # ifdef __NR_setresuid32 if (__libc_missing_32bit_uids <= 0) { - int result; int saved_errno = errno; result = INLINE_SYSCALL (setresuid32, 3, ruid, euid, suid); - if (result == 0 || errno != ENOSYS) + if (result == 0) + goto out; + if (errno != ENOSYS) return result; __set_errno (saved_errno); @@ -65,11 +70,30 @@ __setresuid (uid_t ruid, uid_t euid, uid_t suid) return -1; } - return INLINE_SYSCALL (setresuid, 3, ruid, euid, suid); + result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid); +# ifdef __NR_setresuid32 + out: +# endif # endif + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setresuid32; + cmd.id[0] = ruid; + cmd.id[1] = euid; + cmd.id[2] = suid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; } libc_hidden_def (__setresuid) +#ifndef __setresuid weak_alias (__setresuid, setresuid) +#endif #else diff --git a/sysdeps/unix/sysv/linux/i386/setreuid.c b/sysdeps/unix/sysv/linux/i386/setreuid.c index 2aadf74..1e1bfcf 100644 --- a/sysdeps/unix/sysv/linux/i386/setreuid.c +++ b/sysdeps/unix/sysv/linux/i386/setreuid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,7 @@ #include <linux/posix_types.h> #include "kernel-features.h" +#include <pthread-functions.h> #ifdef __NR_setreuid32 @@ -38,18 +39,21 @@ extern int __libc_missing_32bit_uids; int __setreuid (uid_t ruid, uid_t euid) { + int result; + #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setreuid32, 2, ruid, euid); + result = INLINE_SYSCALL (setreuid32, 2, ruid, euid); #else # ifdef __NR_setreuid32 if (__libc_missing_32bit_uids <= 0) { - int result; int saved_errno = errno; result = INLINE_SYSCALL (setreuid32, 2, ruid, euid); - if (result == 0 || errno != ENOSYS) + if (result == 0) + goto out; + if (errno != ENOSYS) return result; __set_errno (saved_errno); @@ -63,7 +67,25 @@ __setreuid (uid_t ruid, uid_t euid) return -1; } - return INLINE_SYSCALL (setreuid, 2, ruid, euid); + result = INLINE_SYSCALL (setreuid, 2, ruid, euid); +# ifdef __NR_setreuid32 + out: +# endif #endif + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setreuid32; + cmd.id[0] = ruid; + cmd.id[1] = euid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; } +#ifndef __setreuid weak_alias (__setreuid, setreuid) +#endif diff --git a/sysdeps/unix/sysv/linux/i386/setuid.c b/sysdeps/unix/sysv/linux/i386/setuid.c index 69bf425..a11fb7f 100644 --- a/sysdeps/unix/sysv/linux/i386/setuid.c +++ b/sysdeps/unix/sysv/linux/i386/setuid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,6 +25,8 @@ #include <linux/posix_types.h> #include "kernel-features.h" +#include <pthread-functions.h> + #ifdef __NR_setuid32 # if __ASSUME_32BITUIDS == 0 @@ -37,8 +39,10 @@ extern int __libc_missing_32bit_uids; int __setuid (uid_t uid) { -#if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (setuid32, 1, uid); + int result; + +#if __ASSUME_32BITUIDS > 0 && defined __NR_setuid32 + result = INLINE_SYSCALL (setuid32, 1, uid); #else # ifdef __NR_setuid32 if (__libc_missing_32bit_uids <= 0) @@ -47,7 +51,9 @@ __setuid (uid_t uid) int saved_errno = errno; result = INLINE_SYSCALL (setuid32, 1, uid); - if (result == 0 || errno != ENOSYS) + if (result == 0) + goto out; + if (errno != ENOSYS) return result; __set_errno (saved_errno); @@ -62,7 +68,24 @@ __setuid (uid_t uid) return -1; } - return INLINE_SYSCALL (setuid, 1, uid); + result = INLINE_SYSCALL (setuid, 1, uid); +# ifdef __NR_setuid32 + out: +# endif +#endif + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setuid32; + cmd.id[0] = uid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } #endif + + return result; } +#ifndef __setuid weak_alias (__setuid, setuid) +#endif diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index 79ad72a..8845e46 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1992,1993,1995-2000,2002,2003 Free Software Foundation, Inc. +/* Copyright (C) 1992,1993,1995-2000,2002,2003,2004 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995. @@ -343,7 +344,10 @@ asm (".L__X'%ebx = 1\n\t" /* Define a macro which expands inline into the wrapper code for a system call. This use is for internal calls that do not need to handle errors normally. It will never touch errno. This returns just what the kernel - gave back. */ + gave back. + + The _NCS variant allows non-constant syscall numbers but it is not + possible to use more than four parameters. */ #undef INTERNAL_SYSCALL #ifdef I386_USE_SYSENTER # ifdef SHARED @@ -360,6 +364,18 @@ asm (".L__X'%ebx = 1\n\t" : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \ ASMFMT_##nr(args) : "memory", "cc"); \ (int) resultvar; }) +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register unsigned int resultvar; \ + EXTRAVAR_##nr \ + asm volatile ( \ + LOADARGS_##nr \ + "call *%%gs:%P2\n\t" \ + RESTOREARGS_##nr \ + : "=a" (resultvar) \ + : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \ + ASMFMT_##nr(args) : "memory", "cc"); \ + (int) resultvar; }) # else # define INTERNAL_SYSCALL(name, err, nr, args...) \ ({ \ @@ -373,6 +389,17 @@ asm (".L__X'%ebx = 1\n\t" : "=a" (resultvar) \ : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ (int) resultvar; }) +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register unsigned int resultvar; \ + EXTRAVAR_##nr \ + asm volatile ( \ + LOADARGS_##nr \ + "call *_dl_sysinfo\n\t" \ + RESTOREARGS_##nr \ + : "=a" (resultvar) \ + : "0" (name) ASMFMT_##nr(args) : "memory", "cc"); \ + (int) resultvar; }) # endif #else # define INTERNAL_SYSCALL(name, err, nr, args...) \ @@ -387,6 +414,17 @@ asm (".L__X'%ebx = 1\n\t" : "=a" (resultvar) \ : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ (int) resultvar; }) +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register unsigned int resultvar; \ + EXTRAVAR_##nr \ + asm volatile ( \ + LOADARGS_##nr \ + "int $0x80\n\t" \ + RESTOREARGS_##nr \ + : "=a" (resultvar) \ + : "0" (name) ASMFMT_##nr(args) : "memory", "cc"); \ + (int) resultvar; }) #endif #undef INTERNAL_SYSCALL_DECL diff --git a/sysdeps/unix/sysv/linux/ia64/sysdep.h b/sysdeps/unix/sysv/linux/ia64/sysdep.h index 0868ad5..0ebfc56 100644 --- a/sysdeps/unix/sysv/linux/ia64/sysdep.h +++ b/sysdeps/unix/sysv/linux/ia64/sysdep.h @@ -199,33 +199,33 @@ #ifdef IA64_USE_NEW_STUB -#define DO_INLINE_SYSCALL(name, nr, args...) \ - LOAD_ARGS_##nr (args) \ - register long _r8 __asm ("r8"); \ - register long _r10 __asm ("r10"); \ - register long _r15 __asm ("r15") = __NR_##name; \ - register void *_b7 __asm ("b7") = ((tcbhead_t *) __thread_self)->private; \ - long _retval; \ - LOAD_REGS_##nr \ - /* \ - * Don't specify any unwind info here. We mark ar.pfs as \ - * clobbered. This will force the compiler to save ar.pfs \ - * somewhere and emit appropriate unwind info for that save. \ - */ \ - __asm __volatile ("br.call.sptk.many b6=%0;;\n" \ - : "=b"(_b7), "=r" (_r8), "=r" (_r10), "=r" (_r15) \ - ASM_OUTARGS_##nr \ - : "0" (_b7), "3" (_r15) ASM_ARGS_##nr \ - : "memory", "ar.pfs" ASM_CLOBBERS_##nr); \ +# define DO_INLINE_SYSCALL(name, nr, args...) \ + LOAD_ARGS_##nr (args) \ + register long _r8 __asm ("r8"); \ + register long _r10 __asm ("r10"); \ + register long _r15 __asm ("r15") = name; \ + register void *_b7 __asm ("b7") = ((tcbhead_t *) __thread_self)->private; \ + long _retval; \ + LOAD_REGS_##nr \ + /* \ + * Don't specify any unwind info here. We mark ar.pfs as \ + * clobbered. This will force the compiler to save ar.pfs \ + * somewhere and emit appropriate unwind info for that save. \ + */ \ + __asm __volatile ("br.call.sptk.many b6=%0;;\n" \ + : "=b"(_b7), "=r" (_r8), "=r" (_r10), "=r" (_r15) \ + ASM_OUTARGS_##nr \ + : "0" (_b7), "3" (_r15) ASM_ARGS_##nr \ + : "memory", "ar.pfs" ASM_CLOBBERS_##nr); \ _retval = _r8; #else /* !IA64_USE_NEW_STUB */ -#define DO_INLINE_SYSCALL(name, nr, args...) \ +# define DO_INLINE_SYSCALL(name, nr, args...) \ LOAD_ARGS_##nr (args) \ register long _r8 asm ("r8"); \ register long _r10 asm ("r10"); \ - register long _r15 asm ("r15") = __NR_##name; \ + register long _r15 asm ("r15") = name; \ long _retval; \ LOAD_REGS_##nr \ __asm __volatile (BREAK_INSN (__BREAK_SYSCALL) \ @@ -240,7 +240,7 @@ #undef INLINE_SYSCALL #define INLINE_SYSCALL(name, nr, args...) \ ({ \ - DO_INLINE_SYSCALL(name, nr, args) \ + DO_INLINE_SYSCALL(__NR_##name, nr, args) \ if (_r10 == -1) \ { \ __set_errno (_retval); \ @@ -252,11 +252,13 @@ #define INTERNAL_SYSCALL_DECL(err) long int err #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ DO_INLINE_SYSCALL(name, nr, args) \ err = _r10; \ _retval; }) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) #undef INTERNAL_SYSCALL_ERROR_P #define INTERNAL_SYSCALL_ERROR_P(val, err) (err == -1) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h index 269b4dd..2ee3e60 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h @@ -79,7 +79,7 @@ # define INTERNAL_SYSCALL_DECL(err) long int err # undef INTERNAL_SYSCALL -# define INTERNAL_SYSCALL(name, err, nr, args...) \ +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ register long int r0 __asm__ ("r0"); \ register long int r3 __asm__ ("r3"); \ @@ -104,6 +104,8 @@ err = r0; \ (int) r3; \ }) +# define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) # undef INTERNAL_SYSCALL_ERROR_P # define INTERNAL_SYSCALL_ERROR_P(val, err) \ @@ -113,48 +115,48 @@ # define INTERNAL_SYSCALL_ERRNO(val, err) (val) # define LOADARGS_0(name, dummy) \ - r0 = __NR_##name + r0 = name # define LOADARGS_1(name, __arg1) \ long int arg1 = (long int) (__arg1); \ LOADARGS_0(name, 0); \ - extern void __illegally_sized_syscall_##name##_arg1 (void); \ + extern void __illegally_sized_syscall_arg1 (void); \ if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \ - __illegally_sized_syscall_##name##_arg1 (); \ + __illegally_sized_syscall_arg1 (); \ r3 = arg1 # define LOADARGS_2(name, __arg1, __arg2) \ long int arg2 = (long int) (__arg2); \ LOADARGS_1(name, __arg1); \ - extern void __illegally_sized_syscall_##name##_arg2 (void); \ + extern void __illegally_sized_syscall_arg2 (void); \ if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 4) \ - __illegally_sized_syscall_##name##_arg2 (); \ + __illegally_sized_syscall_arg2 (); \ r4 = arg2 # define LOADARGS_3(name, __arg1, __arg2, __arg3) \ long int arg3 = (long int) (__arg3); \ LOADARGS_2(name, __arg1, __arg2); \ - extern void __illegally_sized_syscall_##name##_arg3 (void); \ + extern void __illegally_sized_syscall_arg3 (void); \ if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 4) \ - __illegally_sized_syscall_##name##_arg3 (); \ + __illegally_sized_syscall_arg3 (); \ r5 = arg3 # define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ long int arg4 = (long int) (__arg4); \ LOADARGS_3(name, __arg1, __arg2, __arg3); \ - extern void __illegally_sized_syscall_##name##_arg4 (void); \ + extern void __illegally_sized_syscall_arg4 (void); \ if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 4) \ - __illegally_sized_syscall_##name##_arg4 (); \ + __illegally_sized_syscall_arg4 (); \ r6 = arg4 # define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ long int arg5 = (long int) (__arg5); \ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ - extern void __illegally_sized_syscall_##name##_arg5 (void); \ + extern void __illegally_sized_syscall_arg5 (void); \ if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 4) \ - __illegally_sized_syscall_##name##_arg5 (); \ + __illegally_sized_syscall_arg5 (); \ r7 = arg5 # define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ long int arg6 = (long int) (__arg6); \ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ - extern void __illegally_sized_syscall_##name##_arg6 (void); \ + extern void __illegally_sized_syscall_arg6 (void); \ if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 4) \ - __illegally_sized_syscall_##name##_arg6 (); \ + __illegally_sized_syscall_arg6 (); \ r8 = arg6 # define ASM_INPUT_0 "0" (r0) diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h index 2e1adcc..38a376f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h @@ -91,7 +91,7 @@ the negation of the return value in the kernel gets reverted. */ #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ register long int r0 __asm__ ("r0"); \ register long int r3 __asm__ ("r3"); \ @@ -114,6 +114,8 @@ err = r0; \ (int) r3; \ }) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) #undef INTERNAL_SYSCALL_DECL #define INTERNAL_SYSCALL_DECL(err) long int err @@ -126,48 +128,48 @@ #define INTERNAL_SYSCALL_ERRNO(val, err) (val) #define LOADARGS_0(name, dummy) \ - r0 = __NR_##name + r0 = name #define LOADARGS_1(name, __arg1) \ long int arg1 = (long int) (__arg1); \ LOADARGS_0(name, 0); \ - extern void __illegally_sized_syscall_##name##_arg1 (void); \ + extern void __illegally_sized_syscall_arg1 (void); \ if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 8) \ - __illegally_sized_syscall_##name##_arg1 (); \ + __illegally_sized_syscall_arg1 (); \ r3 = arg1 #define LOADARGS_2(name, __arg1, __arg2) \ long int arg2 = (long int) (__arg2); \ LOADARGS_1(name, __arg1); \ - extern void __illegally_sized_syscall_##name##_arg2 (void); \ + extern void __illegally_sized_syscall_arg2 (void); \ if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 8) \ - __illegally_sized_syscall_##name##_arg2 (); \ + __illegally_sized_syscall_arg2 (); \ r4 = arg2 #define LOADARGS_3(name, __arg1, __arg2, __arg3) \ long int arg3 = (long int) (__arg3); \ LOADARGS_2(name, __arg1, __arg2); \ - extern void __illegally_sized_syscall_##name##_arg3 (void); \ + extern void __illegally_sized_syscall_arg3 (void); \ if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 8) \ - __illegally_sized_syscall_##name##_arg3 (); \ + __illegally_sized_syscall_arg3 (); \ r5 = arg3 #define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ long int arg4 = (long int) (__arg4); \ LOADARGS_3(name, __arg1, __arg2, __arg3); \ - extern void __illegally_sized_syscall_##name##_arg4 (void); \ + extern void __illegally_sized_syscall_arg4 (void); \ if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 8) \ - __illegally_sized_syscall_##name##_arg4 (); \ + __illegally_sized_syscall_arg4 (); \ r6 = arg4 #define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ long int arg5 = (long int) (__arg5); \ LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ - extern void __illegally_sized_syscall_##name##_arg5 (void); \ + extern void __illegally_sized_syscall_arg5 (void); \ if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 8) \ - __illegally_sized_syscall_##name##_arg5 (); \ + __illegally_sized_syscall_arg5 (); \ r7 = arg5 #define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ long int arg6 = (long int) (__arg6); \ LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ - extern void __illegally_sized_syscall_##name##_arg6 (void); \ + extern void __illegally_sized_syscall_arg6 (void); \ if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 8) \ - __illegally_sized_syscall_##name##_arg6 (); \ + __illegally_sized_syscall_arg6 (); \ r8 = arg6 #define ASM_INPUT_0 "0" (r0) diff --git a/sysdeps/unix/sysv/linux/setegid.c b/sysdeps/unix/sysv/linux/setegid.c index 34e64a3..33e91c7 100644 --- a/sysdeps/unix/sysv/linux/setegid.c +++ b/sysdeps/unix/sysv/linux/setegid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,6 +23,8 @@ #include <sysdep.h> #include "kernel-features.h" +#include <pthread-functions.h> + #if defined __NR_setresgid || __ASSUME_SETRESGID_SYSCALL > 0 @@ -40,10 +42,10 @@ setegid (gid_t gid) } # if __ASSUME_32BITUIDS > 0 && defined __NR_setresgid32 - return INLINE_SYSCALL (setresgid32, 3, -1, gid, -1); + result = INLINE_SYSCALL (setresgid32, 3, -1, gid, -1); # else /* First try the syscall. */ - result = __setresgid (-1, gid, -1); + result = INLINE_SYSCALL (setresgid, 3, -1, gid, -1); # if __ASSUME_SETRESGID_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use emulation. This may not work @@ -51,11 +53,29 @@ setegid (gid_t gid) equal to the real group ID, making it impossible to switch back. */ result = __setregid (-1, gid); # endif +# endif - return result; +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; +# ifdef __NR_setresgid32 + cmd.syscall_no = __NR_setresgid32; +# else + cmd.syscall_no = __NR_setresgid; # endif + cmd.id[0] = -1; + cmd.id[1] = gid; + cmd.id[2] = -1; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; } +#ifndef setegid libc_hidden_def (setegid) +#endif #else # include <sysdeps/unix/bsd/setegid.c> #endif diff --git a/sysdeps/unix/sysv/linux/seteuid.c b/sysdeps/unix/sysv/linux/seteuid.c index a1832d6..da03a1e 100644 --- a/sysdeps/unix/sysv/linux/seteuid.c +++ b/sysdeps/unix/sysv/linux/seteuid.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,6 +23,8 @@ #include <sysdep.h> #include "kernel-features.h" +#include <pthread-functions.h> + #if defined __NR_setresuid || __ASSUME_SETRESUID_SYSCALL > 0 @@ -40,22 +42,40 @@ seteuid (uid_t uid) } # if __ASSUME_32BITUIDS > 0 && defined __NR_setresuid32 - return INLINE_SYSCALL (setresuid32, 3, -1, uid, -1); + result = INLINE_SYSCALL (setresuid32, 3, -1, uid, -1); # else /* First try the syscall. */ - result = __setresuid (-1, uid, -1); -# if __ASSUME_SETRESUID_SYSCALL == 0 + result = INLINE_SYSCALL (setresuid, 3, -1, uid, -1); +# if __ASSUME_SETRESUID_SYSCALL == 0 if (result == -1 && errno == ENOSYS) /* No system call available. Use emulation. This may not work since `setreuid' also sets the saved user ID when UID is not equal to the real user ID, making it impossible to switch back. */ result = __setreuid (-1, uid); +# endif # endif - return result; +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; +# ifdef __NR_setresuid32 + cmd.syscall_no = __NR_setresuid32; +# else + cmd.syscall_no = __NR_setresuid; # endif + cmd.id[0] = -1; + cmd.id[1] = uid; + cmd.id[2] = -1; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; } +#ifndef seteuid libc_hidden_def (seteuid) +#endif #else # include <sysdeps/unix/bsd/seteuid.c> #endif diff --git a/sysdeps/unix/sysv/linux/setgid.c b/sysdeps/unix/sysv/linux/setgid.c new file mode 100644 index 0000000..dae642a --- /dev/null +++ b/sysdeps/unix/sysv/linux/setgid.c @@ -0,0 +1,53 @@ +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <linux/posix_types.h> +#include "kernel-features.h" +#include <pthread-functions.h> + + + +int +__setgid (gid_t gid) +{ + int result; + + result = INLINE_SYSCALL (setgid, 1, gid); + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setgid; + cmd.id[0] = gid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; +} +#ifndef __setgid +weak_alias (__setgid, setgid) +#endif diff --git a/sysdeps/unix/sysv/linux/setregid.c b/sysdeps/unix/sysv/linux/setregid.c new file mode 100644 index 0000000..1d53926 --- /dev/null +++ b/sysdeps/unix/sysv/linux/setregid.c @@ -0,0 +1,53 @@ +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <linux/posix_types.h> +#include "kernel-features.h" +#include <pthread-functions.h> + + +int +__setregid (gid_t rgid, gid_t egid) +{ + int result; + + result = INLINE_SYSCALL (setregid, 2, rgid, egid); + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setregid; + cmd.id[0] = rgid; + cmd.id[1] = egid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; +} +#ifndef __setregid +weak_alias (__setregid, setregid) +#endif diff --git a/sysdeps/unix/sysv/linux/setresgid.c b/sysdeps/unix/sysv/linux/setresgid.c new file mode 100644 index 0000000..ae61d42 --- /dev/null +++ b/sysdeps/unix/sysv/linux/setresgid.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <linux/posix_types.h> +#include "kernel-features.h" +#include <pthread-functions.h> + + +int +__setresgid (gid_t rgid, gid_t egid, gid_t sgid) +{ + int result; + + result = INLINE_SYSCALL (setresgid, 3, rgid, egid, sgid); + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setresgid; + cmd.id[0] = rgid; + cmd.id[1] = egid; + cmd.id[2] = sgid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; +} +#ifndef __setresgid +weak_alias (__setresgid, setresgid) +#endif diff --git a/sysdeps/unix/sysv/linux/setresuid.c b/sysdeps/unix/sysv/linux/setresuid.c new file mode 100644 index 0000000..962d944 --- /dev/null +++ b/sysdeps/unix/sysv/linux/setresuid.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <linux/posix_types.h> +#include "kernel-features.h" +#include <pthread-functions.h> + + +int +__setresuid (uid_t ruid, uid_t euid, uid_t suid) +{ + int result; + + result = INLINE_SYSCALL (setresuid, 3, ruid, euid, suid); + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setresuid; + cmd.id[0] = ruid; + cmd.id[1] = euid; + cmd.id[2] = suid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; +} +#ifndef __setresuid +weak_alias (__setresuid, setresuid) +#endif diff --git a/sysdeps/unix/sysv/linux/setreuid.c b/sysdeps/unix/sysv/linux/setreuid.c new file mode 100644 index 0000000..c9d841e --- /dev/null +++ b/sysdeps/unix/sysv/linux/setreuid.c @@ -0,0 +1,53 @@ +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <linux/posix_types.h> +#include "kernel-features.h" +#include <pthread-functions.h> + + +int +__setreuid (uid_t ruid, uid_t euid) +{ + int result; + + result = INLINE_SYSCALL (setreuid, 2, ruid, euid); + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setreuid; + cmd.id[0] = ruid; + cmd.id[1] = euid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; +} +#ifndef __setreuid +weak_alias (__setreuid, setreuid) +#endif diff --git a/sysdeps/unix/sysv/linux/setuid.c b/sysdeps/unix/sysv/linux/setuid.c new file mode 100644 index 0000000..84f3517 --- /dev/null +++ b/sysdeps/unix/sysv/linux/setuid.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <linux/posix_types.h> +#include "kernel-features.h" +#include <pthread-functions.h> + + +int +__setuid (uid_t uid) +{ + int result; + + result = INLINE_SYSCALL (setuid, 1, uid); + +#if defined HAVE_PTR__NPTL_SETXID && !defined SINGLE_THREAD + if (result == 0 && __libc_pthread_functions.ptr__nptl_setxid != NULL) + { + struct xid_command cmd; + cmd.syscall_no = __NR_setuid; + cmd.id[0] = uid; + __libc_pthread_functions.ptr__nptl_setxid (&cmd); + } +#endif + + return result; +} +#ifndef __setuid +weak_alias (__setuid, setuid) +#endif diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c index 96f8074..2e3a54c 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/setegid.c @@ -1,54 +1 @@ -/* Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sys/syscall.h> -#include <sys/types.h> -#include <unistd.h> - -#ifdef __NR_setresgid32 - -extern int __setresgid (gid_t rgid, gid_t egid, gid_t sgid); - -int -setegid (gid_t gid) -{ - int result; - - if (gid == (gid_t) ~0) - { - __set_errno (EINVAL); - return -1; - } - - /* First try the syscall. */ - result = __setresgid (-1, gid, -1); -# if __ASSUME_SETRESGID_SYSCALL == 0 - if (result == -1 && errno == ENOSYS) - /* No system call available. Use emulation. This may not work - since `setregid' also sets the saved group ID when GID is not - equal to the real group ID, making it impossible to switch back. */ - result = __setregid (-1, gid); -# endif - - return result; -} -libc_hidden_def (setegid) -#else -# include <sysdeps/unix/bsd/setegid.c> -#endif +#include <sysdeps/unix/sysv/linux/i386/setegid.c> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c index 34638ce..18e41d0 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/seteuid.c @@ -1,56 +1 @@ -/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <errno.h> -#include <sys/syscall.h> -#include <sys/types.h> -#include <unistd.h> - -#include "kernel-features.h" - -#if defined __NR_setresuid32 || __ASSUME_SETRESUID_SYSCALL > 0 - -extern int __setresuid (uid_t ruid, uid_t euid, uid_t suid); - -int -seteuid (uid_t uid) -{ - int result; - - if (uid == (uid_t) ~0) - { - __set_errno (EINVAL); - return -1; - } - - /* First try the syscall. */ - result = __setresuid (-1, uid, -1); -# if __ASSUME_SETRESUID_SYSCALL == 0 - if (result == -1 && errno == ENOSYS) - /* No system call available. Use emulation. This may not work - since `setreuid' also sets the saved user ID when UID is not - equal to the real user ID, making it impossible to switch back. */ - result = __setreuid (-1, uid); -# endif - - return result; -} -libc_hidden_def (seteuid) -#else -# include <sysdeps/unix/bsd/seteuid.c> -#endif +#include <sysdeps/unix/sysv/linux/i386/seteuid.c> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c new file mode 100644 index 0000000..daca1a4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/setresgid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setresgid.c> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c b/sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c new file mode 100644 index 0000000..3aeabe9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/setresuid.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/i386/setresuid.c> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list b/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list index 6d8e32f..2bfe376 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list @@ -2,7 +2,5 @@ setrlimit - setrlimit 2 __setrlimit setrlimit getrlimit - getrlimit 2 __getrlimit getrlimit -setresuid - setresuid32 3 __setresuid setresuid -setresgid - setresgid32 3 __setresgid setresgid getresuid - getresuid32 3 getresuid getresgid - getresgid32 3 getresgid diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h index 09f8492..56e4422 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h @@ -236,18 +236,19 @@ #undef INTERNAL_SYSCALL_DECL #define INTERNAL_SYSCALL_DECL(err) do { } while (0) -#undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) \ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ ({ \ unsigned long resultvar; \ LOAD_ARGS_##nr (args) \ LOAD_REGS_##nr \ asm volatile ( \ - "movq %1, %%rax\n\t" \ "syscall\n\t" \ : "=a" (resultvar) \ - : "i" (__NR_##name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ + : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ (long) resultvar; }) +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) #undef INTERNAL_SYSCALL_ERROR_P #define INTERNAL_SYSCALL_ERROR_P(val, err) \ |