From: Kees Cook <keescook@chromium.org>
To: Kaiwan N Billimoria <kaiwan@kaiwantech.com>
Cc: kernel-hardening@lists.openwall.com
Subject: [kernel-hardening] [RFC] mm: enable sanitizing via CONFIG
Date: Fri, 24 Feb 2017 16:32:32 -0800 [thread overview]
Message-ID: <20170225003232.GA123380@beast> (raw)
This enables page and slab poisoning by default under CONFIG_MEMORY_SANITIZE.
Based on work by Kaiwan N Billimoria.
Signed-off-by: Kees Cook <keescook@chromium.org>
---
This is more what I had in mind. This is based on the latest patch, but
handles slab and slub. I tested slub with lkdtm's READ_AFTER_FREE and
READ_BUDDY_AFTER_FREE which both trip the poisoning tests.
While doing this, I noticed one major issue with slub/slab poisoning:
it performs poisoning both on alloc and free, which is a rather large
performance hit, so the next step is likely to find a way to split the
poisoning into alloc and free halves so that CONFIG_MEMORY_SANITIZE
poisoning will only happen on the free.
---
init/main.c | 5 +++++
mm/Kconfig.debug | 23 +++++++++++++++++++++++
mm/page_poison.c | 3 ++-
mm/slab.c | 4 ++++
mm/slub.c | 7 +++++++
5 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/init/main.c b/init/main.c
index 24ea48745061..e5f571bfe56f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -1030,6 +1030,11 @@ static noinline void __init kernel_init_freeable(void)
do_basic_setup();
+#ifdef CONFIG_MEMORY_SANITIZE
+ pr_debug("[CONFIG_MEMORY_SANITIZE]: page_poisoning_enabled? %s\n",
+ page_poisoning_enabled() ? "yes" : "no");
+#endif
+
/* Open the /dev/console on the rootfs, this should never fail */
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
pr_err("Warning: unable to open an initial console.\n");
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index afcc550877ff..910a7a359b96 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -90,3 +90,26 @@ config DEBUG_PAGE_REF
careful when enabling this feature because it adds about 30 KB to the
kernel code. However the runtime performance overhead is virtually
nil until the tracepoints are actually enabled.
+
+config MEMORY_SANITIZE
+ bool "Enable memory sanitization features"
+ depends on SLUB || SLAB
+ select SLUB_DEBUG if SLUB
+ select PAGE_POISONING
+ select PAGE_POISONING_NO_SANITY
+ help
+ This option enables memory sanitization features. Particularly,
+ when you turn on this option, it auto-enables:
+ - page poisoning (without sanity checking)
+ - kmem_cache poisoning
+
+ Implication: turning this option on will implicitly enable:
+ - the SLUB_DEBUG switch to the equivalent of the kernel command-line
+ 'slub_debug=p' (where p=SLAB_POISON).
+ - page poisoning, equivalent to passing the kernel command-line
+ option 'page_poison=on'.
+
+ Of course, kernel command-line options 'page_poison' and 'slub_debug'
+ are still honored.
+
+ If unsure, say N.
diff --git a/mm/page_poison.c b/mm/page_poison.c
index 2e647c65916b..6f7e37c8ac2f 100644
--- a/mm/page_poison.c
+++ b/mm/page_poison.c
@@ -7,7 +7,8 @@
#include <linux/ratelimit.h>
static bool __page_poisoning_enabled __read_mostly;
-static bool want_page_poisoning __read_mostly;
+static bool want_page_poisoning __read_mostly =
+ IS_ENABLED(CONFIG_MEMORY_SANITIZE);
static int early_page_poison_param(char *buf)
{
diff --git a/mm/slab.c b/mm/slab.c
index bd63450a9b16..1462b0b8b0a0 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1894,6 +1894,10 @@ unsigned long kmem_cache_flags(unsigned long object_size,
unsigned long flags, const char *name,
void (*ctor)(void *))
{
+#ifdef CONFIG_MEMORY_SANITIZE
+ flags |= SLAB_POISON;
+#endif
+
return flags;
}
diff --git a/mm/slub.c b/mm/slub.c
index 7f4bc7027ed5..5041f42c942b 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -452,6 +452,8 @@ static inline void *restore_red_left(struct kmem_cache *s, void *p)
*/
#if defined(CONFIG_SLUB_DEBUG_ON)
static int slub_debug = DEBUG_DEFAULT_FLAGS;
+#elif defined(CONFIG_MEMORY_SANITIZE)
+static int slub_debug = SLAB_POISON;
#else
static int slub_debug;
#endif
@@ -5755,6 +5757,11 @@ static int __init slab_sysfs_init(void)
struct kmem_cache *s;
int err;
+#ifdef CONFIG_MEMORY_SANITIZE
+ pr_info("[CONFIG_MEMORY_SANITIZE]: slub_debug = P? %s [0x%x]\n",
+ slub_debug & SLAB_POISON ? "yes" : "no", slub_debug);
+#endif
+
mutex_lock(&slab_mutex);
slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj);
--
2.7.4
--
Kees Cook
Pixel Security
next reply other threads:[~2017-02-25 0:32 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-25 0:32 Kees Cook [this message]
2017-02-25 8:36 ` [kernel-hardening] [RFC] mm: enable sanitizing via CONFIG Daniel Micay
2017-03-01 19:16 ` Kees Cook
2017-03-27 10:54 ` Kaiwan N Billimoria
2017-04-20 20:58 ` Kees Cook
2017-04-20 21:02 ` [kernel-hardening] " Kees Cook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170225003232.GA123380@beast \
--to=keescook@chromium.org \
--cc=kaiwan@kaiwantech.com \
--cc=kernel-hardening@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.