[PATCH][BZ #5741] fix segfaul in __libc_dlopen_mode
Steven Munroe
munroesj@linux.vnet.ibm.com
Wed Feb 6 20:00:00 GMT 2008
This is a race condition between the PLT call stubs and _dl_fixup on the
contents of the PLT entry. We have only seen this on out-of-order
machines with deep instruction queues like POWER5 and POWER5+.
In this case case multiple threads are going through pthread_exit,
__pthread_unwind, _Unwind_ForcedUnwind, pthread_cancel_init, __libc_dlopen_mode.
The 1st thread hits the unresolved PLT entry for __libc_dlopen_mode and ends up
in _dl_fixup to update that PLT entry. Other threads may be going through the
same call stubs on other cores and SMT threads.
Because POWER5 is out-of-order the load of the plt->fd_toc may actually execute
before the load of the plt->func executes. In this worst case timing the unlucky
thread may see the unresolved plt->toc value (which in NULL) and the updated
plt-func pointer. The results is a segfault when __libc_dlopen_mode tries to use
the toc pointer to reference static variables.
The patch changes the elf_machine_fixup_plt to flush the toc update out to main
storage before the new function pointer is stored. This insures that the toc load
will be delayed until after the function pointer load.
-------------- next part --------------
2008-01-24 Steven Munroe <sjmunroe@us.ibm.com>
[BZ #5741]
* sysdeps/powerpc/powerpc64/dl-machine.h (PPC_DCBT, PPC_DCBF):
Define additonal Data Cache Block instruction macros.
(elf_machine_fixup_plt): Add dcbt for opd and plt entries.
Replace dcbst with dcbf and sync with sync/isync.
diff -urN libc25-cvstip-20070919/sysdeps/powerpc/powerpc64/dl-machine.h libc25/sysdeps/powerpc/powerpc64/dl-machine.h
--- libc25-cvstip-20070919/sysdeps/powerpc/powerpc64/dl-machine.h 2008-01-04 11:53:49.000000000 -0600
+++ libc25/sysdeps/powerpc/powerpc64/dl-machine.h 2008-02-01 16:43:20.000000000 -0600
@@ -1,6 +1,6 @@
/* Machine-dependent ELF dynamic relocation inline functions.
PowerPC64 version.
- Copyright 1995-2005, 2006 Free Software Foundation, Inc.
+ Copyright 1995-2005, 2006, 2008 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
@@ -282,6 +282,8 @@
#define GLINK_INITIAL_ENTRY_WORDS 8
#define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
+#define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory")
+#define PPC_DCBF(where) asm volatile ("dcbf 0,%0" : : "r"(where) : "memory")
#define PPC_SYNC asm volatile ("sync" : : : "memory")
#define PPC_ISYNC asm volatile ("sync; isync" : : : "memory")
#define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where) : "memory")
@@ -403,6 +405,11 @@
Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
Elf64_Addr offset = 0;
+ PPC_DCBT (&plt->fd_aux);
+ PPC_DCBT (&plt->fd_func);
+ PPC_DCBT (&rel->fd_aux);
+ PPC_DCBT (&rel->fd_func);
+
/* If sym_map is NULL, it's a weak undefined sym; Leave the plt zero. */
if (sym_map == NULL)
return 0;
@@ -425,13 +432,12 @@
plt->fd_aux = rel->fd_aux + offset;
plt->fd_toc = rel->fd_toc + offset;
- PPC_DCBST (&plt->fd_aux);
- PPC_DCBST (&plt->fd_toc);
- PPC_SYNC;
+ PPC_DCBF (&plt->fd_toc);
+ PPC_ISYNC;
plt->fd_func = rel->fd_func + offset;
PPC_DCBST (&plt->fd_func);
- PPC_SYNC;
+ PPC_ISYNC;
return finaladdr;
}
More information about the Libc-alpha
mailing list