diff options
author | Ian Wienand <ianw@gelato.unsw.edu.au> | 2007-11-19 22:12:46 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-12-19 14:06:40 -0500 |
commit | e384f41409cb9e543fbc84b375e2ba46cbcbec6a (patch) | |
tree | b0b47dd81e493ebc3c06878ad61dcb8882231c9c | |
parent | ee211b37aa98123b1d9b19d228011e632a4bbe75 (diff) |
[IA64] set_thread_area fails in IA32 chroot
I tried to upgrade an IA32 chroot on my IA64 to a new glibc with TLS.
It kept dying because set_thread_area was returning -ESRCH
(bugs.debian.org/451939).
I instrumented arch/ia64/ia32/sys_ia32.c:get_free_idx() and ended up
seeing output like
[pid] idx desc->a desc->b
-----------------------------
[2710] 0 -> c6b0ffff 40dff31b
[2710] 1 -> 0 0
[2710] 2 -> 0 0
[2710] 0 -> c6b0ffff 40dff31b
[2710] 1 -> c6b0ffff 40dff31b
[2710] 2 -> 0 0
[2711] 0 -> c6b0ffff 40dff31b
[2711] 1 -> c6b0ffff 40dff31b
[2711] 2 -> 48c0ffff 40dff317
which suggested to me that TLS pointers were surviving exec() calls,
leading to GDT pointers filling up and the eventual failure of
get_free_idx().
I think the solution is flushing the tls array on exec.
Signed-Off-By: Ian Wienand <ianw@gelato.unsw.edu.au>
Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r-- | arch/ia64/kernel/process.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index a70ad185725c..7377d323131d 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -739,6 +739,7 @@ flush_thread (void) | |||
739 | ia32_drop_ia64_partial_page_list(current); | 739 | ia32_drop_ia64_partial_page_list(current); |
740 | current->thread.task_size = IA32_PAGE_OFFSET; | 740 | current->thread.task_size = IA32_PAGE_OFFSET; |
741 | set_fs(USER_DS); | 741 | set_fs(USER_DS); |
742 | memset(current->thread.tls_array, 0, sizeof(current->thread.tls_array)); | ||
742 | } | 743 | } |
743 | #endif | 744 | #endif |
744 | } | 745 | } |