Message ID | 20240116003551.75168-4-iii@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | linux-user: Allow gdbstub to ignore page protection | expand |
Ilya Leoshkevich <iii@linux.ibm.com> writes: > Make sure that qemu gdbstub, like gdbserver, allows reading from and > writing to PROT_NONE pages. > > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Hmm I'm seeing the test hang and drop to the interactive python shell: TEST basic gdbstub support on aarch64 Failed to read a valid object file image from memory. qemu-aarch64: QEMU: Terminated via GDBstub TEST basic gdbstub qXfer:auxv:read support on aarch64 Failed to read a valid object file image from memory. qemu-aarch64: QEMU: Terminated via GDBstub TEST proc mappings support on aarch64 Failed to read a valid object file image from memory. qemu-aarch64: QEMU: Terminated via GDBstub TEST hitting a breakpoint on non-main thread on aarch64 Failed to read a valid object file image from memory. qemu-aarch64: QEMU: Terminated via GDBstub TEST checking register enumeration on aarch64 Failed to read a valid object file image from memory. qemu-aarch64: QEMU: Terminated via GDBstub TEST accessing PROT_NONE memory on aarch64 Failed to read a valid object file image from memory. Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) > --- > tests/tcg/multiarch/Makefile.target | 9 +++++- > tests/tcg/multiarch/gdbstub/prot-none.py | 22 +++++++++++++ > tests/tcg/multiarch/prot-none.c | 40 ++++++++++++++++++++++++ > 3 files changed, 70 insertions(+), 1 deletion(-) > create mode 100644 tests/tcg/multiarch/gdbstub/prot-none.py > create mode 100644 tests/tcg/multiarch/prot-none.c > > diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target > index d31ba8d6ae4..315a2e13588 100644 > --- a/tests/tcg/multiarch/Makefile.target > +++ b/tests/tcg/multiarch/Makefile.target > @@ -101,13 +101,20 @@ run-gdbstub-registers: sha512 > --bin $< --test $(MULTIARCH_SRC)/gdbstub/registers.py, \ > checking register enumeration) > > +run-gdbstub-prot-none: prot-none > + $(call run-test, $@, env PROT_NONE_PY=1 $(GDB_SCRIPT) \ > + --gdb $(GDB) \ > + --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ > + --bin $< --test $(MULTIARCH_SRC)/gdbstub/prot-none.py, \ > + accessing PROT_NONE memory) > + > else > run-gdbstub-%: > $(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support") > endif > EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \ > run-gdbstub-proc-mappings run-gdbstub-thread-breakpoint \ > - run-gdbstub-registers > + run-gdbstub-registers run-gdbstub-prot-none > > # ARM Compatible Semi Hosting Tests > # > diff --git a/tests/tcg/multiarch/gdbstub/prot-none.py b/tests/tcg/multiarch/gdbstub/prot-none.py > new file mode 100644 > index 00000000000..f1f1dd82cbe > --- /dev/null > +++ b/tests/tcg/multiarch/gdbstub/prot-none.py > @@ -0,0 +1,22 @@ > +"""Test that GDB can access PROT_NONE pages. > + > +This runs as a sourced script (via -x, via run-test.py). > + > +SPDX-License-Identifier: GPL-2.0-or-later > +""" > +from test_gdbstub import main, report > + > + > +def run_test(): > + """Run through the tests one by one""" > + gdb.Breakpoint("break_here") > + gdb.execute("continue") > + val = gdb.parse_and_eval("*(char[2] *)q").string() > + report(val == "42", "{} == 42".format(val)) > + gdb.execute("set *(char[3] *)q = \"24\"") > + gdb.execute("continue") > + exitcode = int(gdb.parse_and_eval("$_exitcode")) > + report(exitcode == 0, "{} == 0".format(exitcode)) > + > + > +main(run_test) > diff --git a/tests/tcg/multiarch/prot-none.c b/tests/tcg/multiarch/prot-none.c > new file mode 100644 > index 00000000000..dc56aadb3c5 > --- /dev/null > +++ b/tests/tcg/multiarch/prot-none.c > @@ -0,0 +1,40 @@ > +/* > + * Test that GDB can access PROT_NONE pages. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#include <assert.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/mman.h> > +#include <unistd.h> > + > +void break_here(void *q) > +{ > +} > + > +int main(void) > +{ > + long pagesize = sysconf(_SC_PAGESIZE); > + void *p, *q; > + int err; > + > + p = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + assert(p != MAP_FAILED); > + q = p + pagesize - 1; > + strcpy(q, "42"); > + > + err = mprotect(p, pagesize * 2, PROT_NONE); > + assert(err == 0); > + > + break_here(q); > + > + err = mprotect(p, pagesize * 2, PROT_READ); > + assert(err == 0); > + if (getenv("PROT_NONE_PY")) { > + assert(strcmp(q, "24") == 0); > + } > + > + return EXIT_SUCCESS; > +}
Ilya Leoshkevich <iii@linux.ibm.com> writes: > Make sure that qemu gdbstub, like gdbserver, allows reading from and > writing to PROT_NONE pages. > > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > tests/tcg/multiarch/Makefile.target | 9 +++++- > tests/tcg/multiarch/gdbstub/prot-none.py | 22 +++++++++++++ > tests/tcg/multiarch/prot-none.c | 40 ++++++++++++++++++++++++ > 3 files changed, 70 insertions(+), 1 deletion(-) > create mode 100644 tests/tcg/multiarch/gdbstub/prot-none.py > create mode 100644 tests/tcg/multiarch/prot-none.c > > diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target > index d31ba8d6ae4..315a2e13588 100644 > --- a/tests/tcg/multiarch/Makefile.target > +++ b/tests/tcg/multiarch/Makefile.target > @@ -101,13 +101,20 @@ run-gdbstub-registers: sha512 > --bin $< --test $(MULTIARCH_SRC)/gdbstub/registers.py, \ > checking register enumeration) > > +run-gdbstub-prot-none: prot-none > + $(call run-test, $@, env PROT_NONE_PY=1 $(GDB_SCRIPT) \ > + --gdb $(GDB) \ > + --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ > + --bin $< --test $(MULTIARCH_SRC)/gdbstub/prot-none.py, \ > + accessing PROT_NONE memory) > + > else > run-gdbstub-%: > $(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support") > endif > EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \ > run-gdbstub-proc-mappings run-gdbstub-thread-breakpoint \ > - run-gdbstub-registers > + run-gdbstub-registers run-gdbstub-prot-none > > # ARM Compatible Semi Hosting Tests > # > diff --git a/tests/tcg/multiarch/gdbstub/prot-none.py b/tests/tcg/multiarch/gdbstub/prot-none.py > new file mode 100644 > index 00000000000..f1f1dd82cbe > --- /dev/null > +++ b/tests/tcg/multiarch/gdbstub/prot-none.py > @@ -0,0 +1,22 @@ > +"""Test that GDB can access PROT_NONE pages. > + > +This runs as a sourced script (via -x, via run-test.py). > + > +SPDX-License-Identifier: GPL-2.0-or-later > +""" > +from test_gdbstub import main, report > + > + > +def run_test(): > + """Run through the tests one by one""" > + gdb.Breakpoint("break_here") > + gdb.execute("continue") > + val = gdb.parse_and_eval("*(char[2] *)q").string() Better traceback: Breakpoint 1, break_here (q=0x400000802fff) at /home/alex/lsrc/qemu.git/tests/tcg/multiarch/prot-none.c:14 14 } GDB Exception: Traceback (most recent call last): File "/home/alex/lsrc/qemu.git/tests/guest-debug/test_gdbstub.py", line 42, in main test() File "./tests/tcg/multiarch/gdbstub/prot-none.py", line 14, in run_test val = gdb.parse_and_eval("*(char[2] *)q").string() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ gdb.MemoryError: Cannot access memory at address 0x400000802fff Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> > + report(val == "42", "{} == 42".format(val)) > + gdb.execute("set *(char[3] *)q = \"24\"") > + gdb.execute("continue") > + exitcode = int(gdb.parse_and_eval("$_exitcode")) > + report(exitcode == 0, "{} == 0".format(exitcode)) > + > + > +main(run_test) > diff --git a/tests/tcg/multiarch/prot-none.c b/tests/tcg/multiarch/prot-none.c > new file mode 100644 > index 00000000000..dc56aadb3c5 > --- /dev/null > +++ b/tests/tcg/multiarch/prot-none.c > @@ -0,0 +1,40 @@ > +/* > + * Test that GDB can access PROT_NONE pages. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#include <assert.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/mman.h> > +#include <unistd.h> > + > +void break_here(void *q) > +{ > +} > + > +int main(void) > +{ > + long pagesize = sysconf(_SC_PAGESIZE); > + void *p, *q; > + int err; > + > + p = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + assert(p != MAP_FAILED); > + q = p + pagesize - 1; > + strcpy(q, "42"); > + > + err = mprotect(p, pagesize * 2, PROT_NONE); > + assert(err == 0); > + > + break_here(q); > + > + err = mprotect(p, pagesize * 2, PROT_READ); > + assert(err == 0); > + if (getenv("PROT_NONE_PY")) { > + assert(strcmp(q, "24") == 0); > + } > + > + return EXIT_SUCCESS; > +}
On Mon, Jan 22, 2024 at 03:54:32PM +0000, Alex Bennée wrote: > Ilya Leoshkevich <iii@linux.ibm.com> writes: > > > Make sure that qemu gdbstub, like gdbserver, allows reading from and > > writing to PROT_NONE pages. > > > > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > > --- > > tests/tcg/multiarch/Makefile.target | 9 +++++- > > tests/tcg/multiarch/gdbstub/prot-none.py | 22 +++++++++++++ > > tests/tcg/multiarch/prot-none.c | 40 ++++++++++++++++++++++++ > > 3 files changed, 70 insertions(+), 1 deletion(-) > > create mode 100644 tests/tcg/multiarch/gdbstub/prot-none.py > > create mode 100644 tests/tcg/multiarch/prot-none.c [...] > > +def run_test(): > > + """Run through the tests one by one""" > > + gdb.Breakpoint("break_here") > > + gdb.execute("continue") > > + val = gdb.parse_and_eval("*(char[2] *)q").string() > > Better traceback: > > Breakpoint 1, break_here (q=0x400000802fff) at /home/alex/lsrc/qemu.git/tests/tcg/multiarch/prot-none.c:14 > 14 } > GDB Exception: > Traceback (most recent call last): > File "/home/alex/lsrc/qemu.git/tests/guest-debug/test_gdbstub.py", line 42, in main > test() > File "./tests/tcg/multiarch/gdbstub/prot-none.py", line 14, in run_test > val = gdb.parse_and_eval("*(char[2] *)q").string() > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > gdb.MemoryError: Cannot access memory at address 0x400000802fff > Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux > Type "help", "copyright", "credits" or "license" for more information. > (InteractiveConsole) > >>> Thanks for the debug output. This shows that the feature being tested doesn't work (the value of `q` looks sane to me). May I ask what host distro is this? I tried on x86_64 Fedora 38 and x86_64 Ubuntu 22.04 so far, and the test was successful. [...]
Ilya Leoshkevich <iii@linux.ibm.com> writes: > On Mon, Jan 22, 2024 at 03:54:32PM +0000, Alex Bennée wrote: >> Ilya Leoshkevich <iii@linux.ibm.com> writes: >> >> > Make sure that qemu gdbstub, like gdbserver, allows reading from and >> > writing to PROT_NONE pages. >> > >> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> >> > --- >> > tests/tcg/multiarch/Makefile.target | 9 +++++- >> > tests/tcg/multiarch/gdbstub/prot-none.py | 22 +++++++++++++ >> > tests/tcg/multiarch/prot-none.c | 40 ++++++++++++++++++++++++ >> > 3 files changed, 70 insertions(+), 1 deletion(-) >> > create mode 100644 tests/tcg/multiarch/gdbstub/prot-none.py >> > create mode 100644 tests/tcg/multiarch/prot-none.c > > [...] > >> > +def run_test(): >> > + """Run through the tests one by one""" >> > + gdb.Breakpoint("break_here") >> > + gdb.execute("continue") >> > + val = gdb.parse_and_eval("*(char[2] *)q").string() >> >> Better traceback: >> >> Breakpoint 1, break_here (q=0x400000802fff) at /home/alex/lsrc/qemu.git/tests/tcg/multiarch/prot-none.c:14 >> 14 } >> GDB Exception: >> Traceback (most recent call last): >> File "/home/alex/lsrc/qemu.git/tests/guest-debug/test_gdbstub.py", line 42, in main >> test() >> File "./tests/tcg/multiarch/gdbstub/prot-none.py", line 14, in run_test >> val = gdb.parse_and_eval("*(char[2] *)q").string() >> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >> gdb.MemoryError: Cannot access memory at address 0x400000802fff >> Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux >> Type "help", "copyright", "credits" or "license" for more information. >> (InteractiveConsole) >> >>> > > Thanks for the debug output. This shows that the feature being tested > doesn't work (the value of `q` looks sane to me). May I ask what host > distro is this? I tried on x86_64 Fedora 38 and x86_64 Ubuntu 22.04 so > far, and the test was successful. Debian Bookworm (x86_64) with gdb-multiarch installed. > > [...]
On Mon, Jan 22, 2024 at 11:19:05PM +0000, Alex Bennée wrote: > Ilya Leoshkevich <iii@linux.ibm.com> writes: > > > On Mon, Jan 22, 2024 at 03:54:32PM +0000, Alex Bennée wrote: > >> Ilya Leoshkevich <iii@linux.ibm.com> writes: > >> > >> > Make sure that qemu gdbstub, like gdbserver, allows reading from and > >> > writing to PROT_NONE pages. > >> > > >> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > >> > --- > >> > tests/tcg/multiarch/Makefile.target | 9 +++++- > >> > tests/tcg/multiarch/gdbstub/prot-none.py | 22 +++++++++++++ > >> > tests/tcg/multiarch/prot-none.c | 40 ++++++++++++++++++++++++ > >> > 3 files changed, 70 insertions(+), 1 deletion(-) > >> > create mode 100644 tests/tcg/multiarch/gdbstub/prot-none.py > >> > create mode 100644 tests/tcg/multiarch/prot-none.c > > > > [...] > > > >> > +def run_test(): > >> > + """Run through the tests one by one""" > >> > + gdb.Breakpoint("break_here") > >> > + gdb.execute("continue") > >> > + val = gdb.parse_and_eval("*(char[2] *)q").string() > >> > >> Better traceback: > >> > >> Breakpoint 1, break_here (q=0x400000802fff) at /home/alex/lsrc/qemu.git/tests/tcg/multiarch/prot-none.c:14 > >> 14 } > >> GDB Exception: > >> Traceback (most recent call last): > >> File "/home/alex/lsrc/qemu.git/tests/guest-debug/test_gdbstub.py", line 42, in main > >> test() > >> File "./tests/tcg/multiarch/gdbstub/prot-none.py", line 14, in run_test > >> val = gdb.parse_and_eval("*(char[2] *)q").string() > >> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > >> gdb.MemoryError: Cannot access memory at address 0x400000802fff > >> Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux > >> Type "help", "copyright", "credits" or "license" for more information. > >> (InteractiveConsole) > >> >>> > > > > Thanks for the debug output. This shows that the feature being tested > > doesn't work (the value of `q` looks sane to me). May I ask what host > > distro is this? I tried on x86_64 Fedora 38 and x86_64 Ubuntu 22.04 so > > far, and the test was successful. > > Debian Bookworm (x86_64) with gdb-multiarch installed. > > > > [...] > > -- > Alex Bennée > Virtualisation Tech Lead @ Linaro Hm, I tried that (in a VM, in case the kernel is somehow involved) and that worked too: Breakpoint 1, break_here (q=0x400000802fff) at /qemu/tests/tcg/multiarch/prot-none.c:14 14 } PASS: 42 == 42 I wonder what else can be different. Can it be that in your case the test runs without /proc? Or perhaps some additional LSM is enabled?
diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index d31ba8d6ae4..315a2e13588 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -101,13 +101,20 @@ run-gdbstub-registers: sha512 --bin $< --test $(MULTIARCH_SRC)/gdbstub/registers.py, \ checking register enumeration) +run-gdbstub-prot-none: prot-none + $(call run-test, $@, env PROT_NONE_PY=1 $(GDB_SCRIPT) \ + --gdb $(GDB) \ + --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ + --bin $< --test $(MULTIARCH_SRC)/gdbstub/prot-none.py, \ + accessing PROT_NONE memory) + else run-gdbstub-%: $(call skip-test, "gdbstub test $*", "need working gdb with $(patsubst -%,,$(TARGET_NAME)) support") endif EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read \ run-gdbstub-proc-mappings run-gdbstub-thread-breakpoint \ - run-gdbstub-registers + run-gdbstub-registers run-gdbstub-prot-none # ARM Compatible Semi Hosting Tests # diff --git a/tests/tcg/multiarch/gdbstub/prot-none.py b/tests/tcg/multiarch/gdbstub/prot-none.py new file mode 100644 index 00000000000..f1f1dd82cbe --- /dev/null +++ b/tests/tcg/multiarch/gdbstub/prot-none.py @@ -0,0 +1,22 @@ +"""Test that GDB can access PROT_NONE pages. + +This runs as a sourced script (via -x, via run-test.py). + +SPDX-License-Identifier: GPL-2.0-or-later +""" +from test_gdbstub import main, report + + +def run_test(): + """Run through the tests one by one""" + gdb.Breakpoint("break_here") + gdb.execute("continue") + val = gdb.parse_and_eval("*(char[2] *)q").string() + report(val == "42", "{} == 42".format(val)) + gdb.execute("set *(char[3] *)q = \"24\"") + gdb.execute("continue") + exitcode = int(gdb.parse_and_eval("$_exitcode")) + report(exitcode == 0, "{} == 0".format(exitcode)) + + +main(run_test) diff --git a/tests/tcg/multiarch/prot-none.c b/tests/tcg/multiarch/prot-none.c new file mode 100644 index 00000000000..dc56aadb3c5 --- /dev/null +++ b/tests/tcg/multiarch/prot-none.c @@ -0,0 +1,40 @@ +/* + * Test that GDB can access PROT_NONE pages. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> + +void break_here(void *q) +{ +} + +int main(void) +{ + long pagesize = sysconf(_SC_PAGESIZE); + void *p, *q; + int err; + + p = mmap(NULL, pagesize * 2, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(p != MAP_FAILED); + q = p + pagesize - 1; + strcpy(q, "42"); + + err = mprotect(p, pagesize * 2, PROT_NONE); + assert(err == 0); + + break_here(q); + + err = mprotect(p, pagesize * 2, PROT_READ); + assert(err == 0); + if (getenv("PROT_NONE_PY")) { + assert(strcmp(q, "24") == 0); + } + + return EXIT_SUCCESS; +}
Make sure that qemu gdbstub, like gdbserver, allows reading from and writing to PROT_NONE pages. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- tests/tcg/multiarch/Makefile.target | 9 +++++- tests/tcg/multiarch/gdbstub/prot-none.py | 22 +++++++++++++ tests/tcg/multiarch/prot-none.c | 40 ++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/tcg/multiarch/gdbstub/prot-none.py create mode 100644 tests/tcg/multiarch/prot-none.c