On 17.08.2016 08:48, Suraj Jitindar Singh wrote: > On Power machines if a guest cedes while a tm transaction is in the > suspended state then the checkpointed state of the vcpu may be lost and we > lose the cpu in the host. > > Add a file for tm tests "powerpc/tm.c" and add a test to check if the fix > has been applied to the host kernel. If this fix hasn't been applied then > the test will never complete and the cpu will be lost. Otherwise the test > should succeed. Since this has the ability to mess things up in the host > mark this test as don't run by default. > > This vulnerability has been assigned the ID CVE-2016-5412. > > Based on initial work done by: Cyril Bur <cyril.bur@xxxxxxxxxxx> > > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@xxxxxxxxx> > Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx> > > --- > > Change Log: > > V2 -> V3: > - Remove get_dec() and sleep() functions as sleep functionality is > now provided by a generic implementation in processor.c. > - Replace TM instructions with raw machine code to support older > compilers > V3 -> V4: > - Style Changes > --- > lib/powerpc/asm/hcall.h | 1 + > powerpc/Makefile.common | 3 +- > powerpc/tm.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ > powerpc/unittests.cfg | 6 +++ > 4 files changed, 129 insertions(+), 1 deletion(-) > create mode 100644 powerpc/tm.c > > diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h > index 99bce79..80aa3e3 100644 > --- a/lib/powerpc/asm/hcall.h > +++ b/lib/powerpc/asm/hcall.h > @@ -18,6 +18,7 @@ > #define H_SET_SPRG0 0x24 > #define H_SET_DABR 0x28 > #define H_PAGE_INIT 0x2c > +#define H_CEDE 0xE0 > #define H_PUT_TERM_CHAR 0x58 > #define H_RANDOM 0x300 > #define H_SET_MODE 0x31C > diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common > index 677030a..93e4f66 100644 > --- a/powerpc/Makefile.common > +++ b/powerpc/Makefile.common > @@ -8,7 +8,8 @@ tests-common = \ > $(TEST_DIR)/selftest.elf \ > $(TEST_DIR)/spapr_hcall.elf \ > $(TEST_DIR)/rtas.elf \ > - $(TEST_DIR)/emulator.elf > + $(TEST_DIR)/emulator.elf \ > + $(TEST_DIR)/tm.elf > > all: $(TEST_DIR)/boot_rom.bin test_cases > > diff --git a/powerpc/tm.c b/powerpc/tm.c > new file mode 100644 > index 0000000..6ce750a > --- /dev/null > +++ b/powerpc/tm.c > @@ -0,0 +1,120 @@ > +/* > + * Transactional Memory Unit Tests > + * > + * Copyright 2016 Suraj Jitindar Singh, IBM. > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#include <libcflat.h> > +#include <asm/hcall.h> > +#include <asm/processor.h> > +#include <asm/handlers.h> > +#include <asm/smp.h> > + > +static int h_cede(void) > +{ > + register uint64_t r3 asm("r3") = H_CEDE; > + > + asm volatile ("sc 1" : "+r"(r3) : > + : "r0", "r4", "r5", "r6", "r7", "r8", "r9", > + "r10", "r11", "r12", "xer", "ctr", "cc"); > + > + return r3; > +} > + > +/* > + * Enable transactional memory > + * Returns: FALSE - Failure > + * TRUE - Success > + */ > +static bool enable_tm(void) > +{ > + uint64_t msr = 0; > + > + asm volatile ("mfmsr %[msr]" : [msr] "=r" (msr)); > + > + msr |= (((uint64_t) 1) << 32); > + > + asm volatile ("mtmsrd %[msr]\n\t" > + "mfmsr %[msr]" : [msr] "+r" (msr)); > + > + return !!(msr & (((uint64_t) 1) << 32)); > +} > + > +/* > + * Test H_CEDE call while transactional memory transaction is suspended > + * > + * WARNING: This tests for a known vulnerability in which the host may go down. > + * Probably best not to run this if your host going down is going to cause > + * problems. > + * > + * If the test passes then your kernel probably has the necessary patch. > + * If the test fails then the H_CEDE call was unsuccessful and the > + * vulnerability wasn't tested. > + * If the test hits the vulnerability then it will never complete or report and > + * the qemu process will block indefinitely. RCU stalls will be detected on the > + * cpu and any process scheduled on the lost cpu will also block indefinitely. > + */ > +static void test_h_cede_tm(int argc, char **argv) > +{ > + int i; > + > + if (argc > 2) > + report_abort("Unsupported argument: '%s'", argv[2]); > + > + handle_exception(0x900, &dec_except_handler, NULL); > + > + if (!start_all_cpus(halt, 0)) > + report_abort("Failed to start secondary cpus"); > + > + if (!enable_tm()) > + report_abort("Failed to enable tm"); > + > + /* > + * Begin a transaction and guarantee we are in the suspend state > + * before continuing > + */ > + asm volatile ("1: .long 0x7c00051d\n\t" /* tbegin. */ > + "beq 2f\n\t" > + ".long 0x7c0005dd\n\t" /* tsuspend. */ > + "2: .long 0x7c00059c\n\t" /* tcheck cr0 */ > + "bf 2,1b" : : : "cr0"); > + > + for (i = 0; i < 500; i++) { > + uint64_t rval = h_cede(); > + > + if (rval != H_SUCCESS) > + break; > + mdelay(5); > + } > + > + report("H_CEDE TM", i == 500); > +} > + > +struct { > + const char *name; > + void (*func)(int argc, char **argv); > +} hctests[] = { > + { "h_cede_tm", test_h_cede_tm }, > + { NULL, NULL } > +}; > + > +int main(int argc, char **argv) > +{ > + bool all; > + int i; > + > + report_prefix_push("tm"); > + > + all = argc == 1 || !strcmp(argv[1], "all"); > + > + for (i = 0; hctests[i].name != NULL; i++) { > + if (all || strcmp(argv[1], hctests[i].name) == 0) { > + report_prefix_push(hctests[i].name); > + hctests[i].func(argc, argv); > + report_prefix_pop(); > + } > + } > + > + return report_summary(); > +} > diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg > index 0098cb6..20dbde6 100644 > --- a/powerpc/unittests.cfg > +++ b/powerpc/unittests.cfg > @@ -53,3 +53,9 @@ groups = rtas > > [emulator] > file = emulator.elf > + > +[h_cede_tm] > +file = tm.elf > +smp = 2,threads=2 > +extra_params = -append "h_cede_tm" > +groups = nodefault,h_cede_tm > Reviewed-by: Thomas Huth <thuth@xxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html