From patchwork Wed Nov 1 23:50:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tobin Harding X-Patchwork-Id: 10037725 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 CB816602B5 for ; Wed, 1 Nov 2017 23:51:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BCB1D28C3C for ; Wed, 1 Nov 2017 23:51:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AFB0928C4A; Wed, 1 Nov 2017 23:51:11 +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 1C38D28C3C for ; Wed, 1 Nov 2017 23:51:09 +0000 (UTC) Received: (qmail 5257 invoked by uid 550); 1 Nov 2017 23:51:08 -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 5211 invoked from network); 1 Nov 2017 23:51:07 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tobin.cc; h=cc :date:from:message-id:subject:to:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=7IhqHyn7fS1LmzwM3rSKuEq5aYqu3MCU8GcZhh+/2 9Y=; b=c3hm4YTUzzH2h9uUZkMtwi3BGcEHgY+Go1kadnWyhFJY6LORQedu7SY+3 pfJRSouOsqP/Meuc839RAXdqSoDrOMeyJtbLBluJjn3jDWnGxxur2aVk0HGarWvZ C3KkENqM+UOKpKCQBBnJtphJIJFmSjVE1UCvc2VFWyjRUmmpQfvRS1zV3kaB1Yvo I+XCddk338BWkRskdUjQ2Q7F7/ixa1FlWxtPnFYcUV6esTzE/GTQxiEac+T3fqEL aW4Eu6uSRchpNtydkQktqdBeRHXUj44LZ44dukxDTRAouILMWnc4eAxWTO0qzjlI LaA3Y4aNoBukyRGC7qinb+5bJDocA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:message-id:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=7IhqHyn7fS1LmzwM3 rSKuEq5aYqu3MCU8GcZhh+/29Y=; b=N4qaPrHQxpPObz5n8SGATauN/yTjO5Iy9 Iu2uYkxEVOORYMgIe+KfxeuPD97JhRcBompWB7adwJ/TXBxDfE1gVepuiK2j7hAj HLjJyTQu6js0tjsq6K47s2JvdO4381OvLzwFyfh5+V0NensjfLdkZP46Voxyo4XP yp3kVPAYjI4bNNY73POIJ85W9O8SKsoaAH7GKm6NPm+1lrv9zkJBn0rUcIqLs/mx 62VXnvOdXy+CO1jJ6lXer9jTg2LiYH+9WjRC7QVI0MB++YUhGNgtpEPgQEKcQlyA mdmS18dMOwqbaHCPOfgXuEkI9w0p18IJJAkB77IGiqJ4nq1sVdMfQ== X-ME-Sender: From: "Tobin C. Harding" To: kernel-hardening@lists.openwall.com Cc: "Tobin C. Harding" , Kees Cook Date: Thu, 2 Nov 2017 10:50:40 +1100 Message-Id: <1509580240-28314-1-git-send-email-me@tobin.cc> X-Mailer: git-send-email 2.7.4 Subject: [kernel-hardening] [RFC] vla: add VLA macro and testing X-Virus-Scanned: ClamAV using ClamSMTP Variable Length Arrays (VLA) pose a risk to the stack if the variable passed into the array declaration is too large. If the variable used can be controlled by a malicious party then this poses a security risk to the kernel. Add a macro for declaring VLA's. Macro includes a requested size and a maximum size, if requested size is larger than maximum size then requested size is capped at maximum. Requested size is passed by reference and updated by macro so caller has access to size of array after declaration. Signed-off-by: Tobin C. Harding --- I was unable to get the test module to integrate with the kernel build system correctly. The attempt was to mirror the way `lib/test_printf.c` functions. This effort was unsuccessful, it is included in the patch in the hope of getting better suggestions. To test, the test module was built out of tree and all tests pass. The macro needs some work. It functions as intended but Checkpatch emits ERROR: Macros with multiple statements should be enclosed in a do - while loop. Also for each use of VLA() checkpatch emits WARNING: Missing a blank line after declarations. Also I was unsure where to put the macro definition, appreciate any suggestions. thanks, Tobin. include/linux/vla.h | 24 ++++++++++ lib/Kconfig.debug | 3 ++ lib/Makefile | 1 + lib/test_vla.c | 98 ++++++++++++++++++++++++++++++++++++++ tools/testing/selftests/lib/config | 1 + 5 files changed, 127 insertions(+) create mode 100644 include/linux/vla.h create mode 100644 lib/test_vla.c diff --git a/include/linux/vla.h b/include/linux/vla.h new file mode 100644 index 000000000000..e8f1572bbf42 --- /dev/null +++ b/include/linux/vla.h @@ -0,0 +1,24 @@ +/* + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_VLA_H +#define __LINUX_VLA_H + +/* + * When declaring a local variable using VLA(), VLA() must be the last + * declaration otherwise a compiler warning [-Wdeclaration-after-statement] will + * be generated + */ +#define VLA(type, name, size, max) \ + type name[(*size < max ? *size : max)]; \ + *size = (*size < max ? *size : max) + +#endif /* __LINUX_VLA_H */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index dfdad67d8f6c..3b8eb2789235 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1917,6 +1917,9 @@ config TEST_DEBUG_VIRTUAL If unsure, say N. +config TEST_VLA + tristate "Test VLA macro at runtime" + endmenu # runtime tests config MEMTEST diff --git a/lib/Makefile b/lib/Makefile index dafa79613fb4..b1e8f7c54c5b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_TEST_UUID) += test_uuid.o obj-$(CONFIG_TEST_PARMAN) += test_parman.o obj-$(CONFIG_TEST_KMOD) += test_kmod.o obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o +obj-$(CONFIG_TEST_VLA) += test_vla.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/test_vla.c b/lib/test_vla.c new file mode 100644 index 000000000000..033aeb219062 --- /dev/null +++ b/lib/test_vla.c @@ -0,0 +1,98 @@ +/* + * Tests for VLA macro. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +#include + +#define MAX_VLA_SIZE 32 + +static unsigned total_tests __initdata; +static unsigned failed_tests __initdata; + +static int __init test_vla_less_than_max(int want) +{ + int *size = &want; + VLA(char, myvla, size, MAX_VLA_SIZE); + + total_tests++; + + if (*size != want) { + pr_warn("VLA() declaration error: size=%d want=%d max=%d\n", + *size, want, MAX_VLA_SIZE); + return 1; + } + + /* quiet compiler warning */ + myvla[0] = 'a'; + + return 0; +} + +static int __init test_vla_greater_than_max(int want) +{ + int *size = &want; + VLA(char, myvla, size, MAX_VLA_SIZE); + + total_tests++; + + if (*size != MAX_VLA_SIZE) { + pr_warn("VLA() declaration error: size=%d want=%d max=%d\n", + *size, want, MAX_VLA_SIZE); + return 1; + } + + /* quiet compiler warning */ + myvla[0] = 'a'; + + return 0; +} + +static void __init test_vla_int_type_usage(int want) +{ + int *size = &want; + int i; + VLA(int, myvla, size, MAX_VLA_SIZE); + + total_tests++; + + for (i = 0; i < *size; i++) + myvla[i] = 0; +} + +static int __init test_vla_init(void) +{ + int lt_max = MAX_VLA_SIZE / 2; + int gt_max = MAX_VLA_SIZE * 2; + int err; + + err = test_vla_less_than_max(lt_max); + if (err) + failed_tests++; + + err = test_vla_greater_than_max(gt_max); + if (err) + failed_tests++; + + test_vla_int_type_usage(lt_max); + test_vla_int_type_usage(gt_max); + + if (failed_tests == 0) + pr_info("all %u tests passed\n", total_tests); + else + pr_warn("failed %u out of %u tests\n", + failed_tests, total_tests); + + return failed_tests ? -EINVAL : 0; +} + +module_init(test_vla_init); + +MODULE_AUTHOR("Tobin C. Harding "); +MODULE_LICENSE("GPL"); diff --git a/tools/testing/selftests/lib/config b/tools/testing/selftests/lib/config index 126933bcc950..0776156f881d 100644 --- a/tools/testing/selftests/lib/config +++ b/tools/testing/selftests/lib/config @@ -1,3 +1,4 @@ CONFIG_TEST_PRINTF=m CONFIG_TEST_BITMAP=m CONFIG_PRIME_NUMBERS=m +CONFIG_TEST_VLA=m