From patchwork Mon Aug 29 12:34:06 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tixy X-Patchwork-Id: 1107722 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p7TCcBLJ020267 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 29 Aug 2011 12:38:33 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Qy16G-0006MP-Ih; Mon, 29 Aug 2011 12:38:00 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Qy16G-000103-0G; Mon, 29 Aug 2011 12:38:00 +0000 Received: from smarthost01.mail.zen.net.uk ([212.23.3.140]) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Qy12j-0000gY-AF for linux-arm-kernel@lists.infradead.org; Mon, 29 Aug 2011 12:34:27 +0000 Received: from [82.69.122.217] (helo=plug1) by smarthost01.mail.zen.net.uk with esmtpsa (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.63) (envelope-from ) id 1Qy12f-00027I-NH for linux-arm-kernel@lists.infradead.org; Mon, 29 Aug 2011 12:34:17 +0000 Received: from [192.168.2.20] (helo=computer2) by plug1 with esmtp (Exim 4.72) (envelope-from ) id 1Qy12e-0002pY-CC for linux-arm-kernel@lists.infradead.org; Mon, 29 Aug 2011 13:34:16 +0100 Received: from tixy by computer2 with local (Exim 4.72) (envelope-from ) id 1Qy12e-0000GP-8Z for linux-arm-kernel@lists.infradead.org; Mon, 29 Aug 2011 13:34:16 +0100 From: Tixy To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 07/10] ARM: kprobes: Add decoding table self-consistency tests Date: Mon, 29 Aug 2011 13:34:06 +0100 Message-Id: <1314621249-958-8-git-send-email-tixy@yxit.co.uk> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1314621249-958-1-git-send-email-tixy@yxit.co.uk> References: <1314621249-958-1-git-send-email-tixy@yxit.co.uk> X-Originating-Smarthost01-IP: [82.69.122.217] X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110829_083421_921986_8A101AD8 X-CRM114-Status: GOOD ( 18.77 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [212.23.3.140 listed in list.dnswl.org] X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Mon, 29 Aug 2011 12:38:33 +0000 (UTC) From: Jon Medhurst These check that the bitmask and match value used in the decoding tables are self consistent. Signed-off-by: Jon Medhurst --- arch/arm/kernel/kprobes-test.c | 103 ++++++++++++++++++++++++++++++++++++++-- 1 files changed, 99 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c index 1e7cdda..74a3a34 100644 --- a/arch/arm/kernel/kprobes-test.c +++ b/arch/arm/kernel/kprobes-test.c @@ -443,6 +443,92 @@ static int run_api_tests(long (*func)(long, long)) /* + * Decoding table self-consistency tests + */ + +static const int decode_struct_sizes[NUM_DECODE_TYPES] = { + [DECODE_TYPE_TABLE] = sizeof(struct decode_table), + [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), + [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), + [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), + [DECODE_TYPE_OR] = sizeof(struct decode_or), + [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) +}; + +static int table_iter(const union decode_item *table, + int (*fn)(const struct decode_header *, void *), + void *args) +{ + const struct decode_header *h = (struct decode_header *)table; + int result; + + for (;;) { + enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; + + if (type == DECODE_TYPE_END) + return 0; + + result = fn(h, args); + if (result) + return result; + + h = (struct decode_header *) + ((uintptr_t)h + decode_struct_sizes[type]); + + } +} + +static int table_test_fail(const struct decode_header *h, const char* message) +{ + + pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n", + message, h->mask.bits, h->value.bits); + return -EINVAL; +} + +struct table_test_args { + const union decode_item *root_table; + u32 parent_mask; + u32 parent_value; +}; + +static int table_test_fn(const struct decode_header *h, void *args) +{ + struct table_test_args *a = (struct table_test_args *)args; + enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; + + if (h->value.bits & ~h->mask.bits) + return table_test_fail(h, "Match value has bits not in mask"); + + if ((h->mask.bits & a->parent_mask) != a->parent_mask) + return table_test_fail(h, "Mask has bits not in parent mask"); + + if ((h->value.bits ^ a->parent_value) & a->parent_mask) + return table_test_fail(h, "Value is inconsistent with parent"); + + if (type == DECODE_TYPE_TABLE) { + struct decode_table *d = (struct decode_table *)h; + struct table_test_args args2 = *a; + args2.parent_mask = h->mask.bits; + args2.parent_value = h->value.bits; + return table_iter(d->table.table, table_test_fn, &args2); + } + + return 0; +} + +static int table_test(const union decode_item *table) +{ + struct table_test_args args = { + .root_table = table, + .parent_mask = 0, + .parent_value = 0 + }; + return table_iter(args.root_table, table_test_fn, &args); +} + + +/* * Framework for instruction set test cases */ @@ -1117,8 +1203,15 @@ end: * Top level test functions */ -static int run_test_cases(void (*tests)(void)) +static int run_test_cases(void (*tests)(void), const union decode_item *table) { + int ret; + + pr_info(" Check decoding tables\n"); + ret = table_test(table); + if (ret) + return ret; + pr_info(" Run test cases\n"); tests(); @@ -1140,7 +1233,7 @@ static int __init run_all_tests(void) goto out; pr_info("ARM instruction simulation\n"); - ret = run_test_cases(kprobe_arm_test_cases); + ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table); if (ret) goto out; @@ -1162,12 +1255,14 @@ static int __init run_all_tests(void) goto out; pr_info("16-bit Thumb instruction simulation\n"); - ret = run_test_cases(kprobe_thumb16_test_cases); + ret = run_test_cases(kprobe_thumb16_test_cases, + kprobe_decode_thumb16_table); if (ret) goto out; pr_info("32-bit Thumb instruction simulation\n"); - ret = run_test_cases(kprobe_thumb32_test_cases); + ret = run_test_cases(kprobe_thumb32_test_cases, + kprobe_decode_thumb32_table); if (ret) goto out; #endif