This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] S/390: Fix makecontext with uc_link == NULL
- From: "Andreas Krebbel" <krebbel at linux dot vnet dot ibm dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 10 Jul 2012 12:20:22 +0200
- Subject: [PATCH] S/390: Fix makecontext with uc_link == NULL
Hi,
if the uc_link field in ucontext is set to NULL the thread is supposed
to be exited after returning from the function specfied with
makecontext. Doing this on s390 currently ends with a segfault when
trying to access fields of the ucontext given in uc_link.
With the attached patch exit is called if uc_link turns out to be
NULL.
Tested on s390 and s390x. No regressions.
I'll commit it after waiting a few days for comments.
Bye,
-Andreas-
2012-07-10 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* sysdeps/unix/sysv/linux/s390/s390-32/makecontext.c: Move
__makecontext_ret to ...
* sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
... here and call exit if uc_link is NULL. New file.
* sysdeps/unix/sysv/linux/s390/s390-32/Makefile: Add
__makecontext_ret.S.
* sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c: Move
__makecontext_ret to ...
* sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
... here and call exit if uc_link is NULL. New file.
* sysdeps/unix/sysv/linux/s390/s390-64/Makefile: Add
__makecontext_ret.S.
---
sysdeps/unix/sysv/linux/s390/s390-32/Makefile | 4 +
sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S | 48 +++++++++++++++
sysdeps/unix/sysv/linux/s390/s390-32/makecontext.c | 12 ---
sysdeps/unix/sysv/linux/s390/s390-64/Makefile | 4 +
sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S | 29 +++++++++
sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c | 12 ---
6 files changed, 89 insertions(+), 20 deletions(-)
Index: glibc/sysdeps/unix/sysv/linux/s390/s390-32/makecontext.c
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/s390/s390-32/makecontext.c
+++ glibc/sysdeps/unix/sysv/linux/s390/s390-32/makecontext.c
@@ -80,10 +80,10 @@ __makecontext (ucontext_t *ucp, void (*f
sp -= 24;
*sp = 0;
- /* Pass (*func) to __start_context in %r7. */
+ /* Pass (*func) to __makecontext_ret in %r7. */
ucp->uc_mcontext.gregs[7] = (long int) func;
- /* Pass ucp->uc_link to __start_context in %r8. */
+ /* Pass ucp->uc_link to __makecontext_ret in %r8. */
ucp->uc_mcontext.gregs[8] = (long int) ucp->uc_link;
/* Pass address of setcontext in %r9. */
@@ -93,12 +93,4 @@ __makecontext (ucontext_t *ucp, void (*f
ucp->uc_mcontext.gregs[15] = (long int) sp;
}
-asm (".text\n"
- ".type __makecontext_ret,@function\n"
- "__makecontext_ret:\n"
- " basr %r14,%r7\n"
- " lr %r2,%r8\n"
- " br %r9\n"
- ".size __makecontext_ret, .-__makecontext_ret");
-
weak_alias (__makecontext, makecontext)
Index: glibc/sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S
===================================================================
--- /dev/null
+++ glibc/sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S
@@ -0,0 +1,29 @@
+/* Copyright (C) 2012 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+ENTRY(__makecontext_ret)
+ basr %r14,%r7
+ ltgr %r8,%r8 /* Check whether uc_link is 0. */
+ jz 1f
+ lgr %r2,%r8
+ br %r9
+1: lghi %r2,-1
+ brasl %r14,HIDDEN_JUMPTARGET (exit)
+ j .+2 /* Trap if exit returns. */
+END(__makecontext_ret)
Index: glibc/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c
+++ glibc/sysdeps/unix/sysv/linux/s390/s390-64/makecontext.c
@@ -80,10 +80,10 @@ __makecontext (ucontext_t *ucp, void (*f
sp -= 20;
*sp = 0;
- /* Pass (*func) to __start_context in %r7. */
+ /* Pass (*func) to __makecontext_ret in %r7. */
ucp->uc_mcontext.gregs[7] = (long int) func;
- /* Pass ucp->uc_link to __start_context in %r8. */
+ /* Pass ucp->uc_link to __makecontext_ret in %r8. */
ucp->uc_mcontext.gregs[8] = (long int) ucp->uc_link;
/* Pass address of setcontext in %r9. */
@@ -93,12 +93,4 @@ __makecontext (ucontext_t *ucp, void (*f
ucp->uc_mcontext.gregs[15] = (long int) sp;
}
-asm (".text\n"
- ".type __makecontext_ret,@function\n"
- "__makecontext_ret:\n"
- " basr %r14,%r7\n"
- " lgr %r2,%r8\n"
- " br %r9\n"
- ".size __makecontext_ret, .-__makecontext_ret");
-
weak_alias (__makecontext, makecontext)
Index: glibc/sysdeps/unix/sysv/linux/s390/s390-64/Makefile
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/s390/s390-64/Makefile
+++ glibc/sysdeps/unix/sysv/linux/s390/s390-64/Makefile
@@ -12,3 +12,7 @@ sysdep_routines += framestate
shared-only-routines += framestate
endif
endif
+
+ifeq ($(subdir),stdlib)
+sysdep_routines += __makecontext_ret
+endif
Index: glibc/sysdeps/unix/sysv/linux/s390/s390-32/Makefile
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/s390/s390-32/Makefile
+++ glibc/sysdeps/unix/sysv/linux/s390/s390-32/Makefile
@@ -21,3 +21,7 @@ sysdep_routines += framestate
shared-only-routines += framestate
endif
endif
+
+ifeq ($(subdir),stdlib)
+sysdep_routines += __makecontext_ret
+endif
Index: glibc/sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
===================================================================
--- /dev/null
+++ glibc/sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
@@ -0,0 +1,48 @@
+/* Copyright (C) 2012 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+ENTRY(__makecontext_ret)
+ basr %r14,%r7
+ ltr %r8,%r8 /* Check whether uc_link is 0. */
+ jz 1f
+ lr %r2,%r8
+ br %r9
+1: lhi %r2,-1
+ basr %r13,0
+2:
+#ifdef PIC
+ l %r12,4f-2b(%r13)
+ la %r12,0(%r12,%r13) /* GOT pointer in r12 after this. */
+ l %r1,3f-2b(%r13)
+ bas %r14,0(%r1,%r12)
+ .align 4
+3:
+ .long HIDDEN_JUMPTARGET (exit)@GOTOFF
+4:
+ .long _GLOBAL_OFFSET_TABLE_-2b
+#else
+ l %r1,3f-2b(%r13)
+ basr %r14,%r1
+ .align 4
+3:
+ .long HIDDEN_JUMPTARGET (exit)
+#endif
+ .align 2
+ j .+2 /* Trap if exit returns. */
+END(__makecontext_ret)