mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 2/2] lib: add optional linked list debugging
Date: Wed,  3 Jan 2024 11:19:48 +0100	[thread overview]
Message-ID: <20240103101948.2630473-2-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20240103101948.2630473-1-a.fatoum@pengutronix.de>

When enabled, this outputs messages like:

  list_del corruption, 000000005fe4a9d0->next is LIST_POISON1 (0000000000000100)

which can be useful when debugging.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/Kconfig        |  8 +++++
 include/linux/bug.h   | 17 +++++++++++
 lib/Kconfig.hardening | 10 +++++++
 lib/Makefile          |  1 +
 lib/list_debug.c      | 68 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 104 insertions(+)
 create mode 100644 lib/list_debug.c

diff --git a/common/Kconfig b/common/Kconfig
index c8c23a8e03a2..18ad01713293 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1704,6 +1704,14 @@ config DMA_API_DEBUG
 
 	  If unsure, say N.
 
+config DEBUG_LIST
+	bool "Debug linked list manipulation"
+	help
+	  Enable this to turn on extended checks in the linked-list
+	  walking routines.
+
+	  If unsure, say N.
+
 config PBL_BREAK
 	bool "Execute software break on pbl start"
 	depends on ARM && (!CPU_32v4T && !ARCH_TEGRA)
diff --git a/include/linux/bug.h b/include/linux/bug.h
index d8fc328a0706..8ea5f8d1b260 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -6,4 +6,21 @@
 #include <asm-generic/bug.h>
 #include <linux/build_bug.h>
 
+/*
+ * Since detected data corruption should stop operation on the affected
+ * structures. Return value must be checked and sanely acted on by caller.
+ */
+static inline __must_check bool check_data_corruption(bool v) { return v; }
+#define CHECK_DATA_CORRUPTION(condition, fmt, ...)			 \
+	check_data_corruption(({					 \
+		bool corruption = unlikely(condition);			 \
+		if (corruption) {					 \
+			if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
+				panic(fmt, ##__VA_ARGS__);		 \
+			} else						 \
+				WARN(1, fmt, ##__VA_ARGS__);		 \
+		}							 \
+		corruption;						 \
+	}))
+
 #endif	/* _LINUX_BUG_H */
diff --git a/lib/Kconfig.hardening b/lib/Kconfig.hardening
index 7f74d0d98a9c..28be42a27465 100644
--- a/lib/Kconfig.hardening
+++ b/lib/Kconfig.hardening
@@ -1,5 +1,15 @@
 menu "Hardening options"
 
+config BUG_ON_DATA_CORRUPTION
+	bool "Trigger a BUG when data corruption is detected"
+	select DEBUG_LIST
+	help
+	  Select this option if barebox should BUG when it encounters
+	  data corruption in its memory structures when they get checked
+	  for validity.
+
+	  If unsure, say N.
+
 config STACK_GUARD_PAGE
 	bool "Place guard page to catch stack overflows"
 	depends on ARM && MMU
diff --git a/lib/Makefile b/lib/Makefile
index 38204c8273e5..853d8870fe14 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_FONTS)	+= fonts/
 obj-$(CONFIG_BAREBOX_LOGO)     += logo/
 obj-y			+= reed_solomon/
 obj-$(CONFIG_RATP)	+= ratp.o
+obj-$(CONFIG_DEBUG_LIST) += list_debug.o
 obj-y			+= list_sort.o
 obj-y			+= refcount.o
 obj-y			+= int_sqrt.o
diff --git a/lib/list_debug.c b/lib/list_debug.c
new file mode 100644
index 000000000000..7de4c709a391
--- /dev/null
+++ b/lib/list_debug.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006, Red Hat, Inc., Dave Jones
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the linked list validation for DEBUG_LIST.
+ */
+
+#include <linux/export.h>
+#include <linux/list.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+/*
+ * Check that the data structures for the list manipulations are reasonably
+ * valid. Failures here indicate memory corruption (and possibly an exploit
+ * attempt).
+ */
+
+bool __list_add_valid_or_report(struct list_head *new, struct list_head *prev,
+				struct list_head *next)
+{
+	if (CHECK_DATA_CORRUPTION(prev == NULL,
+			"list_add corruption. prev is NULL.\n") ||
+	    CHECK_DATA_CORRUPTION(next == NULL,
+			"list_add corruption. next is NULL.\n") ||
+	    CHECK_DATA_CORRUPTION(next->prev != prev,
+			"list_add corruption. next->prev should be prev (%px), but was %px. (next=%px).\n",
+			prev, next->prev, next) ||
+	    CHECK_DATA_CORRUPTION(prev->next != next,
+			"list_add corruption. prev->next should be next (%px), but was %px. (prev=%px).\n",
+			next, prev->next, prev) ||
+	    CHECK_DATA_CORRUPTION(new == prev || new == next,
+			"list_add double add: new=%px, prev=%px, next=%px.\n",
+			new, prev, next))
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(__list_add_valid_or_report);
+
+bool __list_del_entry_valid_or_report(struct list_head *entry)
+{
+	struct list_head *prev, *next;
+
+	prev = entry->prev;
+	next = entry->next;
+
+	if (CHECK_DATA_CORRUPTION(next == NULL,
+			"list_del corruption, %px->next is NULL\n", entry) ||
+	    CHECK_DATA_CORRUPTION(prev == NULL,
+			"list_del corruption, %px->prev is NULL\n", entry) ||
+	    CHECK_DATA_CORRUPTION(next == LIST_POISON1,
+			"list_del corruption, %px->next is LIST_POISON1 (%px)\n",
+			entry, LIST_POISON1) ||
+	    CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
+			"list_del corruption, %px->prev is LIST_POISON2 (%px)\n",
+			entry, LIST_POISON2) ||
+	    CHECK_DATA_CORRUPTION(prev->next != entry,
+			"list_del corruption. prev->next should be %px, but was %px. (prev=%px)\n",
+			entry, prev->next, prev) ||
+	    CHECK_DATA_CORRUPTION(next->prev != entry,
+			"list_del corruption. next->prev should be %px, but was %px. (next=%px)\n",
+			entry, next->prev, next))
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(__list_del_entry_valid_or_report);
-- 
2.39.2




  reply	other threads:[~2024-01-03 10:21 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-03 10:19 [PATCH 1/2] list: rename debugging hooks Ahmad Fatoum
2024-01-03 10:19 ` Ahmad Fatoum [this message]
2024-01-04  9:12 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240103101948.2630473-2-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox