-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kmemcheck: add opcode self-testing at boot
We've had some troubles in the past with weird instructions. This patch adds a self-test framework which can be used to verify that a certain set of opcodes are decoded correctly. Of course, the opcodes which are not tested can still give the wrong results. In short, this is just a safeguard to catch unintentional changes in the opcode decoder. It does not mean that errors can't still occur! [rebased for mainline inclusion] Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com>
- Loading branch information
Vegard Nossum
committed
Jun 15, 2009
1 parent
eb63657
commit ac61a75
Showing
4 changed files
with
85 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
obj-y := error.o kmemcheck.o opcode.o pte.o shadow.o | ||
obj-y := error.o kmemcheck.o opcode.o pte.o selftest.o shadow.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#include <linux/kernel.h> | ||
|
||
#include "opcode.h" | ||
#include "selftest.h" | ||
|
||
struct selftest_opcode { | ||
unsigned int expected_size; | ||
const uint8_t *insn; | ||
const char *desc; | ||
}; | ||
|
||
static const struct selftest_opcode selftest_opcodes[] = { | ||
/* REP MOVS */ | ||
{1, "\xf3\xa4", "rep movsb <mem8>, <mem8>"}, | ||
{4, "\xf3\xa5", "rep movsl <mem32>, <mem32>"}, | ||
|
||
/* MOVZX / MOVZXD */ | ||
{1, "\x66\x0f\xb6\x51\xf8", "movzwq <mem8>, <reg16>"}, | ||
{1, "\x0f\xb6\x51\xf8", "movzwq <mem8>, <reg32>"}, | ||
|
||
/* MOVSX / MOVSXD */ | ||
{1, "\x66\x0f\xbe\x51\xf8", "movswq <mem8>, <reg16>"}, | ||
{1, "\x0f\xbe\x51\xf8", "movswq <mem8>, <reg32>"}, | ||
|
||
#ifdef CONFIG_X86_64 | ||
/* MOVZX / MOVZXD */ | ||
{1, "\x49\x0f\xb6\x51\xf8", "movzbq <mem8>, <reg64>"}, | ||
{2, "\x49\x0f\xb7\x51\xf8", "movzbq <mem16>, <reg64>"}, | ||
|
||
/* MOVSX / MOVSXD */ | ||
{1, "\x49\x0f\xbe\x51\xf8", "movsbq <mem8>, <reg64>"}, | ||
{2, "\x49\x0f\xbf\x51\xf8", "movsbq <mem16>, <reg64>"}, | ||
{4, "\x49\x63\x51\xf8", "movslq <mem32>, <reg64>"}, | ||
#endif | ||
}; | ||
|
||
static bool selftest_opcode_one(const struct selftest_opcode *op) | ||
{ | ||
unsigned size; | ||
|
||
kmemcheck_opcode_decode(op->insn, &size); | ||
|
||
if (size == op->expected_size) | ||
return true; | ||
|
||
printk(KERN_WARNING "kmemcheck: opcode %s: expected size %d, got %d\n", | ||
op->desc, op->expected_size, size); | ||
return false; | ||
} | ||
|
||
static bool selftest_opcodes_all(void) | ||
{ | ||
bool pass = true; | ||
unsigned int i; | ||
|
||
for (i = 0; i < ARRAY_SIZE(selftest_opcodes); ++i) | ||
pass = pass && selftest_opcode_one(&selftest_opcodes[i]); | ||
|
||
return pass; | ||
} | ||
|
||
bool kmemcheck_selftest(void) | ||
{ | ||
bool pass = true; | ||
|
||
pass = pass && selftest_opcodes_all(); | ||
|
||
return pass; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#ifndef ARCH_X86_MM_KMEMCHECK_SELFTEST_H | ||
#define ARCH_X86_MM_KMEMCHECK_SELFTEST_H | ||
|
||
bool kmemcheck_selftest(void); | ||
|
||
#endif |