diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2012-07-31 15:30:38 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2012-07-31 15:30:38 +0000 |
commit | dd3105b347f432016fcdc1abd472c3717f557c9e (patch) | |
tree | cbaaecdaa1d3ad240177c9040f7f46c1387716ce /libc/nptl | |
parent | 20f73aac36c2b2c240dcc379d5117488fe44960c (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/ChangeLog | 38 | ||||
-rw-r--r-- | libc/nptl/nptl-init.c | 4 | ||||
-rw-r--r-- | libc/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S | 3 | ||||
-rw-r--r-- | libc/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h | 5 | ||||
-rw-r--r-- | libc/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h | 5 | ||||
-rw-r--r-- | libc/nptl/tst-pthread-getattr.c | 85 |
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 (); } |