summaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/thread_info.h
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2016-07-12 16:19:48 -0700
committerKees Cook <keescook@chromium.org>2016-07-26 14:41:47 -0700
commit0f60a8efe4005ab5e65ce000724b04d4ca04a199 (patch)
treea71bc07c426721394f3156318b2220d8f6299c07 /arch/x86/include/asm/thread_info.h
parent7c15d9bb8231f998ae7dc0b72415f5215459f7fb (diff)
downloadlinux-0-day-0f60a8efe4005ab5e65ce000724b04d4ca04a199.tar.gz
linux-0-day-0f60a8efe4005ab5e65ce000724b04d4ca04a199.tar.xz
mm: Implement stack frame object validation
This creates per-architecture function arch_within_stack_frames() that should validate if a given object is contained by a kernel stack frame. Initial implementation is on x86. This is based on code from PaX. Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'arch/x86/include/asm/thread_info.h')
-rw-r--r--arch/x86/include/asm/thread_info.h44
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 30c133ac05cd8..ab386f1336f2e 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -180,6 +180,50 @@ static inline unsigned long current_stack_pointer(void)
return sp;
}
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ * 1 if within a frame
+ * -1 if placed across a frame boundary (or outside stack)
+ * 0 unable to determine (no frame pointers, etc)
+ */
+static inline int arch_within_stack_frames(const void * const stack,
+ const void * const stackend,
+ const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+ const void *frame = NULL;
+ const void *oldframe;
+
+ oldframe = __builtin_frame_address(1);
+ if (oldframe)
+ frame = __builtin_frame_address(2);
+ /*
+ * low ----------------------------------------------> high
+ * [saved bp][saved ip][args][local vars][saved bp][saved ip]
+ * ^----------------^
+ * allow copies only within here
+ */
+ while (stack <= frame && frame < stackend) {
+ /*
+ * If obj + len extends past the last frame, this
+ * check won't pass and the next frame will be 0,
+ * causing us to bail out and correctly report
+ * the copy as invalid.
+ */
+ if (obj + len <= frame)
+ return obj >= oldframe + 2 * sizeof(void *) ? 1 : -1;
+ oldframe = frame;
+ frame = *(const void * const *)frame;
+ }
+ return -1;
+#else
+ return 0;
+#endif
+}
+
#else /* !__ASSEMBLY__ */
#ifdef CONFIG_X86_64