summaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-20 00:16:11 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-20 00:16:11 +0000
commit2edb61e3f955bfcc9dd3cb6b3b1acfe4806234a6 (patch)
treeeb3ba83120d92a0ea9955520f2df4e00a22bc884 /nptl
parent29e11320c90722aec6335a5f8d8af84d12ba3c6b (diff)
Update.
* 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.
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog34
-rw-r--r--nptl/Makefile6
-rw-r--r--nptl/Versions5
-rw-r--r--nptl/allocatestack.c81
-rw-r--r--nptl/descr.h10
-rw-r--r--nptl/init.c40
-rw-r--r--nptl/pt-allocrtsig.c7
-rw-r--r--nptl/pthreadP.h9
-rw-r--r--nptl/pthread_setegid.c3
-rw-r--r--nptl/pthread_seteuid.c3
-rw-r--r--nptl/pthread_setgid.c3
-rw-r--r--nptl/pthread_setregid.c3
-rw-r--r--nptl/pthread_setresgid.c3
-rw-r--r--nptl/pthread_setresuid.c3
-rw-r--r--nptl/pthread_setreuid.c3
-rw-r--r--nptl/pthread_setuid.c3
-rw-r--r--nptl/sysdeps/pthread/pthread-functions.h2
-rw-r--r--nptl/sysdeps/pthread/pthread.h30
-rw-r--r--nptl/sysdeps/unix/sysv/linux/allocrtsig.c4
19 files changed, 243 insertions, 9 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index db3aeba3f7..e4bcfed2e9 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 e75752f801..beaf6d7eab 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 7e8ac9e271..ee4a6e04b5 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 cbdd781eeb..242da0a5a1 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 3611698048..0f8d347b79 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 e58dae0ba6..aad2c9001f 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 3598dbb49f..9481e15f25 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 c0941f0cf5..1fedce5f3a 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 0000000000..9252dfac7d
--- /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 0000000000..47bb698025
--- /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 0000000000..b06bffbf32
--- /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 0000000000..7461d2b7fd
--- /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 0000000000..369fae2672
--- /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 0000000000..ac57c0fa8d
--- /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 0000000000..aa804ab01d
--- /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 0000000000..ff949c850f
--- /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 23af214518..b1e0fcb26d 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 27666483d9..16f02d1314 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 51aeb22765..b37d54d65b 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;