summaryrefslogtreecommitdiffstats
path: root/drivers/misc/lkdtm_bugs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/lkdtm_bugs.c')
-rw-r--r--drivers/misc/lkdtm_bugs.c94
1 files changed, 79 insertions, 15 deletions
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 91edd0b55e5c..e3f4cd8876b5 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -6,6 +6,7 @@
*/
#include "lkdtm.h"
#include <linux/list.h>
+#include <linux/refcount.h>
#include <linux/sched.h>
struct lkdtm_list {
@@ -80,12 +81,17 @@ void lkdtm_OVERFLOW(void)
(void) recursive_loop(recur_count);
}
+static noinline void __lkdtm_CORRUPT_STACK(void *stack)
+{
+ memset(stack, 'a', 64);
+}
+
noinline void lkdtm_CORRUPT_STACK(void)
{
/* Use default char array length that triggers stack protection. */
char data[8];
+ __lkdtm_CORRUPT_STACK(&data);
- memset((void *)data, 'a', 64);
pr_info("Corrupted stack with '%16s'...\n", data);
}
@@ -129,28 +135,86 @@ void lkdtm_HUNG_TASK(void)
schedule();
}
-void lkdtm_ATOMIC_UNDERFLOW(void)
+void lkdtm_REFCOUNT_SATURATE_INC(void)
{
- atomic_t under = ATOMIC_INIT(INT_MIN);
+ refcount_t over = REFCOUNT_INIT(UINT_MAX - 1);
- pr_info("attempting good atomic increment\n");
- atomic_inc(&under);
- atomic_dec(&under);
+ pr_info("attempting good refcount decrement\n");
+ refcount_dec(&over);
+ refcount_inc(&over);
- pr_info("attempting bad atomic underflow\n");
- atomic_dec(&under);
+ pr_info("attempting bad refcount inc overflow\n");
+ refcount_inc(&over);
+ refcount_inc(&over);
+ if (refcount_read(&over) == UINT_MAX)
+ pr_err("Correctly stayed saturated, but no BUG?!\n");
+ else
+ pr_err("Fail: refcount wrapped\n");
}
-void lkdtm_ATOMIC_OVERFLOW(void)
+void lkdtm_REFCOUNT_SATURATE_ADD(void)
{
- atomic_t over = ATOMIC_INIT(INT_MAX);
+ refcount_t over = REFCOUNT_INIT(UINT_MAX - 1);
- pr_info("attempting good atomic decrement\n");
- atomic_dec(&over);
- atomic_inc(&over);
+ pr_info("attempting good refcount decrement\n");
+ refcount_dec(&over);
+ refcount_inc(&over);
+
+ pr_info("attempting bad refcount add overflow\n");
+ refcount_add(2, &over);
+ if (refcount_read(&over) == UINT_MAX)
+ pr_err("Correctly stayed saturated, but no BUG?!\n");
+ else
+ pr_err("Fail: refcount wrapped\n");
+}
- pr_info("attempting bad atomic overflow\n");
- atomic_inc(&over);
+void lkdtm_REFCOUNT_ZERO_DEC(void)
+{
+ refcount_t zero = REFCOUNT_INIT(1);
+
+ pr_info("attempting bad refcount decrement to zero\n");
+ refcount_dec(&zero);
+ if (refcount_read(&zero) == 0)
+ pr_err("Stayed at zero, but no BUG?!\n");
+ else
+ pr_err("Fail: refcount went crazy\n");
+}
+
+void lkdtm_REFCOUNT_ZERO_SUB(void)
+{
+ refcount_t zero = REFCOUNT_INIT(1);
+
+ pr_info("attempting bad refcount subtract past zero\n");
+ if (!refcount_sub_and_test(2, &zero))
+ pr_info("wrap attempt was noticed\n");
+ if (refcount_read(&zero) == 1)
+ pr_err("Correctly stayed above 0, but no BUG?!\n");
+ else
+ pr_err("Fail: refcount wrapped\n");
+}
+
+void lkdtm_REFCOUNT_ZERO_INC(void)
+{
+ refcount_t zero = REFCOUNT_INIT(0);
+
+ pr_info("attempting bad refcount increment from zero\n");
+ refcount_inc(&zero);
+ if (refcount_read(&zero) == 0)
+ pr_err("Stayed at zero, but no BUG?!\n");
+ else
+ pr_err("Fail: refcount went past zero\n");
+}
+
+void lkdtm_REFCOUNT_ZERO_ADD(void)
+{
+ refcount_t zero = REFCOUNT_INIT(0);
+
+ pr_info("attempting bad refcount addition from zero\n");
+ refcount_add(2, &zero);
+ if (refcount_read(&zero) == 0)
+ pr_err("Stayed at zero, but no BUG?!\n");
+ else
+ pr_err("Fail: refcount went past zero\n");
}
void lkdtm_CORRUPT_LIST_ADD(void)