|
@@ -6,6 +6,7 @@
|
|
|
*/
|
|
|
#include "lkdtm.h"
|
|
|
#include <linux/list.h>
|
|
|
+#include <linux/refcount.h>
|
|
|
#include <linux/sched.h>
|
|
|
|
|
|
struct lkdtm_list {
|
|
@@ -129,28 +130,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_REFCOUNT_SATURATE_ADD(void)
|
|
|
+{
|
|
|
+ refcount_t over = REFCOUNT_INIT(UINT_MAX - 1);
|
|
|
+
|
|
|
+ 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");
|
|
|
+}
|
|
|
+
|
|
|
+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_ATOMIC_OVERFLOW(void)
|
|
|
+void lkdtm_REFCOUNT_ZERO_SUB(void)
|
|
|
{
|
|
|
- atomic_t over = ATOMIC_INIT(INT_MAX);
|
|
|
+ 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");
|
|
|
+}
|
|
|
|
|
|
- pr_info("attempting good atomic decrement\n");
|
|
|
- atomic_dec(&over);
|
|
|
- atomic_inc(&over);
|
|
|
+void lkdtm_REFCOUNT_ZERO_INC(void)
|
|
|
+{
|
|
|
+ refcount_t zero = REFCOUNT_INIT(0);
|
|
|
|
|
|
- pr_info("attempting bad atomic overflow\n");
|
|
|
- atomic_inc(&over);
|
|
|
+ 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)
|