drivers/misc/lkdtm/bugs.c: add arithmetic overflow and array bounds checks
authorKees Cook <keescook@chromium.org>
Tue, 7 Apr 2020 03:12:34 +0000 (20:12 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2020 17:43:44 +0000 (10:43 -0700)
Adds LKDTM tests for arithmetic overflow (both signed and unsigned), as
well as array bounds checking.

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Elena Petrova <lenaptr@google.com>
Cc: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
Link: http://lkml.kernel.org/r/20200227193516.32566-4-keescook@chromium.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/misc/lkdtm/bugs.c
drivers/misc/lkdtm/core.c
drivers/misc/lkdtm/lkdtm.h

index cc92bc3..886459e 100644 (file)
@@ -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>
@@ -175,6 +176,80 @@ void lkdtm_HUNG_TASK(void)
        schedule();
 }
 
+volatile unsigned int huge = INT_MAX - 2;
+volatile unsigned int ignored;
+
+void lkdtm_OVERFLOW_SIGNED(void)
+{
+       int value;
+
+       value = huge;
+       pr_info("Normal signed addition ...\n");
+       value += 1;
+       ignored = value;
+
+       pr_info("Overflowing signed addition ...\n");
+       value += 4;
+       ignored = value;
+}
+
+
+void lkdtm_OVERFLOW_UNSIGNED(void)
+{
+       unsigned int value;
+
+       value = huge;
+       pr_info("Normal unsigned addition ...\n");
+       value += 1;
+       ignored = value;
+
+       pr_info("Overflowing unsigned addition ...\n");
+       value += 4;
+       ignored = value;
+}
+
+/* Intentially using old-style flex array definition of 1 byte. */
+struct array_bounds_flex_array {
+       int one;
+       int two;
+       char data[1];
+};
+
+struct array_bounds {
+       int one;
+       int two;
+       char data[8];
+       int three;
+};
+
+void lkdtm_ARRAY_BOUNDS(void)
+{
+       struct array_bounds_flex_array *not_checked;
+       struct array_bounds *checked;
+       volatile int i;
+
+       not_checked = kmalloc(sizeof(*not_checked) * 2, GFP_KERNEL);
+       checked = kmalloc(sizeof(*checked) * 2, GFP_KERNEL);
+
+       pr_info("Array access within bounds ...\n");
+       /* For both, touch all bytes in the actual member size. */
+       for (i = 0; i < sizeof(checked->data); i++)
+               checked->data[i] = 'A';
+       /*
+        * For the uninstrumented flex array member, also touch 1 byte
+        * beyond to verify it is correctly uninstrumented.
+        */
+       for (i = 0; i < sizeof(not_checked->data) + 1; i++)
+               not_checked->data[i] = 'A';
+
+       pr_info("Array access beyond bounds ...\n");
+       for (i = 0; i < sizeof(checked->data) + 1; i++)
+               checked->data[i] = 'B';
+
+       kfree(not_checked);
+       kfree(checked);
+}
+
 void lkdtm_CORRUPT_LIST_ADD(void)
 {
        /*
index 5ce4ac8..a5e344d 100644 (file)
@@ -130,6 +130,9 @@ static const struct crashtype crashtypes[] = {
        CRASHTYPE(HARDLOCKUP),
        CRASHTYPE(SPINLOCKUP),
        CRASHTYPE(HUNG_TASK),
+       CRASHTYPE(OVERFLOW_SIGNED),
+       CRASHTYPE(OVERFLOW_UNSIGNED),
+       CRASHTYPE(ARRAY_BOUNDS),
        CRASHTYPE(EXEC_DATA),
        CRASHTYPE(EXEC_STACK),
        CRASHTYPE(EXEC_KMALLOC),
index 8d13d01..601a215 100644 (file)
@@ -22,6 +22,9 @@ void lkdtm_SOFTLOCKUP(void);
 void lkdtm_HARDLOCKUP(void);
 void lkdtm_SPINLOCKUP(void);
 void lkdtm_HUNG_TASK(void);
+void lkdtm_OVERFLOW_SIGNED(void);
+void lkdtm_OVERFLOW_UNSIGNED(void);
+void lkdtm_ARRAY_BOUNDS(void);
 void lkdtm_CORRUPT_LIST_ADD(void);
 void lkdtm_CORRUPT_LIST_DEL(void);
 void lkdtm_CORRUPT_USER_DS(void);