Skip to content

Commit

Permalink
drivers/misc/lkdtm/bugs.c: add arithmetic overflow and array bounds c…
Browse files Browse the repository at this point in the history
…hecks

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>
  • Loading branch information
kees authored and torvalds committed Apr 7, 2020
1 parent 277a108 commit ae2e1aa
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
75 changes: 75 additions & 0 deletions drivers/misc/lkdtm/bugs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
{
/*
Expand Down
3 changes: 3 additions & 0 deletions drivers/misc/lkdtm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
3 changes: 3 additions & 0 deletions drivers/misc/lkdtm/lkdtm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit ae2e1aa

Please sign in to comment.