Skip to content

Commit ae2e1aa

Browse files
keestorvalds
authored andcommitted
drivers/misc/lkdtm/bugs.c: add arithmetic overflow and array bounds checks
Adds LKDTM tests for arithmetic overflow (both signed and unsigned), as well as array bounds checking. Signed-off-by: Kees Cook <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Acked-by: Dmitry Vyukov <[email protected]> Cc: Alexander Potapenko <[email protected]> Cc: Andrey Konovalov <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Dan Carpenter <[email protected]> Cc: Elena Petrova <[email protected]> Cc: "Gustavo A. R. Silva" <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 277a108 commit ae2e1aa

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

drivers/misc/lkdtm/bugs.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/sched/signal.h>
1212
#include <linux/sched/task_stack.h>
1313
#include <linux/uaccess.h>
14+
#include <linux/slab.h>
1415

1516
#ifdef CONFIG_X86_32
1617
#include <asm/desc.h>
@@ -175,6 +176,80 @@ void lkdtm_HUNG_TASK(void)
175176
schedule();
176177
}
177178

179+
volatile unsigned int huge = INT_MAX - 2;
180+
volatile unsigned int ignored;
181+
182+
void lkdtm_OVERFLOW_SIGNED(void)
183+
{
184+
int value;
185+
186+
value = huge;
187+
pr_info("Normal signed addition ...\n");
188+
value += 1;
189+
ignored = value;
190+
191+
pr_info("Overflowing signed addition ...\n");
192+
value += 4;
193+
ignored = value;
194+
}
195+
196+
197+
void lkdtm_OVERFLOW_UNSIGNED(void)
198+
{
199+
unsigned int value;
200+
201+
value = huge;
202+
pr_info("Normal unsigned addition ...\n");
203+
value += 1;
204+
ignored = value;
205+
206+
pr_info("Overflowing unsigned addition ...\n");
207+
value += 4;
208+
ignored = value;
209+
}
210+
211+
/* Intentially using old-style flex array definition of 1 byte. */
212+
struct array_bounds_flex_array {
213+
int one;
214+
int two;
215+
char data[1];
216+
};
217+
218+
struct array_bounds {
219+
int one;
220+
int two;
221+
char data[8];
222+
int three;
223+
};
224+
225+
void lkdtm_ARRAY_BOUNDS(void)
226+
{
227+
struct array_bounds_flex_array *not_checked;
228+
struct array_bounds *checked;
229+
volatile int i;
230+
231+
not_checked = kmalloc(sizeof(*not_checked) * 2, GFP_KERNEL);
232+
checked = kmalloc(sizeof(*checked) * 2, GFP_KERNEL);
233+
234+
pr_info("Array access within bounds ...\n");
235+
/* For both, touch all bytes in the actual member size. */
236+
for (i = 0; i < sizeof(checked->data); i++)
237+
checked->data[i] = 'A';
238+
/*
239+
* For the uninstrumented flex array member, also touch 1 byte
240+
* beyond to verify it is correctly uninstrumented.
241+
*/
242+
for (i = 0; i < sizeof(not_checked->data) + 1; i++)
243+
not_checked->data[i] = 'A';
244+
245+
pr_info("Array access beyond bounds ...\n");
246+
for (i = 0; i < sizeof(checked->data) + 1; i++)
247+
checked->data[i] = 'B';
248+
249+
kfree(not_checked);
250+
kfree(checked);
251+
}
252+
178253
void lkdtm_CORRUPT_LIST_ADD(void)
179254
{
180255
/*

drivers/misc/lkdtm/core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ static const struct crashtype crashtypes[] = {
130130
CRASHTYPE(HARDLOCKUP),
131131
CRASHTYPE(SPINLOCKUP),
132132
CRASHTYPE(HUNG_TASK),
133+
CRASHTYPE(OVERFLOW_SIGNED),
134+
CRASHTYPE(OVERFLOW_UNSIGNED),
135+
CRASHTYPE(ARRAY_BOUNDS),
133136
CRASHTYPE(EXEC_DATA),
134137
CRASHTYPE(EXEC_STACK),
135138
CRASHTYPE(EXEC_KMALLOC),

drivers/misc/lkdtm/lkdtm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ void lkdtm_SOFTLOCKUP(void);
2222
void lkdtm_HARDLOCKUP(void);
2323
void lkdtm_SPINLOCKUP(void);
2424
void lkdtm_HUNG_TASK(void);
25+
void lkdtm_OVERFLOW_SIGNED(void);
26+
void lkdtm_OVERFLOW_UNSIGNED(void);
27+
void lkdtm_ARRAY_BOUNDS(void);
2528
void lkdtm_CORRUPT_LIST_ADD(void);
2629
void lkdtm_CORRUPT_LIST_DEL(void);
2730
void lkdtm_CORRUPT_USER_DS(void);

0 commit comments

Comments
 (0)