Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6190aaaf authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

Merge branches 'doc.2016.11.14a', 'fixes.2016.11.14a', 'list.2016.10.31a' and...

Merge branches 'doc.2016.11.14a', 'fixes.2016.11.14a', 'list.2016.10.31a' and 'torture.2016.11.14a' into HEAD

doc.2016.11.14a:  Documentation changes
fixes.2016.11.14aneous fixes
list.2016.10.31a:  List updates
torture.2016.11.14a:  Torture-test updates
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void);
void lkdtm_HUNG_TASK(void);
void lkdtm_HUNG_TASK(void);
void lkdtm_ATOMIC_UNDERFLOW(void);
void lkdtm_ATOMIC_UNDERFLOW(void);
void lkdtm_ATOMIC_OVERFLOW(void);
void lkdtm_ATOMIC_OVERFLOW(void);
void lkdtm_CORRUPT_LIST_ADD(void);
void lkdtm_CORRUPT_LIST_DEL(void);


/* lkdtm_heap.c */
/* lkdtm_heap.c */
void lkdtm_OVERWRITE_ALLOCATION(void);
void lkdtm_OVERWRITE_ALLOCATION(void);
+68 −0
Original line number Original line Diff line number Diff line
@@ -5,8 +5,13 @@
 * test source files.
 * test source files.
 */
 */
#include "lkdtm.h"
#include "lkdtm.h"
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/sched.h>


struct lkdtm_list {
	struct list_head node;
};

/*
/*
 * Make sure our attempts to over run the kernel stack doesn't trigger
 * Make sure our attempts to over run the kernel stack doesn't trigger
 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
 * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -146,3 +151,66 @@ void lkdtm_ATOMIC_OVERFLOW(void)
	pr_info("attempting bad atomic overflow\n");
	pr_info("attempting bad atomic overflow\n");
	atomic_inc(&over);
	atomic_inc(&over);
}
}

void lkdtm_CORRUPT_LIST_ADD(void)
{
	/*
	 * Initially, an empty list via LIST_HEAD:
	 *	test_head.next = &test_head
	 *	test_head.prev = &test_head
	 */
	LIST_HEAD(test_head);
	struct lkdtm_list good, bad;
	void *target[2] = { };
	void *redirection = &target;

	pr_info("attempting good list addition\n");

	/*
	 * Adding to the list performs these actions:
	 *	test_head.next->prev = &good.node
	 *	good.node.next = test_head.next
	 *	good.node.prev = test_head
	 *	test_head.next = good.node
	 */
	list_add(&good.node, &test_head);

	pr_info("attempting corrupted list addition\n");
	/*
	 * In simulating this "write what where" primitive, the "what" is
	 * the address of &bad.node, and the "where" is the address held
	 * by "redirection".
	 */
	test_head.next = redirection;
	list_add(&bad.node, &test_head);

	if (target[0] == NULL && target[1] == NULL)
		pr_err("Overwrite did not happen, but no BUG?!\n");
	else
		pr_err("list_add() corruption not detected!\n");
}

void lkdtm_CORRUPT_LIST_DEL(void)
{
	LIST_HEAD(test_head);
	struct lkdtm_list item;
	void *target[2] = { };
	void *redirection = &target;

	list_add(&item.node, &test_head);

	pr_info("attempting good list removal\n");
	list_del(&item.node);

	pr_info("attempting corrupted list removal\n");
	list_add(&item.node, &test_head);

	/* As with the list_add() test above, this corrupts "next". */
	item.node.next = redirection;
	list_del(&item.node);

	if (target[0] == NULL && target[1] == NULL)
		pr_err("Overwrite did not happen, but no BUG?!\n");
	else
		pr_err("list_del() corruption not detected!\n");
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -197,6 +197,8 @@ struct crashtype crashtypes[] = {
	CRASHTYPE(EXCEPTION),
	CRASHTYPE(EXCEPTION),
	CRASHTYPE(LOOP),
	CRASHTYPE(LOOP),
	CRASHTYPE(OVERFLOW),
	CRASHTYPE(OVERFLOW),
	CRASHTYPE(CORRUPT_LIST_ADD),
	CRASHTYPE(CORRUPT_LIST_DEL),
	CRASHTYPE(CORRUPT_STACK),
	CRASHTYPE(CORRUPT_STACK),
	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
	CRASHTYPE(OVERWRITE_ALLOCATION),
	CRASHTYPE(OVERWRITE_ALLOCATION),
+17 −0
Original line number Original line Diff line number Diff line
@@ -121,4 +121,21 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
}
}


#endif	/* CONFIG_GENERIC_BUG */
#endif	/* CONFIG_GENERIC_BUG */

/*
 * Since detected data corruption should stop operation on the affected
 * structures, this returns false if the corruption condition is found.
 */
#define CHECK_DATA_CORRUPTION(condition, fmt, ...)			 \
	do {								 \
		if (unlikely(condition)) {				 \
			if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
				pr_err(fmt, ##__VA_ARGS__);		 \
				BUG();					 \
			} else						 \
				WARN(1, fmt, ##__VA_ARGS__);		 \
			return false;					 \
		}							 \
	} while (0)

#endif	/* _LINUX_BUG_H */
#endif	/* _LINUX_BUG_H */
+25 −12
Original line number Original line Diff line number Diff line
@@ -28,27 +28,42 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
	list->prev = list;
	list->prev = list;
}
}


#ifdef CONFIG_DEBUG_LIST
extern bool __list_add_valid(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next);
extern bool __list_del_entry_valid(struct list_head *entry);
#else
static inline bool __list_add_valid(struct list_head *new,
				struct list_head *prev,
				struct list_head *next)
{
	return true;
}
static inline bool __list_del_entry_valid(struct list_head *entry)
{
	return true;
}
#endif

/*
/*
 * Insert a new entry between two known consecutive entries.
 * Insert a new entry between two known consecutive entries.
 *
 *
 * This is only for internal list manipulation where we know
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 * the prev/next entries already!
 */
 */
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
static inline void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *prev,
			      struct list_head *next)
			      struct list_head *next)
{
{
	if (!__list_add_valid(new, prev, next))
		return;

	next->prev = new;
	next->prev = new;
	new->next = next;
	new->next = next;
	new->prev = prev;
	new->prev = prev;
	WRITE_ONCE(prev->next, new);
	WRITE_ONCE(prev->next, new);
}
}
#else
extern void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next);
#endif


/**
/**
 * list_add - add a new entry
 * list_add - add a new entry
@@ -96,22 +111,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
 * Note: list_empty() on entry does not return true after this, the entry is
 * Note: list_empty() on entry does not return true after this, the entry is
 * in an undefined state.
 * in an undefined state.
 */
 */
#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
static inline void __list_del_entry(struct list_head *entry)
{
{
	if (!__list_del_entry_valid(entry))
		return;

	__list_del(entry->prev, entry->next);
	__list_del(entry->prev, entry->next);
}
}


static inline void list_del(struct list_head *entry)
static inline void list_del(struct list_head *entry)
{
{
	__list_del(entry->prev, entry->next);
	__list_del_entry(entry);
	entry->next = LIST_POISON1;
	entry->next = LIST_POISON1;
	entry->prev = LIST_POISON2;
	entry->prev = LIST_POISON2;
}
}
#else
extern void __list_del_entry(struct list_head *entry);
extern void list_del(struct list_head *entry);
#endif


/**
/**
 * list_replace - replace old entry by new one
 * list_replace - replace old entry by new one
Loading