From patchwork Tue Oct 25 20:43:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9395449 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D90DA60233 for ; Tue, 25 Oct 2016 20:43:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BD6362972E for ; Tue, 25 Oct 2016 20:43:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B1B0D2976B; Tue, 25 Oct 2016 20:43:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id E64312972E for ; Tue, 25 Oct 2016 20:43:42 +0000 (UTC) Received: (qmail 28502 invoked by uid 550); 25 Oct 2016 20:43:40 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: kernel-hardening@lists.openwall.com Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 28322 invoked from network); 25 Oct 2016 20:43:18 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition; bh=890Rg0L9568jnIxjs9kNVv+OnwN+X2UxYR39NtbcUQ8=; b=ihPNUoUVIVOzxQEipfAtF82/EdtTxI8ju1CZPMKA5H2xI2/LsviCOUkvWDycu4XHgG 1MyNQrc8c5Ns+2V1Ksl77ZeR5u/jTXZ/YFPP2SJfrHggKAoXR+ukOkosxeyKpzDCE2qn 69D1+0GfmwE8yRG+QRTfgcKxUYI6z6Ns8Ai2I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition; bh=890Rg0L9568jnIxjs9kNVv+OnwN+X2UxYR39NtbcUQ8=; b=AqOm9aPw3VcQEoExNMvyGjwKoBKeDLgIMbdn5RKWmKqYf8eS+VwzdPRlZTHe7BegI/ kQL8d7QZZypiztkKMTkEAitJtADcLIf/uzboct/CZm0IAsSZYTEHXLgHCMOcfIFUXuU8 x0Wkdl/t9OFMj3eVOHBWFO6Dk0xdVPkuKwLbvts33Gw7rebzzLbibc3CooZhZZnqt8iv 2FvJqh/AmYDvkKndbftU0DOVwvyvZTY5t5S06dprOyDk1r854a72Eb0Ni3B5m6iMKGaN tGud7E9lWQDbhvzqvi7WhmiyNXQLD87cu/V/fiZuGlpOMHJtq4ON5j//6xi1ebKZf6/P 727A== X-Gm-Message-State: ABUngvfMAt/ViEl/5mJX+ZBOMMiMa28A2jy25rAGMTFtVQEHP2uo7IrYL89A7IqPOimWQpGN X-Received: by 10.98.17.26 with SMTP id z26mr43589801pfi.44.1477428184896; Tue, 25 Oct 2016 13:43:04 -0700 (PDT) Date: Tue, 25 Oct 2016 13:43:03 -0700 From: Kees Cook To: Hans Liljestrand Cc: Elena Reshetova , David Windsor , kernel-hardening@lists.openwall.com Message-ID: <20161025204303.GA36052@beast> MIME-Version: 1.0 Content-Disposition: inline Subject: [kernel-hardening] [RFC v2 PATCH 13.1/13] lkdtm: add tests for atomic over-/underflow X-Virus-Scanned: ClamAV using ClamSMTP This adds additional tests for the remaining atomic functions. Since the bulk of the logic is identical, the functions are generated with macros. Based on work by Hans Liljestrand. Signed-off-by: Kees Cook --- This is a replacement for the 13/13 patch, using macros more extensively and also ignores return values to avoid "calculated but unused" warnings. --- drivers/misc/lkdtm.h | 24 +++++++++++++-- drivers/misc/lkdtm_bugs.c | 74 ++++++++++++++++++++++++++++++++--------------- drivers/misc/lkdtm_core.c | 24 +++++++++++++-- 3 files changed, 95 insertions(+), 27 deletions(-) diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h index fdf954c2107f..62a29b9cd767 100644 --- a/drivers/misc/lkdtm.h +++ b/drivers/misc/lkdtm.h @@ -19,8 +19,28 @@ void lkdtm_SOFTLOCKUP(void); void lkdtm_HARDLOCKUP(void); void lkdtm_SPINLOCKUP(void); void lkdtm_HUNG_TASK(void); -void lkdtm_ATOMIC_UNDERFLOW(void); -void lkdtm_ATOMIC_OVERFLOW(void); +void lkdtm_OVERFLOW_atomic_inc(void); +void lkdtm_OVERFLOW_atomic_inc_return(void); +void lkdtm_OVERFLOW_atomic_inc_and_test(void); +void lkdtm_OVERFLOW_atomic_add(void); +void lkdtm_OVERFLOW_atomic_add_return(void); +void lkdtm_OVERFLOW_atomic_add_unless(void); +void lkdtm_OVERFLOW_atomic_long_inc(void); +void lkdtm_OVERFLOW_atomic_long_inc_return(void); +void lkdtm_OVERFLOW_atomic_long_inc_and_test(void); +void lkdtm_OVERFLOW_atomic_long_add(void); +void lkdtm_OVERFLOW_atomic_long_add_return(void); +void lkdtm_OVERFLOW_atomic_long_add_unless(void); +void lkdtm_UNDERFLOW_atomic_dec(void); +void lkdtm_UNDERFLOW_atomic_dec_return(void); +void lkdtm_UNDERFLOW_atomic_sub(void); +void lkdtm_UNDERFLOW_atomic_sub_return(void); +void lkdtm_UNDERFLOW_atomic_sub_and_test(void); +void lkdtm_UNDERFLOW_atomic_long_dec(void); +void lkdtm_UNDERFLOW_atomic_long_dec_return(void); +void lkdtm_UNDERFLOW_atomic_long_sub(void); +void lkdtm_UNDERFLOW_atomic_long_sub_return(void); +void lkdtm_UNDERFLOW_atomic_long_sub_and_test(void); /* lkdtm_heap.c */ void lkdtm_OVERWRITE_ALLOCATION(void); diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c index 182ae1894b32..2473bd275a87 100644 --- a/drivers/misc/lkdtm_bugs.c +++ b/drivers/misc/lkdtm_bugs.c @@ -123,26 +123,54 @@ void lkdtm_HUNG_TASK(void) schedule(); } -void lkdtm_ATOMIC_UNDERFLOW(void) -{ - atomic_t under = ATOMIC_INIT(INT_MIN); - - pr_info("attempting good atomic increment\n"); - atomic_inc(&under); - atomic_dec(&under); - - pr_info("attempting bad atomic underflow\n"); - atomic_dec(&under); -} - -void lkdtm_ATOMIC_OVERFLOW(void) -{ - atomic_t over = ATOMIC_INIT(INT_MAX); - - pr_info("attempting good atomic decrement\n"); - atomic_dec(&over); - atomic_inc(&over); - - pr_info("attempting bad atomic overflow\n"); - atomic_inc(&over); -} +/* + * Handle the various atomic function prototypes (potentially ignoring + * return values). + */ +#define ATOMIC_ARG_X(func, x) func(x) +#define ATOMIC_ARG_1_X(func, x) func(1, x) +#define ATOMIC_RET_ARG_X(func, x) if (func(x)) ; +#define ATOMIC_RET_ARG_1_X(func, x) if (func(1, x)) ; +#define ATOMIC_RET_ARG_X_1_0(func, x) if (func(x, 1, 0)) ; + +#define ATOMIC_ANY(name, atomic_type, init_func, start, safe_func, \ + test_func_proto, testfunc) \ +void lkdtm_##name##_##testfunc(void) \ +{ \ + atomic_type atomic = init_func(start); \ + \ + pr_info("attempting good " #testfunc "\n"); \ + safe_func(&atomic); \ + test_func_proto(testfunc, &atomic); \ + \ + pr_info("attempting bad " #testfunc "\n"); \ + test_func_proto(testfunc, &atomic); \ +} + +/* Declare underflow test functions for atomic_t and atomic_long_t types. */ +#define LKDTM_ATOMIC_UNDERFLOW(operation, test_func_proto) \ + ATOMIC_ANY(UNDERFLOW, atomic_t, ATOMIC_INIT, INT_MIN, \ + atomic_inc, test_func_proto, atomic_##operation) \ + ATOMIC_ANY(UNDERFLOW, atomic_long_t, ATOMIC_LONG_INIT, \ + LONG_MIN, atomic_long_inc, test_func_proto, \ + atomic_long_##operation) + +/* Declare overflow test functions for atomic_t and atomic_long_t types. */ +#define LKDTM_ATOMIC_OVERFLOW(operation, test_func_proto) \ + ATOMIC_ANY(OVERFLOW, atomic_t, ATOMIC_INIT, INT_MAX, \ + atomic_dec, test_func_proto, atomic_##operation) \ + ATOMIC_ANY(OVERFLOW, atomic_long_t, ATOMIC_LONG_INIT, \ + LONG_MAX, atomic_long_dec, test_func_proto, \ + atomic_long_##operation) + +LKDTM_ATOMIC_UNDERFLOW(dec, ATOMIC_ARG_X) +LKDTM_ATOMIC_UNDERFLOW(dec_return, ATOMIC_RET_ARG_X) +LKDTM_ATOMIC_UNDERFLOW(sub, ATOMIC_ARG_1_X) +LKDTM_ATOMIC_UNDERFLOW(sub_return, ATOMIC_RET_ARG_1_X) +LKDTM_ATOMIC_UNDERFLOW(sub_and_test, ATOMIC_RET_ARG_1_X) +LKDTM_ATOMIC_OVERFLOW(inc, ATOMIC_ARG_X) +LKDTM_ATOMIC_OVERFLOW(inc_return, ATOMIC_RET_ARG_X) +LKDTM_ATOMIC_OVERFLOW(add, ATOMIC_ARG_1_X) +LKDTM_ATOMIC_OVERFLOW(add_return, ATOMIC_RET_ARG_1_X) +LKDTM_ATOMIC_OVERFLOW(add_unless, ATOMIC_RET_ARG_X_1_0) +LKDTM_ATOMIC_OVERFLOW(inc_and_test, ATOMIC_RET_ARG_X) diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c index f9154b8d67f6..05b097f02ce4 100644 --- a/drivers/misc/lkdtm_core.c +++ b/drivers/misc/lkdtm_core.c @@ -218,8 +218,28 @@ struct crashtype crashtypes[] = { CRASHTYPE(WRITE_RO), CRASHTYPE(WRITE_RO_AFTER_INIT), CRASHTYPE(WRITE_KERN), - CRASHTYPE(ATOMIC_UNDERFLOW), - CRASHTYPE(ATOMIC_OVERFLOW), + CRASHTYPE(OVERFLOW_atomic_inc), + CRASHTYPE(OVERFLOW_atomic_inc_return), + CRASHTYPE(OVERFLOW_atomic_inc_and_test), + CRASHTYPE(OVERFLOW_atomic_add), + CRASHTYPE(OVERFLOW_atomic_add_return), + CRASHTYPE(OVERFLOW_atomic_add_unless), + CRASHTYPE(OVERFLOW_atomic_long_inc), + CRASHTYPE(OVERFLOW_atomic_long_inc_return), + CRASHTYPE(OVERFLOW_atomic_long_inc_and_test), + CRASHTYPE(OVERFLOW_atomic_long_add), + CRASHTYPE(OVERFLOW_atomic_long_add_return), + CRASHTYPE(OVERFLOW_atomic_long_add_unless), + CRASHTYPE(UNDERFLOW_atomic_dec), + CRASHTYPE(UNDERFLOW_atomic_dec_return), + CRASHTYPE(UNDERFLOW_atomic_sub), + CRASHTYPE(UNDERFLOW_atomic_sub_return), + CRASHTYPE(UNDERFLOW_atomic_sub_and_test), + CRASHTYPE(UNDERFLOW_atomic_long_dec), + CRASHTYPE(UNDERFLOW_atomic_long_dec_return), + CRASHTYPE(UNDERFLOW_atomic_long_sub), + CRASHTYPE(UNDERFLOW_atomic_long_sub_return), + CRASHTYPE(UNDERFLOW_atomic_long_sub_and_test), CRASHTYPE(USERCOPY_HEAP_SIZE_TO), CRASHTYPE(USERCOPY_HEAP_SIZE_FROM), CRASHTYPE(USERCOPY_HEAP_FLAG_TO),