* [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() @ 2022-10-28 12:42 Ilya Leoshkevich 2022-10-28 12:42 ` [PATCH 1/2] " Ilya Leoshkevich ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: Ilya Leoshkevich @ 2022-10-28 12:42 UTC (permalink / raw) To: Alex Bennée, Richard Henderson, Paolo Bonzini Cc: qemu-devel, Ilya Leoshkevich Hi, This is a fix for the issue reported in [1]. Patch 1 is the fix itself, patch 2 is the test/reproducer. By the way, I noticed that there is no code to free tb_jmp_cache, and object_finalize(CPUState) is never called - in case of system emulation this is fine, but what about linux-user? [1] https://lists.gnu.org/archive/html/qemu-devel/2022-10/msg05181.html Best regards, Ilya Ilya Leoshkevich (2): accel/tcg: Fix concurrent pthread_create() and munmap() tests/tcg/multiarch: Add munmap-pthread.c accel/tcg/tb-maint.c | 5 ++ tests/tcg/multiarch/Makefile.target | 3 ++ tests/tcg/multiarch/munmap-pthread.c | 71 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 tests/tcg/multiarch/munmap-pthread.c -- 2.37.2 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] accel/tcg: Fix concurrent pthread_create() and munmap() 2022-10-28 12:42 [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Ilya Leoshkevich @ 2022-10-28 12:42 ` Ilya Leoshkevich 2022-10-28 18:59 ` Richard Henderson 2022-10-28 12:42 ` [PATCH 2/2] tests/tcg/multiarch: Add munmap-pthread.c Ilya Leoshkevich 2022-10-28 14:14 ` [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Alex Bennée 2 siblings, 1 reply; 5+ messages in thread From: Ilya Leoshkevich @ 2022-10-28 12:42 UTC (permalink / raw) To: Alex Bennée, Richard Henderson, Paolo Bonzini Cc: qemu-devel, Ilya Leoshkevich munmap() flushes jump cache on all CPUs if the unmapped range contains a translation block. This currently includes new CPUs (i.e. qemu-user threads), for which there is no jump cache yet, which leads to a null pointer dereference. Fix by skipping new CPUs. Fixes: a976a99a2975 ("include/hw/core: Create struct CPUJumpCache") Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- accel/tcg/tb-maint.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index c8e921089df..2a063f91aa6 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -241,6 +241,11 @@ static void tb_jmp_cache_inval_tb(TranslationBlock *tb) CPU_FOREACH(cpu) { CPUJumpCache *jc = cpu->tb_jmp_cache; + if (unlikely(!jc)) { + /* This is a new CPU that is not initialized yet. */ + continue; + } + if (qatomic_read(&jc->array[h].tb) == tb) { qatomic_set(&jc->array[h].tb, NULL); } -- 2.37.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] accel/tcg: Fix concurrent pthread_create() and munmap() 2022-10-28 12:42 ` [PATCH 1/2] " Ilya Leoshkevich @ 2022-10-28 18:59 ` Richard Henderson 0 siblings, 0 replies; 5+ messages in thread From: Richard Henderson @ 2022-10-28 18:59 UTC (permalink / raw) To: Ilya Leoshkevich, Alex Bennée, Paolo Bonzini; +Cc: qemu-devel On 10/28/22 23:42, Ilya Leoshkevich wrote: > munmap() flushes jump cache on all CPUs if the unmapped range contains > a translation block. This currently includes new CPUs (i.e. qemu-user > threads), for which there is no jump cache yet, which leads to a null > pointer dereference. > > Fix by skipping new CPUs. > > Fixes: a976a99a2975 ("include/hw/core: Create struct CPUJumpCache") > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > accel/tcg/tb-maint.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c > index c8e921089df..2a063f91aa6 100644 > --- a/accel/tcg/tb-maint.c > +++ b/accel/tcg/tb-maint.c > @@ -241,6 +241,11 @@ static void tb_jmp_cache_inval_tb(TranslationBlock *tb) > CPU_FOREACH(cpu) { > CPUJumpCache *jc = cpu->tb_jmp_cache; > > + if (unlikely(!jc)) { > + /* This is a new CPU that is not initialized yet. */ > + continue; > + } > + Interesting that the new cpu gets linked before realize. I wonder if cpu_list_add should be moved from the top of cpu_exec_realizefn to the end. Thanks for the test case. I'll have a closer look. r~ ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] tests/tcg/multiarch: Add munmap-pthread.c 2022-10-28 12:42 [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Ilya Leoshkevich 2022-10-28 12:42 ` [PATCH 1/2] " Ilya Leoshkevich @ 2022-10-28 12:42 ` Ilya Leoshkevich 2022-10-28 14:14 ` [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Alex Bennée 2 siblings, 0 replies; 5+ messages in thread From: Ilya Leoshkevich @ 2022-10-28 12:42 UTC (permalink / raw) To: Alex Bennée, Richard Henderson, Paolo Bonzini Cc: qemu-devel, Ilya Leoshkevich Add a test to detect races between munmap() and creating new threads. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- tests/tcg/multiarch/Makefile.target | 3 ++ tests/tcg/multiarch/munmap-pthread.c | 71 ++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 tests/tcg/multiarch/munmap-pthread.c diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 78104f9bbb7..5f0fee1aadb 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -36,6 +36,9 @@ threadcount: LDFLAGS+=-lpthread signals: LDFLAGS+=-lrt -lpthread +munmap-pthread: CFLAGS+=-pthread +munmap-pthread: LDFLAGS+=-pthread + # We define the runner for test-mmap after the individual # architectures have defined their supported pages sizes. If no # additional page sizes are defined we only run the default test. diff --git a/tests/tcg/multiarch/munmap-pthread.c b/tests/tcg/multiarch/munmap-pthread.c new file mode 100644 index 00000000000..d2ac9aae604 --- /dev/null +++ b/tests/tcg/multiarch/munmap-pthread.c @@ -0,0 +1,71 @@ +/* Test that munmap() and thread creation do not race. */ +#include <assert.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> + +static const char nop_func[] = { +#if defined(__s390__) + /* br %r14 */ + 0x07, 0xfe, +#elif defined(__i386__) || defined(__x86_64__) + /* ret */ + 0xc3, +#endif +}; + +static void *thread_mmap_munmap(void *arg) +{ + volatile bool *run = arg; + char *p; + int ret; + + while (*run) { + p = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(p != MAP_FAILED); + if (sizeof(nop_func) != 0) { + /* + * Create a small translation block if we have a template for the + * current architecture. + */ + memcpy(p, nop_func, sizeof(nop_func)); + ((void(*)(void))p)(); + } + ret = munmap(p, getpagesize()); + assert(ret == 0); + } + + return NULL; +} + +static void *thread_dummy(void *arg) +{ + return NULL; +} + +int main(void) +{ + pthread_t mmap_munmap, dummy; + volatile bool run = true; + int i, ret; + + ret = pthread_create(&mmap_munmap, NULL, thread_mmap_munmap, (void *)&run); + assert(ret == 0); + + for (i = 0; i < 1000; i++) { + ret = pthread_create(&dummy, NULL, thread_dummy, NULL); + assert(ret == 0); + ret = pthread_join(dummy, NULL); + assert(ret == 0); + } + + run = false; + ret = pthread_join(mmap_munmap, NULL); + assert(ret == 0); + + return EXIT_SUCCESS; +} -- 2.37.2 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() 2022-10-28 12:42 [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Ilya Leoshkevich 2022-10-28 12:42 ` [PATCH 1/2] " Ilya Leoshkevich 2022-10-28 12:42 ` [PATCH 2/2] tests/tcg/multiarch: Add munmap-pthread.c Ilya Leoshkevich @ 2022-10-28 14:14 ` Alex Bennée 2 siblings, 0 replies; 5+ messages in thread From: Alex Bennée @ 2022-10-28 14:14 UTC (permalink / raw) To: Ilya Leoshkevich; +Cc: Richard Henderson, Paolo Bonzini, qemu-devel Ilya Leoshkevich <iii@linux.ibm.com> writes: > Hi, > > This is a fix for the issue reported in [1]. > Patch 1 is the fix itself, patch 2 is the test/reproducer. > > By the way, I noticed that there is no code to free tb_jmp_cache, and > object_finalize(CPUState) is never called - in case of system emulation > this is fine, but what about linux-user? We definitely have a memory leak here. The last attempt to properly finalize CPUState failed because we have duplicate pointers to the cpregs structures that end up in generated code. See: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg02819.html > > [1] https://lists.gnu.org/archive/html/qemu-devel/2022-10/msg05181.html > > Best regards, > Ilya > > Ilya Leoshkevich (2): > accel/tcg: Fix concurrent pthread_create() and munmap() > tests/tcg/multiarch: Add munmap-pthread.c > > accel/tcg/tb-maint.c | 5 ++ > tests/tcg/multiarch/Makefile.target | 3 ++ > tests/tcg/multiarch/munmap-pthread.c | 71 ++++++++++++++++++++++++++++ > 3 files changed, 79 insertions(+) > create mode 100644 tests/tcg/multiarch/munmap-pthread.c -- Alex Bennée ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-10-28 19:01 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-10-28 12:42 [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Ilya Leoshkevich 2022-10-28 12:42 ` [PATCH 1/2] " Ilya Leoshkevich 2022-10-28 18:59 ` Richard Henderson 2022-10-28 12:42 ` [PATCH 2/2] tests/tcg/multiarch: Add munmap-pthread.c Ilya Leoshkevich 2022-10-28 14:14 ` [PATCH 0/2] accel/tcg: Fix concurrent pthread_create() and munmap() Alex Bennée
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).