summaryrefslogtreecommitdiff
path: root/libc/nptl
diff options
context:
space:
mode:
authorjoseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d>2012-07-31 15:30:38 +0000
committerjoseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d>2012-07-31 15:30:38 +0000
commitdd3105b347f432016fcdc1abd472c3717f557c9e (patch)
treecbaaecdaa1d3ad240177c9040f7f46c1387716ce /libc/nptl
parent20f73aac36c2b2c240dcc379d5117488fe44960c (diff)
Merge changes between r19464 and r19920 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@19921 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/nptl')
-rw-r--r--libc/nptl/ChangeLog38
-rw-r--r--libc/nptl/nptl-init.c4
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S3
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h5
-rw-r--r--libc/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h5
-rw-r--r--libc/nptl/tst-pthread-getattr.c85
6 files changed, 109 insertions, 31 deletions
diff --git a/libc/nptl/ChangeLog b/libc/nptl/ChangeLog
index b5d0d7103..6969fd256 100644
--- a/libc/nptl/ChangeLog
+++ b/libc/nptl/ChangeLog
@@ -1,3 +1,41 @@
+2012-07-28 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-pthread-getattr.c (MAX_STACK_SIZE): New macro.
+ (pagesize): New static variable.
+ (allocate_and_test): Return MEM. Rename parameter to TARGET.
+ (check_stack_top): New local variables MEM and PAGEMASK. Cap
+ stack size to MAX_STACK_SIZE. Call allocate_and_test for
+ halfway up the stack top page. Verify that the top page was
+ written into.
+ (do_test): Get pagesize using sysconf.
+
+2012-07-25 Andreas Schwab <schwab@linux-m68k.org>
+
+ * sysdeps/unix/sysv/linux/i386/pt-vfork.S: Remove pseudo_end
+ label.
+ * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO):
+ Likewise.
+
+2012-07-25 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-pthread-getattr.c: Revert last change.
+
+2012-07-20 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-pthread-getattr.c (MAX_STACK_SIZE): New max cap for stack
+ size.
+ (_MIN): New macro.
+ (allocate_and_test): Return STACKADDR. Access STACKADDR instead
+ of MEM to test.
+ (check_stack_top): Read valued written into STACKADDR in
+ allocate_and_test. Cap stack size to MAX_STACK_SIZE.
+
+2012-07-19 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * nptl-init.c (sighandler_setxid): Fix the comment that
+ describes it.
+
2012-06-23 Thomas Schwinge <thomas@codesourcery.com>
* sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S
diff --git a/libc/nptl/nptl-init.c b/libc/nptl/nptl-init.c
index ea3d1ec80..5216ce1f5 100644
--- a/libc/nptl/nptl-init.c
+++ b/libc/nptl/nptl-init.c
@@ -229,7 +229,9 @@ 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. */
+/* We use the SIGSETXID signal in the setuid, setgid, etc. implementations to
+ tell each thread to call the respective setxid syscall on itself. This is
+ the handler. */
static void
sighandler_setxid (int sig, siginfo_t *si, void *ctx)
{
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S b/libc/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
index 7abc325b7..03e4b8ea5 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
+++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Schwab <schwab@gnu.org>.
@@ -60,7 +60,6 @@ ENTRY (__vfork)
cmpl $-4095, %eax
jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */
-.Lpseudo_end:
ret
PSEUDO_END (__vfork)
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/libc/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
index 1856d61d5..7ad822692 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
@@ -48,8 +48,7 @@
POPCARGS_##args; \
POPSTATE_##args \
cmpl $-4095, %eax; \
- jae SYSCALL_ERROR_LABEL; \
- L(pseudo_end):
+ jae SYSCALL_ERROR_LABEL
# define SAVE_OLDTYPE_0 movl %eax, %ecx;
# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0
diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
index 304905061..d1725bb75 100644
--- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
+++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2006, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
@@ -56,8 +56,7 @@
movq %rdx, %rax; \
addq $8,%rsp; cfi_adjust_cfa_offset (-8); \
cmpq $-4095, %rax; \
- jae SYSCALL_ERROR_LABEL; \
- L(pseudo_end):
+ jae SYSCALL_ERROR_LABEL
# ifdef IS_IN_libpthread
diff --git a/libc/nptl/tst-pthread-getattr.c b/libc/nptl/tst-pthread-getattr.c
index 6f2cfc651..5a619fa39 100644
--- a/libc/nptl/tst-pthread-getattr.c
+++ b/libc/nptl/tst-pthread-getattr.c
@@ -21,18 +21,37 @@
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
+#include <sys/param.h>
#include <pthread.h>
#include <alloca.h>
-
-/* Move the stack pointer so that stackaddr is accessible and then check if it
- really is accessible. This will segfault if it fails. */
-static void
-allocate_and_test (void *stackaddr)
+#include <assert.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+/* There is an obscure bug in the kernel due to which RLIMIT_STACK is sometimes
+ returned as unlimited when it is not, which may cause this test to fail.
+ There is also the other case where RLIMIT_STACK is intentionally set as
+ unlimited or very high, which may result in a vma that is too large and again
+ results in a test case failure. To avoid these problems, we cap the stack
+ size to one less than 8M. See the following mailing list threads for more
+ information about this problem:
+ <http://sourceware.org/ml/libc-alpha/2012-06/msg00599.html>
+ <http://sourceware.org/ml/libc-alpha/2012-06/msg00713.html>. */
+#define MAX_STACK_SIZE (8192 * 1024 - 1)
+
+static size_t pagesize;
+
+/* Check if the page in which TARGET lies is accessible. This will segfault
+ if it fails. */
+static volatile char *
+allocate_and_test (char *target)
{
- void *mem = &mem;
- /* FIXME: The difference will be negative for _STACK_GROWSUP. */
- mem = alloca ((size_t) (mem - stackaddr));
- *(int *)(mem) = 0;
+ volatile char *mem = (char *) &mem;
+ /* FIXME: mem >= target for _STACK_GROWSUP. */
+ mem = alloca ((size_t) (mem - target));
+
+ *mem = 42;
+ return mem;
}
static int
@@ -42,13 +61,13 @@ get_self_pthread_attr (const char *id, void **stackaddr, size_t *stacksize)
int ret;
pthread_t me = pthread_self ();
- if ((ret = pthread_getattr_np (me, &attr)))
+ if ((ret = pthread_getattr_np (me, &attr)) < 0)
{
printf ("%s: pthread_getattr_np failed: %s\n", id, strerror (ret));
return 1;
}
- if ((ret = pthread_attr_getstack (&attr, stackaddr, stacksize)))
+ if ((ret = pthread_attr_getstack (&attr, stackaddr, stacksize)) < 0)
{
printf ("%s: pthread_attr_getstack returned error: %s\n", id,
strerror (ret));
@@ -65,8 +84,10 @@ check_stack_top (void)
{
struct rlimit stack_limit;
void *stackaddr;
+ volatile void *mem;
size_t stacksize = 0;
int ret;
+ uintptr_t pagemask = ~(pagesize - 1);
puts ("Verifying that stack top is accessible");
@@ -77,19 +98,22 @@ check_stack_top (void)
return 1;
}
+ printf ("current rlimit_stack is %zu\n", (size_t) stack_limit.rlim_cur);
+
if (get_self_pthread_attr ("check_stack_top", &stackaddr, &stacksize))
return 1;
- /* Reduce the rlimit to a page less that what is currently being returned so
- that we ensure that pthread_getattr_np uses rlimit. The figure is
- intentionally unaligned so to verify that pthread_getattr_np returns an
- aligned stacksize that correctly fits into the rlimit. We don't bother
- about the case where the stack is limited by the vma below it and not by
- the rlimit because the stacksize returned in that case is computed from
- the end of that vma and is hence safe. */
- stack_limit.rlim_cur = stacksize - 4095;
- printf ("Adjusting RLIMIT_STACK to %zu\n", stack_limit.rlim_cur);
- if ((ret = setrlimit (RLIMIT_STACK, &stack_limit)))
+ /* Reduce the rlimit to a page less that what is currently being returned
+ (subject to a maximum of MAX_STACK_SIZE) so that we ensure that
+ pthread_getattr_np uses rlimit. The figure is intentionally unaligned so
+ to verify that pthread_getattr_np returns an aligned stacksize that
+ correctly fits into the rlimit. We don't bother about the case where the
+ stack is limited by the vma below it and not by the rlimit because the
+ stacksize returned in that case is computed from the end of that vma and is
+ hence safe. */
+ stack_limit.rlim_cur = MIN (stacksize - pagesize + 1, MAX_STACK_SIZE);
+ printf ("Adjusting RLIMIT_STACK to %zu\n", (size_t) stack_limit.rlim_cur);
+ if ((ret = setrlimit (RLIMIT_STACK, &stack_limit)) < 0)
{
perror ("setrlimit failed");
return 1;
@@ -100,7 +124,23 @@ check_stack_top (void)
printf ("Adjusted rlimit: stacksize=%zu, stackaddr=%p\n", stacksize,
stackaddr);
- allocate_and_test (stackaddr);
+
+ /* A lot of targets tend to write stuff on top of the user stack during
+ context switches, so we cannot possibly safely go up to the very top of
+ stack and test access there. It is however sufficient to simply check if
+ the top page is accessible, so we target our access halfway up the top
+ page. Thanks Chris Metcalf for this idea. */
+ mem = allocate_and_test (stackaddr + pagesize / 2);
+
+ /* Before we celebrate, make sure we actually did test the same page. */
+ if (((uintptr_t) stackaddr & pagemask) != ((uintptr_t) mem & pagemask))
+ {
+ printf ("We successfully wrote into the wrong page.\n"
+ "Expected %#" PRIxPTR ", but got %#" PRIxPTR "\n",
+ (uintptr_t) stackaddr & pagemask, (uintptr_t) mem & pagemask);
+
+ return 1;
+ }
puts ("Stack top tests done");
@@ -112,6 +152,7 @@ check_stack_top (void)
static int
do_test (void)
{
+ pagesize = sysconf (_SC_PAGESIZE);
return check_stack_top ();
}