From patchwork Fri Apr 13 13:41:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Stoppa X-Patchwork-Id: 10340111 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 E337D604D4 for ; Fri, 13 Apr 2018 13:44:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DBDBF28849 for ; Fri, 13 Apr 2018 13:44:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D01172884B; Fri, 13 Apr 2018 13:44:02 +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=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED 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 6B17B28849 for ; Fri, 13 Apr 2018 13:44:01 +0000 (UTC) Received: (qmail 31756 invoked by uid 550); 13 Apr 2018 13:43:30 -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: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 30613 invoked from network); 13 Apr 2018 13:43:25 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gU1q5AL2YTeMdJiI2RT0RJnEZzj0Bh+10bhgrIzCaBk=; b=mOL3UI+TrUyrn9YKwDh9oiFoOkPSDYSAinoQxXuFMs6ih+ZsxZ02pi45c0xpbd9xKN 2xxubz9uMCY3ZPnV1dx2BnRTKB1dVQryOS2ulpZFunkBVpmOJuijcMKUq3TAjG87U57t hBbBKfY+spTwgr1y4rUBw7nhRXULeD0p0UIPMA3UffYOOBY6EmEQjlyTVopWcdY5o+I4 5URTQUsk0vCZTBQhaFsyEnEeqyJT3EBhRp8Z3QRi0ai8Gy0J7cUMd4g4Ega9i39/2Fx1 oBJLLhBP3MKD/rbv+CgLdQgGOg8uC4WDjtEsRVEWPzrKTlyvjEU/Mkjul0KDNxy1avkR UBew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gU1q5AL2YTeMdJiI2RT0RJnEZzj0Bh+10bhgrIzCaBk=; b=qaOsq9A7Y0kjzW4JSTiGbeCLCrfjJe3I+/5B2MIMpRMAsOV/E783i7VMv9ycaQ5wWs 4Ej7rSQgkuiXIzxwsUVWHgYfa3hF4m4fR1WPORk5zey8iI08R1a4VXLVI5dCzvdUvu/k LDHO6uGpjbAU/GHqIQHYSKoozgAjcT+FgTJ21Mqn45g5Fkzbrf0OMIWLa2apzdtzOC0u 7dM1e/BPtGz47QuUgWlJclhIRXcWkGN+aNugJvslMSTqRWR65zQBjE0A3W+WxYr1cipl VnWuvjHSkLWDYjXWPUiylZVHr0HCvmgMtS9BvlyItKdAzSTZkp6YsFlYbcYpgdzfWtvH gGug== X-Gm-Message-State: ALQs6tDCwYEpZpYmP9O7XyEdHqKwGzKPswLZkjW725Yqky0FQGdDgHlP Q5816p5uZWQ6PlVFkJgBLBU= X-Google-Smtp-Source: AIpwx49jsh3jFFFB9UfRzgAyjzB09/A6UIVE84WwjICThm106KPE+x7WUhIPMtIYua+sePpqeBjC6g== X-Received: by 2002:a19:a949:: with SMTP id s70-v6mr8002665lfe.53.1523626993803; Fri, 13 Apr 2018 06:43:13 -0700 (PDT) From: Igor Stoppa X-Google-Original-From: Igor Stoppa To: willy@infradead.org, keescook@chromium.org, mhocko@kernel.org, corbet@lwn.net Cc: david@fromorbit.com, rppt@linux.vnet.ibm.com, labbott@redhat.com, linux-security-module@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, Igor Stoppa Subject: [PATCH 5/6] Pmalloc selftest Date: Fri, 13 Apr 2018 17:41:30 +0400 Message-Id: <20180413134131.4651-6-igor.stoppa@huawei.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180413134131.4651-1-igor.stoppa@huawei.com> References: <20180413134131.4651-1-igor.stoppa@huawei.com> X-Virus-Scanned: ClamAV using ClamSMTP Add basic self-test functionality for pmalloc. The testing is introduced as early as possible, right after the main dependency, genalloc, has passed successfully, so that it can help diagnosing failures in pmalloc users. Signed-off-by: Igor Stoppa --- include/linux/test_pmalloc.h | 24 ++++++++ init/main.c | 2 + mm/Kconfig | 10 ++++ mm/Makefile | 1 + mm/test_pmalloc.c | 137 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 include/linux/test_pmalloc.h create mode 100644 mm/test_pmalloc.c diff --git a/include/linux/test_pmalloc.h b/include/linux/test_pmalloc.h new file mode 100644 index 000000000000..c7e2e451c17c --- /dev/null +++ b/include/linux/test_pmalloc.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * test_pmalloc.h + * + * (C) Copyright 2018 Huawei Technologies Co. Ltd. + * Author: Igor Stoppa + */ + + +#ifndef __LINUX_TEST_PMALLOC_H +#define __LINUX_TEST_PMALLOC_H + + +#ifdef CONFIG_TEST_PROTECTABLE_MEMORY + +void test_pmalloc(void); + +#else + +static inline void test_pmalloc(void){}; + +#endif + +#endif diff --git a/init/main.c b/init/main.c index b795aa341a3a..27f8479c4578 100644 --- a/init/main.c +++ b/init/main.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -679,6 +680,7 @@ asmlinkage __visible void __init start_kernel(void) */ mem_encrypt_init(); + test_pmalloc(); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { diff --git a/mm/Kconfig b/mm/Kconfig index d7ef40eaa4e8..f98b4c0aebce 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -758,3 +758,13 @@ config PROTECTABLE_MEMORY depends on MMU depends on ARCH_HAS_SET_MEMORY default y + +config TEST_PROTECTABLE_MEMORY + bool "Run self test for pmalloc memory allocator" + depends on MMU + depends on ARCH_HAS_SET_MEMORY + select PROTECTABLE_MEMORY + default n + help + Tries to verify that pmalloc works correctly and that the memory + is effectively protected. diff --git a/mm/Makefile b/mm/Makefile index 6a6668f99799..802cba37013b 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o obj-$(CONFIG_SLOB) += slob.o obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o obj-$(CONFIG_PROTECTABLE_MEMORY) += pmalloc.o +obj-$(CONFIG_TEST_PROTECTABLE_MEMORY) += test_pmalloc.o obj-$(CONFIG_KSM) += ksm.o obj-$(CONFIG_PAGE_POISONING) += page_poison.o obj-$(CONFIG_SLAB) += slab.o diff --git a/mm/test_pmalloc.c b/mm/test_pmalloc.c new file mode 100644 index 000000000000..b0e091bf6329 --- /dev/null +++ b/mm/test_pmalloc.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * test_pmalloc.c + * + * (C) Copyright 2018 Huawei Technologies Co. Ltd. + * Author: Igor Stoppa + */ + +#include +#include +#include +#include + +#define SIZE_1 (PAGE_SIZE * 3) +#define SIZE_2 1000 + + +/* wrapper for is_pmalloc_object() with messages */ +static inline bool validate_alloc(bool expected, void *addr, + unsigned long size) +{ + bool test; + + test = is_pmalloc_object(addr, size) > 0; + pr_notice("must be %s: %s", + expected ? "ok" : "no", test ? "ok" : "no"); + return test == expected; +} + + +#define is_alloc_ok(variable, size) \ + validate_alloc(true, variable, size) + + +#define is_alloc_no(variable, size) \ + validate_alloc(false, variable, size) + +/* tests the basic life-cycle of a pool */ +static bool create_and_destroy_pool(void) +{ + static struct pmalloc_pool *pool; + + pr_notice("Testing pool creation and destruction capability"); + + pool = pmalloc_create_pool(); + if (WARN(!pool, "Cannot allocate memory for pmalloc selftest.")) + return false; + pmalloc_destroy_pool(pool); + return true; +} + + +/* verifies that it's possible to allocate from the pool */ +static bool test_alloc(void) +{ + static struct pmalloc_pool *pool; + static void *p; + + pr_notice("Testing allocation capability"); + pool = pmalloc_create_pool(); + if (WARN(!pool, "Unable to allocate memory for pmalloc selftest.")) + return false; + p = pmalloc(pool, SIZE_1 - 1); + pmalloc_protect_pool(pool); + pmalloc_destroy_pool(pool); + if (WARN(!p, "Failed to allocate memory from the pool")) + return false; + return true; +} + + +/* tests the identification of pmalloc ranges */ +static bool test_is_pmalloc_object(void) +{ + struct pmalloc_pool *pool; + void *pmalloc_p; + void *vmalloc_p; + bool retval = false; + + pr_notice("Test correctness of is_pmalloc_object()"); + + vmalloc_p = vmalloc(SIZE_1); + if (WARN(!vmalloc_p, + "Unable to allocate memory for pmalloc selftest.")) + return false; + pool = pmalloc_create_pool(); + if (WARN(!pool, "Unable to allocate memory for pmalloc selftest.")) + return false; + pmalloc_p = pmalloc(pool, SIZE_1 - 1); + if (WARN(!pmalloc_p, "Failed to allocate memory from the pool")) + goto error; + if (WARN_ON(unlikely(!is_alloc_ok(pmalloc_p, 10))) || + WARN_ON(unlikely(!is_alloc_ok(pmalloc_p, SIZE_1))) || + WARN_ON(unlikely(!is_alloc_ok(pmalloc_p, PAGE_SIZE))) || + WARN_ON(unlikely(!is_alloc_no(pmalloc_p, SIZE_1 + 1))) || + WARN_ON(unlikely(!is_alloc_no(vmalloc_p, 10)))) + goto error; + retval = true; +error: + pmalloc_protect_pool(pool); + pmalloc_destroy_pool(pool); + vfree(vmalloc_p); + return retval; +} + +/* Test out of virtually contiguous memory */ +static void test_oovm(void) +{ + struct pmalloc_pool *pool; + unsigned int i; + + pr_notice("Exhaust vmalloc memory with doubling allocations."); + pool = pmalloc_create_pool(); + if (WARN(!pool, "Failed to create pool")) + return; + for (i = 1; i; i *= 2) + if (unlikely(!pzalloc(pool, i - 1))) + break; + pr_notice("vmalloc oom at %d allocation", i - 1); + pmalloc_protect_pool(pool); + pmalloc_destroy_pool(pool); +} + +/** + * test_pmalloc() -main entry point for running the test cases + */ +void test_pmalloc(void) +{ + + pr_notice("pmalloc-selftest"); + + if (unlikely(!(create_and_destroy_pool() && + test_alloc() && + test_is_pmalloc_object()))) + return; + test_oovm(); +}