@@ -11,6 +11,7 @@
#include <linux/sched/signal.h>
#include <linux/sched/task_stack.h>
#include <linux/uaccess.h>
+#include <linux/slab.h>
#ifdef CONFIG_X86_32
#include <asm/desc.h>
@@ -376,3 +377,53 @@ void lkdtm_DOUBLE_FAULT(void)
panic("tried to double fault but didn't die\n");
}
#endif
+
+void lkdtm_FORTIFY_OBJECT(void)
+{
+ struct target {
+ char a[10];
+ } target[2] = {};
+ int result;
+
+ /*
+ * Using volatile prevents the compiler from determining the value of
+ * 'size' at compile time. Without that, we would get a compile error
+ * rather than a runtime error.
+ */
+ volatile int size = 11;
+
+ pr_info("trying to read past the end of a struct\n");
+
+ result = memcmp(&target[0], &target[1], size);
+
+ /* Print result to prevent the code from being eliminated */
+ pr_err("FAIL: fortify did not catch an object overread!\n"
+ "\"%d\" was the memcmp result.\n", result);
+}
+
+void lkdtm_FORTIFY_SUBOBJECT(void)
+{
+ struct target {
+ char a[10];
+ char b[10];
+ } target;
+ char *src;
+
+ src = kmalloc(20, GFP_KERNEL);
+ strscpy(src, "over ten bytes", 20);
+
+ pr_info("trying to strcpy past the end of a member of a struct\n");
+
+ /*
+ * strncpy(target.a, src, 20); will hit a compile error because the
+ * compiler knows at build time that target.a < 20 bytes. Use strcpy()
+ * to force a runtime error.
+ */
+ strcpy(target.a, src);
+
+ /* Use target.a to prevent the code from being eliminated */
+ pr_err("FAIL: fortify did not catch an sub-object overrun!\n"
+ "\"%s\" was copied.\n", target.a);
+
+ kfree(src);
+}
@@ -117,6 +117,8 @@ static const struct crashtype crashtypes[] = {
CRASHTYPE(STACK_GUARD_PAGE_TRAILING),
CRASHTYPE(UNSET_SMEP),
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
+ CRASHTYPE(FORTIFY_OBJECT),
+ CRASHTYPE(FORTIFY_SUBOBJECT),
CRASHTYPE(OVERWRITE_ALLOCATION),
CRASHTYPE(WRITE_AFTER_FREE),
CRASHTYPE(READ_AFTER_FREE),
@@ -31,6 +31,8 @@ void lkdtm_UNSET_SMEP(void);
#ifdef CONFIG_X86_32
void lkdtm_DOUBLE_FAULT(void);
#endif
+void lkdtm_FORTIFY_OBJECT(void);
+void lkdtm_FORTIFY_SUBOBJECT(void);
/* lkdtm_heap.c */
void __init lkdtm_heap_init(void);