|
|
8ae002 |
commit b3a810d0d3d5c6ce7ddfb61321cd7971808ca703
|
|
|
8ae002 |
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
|
|
|
8ae002 |
Date: Tue May 17 10:45:48 2016 +0200
|
|
|
8ae002 |
|
|
|
8ae002 |
Fix tst-cancel17/tst-cancelx17, which sometimes segfaults while exiting.
|
|
|
8ae002 |
|
|
|
8ae002 |
The testcase tst-cancel[x]17 ends sometimes with a segmentation fault.
|
|
|
8ae002 |
This happens in one of 10000 cases. Then the real testcase has already
|
|
|
8ae002 |
exited with success and returned from do_test(). The segmentation fault
|
|
|
8ae002 |
occurs after returning from main in _dl_fini().
|
|
|
8ae002 |
|
|
|
8ae002 |
In those cases, the aio_read(&a) was not canceled because the read
|
|
|
8ae002 |
request was already in progress. In the meanwhile aio_write(ap) wrote
|
|
|
8ae002 |
something to the pipe and the read request is able to read the
|
|
|
8ae002 |
requested byte.
|
|
|
8ae002 |
The read request hasn't finished before returning from do_test().
|
|
|
8ae002 |
After it finishes, it writes the return value and error code from the
|
|
|
8ae002 |
read syscall to the struct aiocb a, which lies on the stack of do_test.
|
|
|
8ae002 |
The stack of the subsequent function call of _dl_fini or _dl_sort_fini,
|
|
|
8ae002 |
which is inlined in _dl_fini is corrupted.
|
|
|
8ae002 |
|
|
|
8ae002 |
In case of S390, it reads a zero and decrements it by 1:
|
|
|
8ae002 |
unsigned int k = nmaps - 1;
|
|
|
8ae002 |
struct link_map **runp = maps[k]->l_initfini;
|
|
|
8ae002 |
The load from unmapped memory leads to the segmentation fault.
|
|
|
8ae002 |
The stack corruption also happens on other architectures.
|
|
|
8ae002 |
I saw them e.g. on x86 and ppc, too.
|
|
|
8ae002 |
|
|
|
8ae002 |
This patch adds an aio_suspend call to ensure, that the read request
|
|
|
8ae002 |
is finished before returning from do_test().
|
|
|
8ae002 |
|
|
|
8ae002 |
ChangeLog:
|
|
|
8ae002 |
|
|
|
8ae002 |
* nptl/tst-cancel17.c (do_test): Wait for finishing aio_read(&a).
|
|
|
8ae002 |
|
|
|
8ae002 |
diff --git a/nptl/tst-cancel17.c b/nptl/tst-cancel17.c
|
|
|
8ae002 |
index fb89292..eedd28e 100644
|
|
|
8ae002 |
--- a/nptl/tst-cancel17.c
|
|
|
8ae002 |
+++ b/nptl/tst-cancel17.c
|
|
|
8ae002 |
@@ -333,6 +333,22 @@ do_test (void)
|
|
|
8ae002 |
|
|
|
8ae002 |
puts ("early cancellation succeeded");
|
|
|
8ae002 |
|
|
|
8ae002 |
+ if (ap == &a2)
|
|
|
8ae002 |
+ {
|
|
|
8ae002 |
+ /* The aio_read(&a) was not canceled because the read request was
|
|
|
8ae002 |
+ already in progress. In the meanwhile aio_write(ap) wrote something
|
|
|
8ae002 |
+ to the pipe and the read request either has already been finished or
|
|
|
8ae002 |
+ is able to read the requested byte.
|
|
|
8ae002 |
+ Wait for the read request before returning from this function because
|
|
|
8ae002 |
+ the return value and error code from the read syscall will be written
|
|
|
8ae002 |
+ to the struct aiocb a, which lies on the stack of this function.
|
|
|
8ae002 |
+ Otherwise the stack from subsequent function calls - e.g. _dl_fini -
|
|
|
8ae002 |
+ will be corrupted, which can lead to undefined behaviour like a
|
|
|
8ae002 |
+ segmentation fault. */
|
|
|
8ae002 |
+ const struct aiocb *l[1] = { &a };
|
|
|
8ae002 |
+ TEMP_FAILURE_RETRY (aio_suspend(l, 1, NULL));
|
|
|
8ae002 |
+ }
|
|
|
8ae002 |
+
|
|
|
8ae002 |
return 0;
|
|
|
8ae002 |
}
|
|
|
8ae002 |
|